2023-07-27 22:07:24 +08:00

157 lines
4.2 KiB
C#

using Blahblah.FlowerApp.Controls;
using Blahblah.FlowerApp.Data;
using Blahblah.FlowerApp.Data.Model;
using Microsoft.Extensions.Logging;
using static Blahblah.FlowerApp.PropertyExtension;
namespace Blahblah.FlowerApp;
public partial class HomePage : AppContentPage
{
static readonly BindableProperty FlowersProperty = CreateProperty<FlowerClientItem[], HomePage>(nameof(Flowers));
static readonly BindableProperty IsRefreshingProperty = CreateProperty<bool, HomePage>(nameof(IsRefreshing));
public FlowerClientItem[] Flowers
{
get => GetValue<FlowerClientItem[]>(FlowersProperty);
set => SetValue(FlowersProperty, value);
}
public bool IsRefreshing
{
get => GetValue<bool>(IsRefreshingProperty);
set => SetValue(IsRefreshingProperty, value);
}
readonly FlowerDatabase database;
readonly ILogger logger;
bool loaded = false;
double pageWidth;
const int margin = 12;
const int cols = 2;
double[] ys = null!;
int yIndex;
int itemWidth;
int emptyHeight;
public HomePage(FlowerDatabase database, ILogger<HomePage> logger)
{
this.database = database;
this.logger = logger;
InitializeComponent();
}
protected override void OnSizeAllocated(double width, double height)
{
base.OnSizeAllocated(width, height);
pageWidth = width - margin * 2;
if (!loaded)
{
loaded = true;
IsRefreshing = true;
}
else if (Flowers?.Length > 0)
{
DoInitSize();
foreach (var item in Flowers)
{
DoResizeItem(item);
}
}
}
private void DoInitSize()
{
ys = new double[cols];
yIndex = 0;
itemWidth = (int)(pageWidth / cols) - margin * (cols - 1) / 2;
emptyHeight = (int)(itemWidth * AppResources.EmptySize.Height / AppResources.EmptySize.Width);
}
private void DoResizeItem(FlowerClientItem item)
{
int height;
if (item.Width > 0 && item.Height > 0)
{
height = itemWidth * item.Height.Value / item.Width.Value;
}
else
{
height = emptyHeight;
}
height += 36;
double yMin = double.MaxValue;
for (var i = 0; i < cols; i++)
{
if (ys[i] < yMin)
{
yMin = ys[i];
yIndex = i;
}
}
ys[yIndex] += height + margin;
item.Bounds = new Rect(
yIndex,
yMin,
itemWidth,
height);
}
private async void DoRefreshSquare()
{
try
{
var result = await FetchAsync<FlowerResult>("api/flower/latest?photo=true");
if (result?.Count > 0)
{
DoInitSize();
var flowers = result.Flowers.Select(f =>
{
var item = new FlowerClientItem(f);
if (f.Photos?.Length > 0 && f.Photos[0] is PhotoItem cover)
{
item.Cover = new UriImageSource { Uri = new Uri($"{Constants.BaseUrl}/{cover.Url}") };
}
else
{
item.Cover = "empty_flower.jpg";
}
DoResizeItem(item);
return item;
});
logger.LogInformation("got {count} flowers.", result.Count);
Flowers = flowers.ToArray();
}
else
{
Flowers = Array.Empty<FlowerClientItem>();
logger.LogInformation("no flowers.");
}
}
catch (Exception ex)
{
await AlertError(L("failedGetFlowers", "Failed to get flowers, please try again."));
logger.LogError("error occurs in HomePage, {exception}", ex);
}
finally
{
IsRefreshing = false;
}
}
private void RefreshView_Refreshing(object sender, EventArgs e)
{
Task.Run(DoRefreshSquare);
}
}
public record FlowerResult
{
public FlowerItem[] Flowers { get; init; } = null!;
public int Count { get; init; }
}