flower-story/FlowerApp/Extensions.cs
2023-08-02 23:45:04 +08:00

223 lines
7.7 KiB
C#

using Blahblah.FlowerApp.Data;
using Microsoft.Extensions.Logging;
using System.Net.Http.Json;
namespace Blahblah.FlowerApp;
internal sealed class Extensions
{
public static string L(string key, string defaultValue = "")
{
return LocalizationResource.GetText(key, defaultValue);
}
public static BindableProperty CreateProperty<T, V>(string propertyName, T? defaultValue = default, BindingMode defaultBindingMode = BindingMode.OneWay, BindableProperty.BindingPropertyChangedDelegate? propertyChanged = null)
{
return BindableProperty.Create(propertyName, typeof(T), typeof(V), defaultValue, defaultBindingMode, propertyChanged: propertyChanged);
}
public static async Task<T?> FetchAsync<T>(string url, CancellationToken cancellation = default)
{
using var client = new HttpClient();
var authorization = Constants.Authorization;
if (authorization != null)
{
client.DefaultRequestHeaders.TryAddWithoutValidation("Authorization", authorization);
}
return await client.GetFromJsonAsync<T>($"{Constants.BaseUrl}/{url}", cancellation);
}
public static async Task<R?> PostAsync<T, R>(string url, T data, CancellationToken cancellation = default)
{
using var client = new HttpClient();
var authorization = Constants.Authorization;
if (authorization != null)
{
client.DefaultRequestHeaders.TryAddWithoutValidation("Authorization", authorization);
}
using var response = await client.PostAsJsonAsync($"{Constants.BaseUrl}/{url}", data, cancellation);
if (response != null)
{
response.EnsureSuccessStatusCode();
var content = response.Content;
var result = await content.ReadFromJsonAsync<R>(cancellationToken: cancellation);
return result;
}
return default;
}
public static async Task<R?> UploadAsync<R>(string url, MultipartFormDataContent data, CancellationToken cancellation = default)
{
using var client = new HttpClient();
var authorization = Constants.Authorization;
if (authorization != null)
{
client.DefaultRequestHeaders.TryAddWithoutValidation("Authorization", authorization);
}
using var response = await client.PostAsJsonAsync($"{Constants.BaseUrl}/{url}", data, cancellation);
if (response != null)
{
response.EnsureSuccessStatusCode();
var content = response.Content;
var result = await content.ReadFromJsonAsync<R>(cancellationToken: cancellation);
return result;
}
return default;
}
public static async Task<string> CacheFileAsync(FileResult file)
{
string cache = Path.Combine(FileSystem.CacheDirectory, file.FileName);
using Stream source = await file.OpenReadAsync();
using FileStream fs = File.OpenWrite(cache);
await source.CopyToAsync(fs);
return cache;
}
}
internal static class LoggerExtension
{
const LogLevel MinimumLogLevel =
#if DEBUG
LogLevel.Information;
#else
LogLevel.Warning;
#endif
public static void LogInformation(this ILoggerContent content, string message)
{
Log(content, LogLevel.Information, null, message);
}
public static void LogWarning(this ILoggerContent content, string message)
{
Log(content, LogLevel.Warning, null, message);
}
public static void LogError(this ILoggerContent content, Exception? exception, string message)
{
Log(content, LogLevel.Error, exception, message);
}
private static void Log(ILoggerContent content, LogLevel level, Exception? exception, string message)
{
if (content?.Logger is ILogger logger)
{
logger.Log(level, exception, "[{time:MM/dd HH:mm:ss}] - {message}", DateTime.UtcNow, message);
if (level >= MinimumLogLevel && content.Database is FlowerDatabase database)
{
_ = database.AddLog(new Data.Model.LogItem
{
OwnerId = AppResources.User.Id,
LogType = level.ToString(),
LogUnixTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(),
Category = "logger",
ClientAgent = Constants.UserAgent,
Message = message,
Description = exception?.ToString(),
Source = exception?.Source
});
}
}
}
}
internal static class PageExtension
{
public static T Binding<T>(this T obj, BindableProperty property, string path, BindingMode mode = BindingMode.Default, IValueConverter? converter = null) where T : BindableObject
{
obj.SetBinding(property, path, mode, converter);
return obj;
}
public static T AppThemeBinding<T>(this T obj, BindableProperty property, Color light, Color dark) where T : BindableObject
{
obj.SetAppThemeColor(property, light, dark);
return obj;
}
public static T GridColumn<T>(this T view, int column) where T : BindableObject
{
Grid.SetColumn(view, column);
return view;
}
public static T GridRow<T>(this T view, int row) where T : BindableObject
{
Grid.SetRow(view, row);
return view;
}
public static T GridColumnSpan<T>(this T view, int columnSpan) where T : BindableObject
{
Grid.SetColumnSpan(view, columnSpan);
return view;
}
public static T GridRowSpan<T>(this T view, int rowSpan) where T : BindableObject
{
Grid.SetRowSpan(view, rowSpan);
return view;
}
public static Task AlertError(this ContentPage page, string error)
{
return Alert(page, LocalizationResource.GetText("error", "Error"), error);
}
public static Task Alert(this ContentPage page, string title, string message, string? cancel = null)
{
cancel ??= LocalizationResource.GetText("ok", "Ok");
if (MainThread.IsMainThread)
{
return page.DisplayAlert(title, message, cancel);
}
var taskSource = new TaskCompletionSource();
MainThread.BeginInvokeOnMainThread(async () =>
{
await page.DisplayAlert(title, message, cancel);
taskSource.TrySetResult();
});
return taskSource.Task;
}
public static Task<bool> Confirm(this ContentPage page, string title, string question, string? accept = null, string? cancel = null)
{
accept ??= LocalizationResource.GetText("yes", "Yes");
cancel ??= LocalizationResource.GetText("no", "No");
if (MainThread.IsMainThread)
{
return page.DisplayAlert(title, question, accept, cancel);
}
var taskSource = new TaskCompletionSource<bool>();
MainThread.BeginInvokeOnMainThread(async () =>
{
var result = await page.DisplayAlert(title, question, accept, cancel);
taskSource.TrySetResult(result);
});
return taskSource.Task;
}
}
internal static class Res
{
public const string Filter = "\ue17c";
public const string Camera = "\uf030";
public const string Image = "\uf03e";
public const string Heart = "\uf004";
public const string Right = "\uf105";
public const string XMarkLarge = "\ue59b";
public const string Gear = "\uf013";
public const string List = "\uf0ae";
public const string Flag = "\uf2b4";
public const string Check = "\uf00c";
public static readonly Color Gray900 = Color.FromRgb(0x21, 0x21, 0x21);
public static readonly Color Red100 = Color.FromRgb(0xF4, 0x43, 0x36);
public static readonly Color Red300 = Color.FromRgb(0xFF, 0xCD, 0xD2);
}