Ported from the owner's b2b.next and adapted from MudBlazor to the daisyUI
components:
- LocalizableComponentBase provides CascadingState, Navigation, Toast,
IsLoading/IsDefaultDisabled, WhenOnline/StartOnlinePolling, and after-render
jobs that actually run.
- CascadingState starts with initialised state and polls the online status
with a PeriodicTimer. It reports errors through ILoggingService plus a toast,
and disposes what it holds.
- New pieces:
- ToastService + ToastHost, the snackbar, with AddResponseError/Success/
Warning/Exception in SUtility;
- ErrorViewer, which shows the validation messages plus AdditionalError(s);
- LoggingService, which writes to the console and the IndexedDB client log.
- HttpService is rebuilt and registered:
- auth levels Get/Post/Delete, *Anon and *TotallyAnon;
- retry with backoff;
- classified failures (FailureCodes) instead of exceptions;
- HTTP 410 on cancel;
- the "default" client.
ReadWebResult and DefaultReadFromJsonAsync read its responses.
- ClientJsonContext is source-generated, and SUtility.DefaultSerializer and
Blazored.LocalStorage use it.
- WebResult gains a C# 14 IsInvalid extension property.
The code follows the imported rules:
- Every service and async helper takes a CancellationToken last.
- Primary constructors replace constructor-plus-fields.
- MessagesService and IStorage return Task<WebResult> / Task<List<T>>.
MessagesService is still mock, building its results in memory; the seed
feed and thread moved to Faker.
- Index and ExpandMessage follow the page pattern: an offline guard with
WhenOnline, LoadData, and early returns with toasts on the results they used
to ignore. ExpandMessage reloads on route change and shows "not found"
instead of a null message.
- Model and state collections are [], and the fake identity defaults moved
out of the models.
- Components:
- no ?. chains over initialised state;
- [Inject] instead of @inject;
- IsDefaultDisabled on the actions;
- autocomplete on every text input;
- Localizer[key, args] instead of string.Format;
- the localizer no longer leaks its inner _pLocalizer.
- Settings → General gains a language picker (English/Italiano), and
SetDefaultCulture limits the culture to those two.
Bugs fixed along the way:
- A compose with untouched (null) content passed the empty check.
- File errors were joined with <br/> and rendered as markup.
- ClientLogs.ErrorMessage() threw on warnings.
- CoalescingStringLocalizer[key, args] showed a raw "{0}" for missing keys.
- AppStatusService exposed a call to a JS function that doesn't exist.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LsXgEaXee4GCU1hwYgPJXw
Logout:
- It navigated to "authenticatio/logout", a misspelled route.
- The correct template route, authentication/logout, would throw anyway. Its
RemoteAuthenticatorView casts the AuthenticationStateProvider to the OIDC
template's service, and the app registers TokenAuthStateProvider instead.
- It now signs out through TokenAuthStateProvider.LogoutAsync, as the code
commented out in the page intended, and returns home. LoginDisplay's sign-out
goes through it as well.
- This also drops the obsolete SignOutSessionStateManager, the build's last
warning.
The IndexedDB schema never declared the ClientLogs store that IStorage.AddLog
writes to, so every client log write failed inside its try/catch. Version 2 adds
the store, keyed by the Id AddLog assigns.
DInputBase.NameAttribute renders no name instead of name="" when the form maps
no field names.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LsXgEaXee4GCU1hwYgPJXw
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
The project referenced ../SocialPub/SocialPub/SocialPub.ClientModels, a path
that has not existed since the server became PrivaPub; it references
../SocialPub/PrivaPub.ClientModels now, and CI clones SocialPub beside it.
Retargeted to net10.0 with the Microsoft packages at 10.0.9.
BlazorDownloadFileFast moves to 1.0.0.1 because 0.2.0 used
IJSUnmarshalledRuntime, which .NET 9 removed. The Visual Studio bundler and
web compiler packages are gone; the bundle they produced, css/style.min.css,
is committed and stays the stylesheet, and its stale .gz is deleted because
.NET's static-asset compression writes that path itself.
AppConfiguration.ApiBaseAddress (https://privapub.thepra.dev) is the API
client's base address; the template's placeholder OIDC section and the
Toolbelt.Blazor.HotKeys script tag, whose package is not referenced, are
removed. The vhost sends noindex while the feed shows the prototype's mock
posts.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012CzABvBkbcFqoHdmi8b9WB