optimized and add diagnostic feature
@@ -85,6 +85,7 @@
 | 
			
		||||
    <Compile Include="$(MSBuildThisFileDirectory)SplashPage.xaml.cs">
 | 
			
		||||
      <DependentUpon>SplashPage.xaml</DependentUpon>
 | 
			
		||||
    </Compile>
 | 
			
		||||
    <Compile Include="$(MSBuildThisFileDirectory)Models\Logs.cs" />
 | 
			
		||||
  </ItemGroup>
 | 
			
		||||
  <ItemGroup>
 | 
			
		||||
    <EmbeddedResource Include="$(MSBuildThisFileDirectory)MainShell.xaml">
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,4 @@
 | 
			
		||||
using Billing.Models;
 | 
			
		||||
using Billing.Themes;
 | 
			
		||||
using Billing.UI;
 | 
			
		||||
using Billing.Views;
 | 
			
		||||
using System;
 | 
			
		||||
@@ -20,34 +19,35 @@ namespace Billing
 | 
			
		||||
            var time = DateTime.Now.ToString("HH:mm:ss.fff");
 | 
			
		||||
            System.Diagnostics.Debug.WriteLine($"[{time}] - {message}");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static void Error(string category, Exception ex)
 | 
			
		||||
        {
 | 
			
		||||
            Error(category, ex?.Message ?? "unknown error");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static void Error(string category, string message)
 | 
			
		||||
        {
 | 
			
		||||
            var time = DateTime.Now.ToString("HH:mm:ss.fff");
 | 
			
		||||
            System.Diagnostics.Debug.Fail($"[{time}] - {category}", message);
 | 
			
		||||
        }
 | 
			
		||||
#else
 | 
			
		||||
#pragma warning disable IDE0060 // Remove unused parameter
 | 
			
		||||
        public static void Debug(string message)
 | 
			
		||||
        {
 | 
			
		||||
        }
 | 
			
		||||
#pragma warning restore IDE0060 // Remove unused parameter
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
        public static void Error(string category, Exception ex)
 | 
			
		||||
        {
 | 
			
		||||
            MainThread.BeginInvokeOnMainThread(async () => await Shell.Current.DisplayAlert(category, ex.ToString(), "Ok"));
 | 
			
		||||
            Error(category, ex?.ToString() ?? "unknown error");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static void Error(string category, string message)
 | 
			
		||||
        {
 | 
			
		||||
        }
 | 
			
		||||
#pragma warning restore IDE0060 // Remove unused parameter
 | 
			
		||||
#if DEBUG
 | 
			
		||||
            var time = DateTime.Now.ToString("HH:mm:ss.fff");
 | 
			
		||||
            System.Diagnostics.Debug.WriteLine($"[{time}] - {category}", message);
 | 
			
		||||
            MainThread.BeginInvokeOnMainThread(async () => await Shell.Current.DisplayAlert(category, message, "Ok"));
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
            _ = Store.StoreHelper.SaveLogItemAsync(new Logs()
 | 
			
		||||
            {
 | 
			
		||||
                LogTime = DateTime.Now,
 | 
			
		||||
                Category = category,
 | 
			
		||||
                Detail = message
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static bool NetworkAvailable
 | 
			
		||||
        {
 | 
			
		||||
            get
 | 
			
		||||
@@ -89,9 +89,7 @@ namespace Billing
 | 
			
		||||
            return new UIBill(b)
 | 
			
		||||
            {
 | 
			
		||||
                Icon = category?.Icon ?? Definition.DefaultIcon,
 | 
			
		||||
                TintColor = category?.TintColor.IsTransparent() == false ?
 | 
			
		||||
                    category.TintColor.ToColor() :
 | 
			
		||||
                    BaseTheme.CurrentPrimaryColor,
 | 
			
		||||
                TintColor = category?.TintColor ?? Definition.TransparentColor,
 | 
			
		||||
                Name = b.Name,
 | 
			
		||||
                DateCreation = b.CreateTime,
 | 
			
		||||
                Amount = b.Amount,
 | 
			
		||||
 
 | 
			
		||||
@@ -10,6 +10,7 @@ namespace Billing.Languages
 | 
			
		||||
    internal class Resource
 | 
			
		||||
    {
 | 
			
		||||
        public static string Ok => Text(nameof(Ok));
 | 
			
		||||
        public static string Cancel => Text(nameof(Cancel));
 | 
			
		||||
        public static string Yes => Text(nameof(Yes));
 | 
			
		||||
        public static string No => Text(nameof(No));
 | 
			
		||||
        public static string ConfirmDeleteAccount => Text(nameof(ConfirmDeleteAccount));
 | 
			
		||||
@@ -37,9 +38,15 @@ namespace Billing.Languages
 | 
			
		||||
        public static string AmountRequired => Text(nameof(AmountRequired));
 | 
			
		||||
        public static string Income => Text(nameof(Income));
 | 
			
		||||
        public static string Spending => Text(nameof(Spending));
 | 
			
		||||
        public static string LastSelected => Text(nameof(LastSelected));
 | 
			
		||||
        public static string Recent => Text(nameof(Recent));
 | 
			
		||||
        public static string CategoryManage => Text(nameof(CategoryManage));
 | 
			
		||||
        public static string AddCategory => Text(nameof(AddCategory));
 | 
			
		||||
        public static string ConfirmDeleteCategory => Text(nameof(ConfirmDeleteCategory));
 | 
			
		||||
        public static string ShareLogs => Text(nameof(ShareLogs));
 | 
			
		||||
        public static string ManyRecords => Text(nameof(ManyRecords));
 | 
			
		||||
        public static string SendEmail => Text(nameof(SendEmail));
 | 
			
		||||
        public static string HowToShareDiagnostic => Text(nameof(HowToShareDiagnostic));
 | 
			
		||||
 | 
			
		||||
        #region Categories
 | 
			
		||||
        public static string Clothing => Text(nameof(Clothing));
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,7 @@
 | 
			
		||||
<?xml version="1.0" encoding="utf-8"?>
 | 
			
		||||
<root>
 | 
			
		||||
	<Ok>OK</Ok>
 | 
			
		||||
	<Cancel>Cancel</Cancel>
 | 
			
		||||
	<About>About</About>
 | 
			
		||||
	<Version>Version</Version>
 | 
			
		||||
	<Preference>Preference</Preference>
 | 
			
		||||
@@ -63,6 +64,8 @@
 | 
			
		||||
	<AmountRequired>Please enter the amount.</AmountRequired>
 | 
			
		||||
	<Income>Income</Income>
 | 
			
		||||
	<Spending>Spending</Spending>
 | 
			
		||||
	<LastSelected>Last Selected</LastSelected>
 | 
			
		||||
	<Recent>Recent</Recent>
 | 
			
		||||
	<Clothing>Clothing</Clothing>
 | 
			
		||||
	<Food>Food</Food>
 | 
			
		||||
	<Drinks>Drinks</Drinks>
 | 
			
		||||
@@ -104,4 +107,9 @@
 | 
			
		||||
	<NoResult>(no results)</NoResult>
 | 
			
		||||
	<Top10>Top 10</Top10>
 | 
			
		||||
	<CategoryRank>Category Ranking</CategoryRank>
 | 
			
		||||
	<Diagnostic>Diagnostic</Diagnostic>
 | 
			
		||||
	<ShareLogs>Share Logs</ShareLogs>
 | 
			
		||||
	<ManyRecords>{0} record(s)</ManyRecords>
 | 
			
		||||
	<SendEmail>Send Eamil</SendEmail>
 | 
			
		||||
	<HowToShareDiagnostic>How would you like to share diagnostic logs?</HowToShareDiagnostic>
 | 
			
		||||
</root>
 | 
			
		||||
@@ -1,6 +1,7 @@
 | 
			
		||||
<?xml version="1.0" encoding="utf-8"?>
 | 
			
		||||
<root>
 | 
			
		||||
	<Ok>确定</Ok>
 | 
			
		||||
	<Cancel>取消</Cancel>
 | 
			
		||||
	<About>关于</About>
 | 
			
		||||
	<Version>版本号</Version>
 | 
			
		||||
	<Preference>偏好</Preference>
 | 
			
		||||
@@ -63,6 +64,8 @@
 | 
			
		||||
	<AmountRequired>请输入金额。</AmountRequired>
 | 
			
		||||
	<Income>收入</Income>
 | 
			
		||||
	<Spending>支出</Spending>
 | 
			
		||||
	<LastSelected>最后选择</LastSelected>
 | 
			
		||||
	<Recent>最近</Recent>
 | 
			
		||||
	<Clothing>衣物</Clothing>
 | 
			
		||||
	<Food>食品</Food>
 | 
			
		||||
	<Drinks>饮料</Drinks>
 | 
			
		||||
@@ -104,4 +107,9 @@
 | 
			
		||||
	<NoResult>(无记录)</NoResult>
 | 
			
		||||
	<Top10>Top 10</Top10>
 | 
			
		||||
	<CategoryRank>分类排行</CategoryRank>
 | 
			
		||||
	<Diagnostic>诊断</Diagnostic>
 | 
			
		||||
	<ShareLogs>发送日志</ShareLogs>
 | 
			
		||||
	<ManyRecords>{0} 条记录</ManyRecords>
 | 
			
		||||
	<SendEmail>发送邮件</SendEmail>
 | 
			
		||||
	<HowToShareDiagnostic>您想以哪种方式分享诊断日志?</HowToShareDiagnostic>
 | 
			
		||||
</root>
 | 
			
		||||
@@ -6,6 +6,9 @@ namespace Billing.Models
 | 
			
		||||
    {
 | 
			
		||||
        private const string ICON_DEFAULT = "ic_default";
 | 
			
		||||
 | 
			
		||||
        private static Account empty;
 | 
			
		||||
        public static Account Empty => empty ??= new() { Id = -1 };
 | 
			
		||||
 | 
			
		||||
        [PrimaryKey, AutoIncrement]
 | 
			
		||||
        public int Id { get; set; }
 | 
			
		||||
        public string Icon { get; set; } = ICON_DEFAULT;
 | 
			
		||||
 
 | 
			
		||||
@@ -8,6 +8,9 @@ namespace Billing.Models
 | 
			
		||||
        private const string ICON_DEFAULT = "ic_default";
 | 
			
		||||
        private const long TRANSPARENT_COLOR = 0x00ffffffL;
 | 
			
		||||
 | 
			
		||||
        private static Category empty;
 | 
			
		||||
        public static Category Empty => empty ??= new() { Id = -1 };
 | 
			
		||||
 | 
			
		||||
        [PrimaryKey, AutoIncrement]
 | 
			
		||||
        public int Id { get; set; }
 | 
			
		||||
        public CategoryType Type { get; set; }
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										14
									
								
								Billing.Shared/Models/Logs.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,14 @@
 | 
			
		||||
using System;
 | 
			
		||||
using SQLite;
 | 
			
		||||
 | 
			
		||||
namespace Billing.Models
 | 
			
		||||
{
 | 
			
		||||
    public class Logs : IIdItem
 | 
			
		||||
    {
 | 
			
		||||
        [PrimaryKey, AutoIncrement]
 | 
			
		||||
        public int Id { get; set; }
 | 
			
		||||
        public DateTime LogTime { get; set; }
 | 
			
		||||
        public string Category { get; set; }
 | 
			
		||||
        public string Detail { get; set; }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -66,12 +66,24 @@ namespace Billing.Store
 | 
			
		||||
            var instance = new StoreHelper();
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                await database.CreateTablesAsync<Category, Account, Bill>();
 | 
			
		||||
                await database.CreateTablesAsync<Category, Account, Bill, Logs>();
 | 
			
		||||
            } catch (Exception ex)
 | 
			
		||||
            {
 | 
			
		||||
                Helper.Error("database.init.table", ex);
 | 
			
		||||
            }
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                var count = await database.ExecuteScalarAsync<int>("SELECT COUNT(Id) FROM [Category]");
 | 
			
		||||
                if (count <= 0)
 | 
			
		||||
                {
 | 
			
		||||
                    await database.InsertAsync(new Account { Name = Resource.Cash, Icon = "wallet" });
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            catch (Exception ex)
 | 
			
		||||
            {
 | 
			
		||||
                Helper.Error("database.init.account", ex);
 | 
			
		||||
            }
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                var count = await database.ExecuteScalarAsync<int>("SELECT COUNT(Id) FROM [Category]");
 | 
			
		||||
                if (count <= 0)
 | 
			
		||||
@@ -152,6 +164,46 @@ namespace Billing.Store
 | 
			
		||||
            return await instance.DeleteItemAsync(category);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static async Task<int> GetLogsCount()
 | 
			
		||||
        {
 | 
			
		||||
            await Instance;
 | 
			
		||||
            return await database.ExecuteScalarAsync<int>("SELECT COUNT(Id) FROM [Logs]");
 | 
			
		||||
        }
 | 
			
		||||
        public static async Task<int> SaveLogItemAsync(Logs log)
 | 
			
		||||
        {
 | 
			
		||||
            var instance = await Instance;
 | 
			
		||||
            return await instance.SaveItemAsync(log);
 | 
			
		||||
        }
 | 
			
		||||
        public static string GetLogFile()
 | 
			
		||||
        {
 | 
			
		||||
            return Path.Combine(CacheFolder, "logs.csv");
 | 
			
		||||
        }
 | 
			
		||||
        public static async Task<string> ExportLogs()
 | 
			
		||||
        {
 | 
			
		||||
            try
 | 
			
		||||
            {
 | 
			
		||||
                var instance = await Instance;
 | 
			
		||||
                var logs = await instance.GetListAsync<Logs>();
 | 
			
		||||
                var file = GetLogFile();
 | 
			
		||||
                using var writer = new StreamWriter(File.Open(file, FileMode.Create, FileAccess.Write));
 | 
			
		||||
                writer.WriteLine("Id,DateTime,Category,Detail");
 | 
			
		||||
                foreach (var log in logs)
 | 
			
		||||
                {
 | 
			
		||||
                    var category = log.Category?.Replace("\n", " \\n ");
 | 
			
		||||
                    var detail = log.Detail?.Replace("\n", " \\n ");
 | 
			
		||||
                    writer.WriteLine($"{log.Id},{log.LogTime},{category},{detail}");
 | 
			
		||||
                }
 | 
			
		||||
                writer.Flush();
 | 
			
		||||
 | 
			
		||||
                await database.ExecuteAsync("DELETE FROM [Logs]; DELETE FROM [sqlite_sequence] WHERE [name] = 'Logs'");
 | 
			
		||||
                return file;
 | 
			
		||||
            }
 | 
			
		||||
            catch
 | 
			
		||||
            {
 | 
			
		||||
                return null;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private StoreHelper()
 | 
			
		||||
        {
 | 
			
		||||
            if (database == null)
 | 
			
		||||
 
 | 
			
		||||
@@ -244,4 +244,23 @@ namespace Billing.UI
 | 
			
		||||
            throw new NotImplementedException();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public class TintColorConverter : IValueConverter
 | 
			
		||||
    {
 | 
			
		||||
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
 | 
			
		||||
        {
 | 
			
		||||
            if (value is long l)
 | 
			
		||||
            {
 | 
			
		||||
                return l.IsTransparent() ?
 | 
			
		||||
                    BaseTheme.CurrentPrimaryColor :
 | 
			
		||||
                    l.ToColor();
 | 
			
		||||
            }
 | 
			
		||||
            return Color.Transparent;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
 | 
			
		||||
        {
 | 
			
		||||
            throw new NotImplementedException();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -9,6 +9,7 @@ namespace Billing.UI
 | 
			
		||||
    {
 | 
			
		||||
        public const string PrimaryColorKey = "PrimaryColor";
 | 
			
		||||
        public const string DefaultIcon = "ic_default";
 | 
			
		||||
        public const long TransparentColor = 0x00ffffffL;
 | 
			
		||||
 | 
			
		||||
        public static partial (string main, long build) GetVersion();
 | 
			
		||||
        public static partial string GetRegularFontFamily();
 | 
			
		||||
 
 | 
			
		||||
@@ -237,6 +237,13 @@ namespace Billing.UI
 | 
			
		||||
                .Binding(Image.SourceProperty, nameof(ImageSource))
 | 
			
		||||
                .Binding(TintHelper.TintColorProperty, nameof(TintColor)),
 | 
			
		||||
 | 
			
		||||
                new Label
 | 
			
		||||
                {
 | 
			
		||||
                    VerticalOptions = LayoutOptions.Center
 | 
			
		||||
                }
 | 
			
		||||
                .Binding(Label.TextProperty, nameof(Detail))
 | 
			
		||||
                .DynamicResource(Label.TextColorProperty, BaseTheme.SecondaryTextColor),
 | 
			
		||||
 | 
			
		||||
                new TintImage
 | 
			
		||||
                {
 | 
			
		||||
                    HeightRequest = 20,
 | 
			
		||||
 
 | 
			
		||||
@@ -13,6 +13,11 @@
 | 
			
		||||
        <ToolbarItem Order="Primary" IconImageSource="check.png" Command="{Binding CheckBill}"/>
 | 
			
		||||
    </ContentPage.ToolbarItems>
 | 
			
		||||
 | 
			
		||||
    <ContentPage.Resources>
 | 
			
		||||
        <ui:IconConverter x:Key="iconConverter"/>
 | 
			
		||||
        <ui:TintColorConverter x:Key="tintColorConverter"/>
 | 
			
		||||
    </ContentPage.Resources>
 | 
			
		||||
 | 
			
		||||
    <ContentPage.Content>
 | 
			
		||||
        <TableView Intent="Settings" HasUnevenRows="True">
 | 
			
		||||
            <TableSection Title=" ">
 | 
			
		||||
@@ -29,14 +34,18 @@
 | 
			
		||||
                                    Title="{r:Text Name}"
 | 
			
		||||
                                    Text="{Binding Name, Mode=TwoWay}"
 | 
			
		||||
                                    Placeholder="{r:Text NamePlaceholder}"/>
 | 
			
		||||
                <ui:OptionSelectCell Height="44" Icon="project.png"
 | 
			
		||||
                                     Title="{r:Text Category}"
 | 
			
		||||
                                     Detail="{Binding CategoryName}"
 | 
			
		||||
                                     Command="{Binding SelectCategory}"/>
 | 
			
		||||
                <ui:OptionSelectCell Height="44" Icon="wallet.png"
 | 
			
		||||
                                     Title="{r:Text Account}"
 | 
			
		||||
                                     Detail="{Binding WalletName}"
 | 
			
		||||
                                     Command="{Binding SelectWallet}"/>
 | 
			
		||||
                <ui:OptionImageCell Height="44" Icon="project.png"
 | 
			
		||||
                                    Title="{r:Text Category}"
 | 
			
		||||
                                    Detail="{Binding Category.Name}"
 | 
			
		||||
                                    ImageSource="{Binding Category.Icon, Converter={StaticResource iconConverter}}"
 | 
			
		||||
                                    TintColor="{Binding Category.TintColor, Converter={StaticResource tintColorConverter}}"
 | 
			
		||||
                                    Command="{Binding SelectCategory}"/>
 | 
			
		||||
                <ui:OptionImageCell Height="44" Icon="wallet.png"
 | 
			
		||||
                                    Title="{r:Text Account}"
 | 
			
		||||
                                    Detail="{Binding Wallet.Name}"
 | 
			
		||||
                                    ImageSource="{Binding Wallet.Icon, Converter={StaticResource iconConverter}}"
 | 
			
		||||
                                    TintColor="{DynamicResource PrimaryColor}"
 | 
			
		||||
                                    Command="{Binding SelectWallet}"/>
 | 
			
		||||
                <ui:OptionEntryCell Height="44" Icon="online.png"
 | 
			
		||||
                                    Title="{r:Text Store}"
 | 
			
		||||
                                    Text="{Binding Store, Mode=TwoWay}"/>
 | 
			
		||||
 
 | 
			
		||||
@@ -3,6 +3,7 @@ using System.Globalization;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using Billing.Languages;
 | 
			
		||||
using Billing.Models;
 | 
			
		||||
using Billing.Store;
 | 
			
		||||
using Billing.UI;
 | 
			
		||||
using Xamarin.Forms;
 | 
			
		||||
 | 
			
		||||
@@ -12,8 +13,8 @@ namespace Billing.Views
 | 
			
		||||
    {
 | 
			
		||||
        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 CategoryNameProperty = Helper.Create<string, AddBillPage>(nameof(CategoryName));
 | 
			
		||||
        private static readonly BindableProperty WalletNameProperty = Helper.Create<string, AddBillPage>(nameof(WalletName));
 | 
			
		||||
        private static readonly BindableProperty CategoryProperty = Helper.Create<Category, AddBillPage>(nameof(Category));
 | 
			
		||||
        private static readonly BindableProperty WalletProperty = Helper.Create<Account, AddBillPage>(nameof(Wallet));
 | 
			
		||||
        private static readonly BindableProperty StoreProperty = Helper.Create<string, AddBillPage>(nameof(Store));
 | 
			
		||||
        private static readonly BindableProperty CreatedDateProperty = Helper.Create<DateTime, AddBillPage>(nameof(CreatedDate));
 | 
			
		||||
        private static readonly BindableProperty CreatedTimeProperty = Helper.Create<TimeSpan, AddBillPage>(nameof(CreatedTime));
 | 
			
		||||
@@ -29,8 +30,8 @@ namespace Billing.Views
 | 
			
		||||
            get => (string)GetValue(NameProperty);
 | 
			
		||||
            set => SetValue(NameProperty, value);
 | 
			
		||||
        }
 | 
			
		||||
        public string CategoryName => (string)GetValue(CategoryNameProperty);
 | 
			
		||||
        public string WalletName => (string)GetValue(WalletNameProperty);
 | 
			
		||||
        public Category Category => (Category)GetValue(CategoryProperty);
 | 
			
		||||
        public Account Wallet => (Account)GetValue(WalletProperty);
 | 
			
		||||
        public string Store
 | 
			
		||||
        {
 | 
			
		||||
            get => (string)GetValue(StoreProperty);
 | 
			
		||||
@@ -61,8 +62,7 @@ namespace Billing.Views
 | 
			
		||||
        private readonly Bill bill;
 | 
			
		||||
        private readonly DateTime createDate;
 | 
			
		||||
 | 
			
		||||
        private int walletId;
 | 
			
		||||
        private int categoryId;
 | 
			
		||||
        private bool categoryChanged;
 | 
			
		||||
 | 
			
		||||
        public AddBillPage(DateTime date)
 | 
			
		||||
        {
 | 
			
		||||
@@ -94,10 +94,9 @@ namespace Billing.Views
 | 
			
		||||
            {
 | 
			
		||||
                Amount = Math.Abs(bill.Amount).ToString(CultureInfo.InvariantCulture);
 | 
			
		||||
                Name = bill.Name;
 | 
			
		||||
                walletId = bill.WalletId;
 | 
			
		||||
                categoryId = bill.CategoryId;
 | 
			
		||||
                SetValue(WalletNameProperty, App.Accounts.FirstOrDefault(a => a.Id == walletId)?.Name);
 | 
			
		||||
                SetValue(CategoryNameProperty, App.Categories.FirstOrDefault(c => c.Id == categoryId)?.Name);
 | 
			
		||||
                SetValue(WalletProperty, App.Accounts.FirstOrDefault(a => a.Id == bill.WalletId) ?? Account.Empty);
 | 
			
		||||
                SetValue(CategoryProperty, App.Categories.FirstOrDefault(c => c.Id == bill.CategoryId) ?? Category.Empty);
 | 
			
		||||
                categoryChanged = true;
 | 
			
		||||
                Store = bill.Store;
 | 
			
		||||
                CreatedDate = bill.CreateTime.Date;
 | 
			
		||||
                CreatedTime = bill.CreateTime.TimeOfDay;
 | 
			
		||||
@@ -105,12 +104,8 @@ namespace Billing.Views
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                var first = App.Accounts.First();
 | 
			
		||||
                walletId = first.Id;
 | 
			
		||||
                SetValue(WalletNameProperty, first.Name);
 | 
			
		||||
                var firstCategory = App.Categories.First();
 | 
			
		||||
                categoryId = firstCategory.Id;
 | 
			
		||||
                SetValue(CategoryNameProperty, firstCategory.Name);
 | 
			
		||||
                SetValue(WalletProperty, App.Accounts.FirstOrDefault() ?? Account.Empty);
 | 
			
		||||
                SetValue(CategoryProperty, App.Categories.FirstOrDefault() ?? Category.Empty);
 | 
			
		||||
                CreatedDate = createDate.Date;
 | 
			
		||||
                CreatedTime = DateTime.Now.TimeOfDay;
 | 
			
		||||
            }
 | 
			
		||||
@@ -138,8 +133,9 @@ namespace Billing.Views
 | 
			
		||||
                    await this.ShowMessage(Resource.AmountRequired);
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
                var category = Category;
 | 
			
		||||
                var wallet = Wallet;
 | 
			
		||||
                amount = Math.Abs(amount);
 | 
			
		||||
                var category = App.Categories.FirstOrDefault(c => c.Id == categoryId);
 | 
			
		||||
                if (category.Type == CategoryType.Spending)
 | 
			
		||||
                {
 | 
			
		||||
                    amount *= -1;
 | 
			
		||||
@@ -154,8 +150,8 @@ namespace Billing.Views
 | 
			
		||||
                {
 | 
			
		||||
                    bill.Amount = amount;
 | 
			
		||||
                    bill.Name = name;
 | 
			
		||||
                    bill.CategoryId = categoryId;
 | 
			
		||||
                    bill.WalletId = walletId;
 | 
			
		||||
                    bill.CategoryId = category.Id;
 | 
			
		||||
                    bill.WalletId = wallet.Id;
 | 
			
		||||
                    bill.CreateTime = CreatedDate.Date.Add(CreatedTime);
 | 
			
		||||
                    bill.Store = Store;
 | 
			
		||||
                    bill.Note = Note;
 | 
			
		||||
@@ -164,15 +160,17 @@ namespace Billing.Views
 | 
			
		||||
                {
 | 
			
		||||
                    Amount = amount,
 | 
			
		||||
                    Name = name,
 | 
			
		||||
                    CategoryId = categoryId,
 | 
			
		||||
                    WalletId = walletId,
 | 
			
		||||
                    CategoryId = category.Id,
 | 
			
		||||
                    WalletId = wallet.Id,
 | 
			
		||||
                    CreateTime = CreatedDate.Date.Add(CreatedTime),
 | 
			
		||||
                    Store = Store,
 | 
			
		||||
                    Note = Note
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
                category.LastAccountId = walletId;
 | 
			
		||||
                category.LastAccountId = wallet.Id;
 | 
			
		||||
                category.LastUsed = DateTime.Now;
 | 
			
		||||
 | 
			
		||||
                await StoreHelper.SaveCategoryItemAsync(category);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -184,7 +182,7 @@ namespace Billing.Views
 | 
			
		||||
            }
 | 
			
		||||
            using (Tap.Start())
 | 
			
		||||
            {
 | 
			
		||||
                var page = new CategorySelectPage(categoryId);
 | 
			
		||||
                var page = new CategorySelectPage(categoryChanged ? Category.Id : -1);
 | 
			
		||||
                page.CategoryTapped += CategorySelectPage_Tapped;
 | 
			
		||||
                await Navigation.PushAsync(page);
 | 
			
		||||
            }
 | 
			
		||||
@@ -192,16 +190,16 @@ namespace Billing.Views
 | 
			
		||||
 | 
			
		||||
        private void CategorySelectPage_Tapped(object sender, UICategory e)
 | 
			
		||||
        {
 | 
			
		||||
            categoryId = e.Category.Id;
 | 
			
		||||
            SetValue(CategoryProperty, e.Category);
 | 
			
		||||
            categoryChanged = true;
 | 
			
		||||
            if (e.Category.LastAccountId != null)
 | 
			
		||||
            {
 | 
			
		||||
                var wallet = App.Accounts.FirstOrDefault(a => a.Id == e.Category.LastAccountId.Value);
 | 
			
		||||
                if (wallet != null)
 | 
			
		||||
                {
 | 
			
		||||
                    SetValue(WalletNameProperty, wallet.Name);
 | 
			
		||||
                    SetValue(WalletProperty, wallet);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            SetValue(CategoryNameProperty, e.Name);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private async void OnSelectWallet()
 | 
			
		||||
@@ -212,22 +210,15 @@ namespace Billing.Views
 | 
			
		||||
            }
 | 
			
		||||
            using (Tap.Start())
 | 
			
		||||
            {
 | 
			
		||||
                var source = App.Accounts.Select(a => new SelectItem<int>
 | 
			
		||||
                {
 | 
			
		||||
                    Value = a.Id,
 | 
			
		||||
                    Name = a.Name,
 | 
			
		||||
                    Icon = a.Icon
 | 
			
		||||
                });
 | 
			
		||||
                var page = new ItemSelectPage<SelectItem<int>>(source);
 | 
			
		||||
                var page = new ItemSelectPage<Account>(App.Accounts);
 | 
			
		||||
                page.ItemTapped += Wallet_ItemTapped;
 | 
			
		||||
                await Navigation.PushAsync(page);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void Wallet_ItemTapped(object sender, SelectItem<int> account)
 | 
			
		||||
        private void Wallet_ItemTapped(object sender, Account account)
 | 
			
		||||
        {
 | 
			
		||||
            walletId = account.Value;
 | 
			
		||||
            SetValue(WalletNameProperty, account.Name);
 | 
			
		||||
            SetValue(WalletProperty, account);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -20,6 +20,7 @@
 | 
			
		||||
        <ui:BalanceColorConverter x:Key="colorConverter"/>
 | 
			
		||||
        <ui:TimeConverter x:Key="timeConverter"/>
 | 
			
		||||
        <ui:IconConverter x:Key="iconConverter"/>
 | 
			
		||||
        <ui:TintColorConverter x:Key="tintColorConverter"/>
 | 
			
		||||
    </ContentPage.Resources>
 | 
			
		||||
 | 
			
		||||
    <Shell.TitleView>
 | 
			
		||||
@@ -101,7 +102,7 @@
 | 
			
		||||
                                                      CommandParameter="{Binding .}"/>
 | 
			
		||||
                            </Grid.GestureRecognizers>
 | 
			
		||||
                            <ui:TintImage Source="{Binding Icon, Converter={StaticResource iconConverter}}"
 | 
			
		||||
                                          ui:TintHelper.TintColor="{Binding TintColor}"
 | 
			
		||||
                                          ui:TintHelper.TintColor="{Binding TintColor, Converter={StaticResource tintColorConverter}}"
 | 
			
		||||
                                          WidthRequest="26" HeightRequest="20" VerticalOptions="Center"/>
 | 
			
		||||
                            <Label Grid.Column="1" Text="{Binding Name}" TextColor="{DynamicResource TextColor}"
 | 
			
		||||
                                   VerticalOptions="Center"
 | 
			
		||||
 
 | 
			
		||||
@@ -85,7 +85,9 @@ namespace Billing.Views
 | 
			
		||||
 | 
			
		||||
        private void UpdateBill(UIBill bill)
 | 
			
		||||
        {
 | 
			
		||||
            bill.Icon = App.Categories.FirstOrDefault(c => c.Id == bill.Bill.CategoryId)?.Icon ?? Definition.DefaultIcon;
 | 
			
		||||
            var category = App.Categories.FirstOrDefault(c => c.Id == bill.Bill.CategoryId);
 | 
			
		||||
            bill.Icon = category?.Icon ?? Definition.DefaultIcon;
 | 
			
		||||
            bill.TintColor = category?.TintColor ?? Definition.TransparentColor;
 | 
			
		||||
            bill.Name = bill.Bill.Name;
 | 
			
		||||
            bill.DateCreation = bill.Bill.CreateTime;
 | 
			
		||||
            bill.Amount = bill.Bill.Amount;
 | 
			
		||||
@@ -207,7 +209,7 @@ namespace Billing.Views
 | 
			
		||||
    public class UIBill : BindableObject
 | 
			
		||||
    {
 | 
			
		||||
        public static readonly BindableProperty IconProperty = Helper.Create<string, UIBill>(nameof(Icon));
 | 
			
		||||
        public static readonly BindableProperty TintColorProperty = Helper.Create<Color, UIBill>(nameof(TintColor));
 | 
			
		||||
        public static readonly BindableProperty TintColorProperty = Helper.Create<long, UIBill>(nameof(TintColor));
 | 
			
		||||
        public static readonly BindableProperty NameProperty = Helper.Create<string, UIBill>(nameof(Name));
 | 
			
		||||
        public static readonly BindableProperty DateCreationProperty = Helper.Create<DateTime, UIBill>(nameof(DateCreation));
 | 
			
		||||
        public static readonly BindableProperty AmountProperty = Helper.Create<decimal, UIBill>(nameof(Amount));
 | 
			
		||||
@@ -218,9 +220,9 @@ namespace Billing.Views
 | 
			
		||||
            get => (string)GetValue(IconProperty);
 | 
			
		||||
            set => SetValue(IconProperty, value);
 | 
			
		||||
        }
 | 
			
		||||
        public Color TintColor
 | 
			
		||||
        public long TintColor
 | 
			
		||||
        {
 | 
			
		||||
            get => (Color)GetValue(TintColorProperty);
 | 
			
		||||
            get => (long)GetValue(TintColorProperty);
 | 
			
		||||
            set => SetValue(TintColorProperty, value);
 | 
			
		||||
        }
 | 
			
		||||
        public string Name
 | 
			
		||||
 
 | 
			
		||||
@@ -10,6 +10,7 @@
 | 
			
		||||
 | 
			
		||||
    <ContentPage.Resources>
 | 
			
		||||
        <ui:IconConverter x:Key="iconConverter"/>
 | 
			
		||||
        <ui:TintColorConverter x:Key="tintColorConverter"/>
 | 
			
		||||
    </ContentPage.Resources>
 | 
			
		||||
 | 
			
		||||
    <ScrollView>
 | 
			
		||||
@@ -32,7 +33,7 @@
 | 
			
		||||
                                                  CommandParameter="{Binding .}"/>
 | 
			
		||||
                        </Grid.GestureRecognizers>
 | 
			
		||||
                        <ui:TintImage Source="{Binding Icon, Converter={StaticResource iconConverter}}"
 | 
			
		||||
                                      ui:TintHelper.TintColor="{Binding TintColor}"
 | 
			
		||||
                                      ui:TintHelper.TintColor="{Binding TintColor, Converter={StaticResource tintColorConverter}}"
 | 
			
		||||
                                      WidthRequest="26" HeightRequest="20" VerticalOptions="Center"/>
 | 
			
		||||
                        <Label Grid.Column="1" Text="{Binding Name}" TextColor="{DynamicResource TextColor}"
 | 
			
		||||
                               HorizontalOptions="FillAndExpand" VerticalOptions="Center"
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,6 @@
 | 
			
		||||
using Billing.Languages;
 | 
			
		||||
using Billing.Models;
 | 
			
		||||
using Billing.Store;
 | 
			
		||||
using Billing.Themes;
 | 
			
		||||
using Billing.UI;
 | 
			
		||||
using System.Collections;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
@@ -68,9 +67,7 @@ namespace Billing.Views
 | 
			
		||||
                Icon = category.Icon,
 | 
			
		||||
                Name = category.Name,
 | 
			
		||||
                IsTopCategory = IsTopCategory,
 | 
			
		||||
                TintColor = category.TintColor.IsTransparent() ?
 | 
			
		||||
                    BaseTheme.CurrentPrimaryColor :
 | 
			
		||||
                    category.TintColor.ToColor()
 | 
			
		||||
                TintColor = category.TintColor
 | 
			
		||||
            };
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -180,9 +177,7 @@ namespace Billing.Views
 | 
			
		||||
        {
 | 
			
		||||
            c.Name = c.Category.Name;
 | 
			
		||||
            c.Icon = c.Category.Icon;
 | 
			
		||||
            c.TintColor = c.Category.TintColor.IsTransparent() ?
 | 
			
		||||
                BaseTheme.CurrentPrimaryColor :
 | 
			
		||||
                c.Category.TintColor.ToColor();
 | 
			
		||||
            c.TintColor = c.Category.TintColor;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -191,7 +186,7 @@ namespace Billing.Views
 | 
			
		||||
        public static readonly BindableProperty IsCheckedProperty = Helper.Create<bool, UICategory>(nameof(IsChecked));
 | 
			
		||||
        public static readonly BindableProperty IconProperty = Helper.Create<string, UICategory>(nameof(Icon));
 | 
			
		||||
        public static readonly BindableProperty NameProperty = Helper.Create<string, UICategory>(nameof(Name));
 | 
			
		||||
        public static readonly BindableProperty TintColorProperty = Helper.Create<Color, UICategory>(nameof(TintColor));
 | 
			
		||||
        public static readonly BindableProperty TintColorProperty = Helper.Create<long, UICategory>(nameof(TintColor));
 | 
			
		||||
        public static readonly BindableProperty IsTopCategoryProperty = Helper.Create<bool, UICategory>(nameof(IsTopCategory));
 | 
			
		||||
 | 
			
		||||
        public bool IsChecked
 | 
			
		||||
@@ -209,9 +204,9 @@ namespace Billing.Views
 | 
			
		||||
            get => (string)GetValue(NameProperty);
 | 
			
		||||
            set => SetValue(NameProperty, value);
 | 
			
		||||
        }
 | 
			
		||||
        public Color TintColor
 | 
			
		||||
        public long TintColor
 | 
			
		||||
        {
 | 
			
		||||
            get => (Color)GetValue(TintColorProperty);
 | 
			
		||||
            get => (long)GetValue(TintColorProperty);
 | 
			
		||||
            set => SetValue(TintColorProperty, value);
 | 
			
		||||
        }
 | 
			
		||||
        public bool IsTopCategory
 | 
			
		||||
@@ -232,6 +227,10 @@ namespace Billing.Views
 | 
			
		||||
    {
 | 
			
		||||
        public string Key { get; }
 | 
			
		||||
 | 
			
		||||
        public CategoryGrouping(string key) : base()
 | 
			
		||||
        {
 | 
			
		||||
            Key = key;
 | 
			
		||||
        }
 | 
			
		||||
        public CategoryGrouping(string key, IEnumerable<UICategory> categories) : base(categories)
 | 
			
		||||
        {
 | 
			
		||||
            Key = key;
 | 
			
		||||
 
 | 
			
		||||
@@ -13,6 +13,7 @@
 | 
			
		||||
    <ContentPage.Resources>
 | 
			
		||||
        <ui:IconConverter x:Key="iconConverter"/>
 | 
			
		||||
        <ui:SelectBackgroundColorConverter x:Key="backgroundConverter"/>
 | 
			
		||||
        <ui:TintColorConverter x:Key="tintColorConverter"/>
 | 
			
		||||
    </ContentPage.Resources>
 | 
			
		||||
 | 
			
		||||
    <Grid ColumnDefinitions=".5*, .5*">
 | 
			
		||||
@@ -36,7 +37,7 @@
 | 
			
		||||
                                                      CommandParameter="{Binding .}"/>
 | 
			
		||||
                            </Grid.GestureRecognizers>
 | 
			
		||||
                            <ui:TintImage Source="{Binding Icon, Converter={StaticResource iconConverter}}"
 | 
			
		||||
                                          ui:TintHelper.TintColor="{Binding TintColor}"
 | 
			
		||||
                                          ui:TintHelper.TintColor="{Binding TintColor, Converter={StaticResource tintColorConverter}}"
 | 
			
		||||
                                          WidthRequest="26" HeightRequest="20" VerticalOptions="Center"/>
 | 
			
		||||
                            <Label Grid.Column="1" Text="{Binding Name}" TextColor="{DynamicResource TextColor}"
 | 
			
		||||
                                   HorizontalOptions="FillAndExpand" VerticalOptions="Center"
 | 
			
		||||
@@ -58,7 +59,7 @@
 | 
			
		||||
                                                      CommandParameter="{Binding .}"/>
 | 
			
		||||
                            </Grid.GestureRecognizers>
 | 
			
		||||
                            <ui:TintImage Source="{Binding Icon, Converter={StaticResource iconConverter}}"
 | 
			
		||||
                                          ui:TintHelper.TintColor="{Binding TintColor}"
 | 
			
		||||
                                          ui:TintHelper.TintColor="{Binding TintColor, Converter={StaticResource tintColorConverter}}"
 | 
			
		||||
                                          WidthRequest="26" HeightRequest="20" VerticalOptions="Center"/>
 | 
			
		||||
                            <Label Grid.Column="1" Text="{Binding Name}" TextColor="{DynamicResource TextColor}"
 | 
			
		||||
                                   HorizontalOptions="FillAndExpand" VerticalOptions="Center"
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,5 @@
 | 
			
		||||
using Billing.Languages;
 | 
			
		||||
using Billing.Models;
 | 
			
		||||
using Billing.Themes;
 | 
			
		||||
using Billing.UI;
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
@@ -31,12 +30,10 @@ namespace Billing.Views
 | 
			
		||||
        public event EventHandler<UICategory> CategoryTapped;
 | 
			
		||||
 | 
			
		||||
        private readonly int categoryId;
 | 
			
		||||
        private readonly Color defaultColor;
 | 
			
		||||
 | 
			
		||||
        public CategorySelectPage(int id)
 | 
			
		||||
        {
 | 
			
		||||
            categoryId = id;
 | 
			
		||||
            defaultColor = BaseTheme.CurrentPrimaryColor;
 | 
			
		||||
            TapTopCategory = new Command(OnTopCategoryTapped);
 | 
			
		||||
            TapSubCategory = new Command(OnSubCategoryTapped);
 | 
			
		||||
 | 
			
		||||
@@ -45,6 +42,22 @@ namespace Billing.Views
 | 
			
		||||
                new(Resource.Spending, App.Categories.Where(c => c.Type == CategoryType.Spending && c.ParentId == null).Select(c => WrapCategory(c))),
 | 
			
		||||
                new(Resource.Income, App.Categories.Where(c => c.Type == CategoryType.Income && c.ParentId == null).Select(c => WrapCategory(c)))
 | 
			
		||||
            };
 | 
			
		||||
            UICategory last;
 | 
			
		||||
            if (App.Categories.Any(c => c.LastUsed != null))
 | 
			
		||||
            {
 | 
			
		||||
                last = new UICategory(null)
 | 
			
		||||
                {
 | 
			
		||||
                    IsChecked = true,
 | 
			
		||||
                    Icon = "rank",
 | 
			
		||||
                    Name = Resource.LastSelected,
 | 
			
		||||
                    TintColor = Definition.TransparentColor
 | 
			
		||||
                };
 | 
			
		||||
                TopCategories.Insert(0, new(Resource.Recent) { last });
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                last = null;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            UICategory cat;
 | 
			
		||||
            var category = App.Categories.FirstOrDefault(c => c.Id == categoryId);
 | 
			
		||||
@@ -58,7 +71,7 @@ namespace Billing.Views
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                cat = TopCategories.SelectMany(g => g).FirstOrDefault(c => c.Category.Id == category.ParentId);
 | 
			
		||||
                cat = TopCategories.SelectMany(g => g).FirstOrDefault(c => c.Category?.Id == category.ParentId) ?? last;
 | 
			
		||||
            }
 | 
			
		||||
            DoRefreshSubCategories(cat);
 | 
			
		||||
 | 
			
		||||
@@ -72,7 +85,7 @@ namespace Billing.Views
 | 
			
		||||
                IsChecked = c.Id == categoryId,
 | 
			
		||||
                Icon = c.Icon,
 | 
			
		||||
                Name = c.Name,
 | 
			
		||||
                TintColor = c.TintColor.IsTransparent() ? defaultColor : c.TintColor.ToColor()
 | 
			
		||||
                TintColor = c.TintColor
 | 
			
		||||
            };
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -83,7 +96,18 @@ namespace Billing.Views
 | 
			
		||||
            {
 | 
			
		||||
                m.IsChecked = m == category;
 | 
			
		||||
            }
 | 
			
		||||
            SubCategories = App.Categories.Where(c => c.ParentId == category.Category.Id).Select(c => WrapCategory(c)).ToList();
 | 
			
		||||
            if (category == null)
 | 
			
		||||
            {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            if (category.Category == null)
 | 
			
		||||
            {
 | 
			
		||||
                SubCategories = App.Categories.Where(c => c.ParentId != null && c.LastUsed != null).OrderByDescending(c => c.LastUsed).Take(10).Select(c => WrapCategory(c)).ToList();
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                SubCategories = App.Categories.Where(c => c.ParentId == category.Category.Id).Select(c => WrapCategory(c)).ToList();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private async void OnTopCategoryTapped(object o)
 | 
			
		||||
@@ -97,7 +121,7 @@ namespace Billing.Views
 | 
			
		||||
                if (o is UICategory category)
 | 
			
		||||
                {
 | 
			
		||||
                    DoRefreshSubCategories(category);
 | 
			
		||||
                    if (SubCategories.Count == 0)
 | 
			
		||||
                    if (SubCategories?.Count == 0)
 | 
			
		||||
                    {
 | 
			
		||||
                        CategoryTapped?.Invoke(this, category);
 | 
			
		||||
                        await Navigation.PopAsync();
 | 
			
		||||
 
 | 
			
		||||
@@ -66,6 +66,7 @@ namespace Billing.Views
 | 
			
		||||
                new() { Icon = "taxi" },
 | 
			
		||||
                new() { Icon = "fitness" },
 | 
			
		||||
                new() { Icon = "party" },
 | 
			
		||||
                new() { Icon = "share" },
 | 
			
		||||
            };
 | 
			
		||||
            source.AddRange(IconConverter.IconPreset.Select(icon => new BillingIcon { Icon = $"#brand#{icon.Key}" }));
 | 
			
		||||
            foreach (var icon in source)
 | 
			
		||||
 
 | 
			
		||||
@@ -49,6 +49,7 @@
 | 
			
		||||
        <ui:BalanceColorConverter x:Key="colorConverter"/>
 | 
			
		||||
        <ui:TimeConverter x:Key="timeConverter" IncludeDate="True"/>
 | 
			
		||||
        <ui:IconConverter x:Key="iconConverter"/>
 | 
			
		||||
        <ui:TintColorConverter x:Key="tintColorConverter"/>
 | 
			
		||||
        <Style x:Key="titleLabel" TargetType="Label">
 | 
			
		||||
            <Setter Property="FontSize" Value="16"/>
 | 
			
		||||
            <Setter Property="Margin" Value="10, 20, 10, 10"/>
 | 
			
		||||
@@ -116,7 +117,7 @@
 | 
			
		||||
                                                          CommandParameter="{Binding .}"/>
 | 
			
		||||
                                </Grid.GestureRecognizers>
 | 
			
		||||
                                <ui:TintImage Source="{Binding Icon, Converter={StaticResource iconConverter}}"
 | 
			
		||||
                                              ui:TintHelper.TintColor="{Binding TintColor}"
 | 
			
		||||
                                              ui:TintHelper.TintColor="{Binding TintColor, Converter={StaticResource tintColorConverter}}"
 | 
			
		||||
                                              WidthRequest="26" HeightRequest="20" VerticalOptions="Center"/>
 | 
			
		||||
                                <Label Grid.Column="1" Text="{Binding Name}" TextColor="{DynamicResource TextColor}"
 | 
			
		||||
                                       VerticalOptions="Center"
 | 
			
		||||
 
 | 
			
		||||
@@ -12,7 +12,7 @@
 | 
			
		||||
                Shell.TabBarIsVisible="True">
 | 
			
		||||
 | 
			
		||||
    <ContentPage.ToolbarItems>
 | 
			
		||||
        <ToolbarItem Order="Primary" IconImageSource="project.png" Command="{Binding ShareCommand}"/>
 | 
			
		||||
        <ToolbarItem Order="Primary" IconImageSource="share.png" Command="{Binding ShareCommand}"/>
 | 
			
		||||
    </ContentPage.ToolbarItems>
 | 
			
		||||
 | 
			
		||||
    <TableView Intent="Settings" HasUnevenRows="True">
 | 
			
		||||
@@ -39,5 +39,10 @@
 | 
			
		||||
                </Grid>
 | 
			
		||||
            </ViewCell>
 | 
			
		||||
        </TableSection>
 | 
			
		||||
        <TableSection Title="{r:Text Diagnostic}">
 | 
			
		||||
            <ui:OptionSelectCell Height="36" Title="{r:Text ShareLogs}"
 | 
			
		||||
                                 Detail="{Binding ManyRecords}"
 | 
			
		||||
                                 Command="{Binding ShareLogsCommand}"/>
 | 
			
		||||
        </TableSection>
 | 
			
		||||
    </TableView>
 | 
			
		||||
</ui:BillingPage>
 | 
			
		||||
@@ -1,8 +1,10 @@
 | 
			
		||||
using System.IO;
 | 
			
		||||
using Billing.Store;
 | 
			
		||||
using Billing.Themes;
 | 
			
		||||
using Billing.UI;
 | 
			
		||||
using Xamarin.Essentials;
 | 
			
		||||
using Xamarin.Forms;
 | 
			
		||||
using Resource = Billing.Languages.Resource;
 | 
			
		||||
 | 
			
		||||
namespace Billing.Views
 | 
			
		||||
{
 | 
			
		||||
@@ -10,6 +12,7 @@ namespace Billing.Views
 | 
			
		||||
    {
 | 
			
		||||
        private static readonly BindableProperty VersionProperty = Helper.Create<string, SettingPage>(nameof(Version));
 | 
			
		||||
        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 string PrimaryColor
 | 
			
		||||
@@ -17,38 +20,43 @@ namespace Billing.Views
 | 
			
		||||
            get => (string)GetValue(PrimaryColorProperty);
 | 
			
		||||
            set => SetValue(PrimaryColorProperty, value);
 | 
			
		||||
        }
 | 
			
		||||
        public string ManyRecords => (string)GetValue(ManyRecordsProperty);
 | 
			
		||||
 | 
			
		||||
        public Command ShareCommand { get; }
 | 
			
		||||
        public Command CategoryCommand { get; }
 | 
			
		||||
        public Command ColorPickerCommand { get; }
 | 
			
		||||
        public Command ShareLogsCommand { get; }
 | 
			
		||||
 | 
			
		||||
        public SettingPage()
 | 
			
		||||
        {
 | 
			
		||||
            ShareCommand = new Command(OnShareCommand);
 | 
			
		||||
            CategoryCommand = new Command(OnCategoryCommand);
 | 
			
		||||
            ColorPickerCommand = new Command(OnColorPickerCommand);
 | 
			
		||||
            ShareLogsCommand = new Command(OnShareLogsCommand);
 | 
			
		||||
            InitializeComponent();
 | 
			
		||||
 | 
			
		||||
            var (main, build) = Definition.GetVersion();
 | 
			
		||||
            SetValue(VersionProperty, $"{main} ({build})");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        protected override void OnAppearing()
 | 
			
		||||
        protected override async void OnAppearing()
 | 
			
		||||
        {
 | 
			
		||||
            base.OnAppearing();
 | 
			
		||||
 | 
			
		||||
            //SetValue(VersionProperty, $"{AppInfo.VersionString} ({AppInfo.BuildString})");
 | 
			
		||||
            var colorString = Preferences.Get(Definition.PrimaryColorKey, Helper.DEFAULT_COLOR);
 | 
			
		||||
            PrimaryColor = Helper.WrapColorString(colorString);
 | 
			
		||||
 | 
			
		||||
            var count = await StoreHelper.GetLogsCount();
 | 
			
		||||
            SetValue(ManyRecordsProperty, string.Format(Resource.ManyRecords, count));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        protected override void OnDisappearing()
 | 
			
		||||
        {
 | 
			
		||||
            base.OnDisappearing();
 | 
			
		||||
 | 
			
		||||
            var color = PrimaryColor;
 | 
			
		||||
            Preferences.Set(Definition.PrimaryColorKey, color);
 | 
			
		||||
            Light.Instance.RefreshColor(Color.FromHex(color));
 | 
			
		||||
            Preferences.Set(Definition.PrimaryColorKey, PrimaryColor);
 | 
			
		||||
            //Light.Instance.RefreshColor(Color.FromHex(color));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private async void OnShareCommand()
 | 
			
		||||
@@ -61,7 +69,7 @@ namespace Billing.Views
 | 
			
		||||
            {
 | 
			
		||||
                await Share.RequestAsync(new ShareFileRequest
 | 
			
		||||
                {
 | 
			
		||||
                    File = new ShareFile(StoreHelper.DatabasePath)
 | 
			
		||||
                    File = new ShareFile(StoreHelper.DatabasePath, "application/vnd.sqlite3")
 | 
			
		||||
                });
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
@@ -84,6 +92,67 @@ namespace Billing.Views
 | 
			
		||||
            if (o is Color color)
 | 
			
		||||
            {
 | 
			
		||||
                PrimaryColor = Helper.WrapColorString(color.ToHex());
 | 
			
		||||
                Light.Instance.RefreshColor(color);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private async void OnShareLogsCommand()
 | 
			
		||||
        {
 | 
			
		||||
            if (Tap.IsBusy)
 | 
			
		||||
            {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            using (Tap.Start())
 | 
			
		||||
            {
 | 
			
		||||
                string file;
 | 
			
		||||
                var count = await StoreHelper.GetLogsCount();
 | 
			
		||||
                if (count > 0)
 | 
			
		||||
                {
 | 
			
		||||
                    file = await StoreHelper.ExportLogs();
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    file = StoreHelper.GetLogFile();
 | 
			
		||||
                }
 | 
			
		||||
                if (file != null && File.Exists(file))
 | 
			
		||||
                {
 | 
			
		||||
#if __IOS__
 | 
			
		||||
                    var sendEmail = Resource.SendEmail;
 | 
			
		||||
                    var shareLogs = Resource.ShareLogs;
 | 
			
		||||
                    var result = await DisplayActionSheet(Resource.HowToShareDiagnostic, Resource.Cancel, null, sendEmail, shareLogs);
 | 
			
		||||
                    if (result == sendEmail)
 | 
			
		||||
                    {
 | 
			
		||||
                        try
 | 
			
		||||
                        {
 | 
			
		||||
                            await Email.ComposeAsync(new EmailMessage
 | 
			
		||||
                            {
 | 
			
		||||
                                To = { "tsorgy@gmail.com " },
 | 
			
		||||
                                Subject = Resource.ShareLogs,
 | 
			
		||||
                                Attachments =
 | 
			
		||||
                                {
 | 
			
		||||
                                    new(file, "text/csv")
 | 
			
		||||
                                }
 | 
			
		||||
                            });
 | 
			
		||||
                        }
 | 
			
		||||
                        catch (System.Exception ex)
 | 
			
		||||
                        {
 | 
			
		||||
                            Helper.Error("email.send", ex);
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                    else if (result == shareLogs)
 | 
			
		||||
                    {
 | 
			
		||||
                        await Share.RequestAsync(new ShareFileRequest
 | 
			
		||||
                        {
 | 
			
		||||
                            File = new ShareFile(file, "text/csv")
 | 
			
		||||
                        });
 | 
			
		||||
                    }
 | 
			
		||||
#else
 | 
			
		||||
                    await Share.RequestAsync(new ShareFileRequest
 | 
			
		||||
                    {
 | 
			
		||||
                        File = new ShareFile(file, "text/csv")
 | 
			
		||||
                    });
 | 
			
		||||
#endif
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										26
									
								
								Billing.sln
									
									
									
									
									
								
							
							
						
						@@ -9,7 +9,7 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Billing.iOS", "Billing\Bill
 | 
			
		||||
EndProject
 | 
			
		||||
Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "Billing.Shared", "Billing.Shared\Billing.Shared.shproj", "{6AC75D01-70D6-4A07-8685-BC52AFD97A7A}"
 | 
			
		||||
EndProject
 | 
			
		||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Svg2Png", "Svg2Png\Svg2Png.csproj", "{6A012FCA-3B1C-4593-ADD7-0751E5815C67}"
 | 
			
		||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Svg2Png", "Svg2Png\Svg2Png.csproj", "{43BB5B21-61E0-42BB-ADF1-DBCD662E61E1}"
 | 
			
		||||
EndProject
 | 
			
		||||
Global
 | 
			
		||||
	GlobalSection(SharedMSBuildProjectFiles) = preSolution
 | 
			
		||||
@@ -62,18 +62,18 @@ Global
 | 
			
		||||
		{5C4F1C35-6F66-4063-9605-A9F37FCABBA8}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator
 | 
			
		||||
		{5C4F1C35-6F66-4063-9605-A9F37FCABBA8}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator
 | 
			
		||||
		{5C4F1C35-6F66-4063-9605-A9F37FCABBA8}.Release|iPhoneSimulator.Deploy.0 = Release|iPhoneSimulator
 | 
			
		||||
		{6A012FCA-3B1C-4593-ADD7-0751E5815C67}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 | 
			
		||||
		{6A012FCA-3B1C-4593-ADD7-0751E5815C67}.Debug|Any CPU.Build.0 = Debug|Any CPU
 | 
			
		||||
		{6A012FCA-3B1C-4593-ADD7-0751E5815C67}.Debug|iPhone.ActiveCfg = Debug|Any CPU
 | 
			
		||||
		{6A012FCA-3B1C-4593-ADD7-0751E5815C67}.Debug|iPhone.Build.0 = Debug|Any CPU
 | 
			
		||||
		{6A012FCA-3B1C-4593-ADD7-0751E5815C67}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
 | 
			
		||||
		{6A012FCA-3B1C-4593-ADD7-0751E5815C67}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
 | 
			
		||||
		{6A012FCA-3B1C-4593-ADD7-0751E5815C67}.Release|Any CPU.ActiveCfg = Release|Any CPU
 | 
			
		||||
		{6A012FCA-3B1C-4593-ADD7-0751E5815C67}.Release|Any CPU.Build.0 = Release|Any CPU
 | 
			
		||||
		{6A012FCA-3B1C-4593-ADD7-0751E5815C67}.Release|iPhone.ActiveCfg = Release|Any CPU
 | 
			
		||||
		{6A012FCA-3B1C-4593-ADD7-0751E5815C67}.Release|iPhone.Build.0 = Release|Any CPU
 | 
			
		||||
		{6A012FCA-3B1C-4593-ADD7-0751E5815C67}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
 | 
			
		||||
		{6A012FCA-3B1C-4593-ADD7-0751E5815C67}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
 | 
			
		||||
		{43BB5B21-61E0-42BB-ADF1-DBCD662E61E1}.Debug|Any CPU.ActiveCfg = Debug|iPhoneSimulator
 | 
			
		||||
		{43BB5B21-61E0-42BB-ADF1-DBCD662E61E1}.Debug|Any CPU.Build.0 = Debug|iPhoneSimulator
 | 
			
		||||
		{43BB5B21-61E0-42BB-ADF1-DBCD662E61E1}.Debug|iPhone.ActiveCfg = Debug|iPhoneSimulator
 | 
			
		||||
		{43BB5B21-61E0-42BB-ADF1-DBCD662E61E1}.Debug|iPhone.Build.0 = Debug|iPhoneSimulator
 | 
			
		||||
		{43BB5B21-61E0-42BB-ADF1-DBCD662E61E1}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator
 | 
			
		||||
		{43BB5B21-61E0-42BB-ADF1-DBCD662E61E1}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator
 | 
			
		||||
		{43BB5B21-61E0-42BB-ADF1-DBCD662E61E1}.Release|Any CPU.ActiveCfg = Release|iPhoneSimulator
 | 
			
		||||
		{43BB5B21-61E0-42BB-ADF1-DBCD662E61E1}.Release|Any CPU.Build.0 = Release|iPhoneSimulator
 | 
			
		||||
		{43BB5B21-61E0-42BB-ADF1-DBCD662E61E1}.Release|iPhone.ActiveCfg = Release|iPhoneSimulator
 | 
			
		||||
		{43BB5B21-61E0-42BB-ADF1-DBCD662E61E1}.Release|iPhone.Build.0 = Release|iPhoneSimulator
 | 
			
		||||
		{43BB5B21-61E0-42BB-ADF1-DBCD662E61E1}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator
 | 
			
		||||
		{43BB5B21-61E0-42BB-ADF1-DBCD662E61E1}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator
 | 
			
		||||
	EndGlobalSection
 | 
			
		||||
	GlobalSection(SolutionProperties) = preSolution
 | 
			
		||||
		HideSolutionNode = FALSE
 | 
			
		||||
 
 | 
			
		||||
@@ -153,6 +153,22 @@
 | 
			
		||||
      <SubType></SubType>
 | 
			
		||||
      <Generator></Generator>
 | 
			
		||||
    </AndroidResource>
 | 
			
		||||
    <AndroidResource Include="Resources\drawable\share.png">
 | 
			
		||||
      <SubType></SubType>
 | 
			
		||||
      <Generator></Generator>
 | 
			
		||||
    </AndroidResource>
 | 
			
		||||
    <AndroidResource Include="Resources\drawable-mdpi\share.png">
 | 
			
		||||
      <SubType></SubType>
 | 
			
		||||
      <Generator></Generator>
 | 
			
		||||
    </AndroidResource>
 | 
			
		||||
    <AndroidResource Include="Resources\drawable-xhdpi\share.png">
 | 
			
		||||
      <SubType></SubType>
 | 
			
		||||
      <Generator></Generator>
 | 
			
		||||
    </AndroidResource>
 | 
			
		||||
    <AndroidResource Include="Resources\drawable-xxhdpi\share.png">
 | 
			
		||||
      <SubType></SubType>
 | 
			
		||||
      <Generator></Generator>
 | 
			
		||||
    </AndroidResource>
 | 
			
		||||
  </ItemGroup>
 | 
			
		||||
  <ItemGroup>
 | 
			
		||||
    <AndroidResource Include="Resources\drawable\splash_logo.png" />
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,12 @@
 | 
			
		||||
<?xml version="1.0" encoding="utf-8"?>
 | 
			
		||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionName="1.0.312" package="org.tsanie.billing" android:installLocation="auto" android:versionCode="12">
 | 
			
		||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionName="1.1.315" package="org.tsanie.billing" android:installLocation="auto" android:versionCode="13">
 | 
			
		||||
	<uses-sdk android:minSdkVersion="24" android:targetSdkVersion="30" />
 | 
			
		||||
	<application android:label="@string/applabel" android:theme="@style/MainTheme"></application>
 | 
			
		||||
	<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
 | 
			
		||||
	<queries>
 | 
			
		||||
		<intent>
 | 
			
		||||
			<action android:name="android.intent.action.SENDTO" />
 | 
			
		||||
			<data android:scheme="mailto" />
 | 
			
		||||
		</intent>
 | 
			
		||||
	</queries>
 | 
			
		||||
</manifest>
 | 
			
		||||
@@ -19282,37 +19282,40 @@ namespace Billing.Droid
 | 
			
		||||
			public const int settings = 2131165368;
 | 
			
		||||
			
 | 
			
		||||
			// aapt resource value: 0x7F0700B9
 | 
			
		||||
			public const int splash_logo = 2131165369;
 | 
			
		||||
			public const int share = 2131165369;
 | 
			
		||||
			
 | 
			
		||||
			// aapt resource value: 0x7F0700BA
 | 
			
		||||
			public const int splash_screen = 2131165370;
 | 
			
		||||
			public const int splash_logo = 2131165370;
 | 
			
		||||
			
 | 
			
		||||
			// aapt resource value: 0x7F0700BB
 | 
			
		||||
			public const int taxi = 2131165371;
 | 
			
		||||
			public const int splash_screen = 2131165371;
 | 
			
		||||
			
 | 
			
		||||
			// aapt resource value: 0x7F0700BC
 | 
			
		||||
			public const int test_custom_background = 2131165372;
 | 
			
		||||
			public const int taxi = 2131165372;
 | 
			
		||||
			
 | 
			
		||||
			// aapt resource value: 0x7F0700BD
 | 
			
		||||
			public const int tooltip_frame_dark = 2131165373;
 | 
			
		||||
			public const int test_custom_background = 2131165373;
 | 
			
		||||
			
 | 
			
		||||
			// aapt resource value: 0x7F0700BE
 | 
			
		||||
			public const int tooltip_frame_light = 2131165374;
 | 
			
		||||
			public const int tooltip_frame_dark = 2131165374;
 | 
			
		||||
			
 | 
			
		||||
			// aapt resource value: 0x7F0700BF
 | 
			
		||||
			public const int trans = 2131165375;
 | 
			
		||||
			public const int tooltip_frame_light = 2131165375;
 | 
			
		||||
			
 | 
			
		||||
			// aapt resource value: 0x7F0700C0
 | 
			
		||||
			public const int wallet = 2131165376;
 | 
			
		||||
			public const int trans = 2131165376;
 | 
			
		||||
			
 | 
			
		||||
			// aapt resource value: 0x7F0700C1
 | 
			
		||||
			public const int yuan = 2131165377;
 | 
			
		||||
			public const int wallet = 2131165377;
 | 
			
		||||
			
 | 
			
		||||
			// aapt resource value: 0x7F0700C2
 | 
			
		||||
			public const int yuebao = 2131165378;
 | 
			
		||||
			public const int yuan = 2131165378;
 | 
			
		||||
			
 | 
			
		||||
			// aapt resource value: 0x7F0700C3
 | 
			
		||||
			public const int zhaozhaoying = 2131165379;
 | 
			
		||||
			public const int yuebao = 2131165379;
 | 
			
		||||
			
 | 
			
		||||
			// aapt resource value: 0x7F0700C4
 | 
			
		||||
			public const int zhaozhaoying = 2131165380;
 | 
			
		||||
			
 | 
			
		||||
			static Drawable()
 | 
			
		||||
			{
 | 
			
		||||
 
 | 
			
		||||
| 
		 Before Width: | Height: | Size: 508 B After Width: | Height: | Size: 540 B  | 
							
								
								
									
										
											BIN
										
									
								
								Billing/Billing.Android/Resources/drawable-mdpi/share.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 403 B  | 
| 
		 Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								Billing/Billing.Android/Resources/drawable-xhdpi/share.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 774 B  | 
| 
		 Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.0 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								Billing/Billing.Android/Resources/drawable-xxhdpi/share.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 1.4 KiB  | 
| 
		 Before Width: | Height: | Size: 975 B After Width: | Height: | Size: 975 B  | 
							
								
								
									
										
											BIN
										
									
								
								Billing/Billing.Android/Resources/drawable/share.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 647 B  | 
@@ -1,5 +1,6 @@
 | 
			
		||||
using Foundation;
 | 
			
		||||
using UIKit;
 | 
			
		||||
using Xamarin.Essentials;
 | 
			
		||||
 | 
			
		||||
namespace Billing.iOS
 | 
			
		||||
{
 | 
			
		||||
 
 | 
			
		||||
@@ -95,6 +95,9 @@
 | 
			
		||||
    <Compile Include="Renderers\BlurryPanelRenderer.cs" />
 | 
			
		||||
    <Compile Include="Renderers\SegmentedControlRenderer.cs" />
 | 
			
		||||
    <Compile Include="Renderers\OptionPickerRenderer.cs" />
 | 
			
		||||
    <BundleResource Include="Resources\share.png" />
 | 
			
		||||
    <BundleResource Include="Resources\share%402x.png" />
 | 
			
		||||
    <BundleResource Include="Resources\share%403x.png" />
 | 
			
		||||
  </ItemGroup>
 | 
			
		||||
  <ItemGroup>
 | 
			
		||||
    <ImageAsset Include="Assets.xcassets\AppIcon.appiconset\Contents.json">
 | 
			
		||||
 
 | 
			
		||||
@@ -59,10 +59,14 @@
 | 
			
		||||
		</dict>
 | 
			
		||||
	</array>
 | 
			
		||||
	<key>CFBundleVersion</key>
 | 
			
		||||
	<string>12</string>
 | 
			
		||||
	<string>13</string>
 | 
			
		||||
	<key>CFBundleShortVersionString</key>
 | 
			
		||||
	<string>1.0.312</string>
 | 
			
		||||
	<string>1.1.315</string>
 | 
			
		||||
	<key>LSSupportsOpeningDocumentsInPlace</key>
 | 
			
		||||
	<true/>
 | 
			
		||||
	<key>LSApplicationQueriesSchemes</key>
 | 
			
		||||
	<array>
 | 
			
		||||
		<string>mailto</string>
 | 
			
		||||
	</array>
 | 
			
		||||
</dict>
 | 
			
		||||
</plist>
 | 
			
		||||
 
 | 
			
		||||
| 
		 Before Width: | Height: | Size: 508 B After Width: | Height: | Size: 540 B  | 
| 
		 Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB  | 
| 
		 Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.0 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								Billing/Billing.iOS/Resources/share.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 403 B  | 
							
								
								
									
										
											BIN
										
									
								
								Billing/Billing.iOS/Resources/share@2x.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 774 B  | 
							
								
								
									
										
											BIN
										
									
								
								Billing/Billing.iOS/Resources/share@3x.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 1.4 KiB  |