share db
This commit is contained in:
@ -1,9 +1,12 @@
|
|||||||
using System.Collections.Generic;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Billing.Languages;
|
using Billing.Languages;
|
||||||
using Billing.Models;
|
using Billing.Models;
|
||||||
using Billing.Store;
|
using Billing.Store;
|
||||||
using Billing.Themes;
|
using Billing.Themes;
|
||||||
|
using Billing.UI;
|
||||||
using Xamarin.Essentials;
|
using Xamarin.Essentials;
|
||||||
using Xamarin.Forms;
|
using Xamarin.Forms;
|
||||||
|
|
||||||
@ -27,7 +30,7 @@ namespace Billing
|
|||||||
InitResources();
|
InitResources();
|
||||||
|
|
||||||
MainPage = new MainShell();
|
MainPage = new MainShell();
|
||||||
Shell.Current.GoToAsync("//Splash");
|
//Shell.Current.GoToAsync("//Splash");
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnStart()
|
protected override void OnStart()
|
||||||
@ -36,7 +39,7 @@ namespace Billing
|
|||||||
Helper.Debug($"cache folder: {StoreHelper.CacheFolder}");
|
Helper.Debug($"cache folder: {StoreHelper.CacheFolder}");
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static async Task InitilalizeData()
|
internal static async Task InitializeData()
|
||||||
{
|
{
|
||||||
await Task.WhenAll(
|
await Task.WhenAll(
|
||||||
Task.Run(async () => accounts = await StoreHelper.GetAccountsAsync()),
|
Task.Run(async () => accounts = await StoreHelper.GetAccountsAsync()),
|
||||||
@ -79,5 +82,33 @@ namespace Billing
|
|||||||
// TODO: status bar
|
// TODO: status bar
|
||||||
Resources = instance;
|
Resources = instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static bool OpenUrl(Uri uri)
|
||||||
|
{
|
||||||
|
if (uri == null)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
var absolute = uri.AbsolutePath;
|
||||||
|
var url = System.Net.WebUtility.UrlDecode(absolute);
|
||||||
|
if (File.Exists(url))
|
||||||
|
{
|
||||||
|
Task.Run(async () =>
|
||||||
|
{
|
||||||
|
var result = await StoreHelper.ReloadDatabase(url);
|
||||||
|
//if (result)
|
||||||
|
{
|
||||||
|
await InitializeData();
|
||||||
|
|
||||||
|
var current = Shell.Current.CurrentPage;
|
||||||
|
if (current is BillingPage page)
|
||||||
|
{
|
||||||
|
MainThread.BeginInvokeOnMainThread(() => page.TriggerRefresh());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -10,15 +10,14 @@
|
|||||||
TitleColor="{DynamicResource PrimaryColor}"
|
TitleColor="{DynamicResource PrimaryColor}"
|
||||||
Shell.NavBarHasShadow="True">
|
Shell.NavBarHasShadow="True">
|
||||||
|
|
||||||
|
<FlyoutItem>
|
||||||
|
<ShellContent ContentTemplate="{DataTemplate local:SplashPage}" Route="Splash"/>
|
||||||
|
</FlyoutItem>
|
||||||
|
|
||||||
<TabBar>
|
<TabBar>
|
||||||
<ShellContent ContentTemplate="{DataTemplate v:AccountPage}" Route="Accounts" Title="{r:Text Accounts}" Icon="wallet.png"/>
|
<ShellContent ContentTemplate="{DataTemplate v:AccountPage}" Route="Accounts" Title="{r:Text Accounts}" Icon="wallet.png"/>
|
||||||
<ShellContent ContentTemplate="{DataTemplate v:BillPage}" Route="Bills" Title="{r:Text Bills}" Icon="bill.png"/>
|
<ShellContent ContentTemplate="{DataTemplate v:BillPage}" Route="Bills" Title="{r:Text Bills}" Icon="bill.png"/>
|
||||||
<ShellContent ContentTemplate="{DataTemplate v:RankPage}" Route="Ranks" Title="{r:Text Report}" Icon="rank.png"/>
|
<ShellContent ContentTemplate="{DataTemplate v:RankPage}" Route="Ranks" Title="{r:Text Report}" Icon="rank.png"/>
|
||||||
<ShellContent ContentTemplate="{DataTemplate v:SettingPage}" Route="Settings" Title="{r:Text Settings}" Icon="settings.png"/>
|
<ShellContent ContentTemplate="{DataTemplate v:SettingPage}" Route="Settings" Title="{r:Text Settings}" Icon="settings.png"/>
|
||||||
</TabBar>
|
</TabBar>
|
||||||
|
|
||||||
<Tab>
|
|
||||||
<ShellContent ContentTemplate="{DataTemplate local:SplashPage}" Route="Splash"/>
|
|
||||||
</Tab>
|
|
||||||
|
|
||||||
</Shell>
|
</Shell>
|
@ -10,9 +10,9 @@ namespace Billing
|
|||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async void OnLoaded()
|
protected override async void OnLoaded()
|
||||||
{
|
{
|
||||||
await App.InitilalizeData();
|
await App.InitializeData();
|
||||||
|
|
||||||
await Shell.Current.GoToAsync("//Bills");
|
await Shell.Current.GoToAsync("//Bills");
|
||||||
}
|
}
|
||||||
|
@ -14,11 +14,32 @@ namespace Billing.Store
|
|||||||
public static readonly string PersonalFolder = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
|
public static readonly string PersonalFolder = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
|
||||||
public static readonly string CacheFolder = FileSystem.CacheDirectory;
|
public static readonly string CacheFolder = FileSystem.CacheDirectory;
|
||||||
|
|
||||||
|
public static string DatabasePath => Path.Combine(PersonalFolder, dbfile);
|
||||||
|
|
||||||
#region Sqlite3
|
#region Sqlite3
|
||||||
private const string dbfile = "data.db3";
|
private const string dbfile = "data.db3";
|
||||||
private static SQLiteAsyncConnection database;
|
private static SQLiteAsyncConnection database;
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
public static async Task<bool> ReloadDatabase(string file)
|
||||||
|
{
|
||||||
|
var path = DatabasePath;
|
||||||
|
if (string.Equals(file, path, StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (database != null)
|
||||||
|
{
|
||||||
|
await database.CloseAsync();
|
||||||
|
}
|
||||||
|
File.Copy(file, path, true);
|
||||||
|
database = new SQLiteAsyncConnection(path,
|
||||||
|
SQLiteOpenFlags.ReadWrite |
|
||||||
|
SQLiteOpenFlags.Create |
|
||||||
|
SQLiteOpenFlags.SharedCache);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
private static readonly AsyncLazy<StoreHelper> Instance = new(async () =>
|
private static readonly AsyncLazy<StoreHelper> Instance = new(async () =>
|
||||||
{
|
{
|
||||||
var instance = new StoreHelper();
|
var instance = new StoreHelper();
|
||||||
@ -114,10 +135,13 @@ namespace Billing.Store
|
|||||||
|
|
||||||
private StoreHelper()
|
private StoreHelper()
|
||||||
{
|
{
|
||||||
database = new SQLiteAsyncConnection(Path.Combine(PersonalFolder, dbfile),
|
if (database == null)
|
||||||
SQLiteOpenFlags.ReadWrite |
|
{
|
||||||
SQLiteOpenFlags.Create |
|
database = new SQLiteAsyncConnection(DatabasePath,
|
||||||
SQLiteOpenFlags.SharedCache);
|
SQLiteOpenFlags.ReadWrite |
|
||||||
|
SQLiteOpenFlags.Create |
|
||||||
|
SQLiteOpenFlags.SharedCache);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task<List<T>> GetListAsync<T>(string query, params object[] args) where T : new()
|
public Task<List<T>> GetListAsync<T>(string query, params object[] args) where T : new()
|
||||||
|
@ -7,6 +7,7 @@ namespace Billing.UI
|
|||||||
public abstract class BillingPage : ContentPage
|
public abstract class BillingPage : ContentPage
|
||||||
{
|
{
|
||||||
public event EventHandler Loaded;
|
public event EventHandler Loaded;
|
||||||
|
public event EventHandler Refreshed;
|
||||||
|
|
||||||
private bool loaded;
|
private bool loaded;
|
||||||
|
|
||||||
@ -16,11 +17,16 @@ namespace Billing.UI
|
|||||||
Shell.SetTabBarIsVisible(this, false);
|
Shell.SetTabBarIsVisible(this, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void OnLoaded()
|
protected virtual void OnLoaded()
|
||||||
{
|
{
|
||||||
Loaded?.Invoke(this, EventArgs.Empty);
|
Loaded?.Invoke(this, EventArgs.Empty);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected virtual void OnRefresh()
|
||||||
|
{
|
||||||
|
Refreshed?.Invoke(this, EventArgs.Empty);
|
||||||
|
}
|
||||||
|
|
||||||
public void TriggerLoad()
|
public void TriggerLoad()
|
||||||
{
|
{
|
||||||
if (!loaded)
|
if (!loaded)
|
||||||
@ -29,5 +35,10 @@ namespace Billing.UI
|
|||||||
OnLoaded();
|
OnLoaded();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void TriggerRefresh()
|
||||||
|
{
|
||||||
|
OnRefresh();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -73,7 +73,7 @@ namespace Billing.Views
|
|||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void OnLoaded()
|
protected override void OnLoaded()
|
||||||
{
|
{
|
||||||
editorName.SetFocus();
|
editorName.SetFocus();
|
||||||
}
|
}
|
||||||
|
@ -116,7 +116,7 @@ namespace Billing.Views
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void OnLoaded()
|
protected override void OnLoaded()
|
||||||
{
|
{
|
||||||
editorAmount.SetFocus();
|
editorAmount.SetFocus();
|
||||||
}
|
}
|
||||||
|
@ -78,7 +78,7 @@ namespace Billing.Views
|
|||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void OnLoaded()
|
protected override void OnLoaded()
|
||||||
{
|
{
|
||||||
editorName.SetFocus();
|
editorName.SetFocus();
|
||||||
}
|
}
|
||||||
|
@ -55,7 +55,7 @@ namespace Billing.Views
|
|||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void OnLoaded()
|
protected override void OnLoaded()
|
||||||
{
|
{
|
||||||
billingDate.SetDateTime(DateTime.Today);
|
billingDate.SetDateTime(DateTime.Today);
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,10 @@
|
|||||||
BindingContext="{x:Reference settingPage}"
|
BindingContext="{x:Reference settingPage}"
|
||||||
Shell.TabBarIsVisible="True">
|
Shell.TabBarIsVisible="True">
|
||||||
|
|
||||||
|
<ContentPage.ToolbarItems>
|
||||||
|
<ToolbarItem Order="Primary" IconImageSource="project.png" Command="{Binding ShareCommand}"/>
|
||||||
|
</ContentPage.ToolbarItems>
|
||||||
|
|
||||||
<TableView Intent="Settings" HasUnevenRows="True">
|
<TableView Intent="Settings" HasUnevenRows="True">
|
||||||
<TableSection Title="{r:Text About}">
|
<TableSection Title="{r:Text About}">
|
||||||
<ui:OptionTextCell Height="36" Title="{r:Text Version}"
|
<ui:OptionTextCell Height="36" Title="{r:Text Version}"
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
using Billing.Store;
|
||||||
using Billing.Themes;
|
using Billing.Themes;
|
||||||
using Billing.UI;
|
using Billing.UI;
|
||||||
using Xamarin.Essentials;
|
using Xamarin.Essentials;
|
||||||
@ -17,11 +18,13 @@ namespace Billing.Views
|
|||||||
set => SetValue(PrimaryColorProperty, value);
|
set => SetValue(PrimaryColorProperty, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Command ShareCommand { get; }
|
||||||
public Command CategoryCommand { get; }
|
public Command CategoryCommand { get; }
|
||||||
public Command ColorPickerCommand { get; }
|
public Command ColorPickerCommand { get; }
|
||||||
|
|
||||||
public SettingPage()
|
public SettingPage()
|
||||||
{
|
{
|
||||||
|
ShareCommand = new Command(OnShareCommand);
|
||||||
CategoryCommand = new Command(OnCategoryCommand);
|
CategoryCommand = new Command(OnCategoryCommand);
|
||||||
ColorPickerCommand = new Command(OnColorPickerCommand);
|
ColorPickerCommand = new Command(OnColorPickerCommand);
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
@ -48,6 +51,21 @@ namespace Billing.Views
|
|||||||
Light.Instance.RefreshColor(Color.FromHex(color));
|
Light.Instance.RefreshColor(Color.FromHex(color));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async void OnShareCommand()
|
||||||
|
{
|
||||||
|
if (Tap.IsBusy)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
using (Tap.Start())
|
||||||
|
{
|
||||||
|
await Share.RequestAsync(new ShareFileRequest
|
||||||
|
{
|
||||||
|
File = new ShareFile(StoreHelper.DatabasePath)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private async void OnCategoryCommand()
|
private async void OnCategoryCommand()
|
||||||
{
|
{
|
||||||
if (Tap.IsBusy)
|
if (Tap.IsBusy)
|
||||||
|
@ -23,5 +23,10 @@ namespace Billing.iOS
|
|||||||
|
|
||||||
return base.FinishedLaunching(app, options);
|
return base.FinishedLaunching(app, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override bool OpenUrl(UIApplication app, NSUrl url, NSDictionary options)
|
||||||
|
{
|
||||||
|
return App.OpenUrl(url);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -477,6 +477,14 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<BundleResource Include="Resources\left%403x.png" />
|
<BundleResource Include="Resources\left%403x.png" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\Billing.ShareExtension\Billing.ShareExtension.csproj">
|
||||||
|
<IsAppExtension>true</IsAppExtension>
|
||||||
|
<Project>{D4EA6D3A-17E6-4300-80A7-2ED19B738C6B}</Project>
|
||||||
|
<Name>Billing.ShareExtension</Name>
|
||||||
|
<ReferenceSourceTarget></ReferenceSourceTarget>
|
||||||
|
</ProjectReference>
|
||||||
|
</ItemGroup>
|
||||||
<Import Project="..\..\Billing.Shared\Billing.Shared.projitems" Label="Shared" />
|
<Import Project="..\..\Billing.Shared\Billing.Shared.projitems" Label="Shared" />
|
||||||
<Import Project="$(MSBuildExtensionsPath)\Xamarin\iOS\Xamarin.iOS.CSharp.targets" />
|
<Import Project="$(MSBuildExtensionsPath)\Xamarin\iOS\Xamarin.iOS.CSharp.targets" />
|
||||||
</Project>
|
</Project>
|
@ -41,6 +41,21 @@
|
|||||||
<string>OpenSans-Regular.ttf</string>
|
<string>OpenSans-Regular.ttf</string>
|
||||||
<string>OpenSans-SemiBold.ttf</string>
|
<string>OpenSans-SemiBold.ttf</string>
|
||||||
</array>
|
</array>
|
||||||
|
<key>CFBundleDocumentTypes</key>
|
||||||
|
<array>
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleTypeName</key>
|
||||||
|
<string>Master SQLite file</string>
|
||||||
|
<key>LSItemContentTypes</key>
|
||||||
|
<array>
|
||||||
|
<string>public.data</string>
|
||||||
|
</array>
|
||||||
|
<key>CFBundleTypeIconFiles</key>
|
||||||
|
<array>
|
||||||
|
<string>Assets.xcassets/AppIcon.appiconset/Icon180</string>
|
||||||
|
</array>
|
||||||
|
</dict>
|
||||||
|
</array>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>10</string>
|
<string>10</string>
|
||||||
<key>CFBundleShortVersionString</key>
|
<key>CFBundleShortVersionString</key>
|
||||||
|
Reference in New Issue
Block a user