home page for App

This commit is contained in:
2023-07-27 22:07:24 +08:00
parent 02ac33fc07
commit befbc7fc9b
40 changed files with 1175 additions and 398 deletions

View File

@ -0,0 +1,59 @@
namespace Blahblah.FlowerApp;
public class AppContentPage : ContentPage
{
protected static string L(string key, string defaultValue = "")
{
return LocalizationResource.GetText(key, defaultValue);
}
protected static Task<T?> FetchAsync<T>(string url, CancellationToken cancellation = default)
{
return Extensions.FetchAsync<T>(url, cancellation);
}
protected T GetValue<T>(BindableProperty property)
{
return (T)GetValue(property);
}
protected Task AlertError(string error)
{
return Alert(LocalizationResource.GetText("error", "Error"), error);
}
protected Task Alert(string title, string message, string? cancel = null)
{
cancel ??= LocalizationResource.GetText("ok", "Ok");
if (MainThread.IsMainThread)
{
return DisplayAlert(title, message, cancel);
}
var taskSource = new TaskCompletionSource();
MainThread.BeginInvokeOnMainThread(async () =>
{
await DisplayAlert(title, message, cancel);
taskSource.TrySetResult();
});
return taskSource.Task;
}
protected Task<bool> Confirm(string title, string question, string? accept = null, string? cancel = null)
{
accept ??= LocalizationResource.GetText("yes", "Yes");
cancel ??= LocalizationResource.GetText("no", "No");
if (MainThread.IsMainThread)
{
return DisplayAlert(title, question, accept, cancel);
}
var taskSource = new TaskCompletionSource<bool>();
MainThread.BeginInvokeOnMainThread(async () =>
{
var result = await DisplayAlert(title, question, accept, cancel);
taskSource.TrySetResult(result);
});
return taskSource.Task;
}
}

View File

@ -0,0 +1,8 @@
namespace Blahblah.FlowerApp;
internal class AppResources
{
public const string EmptyCover = "empty_flower.jpg";
public static readonly Size EmptySize = new(512, 339);
}

View File

@ -0,0 +1,57 @@
using Blahblah.FlowerApp.Data.Model;
using static Blahblah.FlowerApp.PropertyExtension;
namespace Blahblah.FlowerApp.Controls;
public class FlowerClientItem : BindableObject
{
static readonly BindableProperty NameProperty = CreateProperty<string, FlowerClientItem>(nameof(Name));
static readonly BindableProperty CategoryProperty = CreateProperty<int, FlowerClientItem>(nameof(Category));
static readonly BindableProperty CoverProperty = CreateProperty<ImageSource?, FlowerClientItem>(nameof(Cover));
static readonly BindableProperty BoundsProperty = CreateProperty<Rect, FlowerClientItem>(nameof(Bounds));
public int Id { get; }
public FlowerItem? FlowerItem { get; }
public string Name
{
get => (string)GetValue(NameProperty);
set => SetValue(NameProperty, value);
}
public int Category
{
get => (int)GetValue(CategoryProperty);
set => SetValue(CategoryProperty, value);
}
public ImageSource? Cover
{
get => (ImageSource?)GetValue(CoverProperty);
set => SetValue(CoverProperty, value);
}
public Rect Bounds
{
get => (Rect)GetValue(BoundsProperty);
set => SetValue(BoundsProperty, value);
}
public int? Width { get; set; }
public int? Height { get; set; }
public FlowerClientItem(int id)
{
Id = id;
}
public FlowerClientItem(FlowerItem item) : this(item.Id)
{
FlowerItem = item;
Name = item.Name;
Category = item.Category;
if (item.Photos?.Length > 0 && item.Photos[0] is PhotoItem cover)
{
Width = cover.Width;
Height = cover.Height;
}
}
}

View File

@ -0,0 +1,9 @@
namespace Blahblah.FlowerApp;
internal sealed class PropertyExtension
{
public static BindableProperty CreateProperty<T, V>(string propertyName, T? defaultValue = default)
{
return BindableProperty.Create(propertyName, typeof(T), typeof(V), defaultValue);
}
}

View File

@ -1,12 +0,0 @@
namespace Blahblah.FlowerApp.Controls;
public class WaterfallLayout : View
{
public static readonly BindableProperty ColumnsProperty = BindableProperty.Create(nameof(Columns), typeof(int), typeof(WaterfallLayout), defaultValue: 2);
public int Columns
{
get => (int)GetValue(ColumnsProperty);
set => SetValue(ColumnsProperty, value);
}
}