Build / Build (push) Successful in 1m3s
Completion program R3, with PrivaPub's TOTP routes of the same release. - Settings, the login: TotpEditor turns two-factor sign-in on (the password, then the QR code, the secret and the otpauth:// link, then the app's first code; the ten recovery codes shown once with Copy), shows how many recovery codes are left (warned at three), and turns it off with the password and a code, asked first. - Turning it on, like a password change, ends every other session: AuthService.ContinueSession takes the new JWT and exchanges the persona's token again. - Sign-in: PrivaPub's 428 keeps the name and password and asks for the six digits (DOtp), or a recovery code instead; a wrong code says so; Back returns to the password. - window.copyText (main.js) through AppStatusService.CopyText. - 29 keys in both resx files; CLAUDE.md follows. Verified: dotnet build decePubClient.csproj -c Release (0 errors, no new warnings). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WpVCoDeM1qUTRp4fXQdfof
45 lines
1.9 KiB
C#
45 lines
1.9 KiB
C#
using Microsoft.AspNetCore.Components;
|
|
using decePubClient.Models;
|
|
|
|
using Microsoft.JSInterop;
|
|
|
|
namespace decePubClient.Services;
|
|
|
|
public class AppStatusService(IJSRuntime jsRuntime)
|
|
{
|
|
readonly IJSInProcessRuntime JsSyncRuntime = (IJSInProcessRuntime)jsRuntime;
|
|
|
|
public async ValueTask<bool> IsOnline(CancellationToken cancellationToken = default) =>
|
|
await jsRuntime.InvokeAsync<bool>("isOnline", cancellationToken);
|
|
|
|
public string Language() => JsSyncRuntime.Invoke<string>("getLanguage");
|
|
|
|
public void SetAppBadge(int counter) => JsSyncRuntime.InvokeVoid("setAppBadge", counter);
|
|
|
|
public void ClearAppBadge() => JsSyncRuntime.InvokeVoid("clearAppBadge");
|
|
|
|
// wwwroot/js/theme.js
|
|
public void ApplyTheme(PageSettings pageSettings) => JsSyncRuntime.InvokeVoid("neoTheme.apply", pageSettings);
|
|
|
|
public bool IsDarkTheme() => JsSyncRuntime.Invoke<bool>("neoTheme.isDark");
|
|
|
|
public bool IsMobileMedia() => JsSyncRuntime.Invoke<bool>("isMobileMedia");
|
|
|
|
// whether the navigation being decided came from the Back (or Forward) button
|
|
public bool TookBack() => JsSyncRuntime.Invoke<bool>("tookBack");
|
|
|
|
// whether the pointer can hover (a mouse); a touch screen can't, so what shows on hover there opens on a tap
|
|
public bool CanHover() => JsSyncRuntime.Invoke<bool>("canHover");
|
|
|
|
// read once: a card asks it for each gifv it shows
|
|
bool? reducedMotion;
|
|
|
|
public bool PrefersReducedMotion() => reducedMotion ??= JsSyncRuntime.Invoke<bool>("prefersReducedMotion");
|
|
|
|
// puts the text on the clipboard; false when the browser refused it, which main.js reports through logFromJs
|
|
public async ValueTask<bool> CopyText(string text, CancellationToken cancellationToken = default) =>
|
|
await jsRuntime.InvokeAsync<bool>("copyText", cancellationToken, text);
|
|
|
|
// a sideways-scrolling strip of tabs shows its selected tab
|
|
public void RevealActive(ElementReference strip) => JsSyncRuntime.InvokeVoid("revealActive", strip);
|
|
} |