The pages and components now use the daisyUI wrappers and the neo-* utilities instead of Bulma and the neomorph classes: - buttons are DButton, with pressed states as Active; - nav links are btn / btn-active; - the filter and composer selects are DSelect with a prefix icon; - the composer's fields are DInput and DTextarea; - the message options and scope pickers are DDropdown, which now close on an outside click and on Escape; - the settings and admin sections are DCollapse; - the dark-mode switch is a DToggle with sun and moon icons; - the hue slider is a DRange on the rainbow track. DropdownButton, OpenDownContainer and LoadingData are gone. The loader is DLoading, whose animation runs; the old one's keyframes were never defined. Icons coloured with Bulma's has-text-* now get daisyUI's text-info, success, warning and error, which had no rules before. Tailwind 3 to 4 fixes: - space-x/y become gap, which also handles the flex-col-reverse feeds; - !rounded-lg becomes rounded-lg!; - drop-shadow becomes drop-shadow-sm; - text-md becomes text-base. The thread page marks its message with Content's new Highlighted parameter rather than a second shadow size. neo.css: a select's prefix icon gets the room daisyUI leaves for a span.label, and the inner select lets the well show through. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LsXgEaXee4GCU1hwYgPJXw
153 lines
4.8 KiB
C#
153 lines
4.8 KiB
C#
using Blazored.LocalStorage;
|
|
|
|
using collAnon.Client.Services;
|
|
|
|
using decePubClient.Models;
|
|
using decePubClient.Services;
|
|
|
|
using Markdig;
|
|
|
|
using Microsoft.AspNetCore.Authorization;
|
|
using Microsoft.AspNetCore.Components;
|
|
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
|
|
|
|
using PrivaPub.ClientModels;
|
|
|
|
using System.Collections.Specialized;
|
|
using System.ComponentModel;
|
|
using System.Globalization;
|
|
using System.Text.Json;
|
|
using System.Web;
|
|
|
|
namespace decePubClient.Extensions
|
|
{
|
|
public static class ExtensionMethods
|
|
{
|
|
#region Navigation Manager
|
|
|
|
public static NameValueCollection QueryString(this NavigationManager navigationManager) =>
|
|
HttpUtility.ParseQueryString(new Uri(navigationManager.Uri).Query);
|
|
|
|
public static string QueryString(this NavigationManager navigationManager, string key) =>
|
|
navigationManager.QueryString()[key];
|
|
|
|
public static T QueryString<T>(this NavigationManager navigationManager, string key)
|
|
{
|
|
var value = navigationManager.QueryString()[key];
|
|
var converter = TypeDescriptor.GetConverter(typeof(T));
|
|
if (converter.IsValid(value))
|
|
return (T)Convert.ChangeType(value, typeof(T));
|
|
else
|
|
return default;
|
|
}
|
|
|
|
#endregion Navigation Manager
|
|
|
|
#region Setups
|
|
|
|
public static async Task SetDefaultCulture(this WebAssemblyHost host)
|
|
{
|
|
var culture = default(CultureInfo);
|
|
try
|
|
{
|
|
var storage = host.Services.GetRequiredService<ILocalStorageService>();
|
|
var publicCache = await storage.GetItemAsync<PublicCacheData>(nameof(PublicCacheData));
|
|
if (publicCache is null)
|
|
{
|
|
publicCache = new();
|
|
var status = host.Services.GetRequiredService<AppStatusService>();
|
|
var browserLanguage = status.Language();
|
|
if (browserLanguage.Contains("en"))
|
|
browserLanguage = "en-GB";
|
|
var appConfig = host.Services.GetRequiredService<AppConfiguration>();
|
|
if (!string.IsNullOrEmpty(publicCache.PageSettings.CurrentLanguageCode) &&
|
|
publicCache.PageSettings.CurrentLanguageCode.Contains("en"))
|
|
publicCache.PageSettings.CurrentLanguageCode = "en-GB";
|
|
culture = new(publicCache.PageSettings.CurrentLanguageCode ?? browserLanguage);
|
|
publicCache.PageSettings.CurrentLanguageCode = culture.TwoLetterISOLanguageName;
|
|
await storage.SetItemAsync(nameof(PublicCacheData), publicCache);
|
|
}
|
|
|
|
culture ??= new(publicCache.PageSettings.CurrentLanguageCode == "en" ? "en-GB" : publicCache.PageSettings.CurrentLanguageCode);
|
|
CultureInfo.DefaultThreadCurrentCulture = culture;
|
|
CultureInfo.DefaultThreadCurrentUICulture = culture;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.WriteLine(ex);
|
|
culture = new("en-GB");
|
|
CultureInfo.DefaultThreadCurrentCulture = culture;
|
|
CultureInfo.DefaultThreadCurrentUICulture = culture;
|
|
}
|
|
}
|
|
|
|
#endregion Setups
|
|
|
|
public static string GetLogLevelClass(this string logType) => logType switch
|
|
{
|
|
"Debug" => "text-base-content/60",
|
|
"Information" => "text-info",
|
|
"Warning" => "text-warning",
|
|
"Error" => "text-error",
|
|
"Fatal" => "text-error font-bold",
|
|
_ => string.Empty
|
|
};
|
|
|
|
|
|
#region Formats
|
|
|
|
public static MarkdownPipeline Pipeline =>
|
|
new MarkdownPipelineBuilder().UseGenericAttributes().Build();
|
|
|
|
public static string ToJson(this object value) =>
|
|
JsonSerializer.Serialize(value);
|
|
|
|
public static string ToBase64PngImage(this string base64Image) =>
|
|
$"data:image/png;base64,{base64Image}";
|
|
|
|
#endregion Formats
|
|
|
|
#region Models
|
|
|
|
public static string ToString(this WebResult webResult, CoalescingStringLocalizer localizer) =>
|
|
localizer["{0} - {1}", webResult.StatusCode, webResult.ErrorMessage];
|
|
|
|
public static string Timeframe(this DateTime creationDate, CoalescingStringLocalizer localizer)
|
|
{
|
|
var timeframe = DateTime.Now - creationDate.ToLocalTime();
|
|
switch ((int)timeframe.TotalHours)
|
|
{
|
|
case >= 24:
|
|
return localizer["{0} day/s", (int)timeframe.TotalDays];
|
|
|
|
case >= 1 and < 24:
|
|
return localizer["{0} hour/s", (int)timeframe.TotalHours];
|
|
|
|
case 0:
|
|
return localizer["{0} minute/s", (int)timeframe.TotalMinutes];
|
|
|
|
default:
|
|
return string.Empty;
|
|
}
|
|
}
|
|
|
|
public static AuthorizationPolicy IsAdminPolicy() =>
|
|
new AuthorizationPolicyBuilder().RequireAuthenticatedUser()
|
|
.RequireClaim(Policies.IsAdmin, true.ToString().ToLower())
|
|
.RequireClaim(Policies.IsUser, true.ToString().ToLower())
|
|
.RequireClaim(Policies.IsModerator, true.ToString().ToLower())
|
|
.Build();
|
|
|
|
public static AuthorizationPolicy IsUserPolicy() =>
|
|
new AuthorizationPolicyBuilder().RequireAuthenticatedUser()
|
|
.RequireClaim(Policies.IsUser, true.ToString().ToLower())
|
|
.Build();
|
|
|
|
public static AuthorizationPolicy IsUserModeratorPolicy() =>
|
|
new AuthorizationPolicyBuilder().RequireAuthenticatedUser()
|
|
.RequireClaim(Policies.IsModerator, true.ToString().ToLower())
|
|
.Build();
|
|
|
|
#endregion
|
|
}
|
|
} |