Site-agnostic parts of the X app, behind a small site adapter: - crates/waybetter-host: webview-label security policy and tab rect clamp, account profiles with native-owned accounts (AccountRules), plugin store with bundled-plugin upgrades (PluginHost), signed data-only hotfix channel, update scheduling and crash handshake, tab payloads/link routing/tab-chrome validation, and (feature "tauri") webview helpers and the Windows system menu. - packages/runtime: DOM hub, request hub, plugin API core, OKLab theme color model, split-view rail hiding, link routing and account reporting, each configured by a SiteAdapter. - packages/shell: address bar, pane, link-drop, profile, palette and update-chip models, and window controls with the Tauri API injected. Tests moved/adapted from the app: 45 Rust (headless), 40 TypeScript. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
35 lines
1.5 KiB
TypeScript
35 lines
1.5 KiB
TypeScript
// Tells the app which account is signed in inside this tab's profile, so the account switcher
|
|
// lists real logins (avatar, name, handle) instead of hand-named slots. Read from the site's own
|
|
// UI, which the site renders anyway; nothing is requested. Only a change is reported (`tab_report`),
|
|
// and native code accepts it only from a webview that is on the site, for that webview's own profile.
|
|
|
|
import { watchDom } from './domHub.ts';
|
|
|
|
export type SeenAccount = { handle: string; name: string; avatar: string | null };
|
|
export type AccountReport = { account: SeenAccount } | { signedOut: true };
|
|
|
|
export type AccountSite = {
|
|
/** The account the site's UI shows, or null when there is none (yet). Pure over the DOM. */
|
|
read(root: ParentNode): SeenAccount | null;
|
|
/** The site shows its signed-out page. */
|
|
signedOut(root: ParentNode): boolean;
|
|
};
|
|
|
|
export type Invoke = (command: string, args: Record<string, unknown>) => Promise<unknown>;
|
|
|
|
export function installAccountReport(win: Window, site: AccountSite, invoke?: Invoke) {
|
|
if (!invoke) return { dispose() {} };
|
|
let last = '';
|
|
const send = (report: AccountReport) => {
|
|
const key = JSON.stringify(report);
|
|
if (key === last) return;
|
|
last = key;
|
|
invoke('tab_report', { report }).catch(() => { last = ''; });
|
|
};
|
|
const check = () => {
|
|
const account = site.read(win.document);
|
|
if (account) send({ account });
|
|
else if (site.signedOut(win.document)) send({ signedOut: true });
|
|
};
|
|
return watchDom(win as unknown as Parameters<typeof watchDom>[0], check);
|
|
}
|