|
|
@@ -0,0 +1,106 @@
|
|
|
+using System.ComponentModel;
|
|
|
+using System.Drawing;
|
|
|
+using System.Runtime.CompilerServices;
|
|
|
+using InABox.Core;
|
|
|
+
|
|
|
+namespace InABox.Avalonia.Platform;
|
|
|
+
|
|
|
+public class DefaultGeolocation : INotifyPropertyChanged, IGeolocation
|
|
|
+{
|
|
|
+
|
|
|
+ private DateTime _nextCheck = DateTime.MaxValue;
|
|
|
+
|
|
|
+ public bool Scanning
|
|
|
+ {
|
|
|
+ get => _nextCheck == DateTime.MaxValue;
|
|
|
+ set => SetField(ref _nextCheck, value ? DateTime.MinValue : DateTime.MaxValue);
|
|
|
+ }
|
|
|
+
|
|
|
+ private GeoPoint? _currentLocation;
|
|
|
+ public GeoPoint? CurrentLocation
|
|
|
+ {
|
|
|
+ get => _currentLocation;
|
|
|
+ set
|
|
|
+ {
|
|
|
+ SetField(ref _currentLocation, value);
|
|
|
+ LocationChanged?.Invoke(this, EventArgs.Empty);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public event EventHandler? LocationChanged;
|
|
|
+
|
|
|
+ public Logger? Logger { get; set; }
|
|
|
+
|
|
|
+ public virtual Task<GeoPoint?> GetLocationAsync(CancellationTokenSource cancel)
|
|
|
+ {
|
|
|
+ return Task.FromResult<GeoPoint?>(new GeoPoint());
|
|
|
+ }
|
|
|
+
|
|
|
+ private readonly CancellationTokenSource _cancelTokenSource;
|
|
|
+ private bool _isCheckingLocation;
|
|
|
+
|
|
|
+ public DefaultGeolocation()
|
|
|
+ {
|
|
|
+ _cancelTokenSource = new CancellationTokenSource();
|
|
|
+ try
|
|
|
+ {
|
|
|
+ _ = Task.Run(async () =>
|
|
|
+ {
|
|
|
+ while (!_cancelTokenSource.Token.IsCancellationRequested)
|
|
|
+ {
|
|
|
+ if (_nextCheck < DateTime.Now && !_isCheckingLocation)
|
|
|
+ {
|
|
|
+ try
|
|
|
+ {
|
|
|
+ _isCheckingLocation = true;
|
|
|
+ CurrentLocation = await PlatformTools.Geolocation.GetLocationAsync(_cancelTokenSource);
|
|
|
+ }
|
|
|
+ catch (Exception ex)
|
|
|
+ {
|
|
|
+ Logger?.Send(LogType.Error, "", $"GPS Location Error: {ex.Message}");
|
|
|
+ CurrentLocation = null;
|
|
|
+ }
|
|
|
+ _isCheckingLocation = false;
|
|
|
+ _nextCheck = DateTime.Now.AddSeconds(30);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ );
|
|
|
+ }
|
|
|
+ catch (OperationCanceledException e)
|
|
|
+ {
|
|
|
+ Logger?.Send(LogType.Error, "", $"GPS Scanning Cancelled: {e.Message}");
|
|
|
+ }
|
|
|
+ catch (Exception e)
|
|
|
+ {
|
|
|
+ Logger?.Send(LogType.Error, "", $"GPS Error: {e.Message}");
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ public void Cancel()
|
|
|
+ {
|
|
|
+ if (_isCheckingLocation && _cancelTokenSource.IsCancellationRequested == false)
|
|
|
+ _cancelTokenSource.Cancel();
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ #region INotifyPropertyChanged
|
|
|
+
|
|
|
+ public event PropertyChangedEventHandler? PropertyChanged;
|
|
|
+
|
|
|
+ protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null)
|
|
|
+ {
|
|
|
+ PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
|
|
+ }
|
|
|
+
|
|
|
+ protected bool SetField<T>(ref T field, T value, [CallerMemberName] string? propertyName = null)
|
|
|
+ {
|
|
|
+ if (EqualityComparer<T>.Default.Equals(field, value)) return false;
|
|
|
+ field = value;
|
|
|
+ OnPropertyChanged(propertyName);
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ #endregion
|
|
|
+}
|