From 589c7514f23957e9df3a1b3304d6e19a1ce4004e Mon Sep 17 00:00:00 2001 From: Tsanie Lily Date: Mon, 28 Feb 2022 17:32:40 +0800 Subject: [PATCH] add account page detail --- Billing.Shared/Billing.Shared.projitems | 12 +- Billing.Shared/Models/Account.cs | 3 + Billing.Shared/UI/BillingDate.xaml.cs | 26 +-- Billing.Shared/UI/GroupStackLayout.cs | 159 ++++++++++++++++++ Billing.Shared/UI/ItemSelectPage.cs | 51 ++++++ Billing.Shared/UI/OptionsCells.cs | 1 - Billing.Shared/Views/AccountPage.xaml | 19 ++- Billing.Shared/Views/AccountPage.xaml.cs | 32 +++- Billing.Shared/Views/AddAccountPage.xaml | 29 ++-- Billing.Shared/Views/AddAccountPage.xaml.cs | 31 ++-- .../Resources/drawable-mdpi/creditcard.png | Bin 0 -> 339 bytes .../Resources/drawable-xhdpi/creditcard.png | Bin 0 -> 462 bytes .../Resources/drawable-xxhdpi/creditcard.png | Bin 0 -> 858 bytes .../Resources/drawable/creditcard.png | Bin 0 -> 491 bytes Billing/Billing.iOS/Resources/creditcard.png | Bin 0 -> 339 bytes .../Billing.iOS/Resources/creditcard@2x.png | Bin 0 -> 462 bytes .../Billing.iOS/Resources/creditcard@3x.png | Bin 0 -> 858 bytes 17 files changed, 307 insertions(+), 56 deletions(-) create mode 100644 Billing.Shared/UI/GroupStackLayout.cs create mode 100644 Billing.Shared/UI/ItemSelectPage.cs create mode 100644 Billing/Billing.Android/Resources/drawable-mdpi/creditcard.png create mode 100644 Billing/Billing.Android/Resources/drawable-xhdpi/creditcard.png create mode 100644 Billing/Billing.Android/Resources/drawable-xxhdpi/creditcard.png create mode 100644 Billing/Billing.Android/Resources/drawable/creditcard.png create mode 100644 Billing/Billing.iOS/Resources/creditcard.png create mode 100644 Billing/Billing.iOS/Resources/creditcard@2x.png create mode 100644 Billing/Billing.iOS/Resources/creditcard@3x.png diff --git a/Billing.Shared/Billing.Shared.projitems b/Billing.Shared/Billing.Shared.projitems index cab1ba6..a25db1d 100644 --- a/Billing.Shared/Billing.Shared.projitems +++ b/Billing.Shared/Billing.Shared.projitems @@ -36,12 +36,13 @@ + + AccountPage.xaml AddAccountPage.xaml - Code AddBillPage.xaml @@ -67,6 +68,10 @@ Designer MSBuild:UpdateDesignTimeXaml + + Designer + MSBuild:UpdateDesignTimeXaml + Designer MSBuild:UpdateDesignTimeXaml @@ -80,9 +85,4 @@ MSBuild:UpdateDesignTimeXaml - - - MSBuild:UpdateDesignTimeXaml - - \ No newline at end of file diff --git a/Billing.Shared/Models/Account.cs b/Billing.Shared/Models/Account.cs index bc2a069..3dadad5 100644 --- a/Billing.Shared/Models/Account.cs +++ b/Billing.Shared/Models/Account.cs @@ -8,6 +8,7 @@ namespace Billing.Models public string Icon { get; set; } = ICON_DEFAULT; public AccountCategory Category { get; set; } public string Name { get; set; } + public decimal Initial { get; set; } public decimal Balance { get; set; } public string Memo { get; set; } @@ -17,6 +18,7 @@ namespace Billing.Models Icon = Read(node, nameof(Icon), ICON_DEFAULT); Category = (AccountCategory)Read(node, nameof(Category), 0); Name = Read(node, nameof(Name), string.Empty); + Initial = Read(node, nameof(Initial), 0m); Balance = Read(node, nameof(Balance), 0m); Memo = Read(node, nameof(Memo), null); } @@ -27,6 +29,7 @@ namespace Billing.Models Write(node, nameof(Icon), Icon); Write(node, nameof(Category), (int)Category); Write(node, nameof(Name), Name); + Write(node, nameof(Initial), Initial); Write(node, nameof(Balance), Balance); Write(node, nameof(Memo), Memo); } diff --git a/Billing.Shared/UI/BillingDate.xaml.cs b/Billing.Shared/UI/BillingDate.xaml.cs index e205c79..a87ed25 100644 --- a/Billing.Shared/UI/BillingDate.xaml.cs +++ b/Billing.Shared/UI/BillingDate.xaml.cs @@ -7,13 +7,13 @@ namespace Billing.UI { #region UI Properties - private static readonly BindableProperty SundayProperty = BindableProperty.Create(nameof(Sunday), typeof(BillingDay), typeof(BillingDate)); - private static readonly BindableProperty MondayProperty = BindableProperty.Create(nameof(Monday), typeof(BillingDay), typeof(BillingDate)); - private static readonly BindableProperty TuesdayProperty = BindableProperty.Create(nameof(Tuesday), typeof(BillingDay), typeof(BillingDate)); - private static readonly BindableProperty WednesdayProperty = BindableProperty.Create(nameof(Wednesday), typeof(BillingDay), typeof(BillingDate)); - private static readonly BindableProperty ThursdayProperty = BindableProperty.Create(nameof(Thursday), typeof(BillingDay), typeof(BillingDate)); - private static readonly BindableProperty FridayProperty = BindableProperty.Create(nameof(Friday), typeof(BillingDay), typeof(BillingDate)); - private static readonly BindableProperty SaturdayProperty = BindableProperty.Create(nameof(Saturday), typeof(BillingDay), typeof(BillingDate)); + public static readonly BindableProperty SundayProperty = BindableProperty.Create(nameof(Sunday), typeof(BillingDay), typeof(BillingDate)); + public static readonly BindableProperty MondayProperty = BindableProperty.Create(nameof(Monday), typeof(BillingDay), typeof(BillingDate)); + public static readonly BindableProperty TuesdayProperty = BindableProperty.Create(nameof(Tuesday), typeof(BillingDay), typeof(BillingDate)); + public static readonly BindableProperty WednesdayProperty = BindableProperty.Create(nameof(Wednesday), typeof(BillingDay), typeof(BillingDate)); + public static readonly BindableProperty ThursdayProperty = BindableProperty.Create(nameof(Thursday), typeof(BillingDay), typeof(BillingDate)); + public static readonly BindableProperty FridayProperty = BindableProperty.Create(nameof(Friday), typeof(BillingDay), typeof(BillingDate)); + public static readonly BindableProperty SaturdayProperty = BindableProperty.Create(nameof(Saturday), typeof(BillingDay), typeof(BillingDate)); public BillingDay Sunday => (BillingDay)GetValue(SundayProperty); public BillingDay Monday => (BillingDay)GetValue(MondayProperty); @@ -219,12 +219,12 @@ namespace Billing.UI public class BillingDay : BindableObject { - private static readonly BindableProperty DateProperty = BindableProperty.Create(nameof(Date), typeof(DateTime), typeof(BillingDay), propertyChanged: OnDatePropertyChanged); - private static readonly BindableProperty TextProperty = BindableProperty.Create(nameof(Text), typeof(string), typeof(BillingDay)); - private static readonly BindableProperty FontFamilyProperty = BindableProperty.Create(nameof(FontFamily), typeof(string), typeof(BillingDay), defaultValue: Definition.GetCascadiaRegularFontFamily()); - private static readonly BindableProperty IsSelectedProperty = BindableProperty.Create(nameof(IsSelected), typeof(bool), typeof(BillingDay)); - private static readonly BindableProperty OpacityProperty = BindableProperty.Create(nameof(Opacity), typeof(double), typeof(BillingDay), defaultValue: 1.0); - private static readonly BindableProperty TextOpacityProperty = BindableProperty.Create(nameof(TextOpacity), typeof(double), typeof(BillingDay), defaultValue: 1.0); + public static readonly BindableProperty DateProperty = BindableProperty.Create(nameof(Date), typeof(DateTime), typeof(BillingDay), propertyChanged: OnDatePropertyChanged); + public static readonly BindableProperty TextProperty = BindableProperty.Create(nameof(Text), typeof(string), typeof(BillingDay)); + public static readonly BindableProperty FontFamilyProperty = BindableProperty.Create(nameof(FontFamily), typeof(string), typeof(BillingDay), defaultValue: Definition.GetCascadiaRegularFontFamily()); + public static readonly BindableProperty IsSelectedProperty = BindableProperty.Create(nameof(IsSelected), typeof(bool), typeof(BillingDay)); + public static readonly BindableProperty OpacityProperty = BindableProperty.Create(nameof(Opacity), typeof(double), typeof(BillingDay), defaultValue: 1.0); + public static readonly BindableProperty TextOpacityProperty = BindableProperty.Create(nameof(TextOpacity), typeof(double), typeof(BillingDay), defaultValue: 1.0); private static void OnDatePropertyChanged(BindableObject obj, object old, object @new) { diff --git a/Billing.Shared/UI/GroupStackLayout.cs b/Billing.Shared/UI/GroupStackLayout.cs new file mode 100644 index 0000000..0ae2020 --- /dev/null +++ b/Billing.Shared/UI/GroupStackLayout.cs @@ -0,0 +1,159 @@ +using System.Collections; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.Linq; +using Xamarin.Forms; + +namespace Billing.UI +{ + public class GroupStackLayout : Layout + { + public static readonly BindableProperty GroupHeaderTemplateProperty = BindableProperty.Create(nameof(GroupHeaderTemplate), typeof(DataTemplate), typeof(GroupStackLayout)); + public static readonly BindableProperty ItemTemplateProperty = BindableProperty.Create(nameof(ItemTemplate), typeof(DataTemplate), typeof(GroupStackLayout)); + public static readonly BindableProperty ItemsSourceProperty = BindableProperty.Create(nameof(ItemsSource), typeof(IList), typeof(GroupStackLayout), propertyChanged: OnItemsSourcePropertyChanged); + public static readonly BindableProperty SpacingProperty = BindableProperty.Create(nameof(Spacing), typeof(double), typeof(GroupStackLayout), defaultValue: 4d); + + public DataTemplate GroupHeaderTemplate + { + get => (DataTemplate)GetValue(GroupHeaderTemplateProperty); + set => SetValue(GroupHeaderTemplateProperty, value); + } + public DataTemplate ItemTemplate + { + get => (DataTemplate)GetValue(ItemTemplateProperty); + set => SetValue(ItemTemplateProperty, value); + } + public IList ItemsSource + { + get => (IList)GetValue(ItemsSourceProperty); + set => SetValue(ItemsSourceProperty, value); + } + public double Spacing + { + get => (double)GetValue(SpacingProperty); + set => SetValue(SpacingProperty, value); + } + + private static void OnItemsSourcePropertyChanged(BindableObject obj, object old, object @new) + { + var stack = (GroupStackLayout)obj; + stack.lastWidth = -1; + if (@new == null) + { + stack.cachedLayout.Clear(); + stack.Children.Clear(); + stack.InvalidateLayout(); + } + else if (@new is IList list) + { + stack.freezed = true; + stack.cachedLayout.Clear(); + stack.Children.Clear(); + var groupTemplate = stack.GroupHeaderTemplate; + var itemTemplate = stack.ItemTemplate; + for (var i = 0; i < list.Count; i++) + { + var item = list[i]; + if (item is IList sublist) + { + if (groupTemplate != null) + { + var child = groupTemplate.CreateContent(); + if (child is View view) + { + view.BindingContext = item; + stack.Children.Add(view); + } + } + foreach (var it in sublist) + { + var child = itemTemplate.CreateContent(); + if (child is View view) + { + view.BindingContext = it; + stack.Children.Add(view); + } + } + } + else + { + var child = itemTemplate.CreateContent(); + if (child is View view) + { + view.BindingContext = list[i]; + stack.Children.Add(view); + } + } + } + stack.freezed = false; + stack.UpdateChildrenLayout(); + stack.InvalidateLayout(); + } + } + + private readonly Dictionary cachedLayout = new(); + + private bool freezed; + private double lastWidth = -1; + private SizeRequest lastSizeRequest; + + public void Refresh(IList list) + { + OnItemsSourcePropertyChanged(this, null, list); + } + + protected override void LayoutChildren(double x, double y, double width, double height) + { + if (freezed) + { + return; + } + var source = ItemsSource; + if (source == null || source.Count <= 0) + { + return; + } + var spacing = Spacing; + var lastHeight = 0.0; + foreach (var item in Children) + { + var measured = item.Measure(width, height, MeasureFlags.IncludeMargins); + var rect = new Rectangle( + 0, lastHeight, width, + measured.Request.Height); + if (cachedLayout.TryGetValue(item, out var v)) + { + if (v != rect) + { + cachedLayout[item] = rect; + item.Layout(rect); + } + } + else + { + cachedLayout.Add(item, rect); + item.Layout(rect); + } + lastHeight += rect.Height + spacing; + } + } + + protected override SizeRequest OnMeasure(double widthConstraint, double heightConstraint) + { + if (lastWidth == widthConstraint) + { + return lastSizeRequest; + } + lastWidth = widthConstraint; + var spacing = Spacing; + var lastHeight = 0.0; + foreach (var item in Children) + { + var measured = item.Measure(widthConstraint, heightConstraint, MeasureFlags.IncludeMargins); + lastHeight += measured.Request.Height + spacing; + } + lastSizeRequest = new SizeRequest(new Size(widthConstraint, lastHeight)); + return lastSizeRequest; + } + } +} diff --git a/Billing.Shared/UI/ItemSelectPage.cs b/Billing.Shared/UI/ItemSelectPage.cs new file mode 100644 index 0000000..12c7446 --- /dev/null +++ b/Billing.Shared/UI/ItemSelectPage.cs @@ -0,0 +1,51 @@ +using Billing.Themes; +using System.Collections; + +using Xamarin.Forms; + +namespace Billing.UI +{ + public class ItemSelectPage : ContentPage + { + public ItemSelectPage(IList source) + { + Content = new ListView + { + ItemsSource = source, + ItemTemplate = new DataTemplate(() => new StackLayout + { + Orientation = StackOrientation.Horizontal, + Padding = new Thickness(20, 0), + Spacing = 10, + Children = + { + new Image + { + WidthRequest = 22, + HeightRequest = 22, + Aspect = Aspect.AspectFit, + VerticalOptions = LayoutOptions.Center + } + .Binding(Image.SourceProperty, "Icon"), + + new Label + { + VerticalOptions = LayoutOptions.Center, + LineBreakMode = LineBreakMode.TailTruncation + } + .Binding(Label.TextProperty, "Name") + .DynamicResource(Label.TextColorProperty, BaseTheme.TextColor) + } + }) + } + .DynamicResource(BackgroundColorProperty, BaseTheme.WindowBackgroundColor); + } + } + + public class SelectItem + { + public string Icon { get; set; } + public T Value { get; set; } + public string Name { get; set; } + } +} \ No newline at end of file diff --git a/Billing.Shared/UI/OptionsCells.cs b/Billing.Shared/UI/OptionsCells.cs index f84dd11..a71167c 100644 --- a/Billing.Shared/UI/OptionsCells.cs +++ b/Billing.Shared/UI/OptionsCells.cs @@ -4,7 +4,6 @@ using Xamarin.Forms; namespace Billing.UI { - public class OptionEntry : Entry { } public class OptionEditor : Editor { } diff --git a/Billing.Shared/Views/AccountPage.xaml b/Billing.Shared/Views/AccountPage.xaml index 598a4f7..86fb32c 100644 --- a/Billing.Shared/Views/AccountPage.xaml +++ b/Billing.Shared/Views/AccountPage.xaml @@ -13,7 +13,7 @@ - + @@ -42,8 +42,17 @@ Text="{Binding Liability, Converter={StaticResource moneyConverter}}"/> - - + + + + + + + + @@ -56,8 +65,8 @@ - - + + \ No newline at end of file diff --git a/Billing.Shared/Views/AccountPage.xaml.cs b/Billing.Shared/Views/AccountPage.xaml.cs index d965a13..1c843dd 100644 --- a/Billing.Shared/Views/AccountPage.xaml.cs +++ b/Billing.Shared/Views/AccountPage.xaml.cs @@ -1,4 +1,6 @@ +using System.Collections.Generic; using System.Collections.ObjectModel; +using System.Linq; using Billing.Models; using Billing.UI; using Xamarin.Forms; @@ -10,21 +12,21 @@ namespace Billing.Views private static readonly BindableProperty BalanceProperty = BindableProperty.Create(nameof(Balance), typeof(decimal), typeof(AccountPage)); private static readonly BindableProperty AssetProperty = BindableProperty.Create(nameof(Asset), typeof(decimal), typeof(AccountPage)); private static readonly BindableProperty LiabilityProperty = BindableProperty.Create(nameof(Liability), typeof(decimal), typeof(AccountPage)); - private static readonly BindableProperty AccountsProperty = BindableProperty.Create(nameof(Accounts), typeof(ObservableCollection), typeof(AccountPage)); + private static readonly BindableProperty AccountsProperty = BindableProperty.Create(nameof(Accounts), typeof(List), typeof(AccountPage)); public decimal Balance => (decimal)GetValue(BalanceProperty); public decimal Asset => (decimal)GetValue(AssetProperty); public decimal Liability => (decimal)GetValue(LiabilityProperty); - public ObservableCollection Accounts => (ObservableCollection)GetValue(AccountsProperty); + public List Accounts => (List)GetValue(AccountsProperty); public Command AddAccount { get; } - private readonly ObservableCollection accounts; + private readonly List accounts; public AccountPage() { AddAccount = new Command(OnAddAccount); - accounts = new ObservableCollection(); + accounts = new List(); SetValue(AccountsProperty, accounts); InitializeComponent(); @@ -47,7 +49,27 @@ namespace Billing.Views private void AccountChecked(object sender, AccountEventArgs e) { Helper.Debug(e.Account.ToString()); - accounts.Add(e.Account); + var group = accounts.FirstOrDefault(g => g.Key == e.Account.Category); + if (group == null) + { + group = new AccountGrouping(e.Account.Category) + { + e.Account + }; + accounts.Add(group); + } + else + { + group.Add(e.Account); + } + groupLayout.Refresh(accounts); } } + + public class AccountGrouping : List, IGrouping + { + public AccountGrouping(AccountCategory key) : base() => Key = key; + public AccountCategory Key { get; } + public decimal Balance { get; set; } + } } \ No newline at end of file diff --git a/Billing.Shared/Views/AddAccountPage.xaml b/Billing.Shared/Views/AddAccountPage.xaml index 37761d7..07e1dae 100644 --- a/Billing.Shared/Views/AddAccountPage.xaml +++ b/Billing.Shared/Views/AddAccountPage.xaml @@ -13,7 +13,6 @@ - @@ -23,14 +22,16 @@ - - + - @@ -38,20 +39,22 @@ - - + - + Placeholder="{r:Text MemoPlaceholder}"/> diff --git a/Billing.Shared/Views/AddAccountPage.xaml.cs b/Billing.Shared/Views/AddAccountPage.xaml.cs index 6b365ab..87e93a6 100644 --- a/Billing.Shared/Views/AddAccountPage.xaml.cs +++ b/Billing.Shared/Views/AddAccountPage.xaml.cs @@ -1,6 +1,8 @@ -using Billing.Models; +using Billing.Languages; +using Billing.Models; using Billing.UI; using System; +using System.Collections.Generic; using Xamarin.Forms; namespace Billing.Views @@ -69,16 +71,6 @@ namespace Billing.Views InitializeComponent(); } - private void Balance_Unfocused(object sender, FocusEventArgs e) - { - if (sender is OptionEntry entry && decimal.TryParse(entry.Text, out decimal d)) - { - var converter = (MoneyConverter)Resources["moneyConverter"]; - entry.Text = converter.Convert(d, null, null, null)?.ToString(); - //Balance = d; - } - } - private async void OnCheckAccount() { if (Tap.IsBusy) @@ -108,9 +100,22 @@ namespace Billing.Views } - private void OnSelectCategory() + private async void OnSelectCategory() { - + if (Tap.IsBusy) + { + return; + } + using (Tap.Start()) + { + await Navigation.PushAsync(new ItemSelectPage(new List> + { + new() { Icon = "sackdollar", Value = AccountCategory.Cash, Name = Resource.Cash }, + new() { Icon = "creditcard", Value = AccountCategory.CreditCard, Name = Resource.CreditCard }, + new() { Icon = "", Value = AccountCategory.DebitCard, Name = Resource.DebitCard }, + new() { Icon = "", Value = AccountCategory.ElecAccount, Name = Resource.ElecAccount } + })); + } } } diff --git a/Billing/Billing.Android/Resources/drawable-mdpi/creditcard.png b/Billing/Billing.Android/Resources/drawable-mdpi/creditcard.png new file mode 100644 index 0000000000000000000000000000000000000000..948d197a57b7abb0458285728f9e6d26ee61e646 GIT binary patch literal 339 zcmV-Z0j&OsP)aJ9TOVA%Z=F;G%c|7wy7*&LDawFVO=O>3&FSg=MDci!~5X}dJ+#$FOK}+U`le-1yE9&6|YO@Et-*t z0d>IziO5?tGaBPgh*h{TwyvS2oEdNW0QdIefACH&1YP$5{)17Jg@|{GIY>bwph#p! zq4@LwkfP)TxgV)jum!Ci@8lFz ziD-R0^PtyZ2Z6S9wcSl3E+!s(D+IKUc3)fmA?Bm#mzg!}A77mf7kJ~SU-cnnVHW?l zDQ|k%GndZV;d%L;*@pY78?5U;rQYyWVC2}rc>MTRzjAlU8&|Xr)eFmc1Sw~-{-{b}sw88o!*{zovWB!M!Kl&a6KDD0~~&OzA+4 zTc*cS)C0P%Ms5mKNRvGK)Tb|Dnjqr|daEpvdw6&+lmFvI`|&nbM)c*2CpuQusVh{M~P!eQfI=8gD3h&b-6$qw$0A zBR?FK4z?^X$W44_tGA>mWX8;cb_ zc=kSKb_R)iH@EI|uU^0J?+I(Q^|2;(7mFDSLM!e&W|tPKF+O9uFxBv`jMc+Q#e%DZ zSu!o$O9cy#z5JiuA+Trqw1%*tl4;j!|8RDHjuvDnH}cXm3SDQZz{a7Jy8L&(AfxeR zg9gq8Mpct0sb?Qhnmco!t=H6Bz6@VCP1czxR#P><_3>$odrAxo-*=OutME7PryXxX{%s<}OJahL?)71fUqi!Fb_hQe#XCf(^3ZEuQWu1Mpp!Lh9 zhnf>+tB6D#{?9biXodmT1r05^8@FDrdEmZ#H!H*OdLP3iIq{I=nWx{^`ZSvHGQOD1 z!H}?MahzE^kCNawInSG&JWThL6FZ{ytS2@)q|DS*(P#YfRxe-RBL}DQo`RFFW~Zz$ zeCSxyvsRS{dLPW9*6s;=RVGS z*}5Yr|N139ONJ9wd-T5i_J(|BgEBEiAd5ID`YuH!z#jHMD TIdLyAvoLtN`njxgN@xNAac_Rt literal 0 HcmV?d00001 diff --git a/Billing/Billing.Android/Resources/drawable/creditcard.png b/Billing/Billing.Android/Resources/drawable/creditcard.png new file mode 100644 index 0000000000000000000000000000000000000000..e40b05dcf2525dc753b77818169b94b426c093bf GIT binary patch literal 491 zcmVZGrPtSKN1CLFmjM98VXA&B`s3YAb5rFa6CX- zLX{M>sUna7A&{V;2*O^^y%c86E?_5Xkar7z-OQf7^Ucq$2B-i8z*cK3zFY8aSSTbN zX4@{R*?VL!ZhHZLzIV9T+M35q?Xz=SCg=-H;7u5;7lNJRzVp+w9&b32=A;HsA?Uqh zGt^@h5ot_XAd84JgkV&r1i?tk6iD$xel1-B#Fw%qDzP0?iIk~CN+l$`s_m66QHhn9 zN~BamB7c*j{iWI^DGG`KfKfe^D+cov98(d}X8-_GzLp(d!sPmD@#Y5(4tj&Wc02lr z<_;8dR~>hV-}~L6)iT*468Y_*YEA$Ej*b!p_Gdmy;CXgz2@}EQW`1?r?Fi2LH|Vw9 zcx1I~wg6mO-~N_q-cjt5itywGH`r&|i5PpY6?%~^fHzq3bkDR8rdZ9brvkuZkMWa^ zs+P_ECk9JIRnH2&_0Fi-sjJVgUaNDn6wDHw*nh)dNeDQVuKpSvxa9>n?cNtYRO2G? hjGf;i{PT;O6c6m0ozW0y&-efU002ovPDHLkV1hL+)+_)3 literal 0 HcmV?d00001 diff --git a/Billing/Billing.iOS/Resources/creditcard.png b/Billing/Billing.iOS/Resources/creditcard.png new file mode 100644 index 0000000000000000000000000000000000000000..948d197a57b7abb0458285728f9e6d26ee61e646 GIT binary patch literal 339 zcmV-Z0j&OsP)aJ9TOVA%Z=F;G%c|7wy7*&LDawFVO=O>3&FSg=MDci!~5X}dJ+#$FOK}+U`le-1yE9&6|YO@Et-*t z0d>IziO5?tGaBPgh*h{TwyvS2oEdNW0QdIefACH&1YP$5{)17Jg@|{GIY>bwph#p! zq4@LwkfP)TxgV)jum!Ci@8lFz ziD-R0^PtyZ2Z6S9wcSl3E+!s(D+IKUc3)fmA?Bm#mzg!}A77mf7kJ~SU-cnnVHW?l zDQ|k%GndZV;d%L;*@pY78?5U;rQYyWVC2}rc>MTRzjAlU8&|Xr)eFmc1Sw~-{-{b}sw88o!*{zovWB!M!Kl&a6KDD0~~&OzA+4 zTc*cS)C0P%Ms5mKNRvGK)Tb|Dnjqr|daEpvdw6&+lmFvI`|&nbM)c*2CpuQusVh{M~P!eQfI=8gD3h&b-6$qw$0A zBR?FK4z?^X$W44_tGA>mWX8;cb_ zc=kSKb_R)iH@EI|uU^0J?+I(Q^|2;(7mFDSLM!e&W|tPKF+O9uFxBv`jMc+Q#e%DZ zSu!o$O9cy#z5JiuA+Trqw1%*tl4;j!|8RDHjuvDnH}cXm3SDQZz{a7Jy8L&(AfxeR zg9gq8Mpct0sb?Qhnmco!t=H6Bz6@VCP1czxR#P><_3>$odrAxo-*=OutME7PryXxX{%s<}OJahL?)71fUqi!Fb_hQe#XCf(^3ZEuQWu1Mpp!Lh9 zhnf>+tB6D#{?9biXodmT1r05^8@FDrdEmZ#H!H*OdLP3iIq{I=nWx{^`ZSvHGQOD1 z!H}?MahzE^kCNawInSG&JWThL6FZ{ytS2@)q|DS*(P#YfRxe-RBL}DQo`RFFW~Zz$ zeCSxyvsRS{dLPW9*6s;=RVGS z*}5Yr|N139ONJ9wd-T5i_J(|BgEBEiAd5ID`YuH!z#jHMD TIdLyAvoLtN`njxgN@xNAac_Rt literal 0 HcmV?d00001