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:
CRTkafa 2026-09-28 03:01:33 +07:00
commit 41267a22fd
48 changed files with 9768 additions and 0 deletions

View file

@ -0,0 +1,185 @@
//! Tauri glue that does not depend on the app's own state: caller checks, shell events, tab
//! webview lookups and actions, app-data JSON files, profile data folders and the Windows system
//! menu. The app keeps its `#[tauri::command]` wrappers (so IPC names and capabilities stay the
//! app's) and calls these.
use crate::{
policy,
profiles::{self, ProfileSettings},
site::SiteSpec,
tabs::{self, TabAction, TabState},
};
use serde::Serialize;
use tauri::{AppHandle, Emitter, EventTarget, Manager, Runtime, Webview};
use url::Url;
/// Shell-only commands: the trusted local `shell` webview (debug builds also accept the dev server).
pub fn shell_only<R: Runtime>(webview: &Webview<R>) -> Result<(), String> {
let url = webview.url().map_err(|_| "FORBIDDEN: cannot verify workspace origin")?;
policy::require_local(webview.label(), &url, cfg!(debug_assertions))
}
/// Tab-chrome commands: any tab webview, speaking only about itself. Returns its tab id.
pub fn tab_only<R: Runtime>(webview: &Webview<R>) -> Result<String, String> {
policy::tab_id(webview.label())
.map(str::to_owned)
.ok_or_else(|| "FORBIDDEN: tab webview required".into())
}
/// Site-only commands: a tab webview that is exactly on the site right now. Returns its URL (the
/// webview's own, never the page's claim).
pub fn site_tab_only<R: Runtime>(site: &SiteSpec, webview: &Webview<R>) -> Result<Url, String> {
let url = webview.url().map_err(|_| "FORBIDDEN: cannot verify origin")?;
policy::require_site_tab(site, webview.label(), &url)?;
Ok(url)
}
pub fn emit_shell<R: Runtime, S: Serialize + Clone>(app: &AppHandle<R>, event: &str, payload: S) {
let _ = app.emit_to(EventTarget::webview(policy::SHELL_LABEL), event, payload);
}
pub fn emit_tab_state<R: Runtime>(app: &AppHandle<R>, state: TabState) {
emit_shell(app, tabs::EVENT_TAB_STATE, state);
}
pub fn tab_webview<R: Runtime>(app: &AppHandle<R>, id: &str) -> Option<Webview<R>> {
app.get_webview(&policy::tab_label(id))
}
/// Evaluates `script` in every tab that is on the site right now.
pub fn eval_in_site_tabs<R: Runtime>(app: &AppHandle<R>, site: &SiteSpec, script: &str) {
for (label, webview) in app.webviews() {
if policy::tab_id(&label).is_some() && webview.url().is_ok_and(|url| site.is_origin(&url)) {
let _ = webview.eval(script);
}
}
}
pub fn data_file<R: Runtime>(app: &AppHandle<R>, name: &str) -> Option<std::path::PathBuf> {
app.path().app_data_dir().ok().map(|dir| dir.join(name))
}
pub fn read_json<R: Runtime, T: serde::de::DeserializeOwned>(app: &AppHandle<R>, name: &str) -> Option<T> {
serde_json::from_str(&std::fs::read_to_string(data_file(app, name)?).ok()?).ok()
}
pub fn write_json<R: Runtime, T: Serialize>(app: &AppHandle<R>, name: &str, value: &T) -> Result<(), String> {
let path = data_file(app, name).ok_or("STORAGE: no application data directory")?;
let json = serde_json::to_string_pretty(value).map_err(|_| "STORAGE: serialization failed")?;
std::fs::write(path, json).map_err(|error| format!("STORAGE: {error}"))
}
pub fn navigate_tab<R: Runtime>(app: &AppHandle<R>, id: &str, url: &str) -> Result<(), String> {
let url = tabs::parse_web_url(url)?;
let tab = tab_webview(app, id).ok_or("TAB: not found")?;
tab.navigate(url).map_err(|error| format!("TAB: {error}"))
}
pub fn tab_action<R: Runtime>(app: &AppHandle<R>, id: &str, action: &str) -> Result<(), String> {
let action = TabAction::parse(action)?;
let tab = tab_webview(app, id).ok_or("TAB: not found")?;
let result = match action {
TabAction::Back => tab.eval("history.back()"),
TabAction::Forward => tab.eval("history.forward()"),
TabAction::Reload => tab.reload(),
TabAction::Stop => tab.eval("window.stop()"),
TabAction::Focus => tab.set_focus(),
};
result.map_err(|error| format!("TAB: {error}"))
}
/// A browser shortcut pressed inside tab `id`, forwarded to the shell (`tab-shortcut`).
pub fn forward_shortcut<R: Runtime>(app: &AppHandle<R>, id: String, shortcut: String) -> Result<(), String> {
if !tabs::valid_shortcut(&shortcut) {
return Err("VALIDATION: unknown shortcut".into());
}
#[derive(Clone, Serialize)]
struct Shortcut {
id: String,
shortcut: String,
}
emit_shell(app, tabs::EVENT_TAB_SHORTCUT, Shortcut { id, shortcut });
Ok(())
}
/// A link drag started/entered/ended in tab `id` (`link-drag`); the link opens only as a new tab.
pub fn forward_link_drag<R: Runtime>(app: &AppHandle<R>, id: String, phase: String, url: Option<String>) -> Result<(), String> {
let url = tabs::link_drag(&phase, url)?;
#[derive(Clone, Serialize)]
struct LinkDrag {
id: String,
phase: String,
url: Option<String>,
}
emit_shell(app, tabs::EVENT_LINK_DRAG, LinkDrag { id, phase, url });
Ok(())
}
/// Deletes the WebView data folders (the logins) of removed profiles.
pub fn remove_profile_dirs<R: Runtime>(app: &AppHandle<R>, site: &SiteSpec, removed: &[String]) {
let Ok(local) = app.path().app_local_data_dir() else { return };
for id in removed {
if let Some(dir) = profiles::data_dir(&local, id) {
if let Err(error) = std::fs::remove_dir_all(&dir) {
if error.kind() != std::io::ErrorKind::NotFound {
eprintln!("{}: could not remove profile data {}: {error}", site.product, dir.display());
}
}
}
}
}
/// Deletes WebView data folders of profiles that no longer exist (see [`profiles::orphan_dirs`]).
pub fn prune_profile_dirs<R: Runtime>(app: &AppHandle<R>, settings: &ProfileSettings) {
let Ok(local) = app.path().app_local_data_dir() else { return };
for dir in profiles::orphan_dirs(&local, settings) {
let _ = std::fs::remove_dir_all(dir);
}
}
/// Moves app-data and app-local data (WebView profile, i.e. the site login) from a previous bundle
/// identifier. Never overwrites an existing new folder.
pub fn migrate_identifier<R: Runtime>(app: &AppHandle<R>, site: &SiteSpec, legacy_identifier: &str) {
let dirs = [app.path().app_data_dir(), app.path().app_local_data_dir()];
for new_dir in dirs.into_iter().flatten() {
let Some(parent) = new_dir.parent() else { continue };
let old_dir = parent.join(legacy_identifier);
if old_dir.is_dir() && !new_dir.exists() {
if let Err(error) = std::fs::rename(&old_dir, &new_dir) {
eprintln!("{}: could not migrate {}: {error}", site.product, old_dir.display());
}
}
}
}
/// Shows the native window system menu (Restore, Move, Size, Minimize, Maximize, Close) at a
/// screen position, for a right-click on the custom titlebar. No-op outside Windows.
pub fn system_menu<R: Runtime>(webview: &Webview<R>, x: f64, y: f64) -> Result<(), String> {
if !x.is_finite() || !y.is_finite() {
return Err("VALIDATION: non-finite position".into());
}
#[cfg(windows)]
{
use windows::Win32::Foundation::{LPARAM, WPARAM};
use windows::Win32::UI::WindowsAndMessaging::{
GetSystemMenu, PostMessageW, SetForegroundWindow, TrackPopupMenu, TPM_RETURNCMD, TPM_RIGHTBUTTON,
WM_SYSCOMMAND,
};
let hwnd = webview.window().hwnd().map_err(|error| format!("WINDOW: {error}"))?;
// SAFETY: plain Win32 calls on our own top-level window handle.
unsafe {
let menu = GetSystemMenu(hwnd, false);
if menu.is_invalid() {
return Ok(());
}
let _ = SetForegroundWindow(hwnd);
let command = TrackPopupMenu(menu, TPM_RETURNCMD | TPM_RIGHTBUTTON, x as i32, y as i32, None, hwnd, None);
if command.0 != 0 {
let _ = PostMessageW(Some(hwnd), WM_SYSCOMMAND, WPARAM(command.0 as usize), LPARAM(0));
}
}
}
#[cfg(not(windows))]
let _ = webview;
Ok(())
}