diff --git a/.bashrc b/.bashrc deleted file mode 100644 index 272a82c..0000000 --- a/.bashrc +++ /dev/null @@ -1,3 +0,0 @@ -if [ -t 1 ]; then -exec zsh -fi diff --git a/GeoClient.sln b/GeoClient.sln index 0ccd45f..4d87a9e 100644 --- a/GeoClient.sln +++ b/GeoClient.sln @@ -9,7 +9,9 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GeoClient.iOS", "GeoClient\ EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GeoClient.UWP", "GeoClient\GeoClient.UWP\GeoClient.UWP.csproj", "{FC79F765-A59D-4681-8326-82124E1BA340}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GeoClient", "GeoClient\GeoClient\GeoClient.csproj", "{FA8B858C-9662-4B4F-86B6-0F6515B5480D}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GeoClient", "GeoClient\GeoClient\GeoClient.csproj", "{FA8B858C-9662-4B4F-86B6-0F6515B5480D}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GeoClientTests", "GeoClientTests\GeoClientTests.csproj", "{B19C892E-2628-4CA7-AD27-08D406A3B14B}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -171,6 +173,30 @@ Global {FA8B858C-9662-4B4F-86B6-0F6515B5480D}.Release|x86.ActiveCfg = Release|Any CPU {FA8B858C-9662-4B4F-86B6-0F6515B5480D}.Release|x86.Build.0 = Release|Any CPU {FA8B858C-9662-4B4F-86B6-0F6515B5480D}.Release|x86.Deploy.0 = Release|Any CPU + {B19C892E-2628-4CA7-AD27-08D406A3B14B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B19C892E-2628-4CA7-AD27-08D406A3B14B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B19C892E-2628-4CA7-AD27-08D406A3B14B}.Debug|ARM.ActiveCfg = Debug|Any CPU + {B19C892E-2628-4CA7-AD27-08D406A3B14B}.Debug|ARM.Build.0 = Debug|Any CPU + {B19C892E-2628-4CA7-AD27-08D406A3B14B}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {B19C892E-2628-4CA7-AD27-08D406A3B14B}.Debug|iPhone.Build.0 = Debug|Any CPU + {B19C892E-2628-4CA7-AD27-08D406A3B14B}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {B19C892E-2628-4CA7-AD27-08D406A3B14B}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU + {B19C892E-2628-4CA7-AD27-08D406A3B14B}.Debug|x64.ActiveCfg = Debug|Any CPU + {B19C892E-2628-4CA7-AD27-08D406A3B14B}.Debug|x64.Build.0 = Debug|Any CPU + {B19C892E-2628-4CA7-AD27-08D406A3B14B}.Debug|x86.ActiveCfg = Debug|Any CPU + {B19C892E-2628-4CA7-AD27-08D406A3B14B}.Debug|x86.Build.0 = Debug|Any CPU + {B19C892E-2628-4CA7-AD27-08D406A3B14B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B19C892E-2628-4CA7-AD27-08D406A3B14B}.Release|Any CPU.Build.0 = Release|Any CPU + {B19C892E-2628-4CA7-AD27-08D406A3B14B}.Release|ARM.ActiveCfg = Release|Any CPU + {B19C892E-2628-4CA7-AD27-08D406A3B14B}.Release|ARM.Build.0 = Release|Any CPU + {B19C892E-2628-4CA7-AD27-08D406A3B14B}.Release|iPhone.ActiveCfg = Release|Any CPU + {B19C892E-2628-4CA7-AD27-08D406A3B14B}.Release|iPhone.Build.0 = Release|Any CPU + {B19C892E-2628-4CA7-AD27-08D406A3B14B}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {B19C892E-2628-4CA7-AD27-08D406A3B14B}.Release|iPhoneSimulator.Build.0 = Release|Any CPU + {B19C892E-2628-4CA7-AD27-08D406A3B14B}.Release|x64.ActiveCfg = Release|Any CPU + {B19C892E-2628-4CA7-AD27-08D406A3B14B}.Release|x64.Build.0 = Release|Any CPU + {B19C892E-2628-4CA7-AD27-08D406A3B14B}.Release|x86.ActiveCfg = Release|Any CPU + {B19C892E-2628-4CA7-AD27-08D406A3B14B}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/GeoClient/GeoClient.Android/GeoClient.Android.csproj b/GeoClient/GeoClient.Android/GeoClient.Android.csproj index b7748bd..19c7786 100644 --- a/GeoClient/GeoClient.Android/GeoClient.Android.csproj +++ b/GeoClient/GeoClient.Android/GeoClient.Android.csproj @@ -31,7 +31,7 @@ None - true + false pdbonly true bin\Release diff --git a/GeoClient/GeoClient.Android/Properties/AndroidManifest.xml b/GeoClient/GeoClient.Android/Properties/AndroidManifest.xml index 786291d..79bdeda 100644 --- a/GeoClient/GeoClient.Android/Properties/AndroidManifest.xml +++ b/GeoClient/GeoClient.Android/Properties/AndroidManifest.xml @@ -1,5 +1,5 @@  - + diff --git a/GeoClient/GeoClient.iOS/Info.plist b/GeoClient/GeoClient.iOS/Info.plist index 6e25cc2..50a8863 100644 --- a/GeoClient/GeoClient.iOS/Info.plist +++ b/GeoClient/GeoClient.iOS/Info.plist @@ -28,7 +28,7 @@ CFBundleIdentifier com.companyname.GeoClient CFBundleVersion - 1.1.0 + 1.1.1 UILaunchStoryboardName LaunchScreen CFBundleName diff --git a/GeoClient/GeoClient/GeoClient.csproj b/GeoClient/GeoClient/GeoClient.csproj index 32bd58b..a9ffb08 100644 --- a/GeoClient/GeoClient/GeoClient.csproj +++ b/GeoClient/GeoClient/GeoClient.csproj @@ -6,8 +6,8 @@ Daniel Steiner, Robert Wittek MIT License App to share the position data - 1.1.0 - 1.1.0.0 + 1.1.1 + 1.1.1.0 diff --git a/GeoClient/GeoClient/Models/GeoPoint.cs b/GeoClient/GeoClient/Models/GeoPoint.cs index d010292..98f385b 100644 --- a/GeoClient/GeoClient/Models/GeoPoint.cs +++ b/GeoClient/GeoClient/Models/GeoPoint.cs @@ -1,18 +1,40 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace GeoClient.Models +namespace GeoClient.Models { public class GeoPoint { - public string Latitude { get; } - public string Longitude { get; } + public double Latitude { get; } + public double Longitude { get; } - public GeoPoint(string latitude, string longitude) + public GeoPoint(double latitude, double longitude) { Latitude = latitude; Longitude = longitude; } + + protected bool Equals(GeoPoint other) + { + return Latitude.Equals(other.Latitude) && Longitude.Equals(other.Longitude); + } + + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) return false; + if (ReferenceEquals(this, obj)) return true; + if (obj.GetType() != this.GetType()) return false; + return Equals((GeoPoint) obj); + } + + public override int GetHashCode() + { + unchecked + { + return (Latitude.GetHashCode() * 397) ^ Longitude.GetHashCode(); + } + } + + public override string ToString() + { + return $"{nameof(Latitude)}: {Latitude}, {nameof(Longitude)}: {Longitude}"; + } } } diff --git a/GeoClient/GeoClient/Models/IncidentItem.cs b/GeoClient/GeoClient/Models/IncidentItem.cs index 0327f2b..44f5b0b 100644 --- a/GeoClient/GeoClient/Models/IncidentItem.cs +++ b/GeoClient/GeoClient/Models/IncidentItem.cs @@ -2,32 +2,98 @@ using GeoClient.Services.Utils; using System; using System.Collections.Generic; +using System.Linq; +using GeoClient.Views.Utils; using Xamarin.Forms; namespace GeoClient.Models { - public class IncidentItem + public class IncidentItem : IComparable { public string Id { get; } - public GeoIncidentType? Type { get; set; } - public string Info { get; set; } - public bool Priority { get; set; } - public bool Blue { get; set; } - public GeoPoint Location { get; set; } + public GeoIncidentType? Type { get; } + public string Info { get; } + public bool Priority { get; } + public bool Blue { get; } + public GeoPoint Location { get; } - public SortedSet Units { get; set; } + public List Units { get; } public string DescriptiveType => GetDescriptiveType(); public Color BackgroundColor => GetBackgroundColor(); public Color ForegroundColor => GetForegroundColor(); public IncidentTaskState? OwnTaskState => GetOwnTaskState(); public string OwnTaskStateIcon => GetOwnTaskStateIcon(); + public string OwnTaskStateDescription => OwnTaskState?.GetDescription(); + public bool IsUnitAssignedToTask => GetIsUnitAssignedToTask(); RegistrationService _registrationService = RegistrationService.Instance; - public IncidentItem(string id) + public IncidentItem( + string id, + GeoIncidentType type = GeoIncidentType.Unknown, + string info = "", + bool priority = false, + bool blue = false, + GeoPoint location = null, + List units = null) { Id = id; + Type = type; + Info = info; + Priority = priority; + Blue = blue; + Location = location; + Units = units ?? new List(); + } + + protected bool Equals(IncidentItem other) + { + return string.Equals(Id, other.Id) + && Type == other.Type + && string.Equals(Info, other.Info) + && Priority == other.Priority + && Blue == other.Blue + && Equals(Location, other.Location) + && ListEquals(Units, other.Units); + } + + private bool ListEquals(List units, List otherUnits) + { + if (units == null) + return otherUnits == null; + if (otherUnits == null) + return false; + return units.SequenceEqual(otherUnits); + } + + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) return false; + if (ReferenceEquals(this, obj)) return true; + if (obj.GetType() != GetType()) return false; + return Equals((IncidentItem) obj); + } + + public override int GetHashCode() + { + unchecked + { + var hashCode = (Id != null ? Id.GetHashCode() : 0); + hashCode = (hashCode * 397) ^ Type.GetHashCode(); + hashCode = (hashCode * 397) ^ (Info != null ? Info.GetHashCode() : 0); + hashCode = (hashCode * 397) ^ Priority.GetHashCode(); + hashCode = (hashCode * 397) ^ Blue.GetHashCode(); + hashCode = (hashCode * 397) ^ (Location != null ? Location.GetHashCode() : 0); + hashCode = (hashCode * 397) ^ (Units != null ? Units.GetHashCode() : 0); + return hashCode; + } + } + + public override string ToString() + { + return + $"{nameof(Id)}: {Id}, {nameof(Type)}: {Type}, {nameof(Info)}: {Info}, {nameof(Priority)}: {Priority}, {nameof(Blue)}: {Blue}, {nameof(Location)}: {Location}, Units.Count: {Units.Count}"; } private string GetDescriptiveType() @@ -82,5 +148,33 @@ private string GetOwnTaskStateIcon() { return StatusIconResolver.GetIconForTaskState(OwnTaskState); } + + private bool GetIsUnitAssignedToTask() + { + return OwnTaskState != IncidentTaskState.Unknown; + } + + public int CompareTo(IncidentItem other) + { + if (ReferenceEquals(this, other)) return 0; + if (ReferenceEquals(null, other)) return 1; + + var assignmentComparison = IsUnitAssignedToTask.CompareTo(other.IsUnitAssignedToTask); + if (assignmentComparison != 0) + return -assignmentComparison; + + var blueComparison = Blue.CompareTo(other.Blue); + if (blueComparison != 0) + return -blueComparison; + + var priorityComparison = Priority.CompareTo(other.Priority); + if (priorityComparison != 0) + return -priorityComparison; + + var typeComparison = Nullable.Compare(Type, other.Type); + if (typeComparison != 0) return typeComparison; + + return string.Compare(Info, other.Info, StringComparison.OrdinalIgnoreCase); + } } } \ No newline at end of file diff --git a/GeoClient/GeoClient/Models/IncidentTaskState.cs b/GeoClient/GeoClient/Models/IncidentTaskState.cs index 5f471e7..c4bb5c3 100644 --- a/GeoClient/GeoClient/Models/IncidentTaskState.cs +++ b/GeoClient/GeoClient/Models/IncidentTaskState.cs @@ -1,12 +1,25 @@ -namespace GeoClient.Models +using System.ComponentModel; + +namespace GeoClient.Models { public enum IncidentTaskState { + [Description("Alarmiert")] Assigned, + + [Description("Zum Berufungsort")] Zbo, + + [Description("Am Berufungsort")] Abo, + + [Description("Zum Abgabeort")] Zao, + + [Description("Am Abgabeort")] Aao, + + [Description("Unbekannt")] Unknown } } diff --git a/GeoClient/GeoClient/Models/Unit.cs b/GeoClient/GeoClient/Models/Unit.cs new file mode 100644 index 0000000..93231e8 --- /dev/null +++ b/GeoClient/GeoClient/Models/Unit.cs @@ -0,0 +1,75 @@ +using GeoClient.Services.Utils; +using System; + +namespace GeoClient.Models +{ + public class Unit : IComparable + { + public string Id { get; } + public string Name { get; } + + // TODO: This is actually a position, not only a point. There is more detailed information available. + public GeoPoint LastPoint { get; } + public IncidentTaskState State { get; } + + public string TaskStateIcon => GetTaskStateIcon(); + + public Unit( + string id, + string name, + GeoPoint lastPoint = null, + IncidentTaskState state = IncidentTaskState.Unknown) + { + Id = id; + Name = name; + LastPoint = lastPoint; + State = state; + } + + public int CompareTo(Unit other) + { + if (ReferenceEquals(this, other)) return 0; + if (ReferenceEquals(null, other)) return 1; + return string.Compare(Name, other.Name, StringComparison.OrdinalIgnoreCase); + } + + protected bool Equals(Unit other) + { + return string.Equals(Id, other.Id) + && string.Equals(Name, other.Name) + && Equals(LastPoint, other.LastPoint) + && State == other.State; + } + + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) return false; + if (ReferenceEquals(this, obj)) return true; + if (obj.GetType() != GetType()) return false; + return Equals((Unit) obj); + } + + public override int GetHashCode() + { + unchecked + { + var hashCode = (Id != null ? Id.GetHashCode() : 0); + hashCode = (hashCode * 397) ^ (Name != null ? Name.GetHashCode() : 0); + hashCode = (hashCode * 397) ^ (LastPoint != null ? LastPoint.GetHashCode() : 0); + hashCode = (hashCode * 397) ^ (int) State; + return hashCode; + } + } + + public override string ToString() + { + return + $"{nameof(Id)}: {Id}, {nameof(Name)}: {Name}, {nameof(LastPoint)}: {LastPoint}, {nameof(State)}: {State}"; + } + + private string GetTaskStateIcon() + { + return StatusIconResolver.GetIconForTaskState(State); + } + } +} \ No newline at end of file diff --git a/GeoClient/GeoClient/Models/Units.cs b/GeoClient/GeoClient/Models/Units.cs deleted file mode 100644 index e015d5d..0000000 --- a/GeoClient/GeoClient/Models/Units.cs +++ /dev/null @@ -1,34 +0,0 @@ -using System; -using GeoClient.Services.Utils; - -namespace GeoClient.Models -{ - public class Unit : IComparable - { - public string Id { get; } - public string Name { get; set; } - - // TODO: This is actually a position, not only a point. There is more detailed information available. - public GeoPoint LastPoint { get; set; } - public IncidentTaskState State { get; set; } - - public string TaskStateIcon => GetTaskStateIcon(); - - public Unit(string id) - { - Id = id; - } - - public int CompareTo(Unit other) - { - if (ReferenceEquals(this, other)) return 0; - if (ReferenceEquals(null, other)) return 1; - return string.Compare(Name, other.Name, StringComparison.OrdinalIgnoreCase); - } - - private string GetTaskStateIcon() - { - return StatusIconResolver.GetIconForTaskState(State); - } - } -} \ No newline at end of file diff --git a/GeoClient/GeoClient/Services/IncidentItemFactory.cs b/GeoClient/GeoClient/Services/IncidentItemFactory.cs index e7525da..3940c57 100644 --- a/GeoClient/GeoClient/Services/IncidentItemFactory.cs +++ b/GeoClient/GeoClient/Services/IncidentItemFactory.cs @@ -1,12 +1,11 @@ using GeoClient.Models; -using GeoClient.Services.Boundary; using GeoClient.Services.Utils; +using GeoClient.Views.Utils; using Newtonsoft.Json.Linq; using System; -using System.Collections.Concurrent; using System.Collections.Generic; -using System.Threading.Tasks; -using GeoClient.Views.Utils; +using System.Globalization; +using static System.Double; namespace GeoClient.Services { @@ -25,61 +24,109 @@ public static List CreateIncidentItemList(List incidents, incidentList.Add(incidentItem); } } + else + { + Console.WriteLine("Provided incidents are null. Cannot parse incident items."); + } return incidentList; } private static IncidentItem CreateIncidentItem(JObject incident, List unitJsonObjects) { - IncidentItem incidentItem = new IncidentItem((string) incident["id"]); - incidentItem.Info = (string) incident["info"]; - incidentItem.Type = GeoIncidentTypeFactory.GetTypeFromString((string) incident["type"]); - incidentItem.Priority = bool.Parse((string) incident["priority"]); - incidentItem.Blue = bool.Parse((string) incident["blue"]); - incidentItem.Location = CreateGeoPoint(incident["location"]); Dictionary rawAssignedUnits = incident["assignedUnits"].ToObject>(); - - incidentItem.Units = CreateUnitList(rawAssignedUnits, unitJsonObjects); - - return incidentItem; + var unitList = CreateUnitList(rawAssignedUnits, unitJsonObjects); + + return new IncidentItem( + incident.Value("id"), + GeoIncidentTypeFactory.GetTypeFromString((string)incident["type"]), + incident.Value("info"), + incident.Value("priority"), + incident.Value("blue"), + CreateGeoPoint(incident["location"]), + unitList); } - private static GeoPoint CreateGeoPoint(JToken incidentPoint) + private static GeoPoint CreateGeoPoint(JToken pointJToken) { GeoPoint geoPoint = null; - string latitude = (string)incidentPoint?["latitude"]; - string longitude = (string)incidentPoint?["longitude"]; + string latitudeString = (string) pointJToken?["latitude"]; + string longitudeString = (string) pointJToken?["longitude"]; + + if (GeoPointUtil.NotBlank(latitudeString) && GeoPointUtil.NotBlank(longitudeString)) + { + geoPoint = CreateGeoPoint(latitudeString, longitudeString); + } + + return geoPoint; + } - if (GeoPointUtil.NotBlank(latitude) && GeoPointUtil.NotBlank(longitude)) + private static GeoPoint CreateGeoPoint(string latitudeString, string longitudeString) + { + GeoPoint geoPoint = null; + try { + double latitude = Parse(latitudeString, CultureInfo.InvariantCulture); + double longitude = Parse(longitudeString, CultureInfo.InvariantCulture); geoPoint = new GeoPoint(latitude, longitude); } + catch (ArgumentNullException) + { + Console.WriteLine("Cannot parse double of coordinate value 'null'."); + } + catch (FormatException) + { + Console.WriteLine( + "Provided coordinates does not contain valid numbers. lat=" + latitudeString + + ", lon=" + longitudeString); + } + catch (OverflowException) + { + Console.WriteLine("Coordinate values are out of range."); + } return geoPoint; } - private static SortedSet CreateUnitList(IReadOnlyDictionary rawAssignedUnits, List unitJsonObjects) + private static List CreateUnitList( + IReadOnlyDictionary rawAssignedUnits, + List unitJsonObjects) { - var units = new SortedSet(); + var units = new List(); if (unitJsonObjects != null) { - foreach (var unitJsonObject in unitJsonObjects) + foreach (var rawAssignedUnit in rawAssignedUnits) { - Unit unit = new Unit((string) unitJsonObject["id"]); - unit.Name = (string) unitJsonObject["name"]; - unit.LastPoint = CreateGeoPoint(unitJsonObject["lastPoint"]); - - rawAssignedUnits.TryGetValue(unit.Id, out var rawUnitState); - unit.State = IncidentTaskStateFactory.GetTaskStateFromString(rawUnitState); - + var taskState = IncidentTaskStateFactory.GetTaskStateFromString(rawAssignedUnit.Value); + var unit = GetUnitFromUnitList(rawAssignedUnit.Key, unitJsonObjects, taskState); units.Add(unit); } } return units; } + + private static Unit GetUnitFromUnitList(string unitId, List unitJsonObjects, IncidentTaskState taskStateOfUnit) + { + foreach (var unitJsonObject in unitJsonObjects) + { + if ((string) unitJsonObject["id"] == unitId) + { + Unit unit = new Unit(unitId, + unitJsonObject.Value("name"), + CreateGeoPoint(unitJsonObject["lastPoint"]), + taskStateOfUnit + ); + + return unit; + } + } + + Console.WriteLine($"Unit with ID {unitId} is not present in list of units!"); + return null; + } } } \ No newline at end of file diff --git a/GeoClient/GeoClient/ViewModels/BaseViewModel.cs b/GeoClient/GeoClient/ViewModels/BaseViewModel.cs index 356423e..bbd99e3 100644 --- a/GeoClient/GeoClient/ViewModels/BaseViewModel.cs +++ b/GeoClient/GeoClient/ViewModels/BaseViewModel.cs @@ -7,22 +7,18 @@ namespace GeoClient.ViewModels { public class BaseViewModel : INotifyPropertyChanged { - bool isBusy = false; - public bool IsBusy - { - get => isBusy; - set => SetProperty(ref isBusy, value); - } - string _title = string.Empty; + public string Title { get => _title; set => SetProperty(ref _title, value); } - protected bool SetProperty(ref T backingStore, T value, - [CallerMemberName]string propertyName = "", + protected bool SetProperty( + ref T backingStore, + T value, + [CallerMemberName] string propertyName = "", Action onChanged = null) { if (EqualityComparer.Default.Equals(backingStore, value)) @@ -35,13 +31,16 @@ protected bool SetProperty(ref T backingStore, T value, } #region INotifyPropertyChanged + public event PropertyChangedEventHandler PropertyChanged; + protected void OnPropertyChanged([CallerMemberName] string propertyName = "") { var changed = PropertyChanged; changed?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } + #endregion } -} +} \ No newline at end of file diff --git a/GeoClient/GeoClient/ViewModels/IncidentsViewModel.cs b/GeoClient/GeoClient/ViewModels/IncidentsViewModel.cs index c6bd2cf..96d059d 100644 --- a/GeoClient/GeoClient/ViewModels/IncidentsViewModel.cs +++ b/GeoClient/GeoClient/ViewModels/IncidentsViewModel.cs @@ -8,11 +8,18 @@ namespace GeoClient.ViewModels { public class IncidentsViewModel : BaseViewModel { - public ObservableCollection Incidents { get; set; } - public Command LoadItemsCommand { get; set; } + public ObservableCollection Incidents { get; } + public Command LoadItemsCommand { get; } + private bool _isBusy; private string _emptyListMessage; + public bool IsBusy + { + get => _isBusy; + set => SetProperty(ref _isBusy, value); + } + public string EmptyListMessage { get => _emptyListMessage; @@ -55,6 +62,8 @@ private void ExecuteLoadItemsCommand() return; } + IsBusy = true; + _restService.GetScope(); } } diff --git a/GeoClient/GeoClient/Views/AboutPage.xaml b/GeoClient/GeoClient/Views/AboutPage.xaml index 1a7dc57..c3380bb 100644 --- a/GeoClient/GeoClient/Views/AboutPage.xaml +++ b/GeoClient/GeoClient/Views/AboutPage.xaml @@ -26,7 +26,7 @@ - + @@ -44,13 +44,13 @@ - + -