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(string propertyName, T? defaultValue = default) { return BindableProperty.Create(propertyName, typeof(T), typeof(V), defaultValue); } public static async Task FetchAsync(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($"{Constants.BaseUrl}/{url}", cancellation); } public static async Task PostAsync(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; if (content.Headers.TryGetValues("Authorization", out var values) && values.FirstOrDefault() is string oAuth) { Constants.SetAuthorization(oAuth); var result = await content.ReadFromJsonAsync(cancellationToken: cancellation); return result; } } return default; } } internal static class LoggerExtension { const LogLevel MinimumLogLevel = LogLevel.Information; 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 (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 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 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(); MainThread.BeginInvokeOnMainThread(async () => { var result = await page.DisplayAlert(title, question, accept, cancel); taskSource.TrySetResult(result); }); return taskSource.Task; } }