Extract the wayBetter framework core from wayBetter for X
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>
This commit is contained in:
commit
41267a22fd
48 changed files with 9768 additions and 0 deletions
35
packages/runtime/src/accountReport.ts
Normal file
35
packages/runtime/src/accountReport.ts
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
// 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);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue