language version degraded to 9.0
This commit is contained in:
@ -1,289 +1,290 @@
|
||||
using System;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Billing.UI;
|
||||
|
||||
public partial class BillingDate : ContentView
|
||||
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 BillingDay Sunday => (BillingDay)GetValue(SundayProperty);
|
||||
public BillingDay Monday => (BillingDay)GetValue(MondayProperty);
|
||||
public BillingDay Tuesday => (BillingDay)GetValue(TuesdayProperty);
|
||||
public BillingDay Wednesday => (BillingDay)GetValue(WednesdayProperty);
|
||||
public BillingDay Thursday => (BillingDay)GetValue(ThursdayProperty);
|
||||
public BillingDay Friday => (BillingDay)GetValue(FridayProperty);
|
||||
public BillingDay Saturday => (BillingDay)GetValue(SaturdayProperty);
|
||||
|
||||
#endregion
|
||||
|
||||
private static BindableProperty GetWeekProperty(int week)
|
||||
public partial class BillingDate : ContentView
|
||||
{
|
||||
return (DayOfWeek)week switch
|
||||
{
|
||||
DayOfWeek.Monday => MondayProperty,
|
||||
DayOfWeek.Tuesday => TuesdayProperty,
|
||||
DayOfWeek.Wednesday => WednesdayProperty,
|
||||
DayOfWeek.Thursday => ThursdayProperty,
|
||||
DayOfWeek.Friday => FridayProperty,
|
||||
DayOfWeek.Saturday => SaturdayProperty,
|
||||
_ => SundayProperty
|
||||
};
|
||||
}
|
||||
#region UI Properties
|
||||
|
||||
public static readonly BindableProperty LocatedDateProperty = BindableProperty.Create(nameof(LocatedDate), typeof(DateTime), typeof(BillingDate), propertyChanged: OnLocatedDatePropertyChanged);
|
||||
public static readonly BindableProperty SelectedDateProperty = BindableProperty.Create(nameof(SelectedDate), typeof(DateTime), typeof(BillingDate), propertyChanged: OnSelectedDatePropertyChanged);
|
||||
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));
|
||||
|
||||
private static void OnLocatedDatePropertyChanged(BindableObject obj, object old, object @new)
|
||||
{
|
||||
if (obj is BillingDate billingDate && @new is DateTime date)
|
||||
public BillingDay Sunday => (BillingDay)GetValue(SundayProperty);
|
||||
public BillingDay Monday => (BillingDay)GetValue(MondayProperty);
|
||||
public BillingDay Tuesday => (BillingDay)GetValue(TuesdayProperty);
|
||||
public BillingDay Wednesday => (BillingDay)GetValue(WednesdayProperty);
|
||||
public BillingDay Thursday => (BillingDay)GetValue(ThursdayProperty);
|
||||
public BillingDay Friday => (BillingDay)GetValue(FridayProperty);
|
||||
public BillingDay Saturday => (BillingDay)GetValue(SaturdayProperty);
|
||||
|
||||
#endregion
|
||||
|
||||
private static BindableProperty GetWeekProperty(int week)
|
||||
{
|
||||
var week = (int)date.DayOfWeek;
|
||||
var tmpDate = date.AddDays(-week);
|
||||
for (var i = 0; i < 7; i++)
|
||||
return (DayOfWeek)week switch
|
||||
{
|
||||
var prop = GetWeekProperty(i);
|
||||
var day = new BillingDay(tmpDate);
|
||||
billingDate.SetValue(prop, day);
|
||||
tmpDate = tmpDate.AddDays(1);
|
||||
}
|
||||
DayOfWeek.Monday => MondayProperty,
|
||||
DayOfWeek.Tuesday => TuesdayProperty,
|
||||
DayOfWeek.Wednesday => WednesdayProperty,
|
||||
DayOfWeek.Thursday => ThursdayProperty,
|
||||
DayOfWeek.Friday => FridayProperty,
|
||||
DayOfWeek.Saturday => SaturdayProperty,
|
||||
_ => SundayProperty
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private static void OnSelectedDatePropertyChanged(BindableObject obj, object old, object @new)
|
||||
{
|
||||
if (obj is BillingDate billingDate && @new is DateTime selected)
|
||||
public static readonly BindableProperty LocatedDateProperty = BindableProperty.Create(nameof(LocatedDate), typeof(DateTime), typeof(BillingDate), propertyChanged: OnLocatedDatePropertyChanged);
|
||||
public static readonly BindableProperty SelectedDateProperty = BindableProperty.Create(nameof(SelectedDate), typeof(DateTime), typeof(BillingDate), propertyChanged: OnSelectedDatePropertyChanged);
|
||||
|
||||
private static void OnLocatedDatePropertyChanged(BindableObject obj, object old, object @new)
|
||||
{
|
||||
for (var i = 0; i < 7; i++)
|
||||
if (obj is BillingDate billingDate && @new is DateTime date)
|
||||
{
|
||||
var prop = GetWeekProperty(i);
|
||||
var day = (BillingDay)billingDate.GetValue(prop);
|
||||
day.Refresh(selected);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public DateTime LocatedDate
|
||||
{
|
||||
get => (DateTime)GetValue(LocatedDateProperty);
|
||||
set => SetValue(LocatedDateProperty, value);
|
||||
}
|
||||
public DateTime SelectedDate
|
||||
{
|
||||
get => (DateTime)GetValue(SelectedDateProperty);
|
||||
set => SetValue(SelectedDateProperty, value);
|
||||
}
|
||||
|
||||
public Command OnDayTapped { get; }
|
||||
|
||||
public event EventHandler<DateEventArgs> DateSelected;
|
||||
|
||||
private DateTime lastDate;
|
||||
private double? x1;
|
||||
private double x2;
|
||||
|
||||
public BillingDate()
|
||||
{
|
||||
OnDayTapped = new Command(OnDayChanged);
|
||||
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
public void SetDateTime(DateTime selectedDate, DateTime? locatedDate = null)
|
||||
{
|
||||
if (locatedDate != null)
|
||||
{
|
||||
LocatedDate = locatedDate.Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
LocatedDate = selectedDate;
|
||||
}
|
||||
SelectedDate = selectedDate;
|
||||
DateSelected?.Invoke(this, new DateEventArgs(selectedDate));
|
||||
}
|
||||
|
||||
private void OnDayChanged(object o)
|
||||
{
|
||||
var selected = SelectedDate;
|
||||
if (o is BillingDay day && (selected.Year != day.Date.Year || selected.DayOfYear != day.Date.DayOfYear))
|
||||
{
|
||||
for (var i = 0; i < 7; i++)
|
||||
{
|
||||
var d = (BillingDay)GetValue(GetWeekProperty(i));
|
||||
if (d.IsSelected)
|
||||
var week = (int)date.DayOfWeek;
|
||||
var tmpDate = date.AddDays(-week);
|
||||
for (var i = 0; i < 7; i++)
|
||||
{
|
||||
this.AbortAnimation("unselected");
|
||||
this.Animate("unselected", v =>
|
||||
{
|
||||
d.Opacity = v;
|
||||
},
|
||||
start: 1, end: 0,
|
||||
easing: Easing.CubicOut,
|
||||
finished: (v, b) =>
|
||||
{
|
||||
d.Opacity = 0;
|
||||
d.IsSelected = false;
|
||||
});
|
||||
var prop = GetWeekProperty(i);
|
||||
var day = new BillingDay(tmpDate);
|
||||
billingDate.SetValue(prop, day);
|
||||
tmpDate = tmpDate.AddDays(1);
|
||||
}
|
||||
}
|
||||
SelectedDate = day.Date;
|
||||
this.AbortAnimation("selected");
|
||||
this.Animate("selected", v =>
|
||||
{
|
||||
day.Opacity = v;
|
||||
},
|
||||
start: 0, end: 1,
|
||||
easing: Easing.CubicOut,
|
||||
finished: (v, b) =>
|
||||
{
|
||||
day.Opacity = 1;
|
||||
});
|
||||
DateSelected?.Invoke(this, new DateEventArgs(day.Date));
|
||||
}
|
||||
}
|
||||
|
||||
private void OnPanUpdated(object sender, PanUpdatedEventArgs e)
|
||||
{
|
||||
if (e.StatusType == GestureStatus.Started)
|
||||
private static void OnSelectedDatePropertyChanged(BindableObject obj, object old, object @new)
|
||||
{
|
||||
lastDate = DateTime.Now;
|
||||
x1 = null;
|
||||
if (obj is BillingDate billingDate && @new is DateTime selected)
|
||||
{
|
||||
for (var i = 0; i < 7; i++)
|
||||
{
|
||||
var prop = GetWeekProperty(i);
|
||||
var day = (BillingDay)billingDate.GetValue(prop);
|
||||
day.Refresh(selected);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (e.StatusType == GestureStatus.Running)
|
||||
|
||||
public DateTime LocatedDate
|
||||
{
|
||||
if (x1 == null)
|
||||
{
|
||||
x1 = e.TotalX;
|
||||
}
|
||||
x2 = e.TotalX;
|
||||
get => (DateTime)GetValue(LocatedDateProperty);
|
||||
set => SetValue(LocatedDateProperty, value);
|
||||
}
|
||||
else if (e.StatusType == GestureStatus.Completed)
|
||||
public DateTime SelectedDate
|
||||
{
|
||||
if (x1 == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
var totalX = x2 - x1.Value;
|
||||
x1 = null;
|
||||
var ms = (DateTime.Now - lastDate).TotalMilliseconds;
|
||||
var speed = totalX / ms;
|
||||
Helper.Debug($"completed, speed: {speed}");
|
||||
if (speed < -0.7)
|
||||
{
|
||||
LocatedDate = LocatedDate.AddDays(7);
|
||||
}
|
||||
else if (speed > 0.7)
|
||||
{
|
||||
LocatedDate = LocatedDate.AddDays(-7);
|
||||
}
|
||||
OnSelectedDatePropertyChanged(this, null, SelectedDate);
|
||||
get => (DateTime)GetValue(SelectedDateProperty);
|
||||
set => SetValue(SelectedDateProperty, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class DateEventArgs : EventArgs
|
||||
{
|
||||
public DateTime Date { get; }
|
||||
public Command OnDayTapped { get; }
|
||||
|
||||
public DateEventArgs(DateTime date)
|
||||
{
|
||||
Date = date;
|
||||
}
|
||||
}
|
||||
public event EventHandler<DateEventArgs> DateSelected;
|
||||
|
||||
public class BillingDayView : ContentView
|
||||
{
|
||||
public static readonly BindableProperty BillingDayProperty = BindableProperty.Create(nameof(BillingDay), typeof(BillingDay), typeof(BillingDayView));
|
||||
public static readonly BindableProperty CommandProperty = BindableProperty.Create(nameof(Command), typeof(Command), typeof(BillingDayView));
|
||||
private DateTime lastDate;
|
||||
private double? x1;
|
||||
private double x2;
|
||||
|
||||
public BillingDay BillingDay
|
||||
{
|
||||
get => (BillingDay)GetValue(BillingDayProperty);
|
||||
set => SetValue(BillingDayProperty, value);
|
||||
}
|
||||
public Command Command
|
||||
{
|
||||
get => (Command)GetValue(CommandProperty);
|
||||
set => SetValue(CommandProperty, value);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
private static void OnDatePropertyChanged(BindableObject obj, object old, object @new)
|
||||
{
|
||||
if (obj is BillingDay day && @new is DateTime date)
|
||||
public BillingDate()
|
||||
{
|
||||
if (date.Day == 1)
|
||||
OnDayTapped = new Command(OnDayChanged);
|
||||
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
public void SetDateTime(DateTime selectedDate, DateTime? locatedDate = null)
|
||||
{
|
||||
if (locatedDate != null)
|
||||
{
|
||||
day.SetValue(TextProperty, date.ToString("MMM"));
|
||||
LocatedDate = locatedDate.Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
day.SetValue(TextProperty, date.Day.ToString());
|
||||
LocatedDate = selectedDate;
|
||||
}
|
||||
SelectedDate = selectedDate;
|
||||
DateSelected?.Invoke(this, new DateEventArgs(selectedDate));
|
||||
}
|
||||
|
||||
private void OnDayChanged(object o)
|
||||
{
|
||||
var selected = SelectedDate;
|
||||
if (o is BillingDay day && (selected.Year != day.Date.Year || selected.DayOfYear != day.Date.DayOfYear))
|
||||
{
|
||||
for (var i = 0; i < 7; i++)
|
||||
{
|
||||
var d = (BillingDay)GetValue(GetWeekProperty(i));
|
||||
if (d.IsSelected)
|
||||
{
|
||||
this.AbortAnimation("unselected");
|
||||
this.Animate("unselected", v =>
|
||||
{
|
||||
d.Opacity = v;
|
||||
},
|
||||
start: 1, end: 0,
|
||||
easing: Easing.CubicOut,
|
||||
finished: (v, b) =>
|
||||
{
|
||||
d.Opacity = 0;
|
||||
d.IsSelected = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
SelectedDate = day.Date;
|
||||
this.AbortAnimation("selected");
|
||||
this.Animate("selected", v =>
|
||||
{
|
||||
day.Opacity = v;
|
||||
},
|
||||
start: 0, end: 1,
|
||||
easing: Easing.CubicOut,
|
||||
finished: (v, b) =>
|
||||
{
|
||||
day.Opacity = 1;
|
||||
});
|
||||
DateSelected?.Invoke(this, new DateEventArgs(day.Date));
|
||||
}
|
||||
}
|
||||
|
||||
private void OnPanUpdated(object sender, PanUpdatedEventArgs e)
|
||||
{
|
||||
if (e.StatusType == GestureStatus.Started)
|
||||
{
|
||||
lastDate = DateTime.Now;
|
||||
x1 = null;
|
||||
}
|
||||
else if (e.StatusType == GestureStatus.Running)
|
||||
{
|
||||
if (x1 == null)
|
||||
{
|
||||
x1 = e.TotalX;
|
||||
}
|
||||
x2 = e.TotalX;
|
||||
}
|
||||
else if (e.StatusType == GestureStatus.Completed)
|
||||
{
|
||||
if (x1 == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
var totalX = x2 - x1.Value;
|
||||
x1 = null;
|
||||
var ms = (DateTime.Now - lastDate).TotalMilliseconds;
|
||||
var speed = totalX / ms;
|
||||
Helper.Debug($"completed, speed: {speed}");
|
||||
if (speed < -0.7)
|
||||
{
|
||||
LocatedDate = LocatedDate.AddDays(7);
|
||||
}
|
||||
else if (speed > 0.7)
|
||||
{
|
||||
LocatedDate = LocatedDate.AddDays(-7);
|
||||
}
|
||||
OnSelectedDatePropertyChanged(this, null, SelectedDate);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public DateTime Date
|
||||
public class DateEventArgs : EventArgs
|
||||
{
|
||||
get => (DateTime)GetValue(DateProperty);
|
||||
set => SetValue(DateProperty, value);
|
||||
}
|
||||
public string Text => (string)GetValue(TextProperty);
|
||||
public string FontFamily => (string)GetValue(FontFamilyProperty);
|
||||
public bool IsSelected
|
||||
{
|
||||
get => (bool)GetValue(IsSelectedProperty);
|
||||
set => SetValue(IsSelectedProperty, value);
|
||||
}
|
||||
public double Opacity
|
||||
{
|
||||
get => (double)GetValue(OpacityProperty);
|
||||
set => SetValue(OpacityProperty, value);
|
||||
}
|
||||
public double TextOpacity => (double)GetValue(TextOpacityProperty);
|
||||
public DateTime Date { get; }
|
||||
|
||||
public BillingDay(DateTime date)
|
||||
{
|
||||
Date = date;
|
||||
public DateEventArgs(DateTime date)
|
||||
{
|
||||
Date = date;
|
||||
}
|
||||
}
|
||||
|
||||
public void Refresh(DateTime selected)
|
||||
public class BillingDayView : ContentView
|
||||
{
|
||||
var date = Date;
|
||||
if (date.Year == selected.Year && date.DayOfYear == selected.DayOfYear)
|
||||
public static readonly BindableProperty BillingDayProperty = BindableProperty.Create(nameof(BillingDay), typeof(BillingDay), typeof(BillingDayView));
|
||||
public static readonly BindableProperty CommandProperty = BindableProperty.Create(nameof(Command), typeof(Command), typeof(BillingDayView));
|
||||
|
||||
public BillingDay BillingDay
|
||||
{
|
||||
SetValue(IsSelectedProperty, true);
|
||||
SetValue(FontFamilyProperty, Definition.GetCascadiaBoldFontFamily());
|
||||
get => (BillingDay)GetValue(BillingDayProperty);
|
||||
set => SetValue(BillingDayProperty, value);
|
||||
}
|
||||
else
|
||||
public Command Command
|
||||
{
|
||||
SetValue(FontFamilyProperty, Definition.GetCascadiaRegularFontFamily());
|
||||
}
|
||||
if (date.Year == selected.Year && date.Month == selected.Month)
|
||||
{
|
||||
SetValue(TextOpacityProperty, 1.0);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetValue(TextOpacityProperty, .4);
|
||||
get => (Command)GetValue(CommandProperty);
|
||||
set => SetValue(CommandProperty, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
private static void OnDatePropertyChanged(BindableObject obj, object old, object @new)
|
||||
{
|
||||
if (obj is BillingDay day && @new is DateTime date)
|
||||
{
|
||||
if (date.Day == 1)
|
||||
{
|
||||
day.SetValue(TextProperty, date.ToString("MMM"));
|
||||
}
|
||||
else
|
||||
{
|
||||
day.SetValue(TextProperty, date.Day.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public DateTime Date
|
||||
{
|
||||
get => (DateTime)GetValue(DateProperty);
|
||||
set => SetValue(DateProperty, value);
|
||||
}
|
||||
public string Text => (string)GetValue(TextProperty);
|
||||
public string FontFamily => (string)GetValue(FontFamilyProperty);
|
||||
public bool IsSelected
|
||||
{
|
||||
get => (bool)GetValue(IsSelectedProperty);
|
||||
set => SetValue(IsSelectedProperty, value);
|
||||
}
|
||||
public double Opacity
|
||||
{
|
||||
get => (double)GetValue(OpacityProperty);
|
||||
set => SetValue(OpacityProperty, value);
|
||||
}
|
||||
public double TextOpacity => (double)GetValue(TextOpacityProperty);
|
||||
|
||||
public BillingDay(DateTime date)
|
||||
{
|
||||
Date = date;
|
||||
}
|
||||
|
||||
public void Refresh(DateTime selected)
|
||||
{
|
||||
var date = Date;
|
||||
if (date.Year == selected.Year && date.DayOfYear == selected.DayOfYear)
|
||||
{
|
||||
SetValue(IsSelectedProperty, true);
|
||||
SetValue(FontFamilyProperty, Definition.GetCascadiaBoldFontFamily());
|
||||
}
|
||||
else
|
||||
{
|
||||
SetValue(FontFamilyProperty, Definition.GetCascadiaRegularFontFamily());
|
||||
}
|
||||
if (date.Year == selected.Year && date.Month == selected.Month)
|
||||
{
|
||||
SetValue(TextOpacityProperty, 1.0);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetValue(TextOpacityProperty, .4);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,12 +1,13 @@
|
||||
using Billing.Themes;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Billing.UI;
|
||||
|
||||
public abstract class BillingPage : ContentPage
|
||||
namespace Billing.UI
|
||||
{
|
||||
public BillingPage()
|
||||
public abstract class BillingPage : ContentPage
|
||||
{
|
||||
SetDynamicResource(BackgroundColorProperty, BaseTheme.WindowBackgroundColor);
|
||||
public BillingPage()
|
||||
{
|
||||
SetDynamicResource(BackgroundColorProperty, BaseTheme.WindowBackgroundColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -3,38 +3,39 @@ using System;
|
||||
using System.Globalization;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Billing.UI;
|
||||
|
||||
public class TitleDateConverter : IValueConverter
|
||||
namespace Billing.UI
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
public class TitleDateConverter : IValueConverter
|
||||
{
|
||||
if (value is DateTime date)
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
return date.ToString(Resource.TitleDateFormat);
|
||||
if (value is DateTime date)
|
||||
{
|
||||
return date.ToString(Resource.TitleDateFormat);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
public class MoneyConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
if (value is decimal d)
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
return "¥ " + d.ToString("n2", CultureInfo.InvariantCulture);
|
||||
return value;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
public class MoneyConverter : IValueConverter
|
||||
{
|
||||
return value;
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
if (value is decimal d)
|
||||
{
|
||||
return "¥ " + d.ToString("n2", CultureInfo.InvariantCulture);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -2,153 +2,154 @@
|
||||
using System;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Billing.UI;
|
||||
|
||||
public class TintImage : Image
|
||||
namespace Billing.UI
|
||||
{
|
||||
public static readonly BindableProperty PrimaryColorProperty = BindableProperty.Create(nameof(PrimaryColor), typeof(Color?), typeof(TintImage));
|
||||
|
||||
public Color? PrimaryColor
|
||||
public class TintImage : Image
|
||||
{
|
||||
get => (Color?)GetValue(PrimaryColorProperty);
|
||||
set => SetValue(PrimaryColorProperty, value);
|
||||
}
|
||||
}
|
||||
public static readonly BindableProperty PrimaryColorProperty = BindableProperty.Create(nameof(PrimaryColor), typeof(Color?), typeof(TintImage));
|
||||
|
||||
public class LongPressButton : Button
|
||||
{
|
||||
public event EventHandler LongPressed;
|
||||
|
||||
public LongPressButton()
|
||||
{
|
||||
Padding = 0;
|
||||
BackgroundColor = Color.Transparent;
|
||||
}
|
||||
|
||||
public void TriggerLongPress()
|
||||
{
|
||||
LongPressed?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
public class OptionEntry : Entry { }
|
||||
|
||||
public abstract class OptionCell : ViewCell
|
||||
{
|
||||
public static readonly BindableProperty TitleProperty = BindableProperty.Create(nameof(Title), typeof(string), typeof(OptionCell));
|
||||
public static readonly BindableProperty BackgroundColorProperty = BindableProperty.Create(nameof(BackgroundColor), typeof(Color), typeof(OptionCell));
|
||||
|
||||
public string Title
|
||||
{
|
||||
get => (string)GetValue(TitleProperty);
|
||||
set => SetValue(TitleProperty, value);
|
||||
}
|
||||
public Color BackgroundColor
|
||||
{
|
||||
get => (Color)GetValue(BackgroundColorProperty);
|
||||
set => SetValue(BackgroundColorProperty, value);
|
||||
}
|
||||
|
||||
protected abstract View Content { get; }
|
||||
|
||||
public OptionCell()
|
||||
{
|
||||
View = new Grid
|
||||
public Color? PrimaryColor
|
||||
{
|
||||
BindingContext = this,
|
||||
Padding = new Thickness(20, 0),
|
||||
ColumnDefinitions =
|
||||
{
|
||||
new ColumnDefinition { Width = new GridLength(.3, GridUnitType.Star) },
|
||||
new ColumnDefinition { Width = new GridLength(.7, GridUnitType.Star) }
|
||||
},
|
||||
Children =
|
||||
{
|
||||
new Label
|
||||
{
|
||||
LineBreakMode = LineBreakMode.TailTruncation,
|
||||
VerticalOptions = LayoutOptions.Center
|
||||
}
|
||||
.Binding(Label.TextProperty, nameof(Title))
|
||||
.DynamicResource(Label.TextColorProperty, BaseTheme.TextColor),
|
||||
|
||||
Content.GridColumn(1)
|
||||
}
|
||||
get => (Color?)GetValue(PrimaryColorProperty);
|
||||
set => SetValue(PrimaryColorProperty, value);
|
||||
}
|
||||
}
|
||||
|
||||
public class LongPressButton : Button
|
||||
{
|
||||
public event EventHandler LongPressed;
|
||||
|
||||
public LongPressButton()
|
||||
{
|
||||
Padding = 0;
|
||||
BackgroundColor = Color.Transparent;
|
||||
}
|
||||
|
||||
public void TriggerLongPress()
|
||||
{
|
||||
LongPressed?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
public class OptionEntry : Entry { }
|
||||
|
||||
public abstract class OptionCell : ViewCell
|
||||
{
|
||||
public static readonly BindableProperty TitleProperty = BindableProperty.Create(nameof(Title), typeof(string), typeof(OptionCell));
|
||||
public static readonly BindableProperty BackgroundColorProperty = BindableProperty.Create(nameof(BackgroundColor), typeof(Color), typeof(OptionCell));
|
||||
|
||||
public string Title
|
||||
{
|
||||
get => (string)GetValue(TitleProperty);
|
||||
set => SetValue(TitleProperty, value);
|
||||
}
|
||||
public Color BackgroundColor
|
||||
{
|
||||
get => (Color)GetValue(BackgroundColorProperty);
|
||||
set => SetValue(BackgroundColorProperty, value);
|
||||
}
|
||||
|
||||
protected abstract View Content { get; }
|
||||
|
||||
public OptionCell()
|
||||
{
|
||||
View = new Grid
|
||||
{
|
||||
BindingContext = this,
|
||||
Padding = new Thickness(20, 0),
|
||||
ColumnDefinitions =
|
||||
{
|
||||
new ColumnDefinition { Width = new GridLength(.3, GridUnitType.Star) },
|
||||
new ColumnDefinition { Width = new GridLength(.7, GridUnitType.Star) }
|
||||
},
|
||||
Children =
|
||||
{
|
||||
new Label
|
||||
{
|
||||
LineBreakMode = LineBreakMode.TailTruncation,
|
||||
VerticalOptions = LayoutOptions.Center
|
||||
}
|
||||
.Binding(Label.TextProperty, nameof(Title))
|
||||
.DynamicResource(Label.TextColorProperty, BaseTheme.TextColor),
|
||||
|
||||
Content.GridColumn(1)
|
||||
}
|
||||
}
|
||||
.DynamicResource(VisualElement.BackgroundColorProperty, BaseTheme.OptionTintColor);
|
||||
}
|
||||
}
|
||||
|
||||
public class OptionTextCell : OptionCell
|
||||
{
|
||||
public static readonly BindableProperty DetailProperty = BindableProperty.Create(nameof(Detail), typeof(string), typeof(OptionTextCell));
|
||||
|
||||
public string Detail
|
||||
{
|
||||
get => (string)GetValue(DetailProperty);
|
||||
set => SetValue(DetailProperty, value);
|
||||
}
|
||||
|
||||
protected override View Content => new Label
|
||||
{
|
||||
HorizontalOptions = LayoutOptions.End,
|
||||
VerticalOptions = LayoutOptions.Center
|
||||
}
|
||||
.Binding(Label.TextProperty, nameof(Detail))
|
||||
.DynamicResource(Label.TextColorProperty, BaseTheme.SecondaryTextColor);
|
||||
}
|
||||
|
||||
public class OptionSwitchCell : OptionCell
|
||||
{
|
||||
public static readonly BindableProperty IsToggledProperty = BindableProperty.Create(nameof(IsToggled), typeof(bool), typeof(OptionSwitchCell));
|
||||
|
||||
public bool IsToggled
|
||||
{
|
||||
get => (bool)GetValue(IsToggledProperty);
|
||||
set => SetValue(IsToggledProperty, value);
|
||||
}
|
||||
|
||||
protected override View Content => new Switch
|
||||
{
|
||||
HorizontalOptions = LayoutOptions.End,
|
||||
VerticalOptions = LayoutOptions.Center
|
||||
}
|
||||
.Binding(Switch.IsToggledProperty, nameof(IsToggled), BindingMode.TwoWay);
|
||||
}
|
||||
|
||||
public class OptionEntryCell : OptionCell
|
||||
{
|
||||
public static readonly BindableProperty TextProperty = BindableProperty.Create(nameof(Text), typeof(string), typeof(OptionEntryCell));
|
||||
public static readonly BindableProperty KeyboardProperty = BindableProperty.Create(nameof(Keyboard), typeof(Keyboard), typeof(OptionEntryCell));
|
||||
public static readonly BindableProperty PlaceholderProperty = BindableProperty.Create(nameof(Placeholder), typeof(string), typeof(OptionEntryCell));
|
||||
|
||||
public string Text
|
||||
{
|
||||
get => (string)GetValue(TextProperty);
|
||||
set => SetValue(TextProperty, value);
|
||||
}
|
||||
public Keyboard Keyboard
|
||||
{
|
||||
get => (Keyboard)GetValue(KeyboardProperty);
|
||||
set => SetValue(KeyboardProperty, value);
|
||||
}
|
||||
public string Placeholder
|
||||
{
|
||||
get => (string)GetValue(PlaceholderProperty);
|
||||
set => SetValue(PlaceholderProperty, value);
|
||||
}
|
||||
|
||||
protected override View Content => new OptionEntry
|
||||
{
|
||||
HorizontalOptions = LayoutOptions.Fill,
|
||||
HorizontalTextAlignment = TextAlignment.End,
|
||||
VerticalOptions = LayoutOptions.Center,
|
||||
ReturnType = ReturnType.Next
|
||||
}
|
||||
.Binding(Entry.TextProperty, nameof(Text), BindingMode.TwoWay)
|
||||
.Binding(InputView.KeyboardProperty, nameof(Keyboard))
|
||||
.Binding(Entry.PlaceholderProperty, nameof(Placeholder))
|
||||
.DynamicResource(Entry.TextColorProperty, BaseTheme.TextColor)
|
||||
.DynamicResource(Entry.PlaceholderColorProperty, BaseTheme.SecondaryTextColor)
|
||||
.DynamicResource(VisualElement.BackgroundColorProperty, BaseTheme.OptionTintColor);
|
||||
}
|
||||
}
|
||||
|
||||
public class OptionTextCell : OptionCell
|
||||
{
|
||||
public static readonly BindableProperty DetailProperty = BindableProperty.Create(nameof(Detail), typeof(string), typeof(OptionTextCell));
|
||||
|
||||
public string Detail
|
||||
{
|
||||
get => (string)GetValue(DetailProperty);
|
||||
set => SetValue(DetailProperty, value);
|
||||
}
|
||||
|
||||
protected override View Content => new Label
|
||||
{
|
||||
HorizontalOptions = LayoutOptions.End,
|
||||
VerticalOptions = LayoutOptions.Center
|
||||
}
|
||||
.Binding(Label.TextProperty, nameof(Detail))
|
||||
.DynamicResource(Label.TextColorProperty, BaseTheme.SecondaryTextColor);
|
||||
}
|
||||
|
||||
public class OptionSwitchCell : OptionCell
|
||||
{
|
||||
public static readonly BindableProperty IsToggledProperty = BindableProperty.Create(nameof(IsToggled), typeof(bool), typeof(OptionSwitchCell));
|
||||
|
||||
public bool IsToggled
|
||||
{
|
||||
get => (bool)GetValue(IsToggledProperty);
|
||||
set => SetValue(IsToggledProperty, value);
|
||||
}
|
||||
|
||||
protected override View Content => new Switch
|
||||
{
|
||||
HorizontalOptions = LayoutOptions.End,
|
||||
VerticalOptions = LayoutOptions.Center
|
||||
}
|
||||
.Binding(Switch.IsToggledProperty, nameof(IsToggled), BindingMode.TwoWay);
|
||||
}
|
||||
|
||||
public class OptionEntryCell : OptionCell
|
||||
{
|
||||
public static readonly BindableProperty TextProperty = BindableProperty.Create(nameof(Text), typeof(string), typeof(OptionEntryCell));
|
||||
public static readonly BindableProperty KeyboardProperty = BindableProperty.Create(nameof(Keyboard), typeof(Keyboard), typeof(OptionEntryCell));
|
||||
public static readonly BindableProperty PlaceholderProperty = BindableProperty.Create(nameof(Placeholder), typeof(string), typeof(OptionEntryCell));
|
||||
|
||||
public string Text
|
||||
{
|
||||
get => (string)GetValue(TextProperty);
|
||||
set => SetValue(TextProperty, value);
|
||||
}
|
||||
public Keyboard Keyboard
|
||||
{
|
||||
get => (Keyboard)GetValue(KeyboardProperty);
|
||||
set => SetValue(KeyboardProperty, value);
|
||||
}
|
||||
public string Placeholder
|
||||
{
|
||||
get => (string)GetValue(PlaceholderProperty);
|
||||
set => SetValue(PlaceholderProperty, value);
|
||||
}
|
||||
|
||||
protected override View Content => new OptionEntry
|
||||
{
|
||||
HorizontalOptions = LayoutOptions.Fill,
|
||||
HorizontalTextAlignment = TextAlignment.End,
|
||||
VerticalOptions = LayoutOptions.Center,
|
||||
ReturnType = ReturnType.Next
|
||||
}
|
||||
.Binding(Entry.TextProperty, nameof(Text), BindingMode.TwoWay)
|
||||
.Binding(InputView.KeyboardProperty, nameof(Keyboard))
|
||||
.Binding(Entry.PlaceholderProperty, nameof(Placeholder))
|
||||
.DynamicResource(Entry.TextColorProperty, BaseTheme.TextColor)
|
||||
.DynamicResource(Entry.PlaceholderColorProperty, BaseTheme.SecondaryTextColor)
|
||||
.DynamicResource(VisualElement.BackgroundColorProperty, BaseTheme.OptionTintColor);
|
||||
}
|
@ -1,15 +1,16 @@
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Billing.UI;
|
||||
|
||||
public class ShadowEffect : RoutingEffect
|
||||
namespace Billing.UI
|
||||
{
|
||||
public float Radius { get; set; }
|
||||
public Color Color { get; set; }
|
||||
public Size Offect { get; set; }
|
||||
public float Opacity { get; set; }
|
||||
|
||||
public ShadowEffect() : base($"Org.Tsanie.{nameof(ShadowEffect)}")
|
||||
public class ShadowEffect : RoutingEffect
|
||||
{
|
||||
public float Radius { get; set; }
|
||||
public Color Color { get; set; }
|
||||
public Size Offect { get; set; }
|
||||
public float Opacity { get; set; }
|
||||
|
||||
public ShadowEffect() : base($"Org.Tsanie.{nameof(ShadowEffect)}")
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,68 +1,69 @@
|
||||
using System;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Billing.UI;
|
||||
|
||||
public static partial class Definition
|
||||
namespace Billing.UI
|
||||
{
|
||||
public static partial string GetCascadiaRegularFontFamily();
|
||||
public static partial string GetCascadiaBoldFontFamily();
|
||||
public static partial string GetRobotoCondensedRegularFontFamily();
|
||||
public static partial string GetRobotoCondensedBoldFontFamily();
|
||||
}
|
||||
|
||||
public static class ExtensionHelper
|
||||
{
|
||||
public static View Binding(this View view, BindableProperty property, string path, BindingMode mode = BindingMode.Default, IValueConverter converter = null)
|
||||
public static partial class Definition
|
||||
{
|
||||
view.SetBinding(property, path, mode, converter);
|
||||
return view;
|
||||
public static partial string GetCascadiaRegularFontFamily();
|
||||
public static partial string GetCascadiaBoldFontFamily();
|
||||
public static partial string GetRobotoCondensedRegularFontFamily();
|
||||
public static partial string GetRobotoCondensedBoldFontFamily();
|
||||
}
|
||||
|
||||
public static View DynamicResource(this View view, BindableProperty property, string key)
|
||||
public static class ExtensionHelper
|
||||
{
|
||||
view.SetDynamicResource(property, key);
|
||||
return view;
|
||||
}
|
||||
|
||||
public static View GridColumn(this View view, int column)
|
||||
{
|
||||
Grid.SetColumn(view, column);
|
||||
return view;
|
||||
}
|
||||
|
||||
public static View GridRow(this View view, int row)
|
||||
{
|
||||
Grid.SetRow(view, row);
|
||||
return view;
|
||||
}
|
||||
}
|
||||
|
||||
public class Tap : IDisposable
|
||||
{
|
||||
private readonly static object sync = new();
|
||||
private static Tap instance;
|
||||
|
||||
private bool busy = false;
|
||||
|
||||
private Tap() { }
|
||||
|
||||
public static bool IsBusy => instance?.busy ?? false;
|
||||
|
||||
public static Tap Start()
|
||||
{
|
||||
lock (sync)
|
||||
public static View Binding(this View view, BindableProperty property, string path, BindingMode mode = BindingMode.Default, IValueConverter converter = null)
|
||||
{
|
||||
(instance ??= new Tap()).busy = true;
|
||||
view.SetBinding(property, path, mode, converter);
|
||||
return view;
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
lock (sync)
|
||||
public static View DynamicResource(this View view, BindableProperty property, string key)
|
||||
{
|
||||
busy = false;
|
||||
view.SetDynamicResource(property, key);
|
||||
return view;
|
||||
}
|
||||
|
||||
public static View GridColumn(this View view, int column)
|
||||
{
|
||||
Grid.SetColumn(view, column);
|
||||
return view;
|
||||
}
|
||||
|
||||
public static View GridRow(this View view, int row)
|
||||
{
|
||||
Grid.SetRow(view, row);
|
||||
return view;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class Tap : IDisposable
|
||||
{
|
||||
private readonly static object sync = new();
|
||||
private static Tap instance;
|
||||
|
||||
private bool busy = false;
|
||||
|
||||
private Tap() { }
|
||||
|
||||
public static bool IsBusy => instance?.busy ?? false;
|
||||
|
||||
public static Tap Start()
|
||||
{
|
||||
lock (sync)
|
||||
{
|
||||
(instance ??= new Tap()).busy = true;
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
lock (sync)
|
||||
{
|
||||
busy = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user