feature: save location
This commit is contained in:
@@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using Billing.Languages;
|
||||
@@ -14,15 +13,19 @@ namespace Billing
|
||||
{
|
||||
public class App : Application
|
||||
{
|
||||
private const string SaveLocationKey = nameof(SaveLocationKey);
|
||||
|
||||
public static AppTheme CurrentTheme { get; private set; }
|
||||
public static PlatformCulture CurrentCulture { get; private set; }
|
||||
public static List<Bill> Bills => bills ??= new List<Bill>();
|
||||
public static List<Account> Accounts => accounts ??= new List<Account>();
|
||||
public static List<Category> Categories => categories ??= new List<Category>();
|
||||
public static bool SaveLocation => saveLocation;
|
||||
|
||||
private static List<Bill> bills;
|
||||
private static List<Account> accounts;
|
||||
private static List<Category> categories;
|
||||
private static bool saveLocation;
|
||||
|
||||
private string initialUrl;
|
||||
|
||||
@@ -48,15 +51,6 @@ namespace Billing
|
||||
}
|
||||
}
|
||||
|
||||
public static async Task InitializeData()
|
||||
{
|
||||
var instance = await StoreHelper.Instance;
|
||||
await Task.WhenAll(
|
||||
Task.Run(async () => accounts = await instance.GetListAsync<Account>()),
|
||||
Task.Run(async () => categories = await instance.GetListAsync<Category>()),
|
||||
Task.Run(async () => bills = await instance.GetListAsync<Bill>()));
|
||||
}
|
||||
|
||||
protected override void OnResume()
|
||||
{
|
||||
SetTheme(AppInfo.RequestedTheme);
|
||||
@@ -93,6 +87,21 @@ namespace Billing
|
||||
Resources = instance;
|
||||
}
|
||||
|
||||
public static void SetSaveLocation(bool flag)
|
||||
{
|
||||
saveLocation = flag;
|
||||
Preferences.Set(SaveLocationKey, flag);
|
||||
}
|
||||
|
||||
public static async Task InitializeData()
|
||||
{
|
||||
var instance = await StoreHelper.Instance;
|
||||
await Task.WhenAll(
|
||||
Task.Run(async () => accounts = await instance.GetListAsync<Account>()),
|
||||
Task.Run(async () => categories = await instance.GetListAsync<Category>()),
|
||||
Task.Run(async () => bills = await instance.GetListAsync<Bill>()));
|
||||
}
|
||||
|
||||
public static async Task<bool> OpenUrl(string url)
|
||||
{
|
||||
if (string.IsNullOrEmpty(url))
|
||||
@@ -101,12 +110,7 @@ namespace Billing
|
||||
}
|
||||
if (File.Exists(url))
|
||||
{
|
||||
var status = await Permissions.CheckStatusAsync<Permissions.StorageRead>();
|
||||
if (status != PermissionStatus.Disabled &&
|
||||
status != PermissionStatus.Granted)
|
||||
{
|
||||
status = await Permissions.RequestAsync<Permissions.StorageRead>();
|
||||
}
|
||||
var status = await Helper.CheckAndRequestPermissionAsync<Permissions.StorageRead>();
|
||||
if (status != PermissionStatus.Granted)
|
||||
{
|
||||
return false;
|
||||
|
@@ -136,6 +136,17 @@ namespace Billing
|
||||
}
|
||||
|
||||
public delegate void PropertyValueChanged<TResult, TOwner>(TOwner obj, TResult old, TResult @new);
|
||||
|
||||
public static async Task<PermissionStatus> CheckAndRequestPermissionAsync<T>() where T : Permissions.BasePermission, new()
|
||||
{
|
||||
var status = await Permissions.CheckStatusAsync<T>();
|
||||
if (status != PermissionStatus.Disabled &&
|
||||
status != PermissionStatus.Granted)
|
||||
{
|
||||
status = await Permissions.RequestAsync<T>();
|
||||
}
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
public class AsyncLazy<T>
|
||||
|
@@ -101,6 +101,7 @@
|
||||
<Feature>Feature</Feature>
|
||||
<CategoryManage>Category Management</CategoryManage>
|
||||
<Detail>Detail</Detail>
|
||||
<SaveLocation>Save Location</SaveLocation>
|
||||
<AddCategory>Add Category</AddCategory>
|
||||
<ConfirmDeleteCategory>Are you sure you want to delete the category: {0}?</ConfirmDeleteCategory>
|
||||
<SelectCategory>Select Category</SelectCategory>
|
||||
|
@@ -101,6 +101,7 @@
|
||||
<Feature>功能</Feature>
|
||||
<CategoryManage>分类管理</CategoryManage>
|
||||
<Detail>详细</Detail>
|
||||
<SaveLocation>保存位置</SaveLocation>
|
||||
<AddCategory>新建分类</AddCategory>
|
||||
<ConfirmDeleteCategory>是否确认删除该分类:{0}?</ConfirmDeleteCategory>
|
||||
<SelectCategory>选择类别</SelectCategory>
|
||||
|
@@ -14,5 +14,10 @@ namespace Billing.Models
|
||||
public string Store { get; set; }
|
||||
public DateTime CreateTime { get; set; }
|
||||
public string Note { get; set; }
|
||||
public double? Latitude { get; set; }
|
||||
public double? Longitude { get; set; }
|
||||
public double? Altitude { get; set; }
|
||||
public double? Accuracy { get; set; }
|
||||
public bool? IsGps { get; set; }
|
||||
}
|
||||
}
|
@@ -1,7 +1,8 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using Billing.Languages;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Billing.Models;
|
||||
using Billing.Store;
|
||||
using Billing.UI;
|
||||
@@ -13,6 +14,7 @@ namespace Billing.Views
|
||||
{
|
||||
public partial class AddBillPage : BillingPage
|
||||
{
|
||||
private static readonly BindableProperty CheckBillProperty = Helper.Create<Command, AddBillPage>(nameof(CheckBill), defaultValue: new Command(() => { }, () => false));
|
||||
private static readonly BindableProperty AmountProperty = Helper.Create<string, AddBillPage>(nameof(Amount));
|
||||
private static readonly BindableProperty NameProperty = Helper.Create<string, AddBillPage>(nameof(Name));
|
||||
private static readonly BindableProperty CategoryProperty = Helper.Create<Category, AddBillPage>(nameof(Category));
|
||||
@@ -22,6 +24,7 @@ namespace Billing.Views
|
||||
private static readonly BindableProperty CreatedTimeProperty = Helper.Create<TimeSpan, AddBillPage>(nameof(CreatedTime));
|
||||
private static readonly BindableProperty NoteProperty = Helper.Create<string, AddBillPage>(nameof(Note));
|
||||
|
||||
public Command CheckBill => (Command)GetValue(CheckBillProperty);
|
||||
public string Amount
|
||||
{
|
||||
get => (string)GetValue(AmountProperty);
|
||||
@@ -55,7 +58,6 @@ namespace Billing.Views
|
||||
set => SetValue(NoteProperty, value);
|
||||
}
|
||||
|
||||
public Command CheckBill { get; }
|
||||
public Command SelectCategory { get; }
|
||||
public Command SelectWallet { get; }
|
||||
|
||||
@@ -65,11 +67,12 @@ namespace Billing.Views
|
||||
private readonly DateTime createDate;
|
||||
|
||||
private bool categoryChanged;
|
||||
private CancellationTokenSource tokenSource;
|
||||
private Location location;
|
||||
|
||||
public AddBillPage(DateTime date)
|
||||
{
|
||||
createDate = date;
|
||||
CheckBill = new Command(OnCheckBill);
|
||||
SelectCategory = new Command(OnSelectCategory);
|
||||
SelectWallet = new Command(OnSelectWallet);
|
||||
InitializeComponent();
|
||||
@@ -81,7 +84,6 @@ namespace Billing.Views
|
||||
public AddBillPage(Bill bill)
|
||||
{
|
||||
this.bill = bill;
|
||||
CheckBill = new Command(OnCheckBill);
|
||||
SelectCategory = new Command(OnSelectCategory);
|
||||
SelectWallet = new Command(OnSelectWallet);
|
||||
InitializeComponent();
|
||||
@@ -90,6 +92,15 @@ namespace Billing.Views
|
||||
Initial();
|
||||
}
|
||||
|
||||
protected override void OnDisappearing()
|
||||
{
|
||||
if (tokenSource != null && !tokenSource.IsCancellationRequested)
|
||||
{
|
||||
tokenSource.Cancel();
|
||||
}
|
||||
base.OnDisappearing();
|
||||
}
|
||||
|
||||
private void Initial()
|
||||
{
|
||||
if (bill != null)
|
||||
@@ -116,6 +127,41 @@ namespace Billing.Views
|
||||
protected override void OnLoaded()
|
||||
{
|
||||
editorAmount.SetFocus();
|
||||
|
||||
if (App.SaveLocation)
|
||||
{
|
||||
_ = GetCurrentLocation();
|
||||
}
|
||||
else
|
||||
{
|
||||
SetValue(CheckBillProperty, new Command(OnCheckBill));
|
||||
}
|
||||
}
|
||||
|
||||
private async Task GetCurrentLocation()
|
||||
{
|
||||
try
|
||||
{
|
||||
var request = new GeolocationRequest(GeolocationAccuracy.Best, TimeSpan.FromSeconds(10));
|
||||
tokenSource = new CancellationTokenSource();
|
||||
var status = await Helper.CheckAndRequestPermissionAsync<Permissions.LocationWhenInUse>();
|
||||
if (status != PermissionStatus.Granted)
|
||||
{
|
||||
return;
|
||||
}
|
||||
location = await Geolocation.GetLocationAsync(request, tokenSource.Token);
|
||||
}
|
||||
catch (FeatureNotSupportedException) { }
|
||||
catch (FeatureNotEnabledException) { }
|
||||
catch (PermissionException) { }
|
||||
catch (Exception ex)
|
||||
{
|
||||
Helper.Error("location.get", ex);
|
||||
}
|
||||
finally
|
||||
{
|
||||
SetValue(CheckBillProperty, new Command(OnCheckBill));
|
||||
}
|
||||
}
|
||||
|
||||
private async void OnCheckBill()
|
||||
@@ -148,26 +194,27 @@ namespace Billing.Views
|
||||
{
|
||||
name = category.Name;
|
||||
}
|
||||
if (bill != null)
|
||||
{
|
||||
bill.Amount = amount;
|
||||
bill.Name = name;
|
||||
bill.CategoryId = category.Id;
|
||||
bill.WalletId = wallet.Id;
|
||||
bill.CreateTime = CreatedDate.Date.Add(CreatedTime);
|
||||
bill.Store = Store;
|
||||
bill.Note = Note;
|
||||
Bill b = bill;
|
||||
if (b == null)
|
||||
{
|
||||
b = new Bill();
|
||||
}
|
||||
b.Amount = amount;
|
||||
b.Name = name;
|
||||
b.CategoryId = category.Id;
|
||||
b.WalletId = wallet.Id;
|
||||
b.CreateTime = CreatedDate.Date.Add(CreatedTime);
|
||||
b.Store = Store;
|
||||
b.Note = Note;
|
||||
if (location != null)
|
||||
{
|
||||
b.Latitude = location.Latitude;
|
||||
b.Longitude = location.Longitude;
|
||||
b.Altitude = location.Altitude;
|
||||
b.Accuracy = location.Accuracy;
|
||||
b.IsGps = location.IsFromMockProvider;
|
||||
}
|
||||
BillChecked?.Invoke(this, bill ?? new Bill
|
||||
{
|
||||
Amount = amount,
|
||||
Name = name,
|
||||
CategoryId = category.Id,
|
||||
WalletId = wallet.Id,
|
||||
CreateTime = CreatedDate.Date.Add(CreatedTime),
|
||||
Store = Store,
|
||||
Note = Note
|
||||
});
|
||||
BillChecked?.Invoke(this, b);
|
||||
|
||||
category.LastAccountId = wallet.Id;
|
||||
category.LastUsed = DateTime.Now;
|
||||
|
@@ -189,13 +189,17 @@ namespace Billing.Views
|
||||
LeftCommand = new Command(OnLeftCommand);
|
||||
RightCommand = new Command(OnRightCommand);
|
||||
FilterCommand = new Command(OnFilterCommand);
|
||||
EditBilling = new Command(OnEditBilling);
|
||||
|
||||
var style = SKFontManager.Default.GetFontStyles("PingFang SC");
|
||||
EditBilling = new Command(OnEditBilling);
|
||||
|
||||
#if __IOS__
|
||||
var style = SKFontManager.Default.GetFontStyles("PingFang SC");
|
||||
if (style != null)
|
||||
{
|
||||
font = style.CreateTypeface(SKFontStyle.Normal);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
font = SKFontManager.Default.MatchCharacter(0x4e00);
|
||||
|
||||
DateTypes = new List<string>
|
||||
{
|
||||
|
@@ -24,6 +24,8 @@
|
||||
<ui:OptionSelectCell Height="36" Title="{r:Text CategoryManage}"
|
||||
Detail="{r:Text Detail}"
|
||||
Command="{Binding CategoryCommand}"/>
|
||||
<ui:OptionSwitchCell Height="36" Title="{r:Text SaveLocation}"
|
||||
IsToggled="{Binding SaveLocation, Mode=TwoWay}"/>
|
||||
</TableSection>
|
||||
<TableSection Title="{r:Text Preference}">
|
||||
<ui:OptionEntryCell Height="36" Title="{r:Text PrimaryColor}"
|
||||
|
@@ -11,10 +11,16 @@ namespace Billing.Views
|
||||
public partial class SettingPage : BillingPage
|
||||
{
|
||||
private static readonly BindableProperty VersionProperty = Helper.Create<string, SettingPage>(nameof(Version));
|
||||
private static readonly BindableProperty SaveLocationProperty = Helper.Create<bool, SettingPage>(nameof(SaveLocation));
|
||||
private static readonly BindableProperty PrimaryColorProperty = Helper.Create<string, SettingPage>(nameof(PrimaryColor));
|
||||
private static readonly BindableProperty ManyRecordsProperty = Helper.Create<string, SettingPage>(nameof(ManyRecords));
|
||||
|
||||
public string Version => (string)GetValue(VersionProperty);
|
||||
public bool SaveLocation
|
||||
{
|
||||
get => (bool)GetValue(SaveLocationProperty);
|
||||
set => SetValue(SaveLocationProperty, value);
|
||||
}
|
||||
public string PrimaryColor
|
||||
{
|
||||
get => (string)GetValue(PrimaryColorProperty);
|
||||
@@ -35,16 +41,14 @@ namespace Billing.Views
|
||||
ShareLogsCommand = new Command(OnShareLogsCommand);
|
||||
InitializeComponent();
|
||||
|
||||
var main = AppInfo.VersionString;
|
||||
var build = AppInfo.BuildString;
|
||||
SetValue(VersionProperty, $"{main} ({build})");
|
||||
SetValue(VersionProperty, $"{AppInfo.VersionString} ({AppInfo.BuildString})");
|
||||
}
|
||||
|
||||
protected override async void OnAppearing()
|
||||
{
|
||||
base.OnAppearing();
|
||||
|
||||
//SetValue(VersionProperty, $"{AppInfo.VersionString} ({AppInfo.BuildString})");
|
||||
SaveLocation = App.SaveLocation;
|
||||
var colorString = Preferences.Get(Definition.PrimaryColorKey, Helper.DEFAULT_COLOR);
|
||||
PrimaryColor = Helper.WrapColorString(colorString);
|
||||
|
||||
@@ -56,8 +60,8 @@ namespace Billing.Views
|
||||
{
|
||||
base.OnDisappearing();
|
||||
|
||||
App.SetSaveLocation(SaveLocation);
|
||||
Preferences.Set(Definition.PrimaryColorKey, PrimaryColor);
|
||||
//Light.Instance.RefreshColor(Color.FromHex(color));
|
||||
}
|
||||
|
||||
protected override async void OnRefresh()
|
||||
|
Reference in New Issue
Block a user