App menu: the titlebar's "Settings and more" (Alt+F, F10, the palette, the account menu's last row) with rows from the site config; page zoom per tab in the host

Frame: AppMenu.tsx is a menu at the end of the titlebar cluster (before the caption buttons; macOS has none there). Its rows are `ShellSite.menu`: ordered groups of built-in rows by name and the app's own ({id, label, icon, shortcut, hint, when, checked, run | submenu}); `DEFAULT_MENU`, `menuWith` and `menuWithout` order, add and remove. A built-in row shows only when the app serves it (decks, `menu.languages`, themes, `menu.modes`, and `features`: zoom, store, workspaces, developer, updates), so no app gets a dead row. Language, Theme, Mode, Workspaces and Developer are submenus; Language and Theme apply live and keep the menu open, Mode asks the same keep-my-changes question as Settings (panel `menuModes()`). Keyboard: arrows, Home/End, type-ahead, the arrow along the reading direction opens a submenu, Esc closes one level; ARIA menu roles; submenus stay inside the window; one highlight for pointer and keys. It is an overlay like the other shell menus (the shell is raised, panes stay visible, nothing is dimmed).

Words: menuMessages.en.json (`wb.menu.*`), read through the framework i18n with that English as the fallback until the catalogs have them; words the panel already has are reused.

Host: `tab_zoom {id, factor}` (shell-only) sets a tab's page zoom with the engine's own zoom, clamped to 25%..500% and remembered per tab id in app data `zoom.json` (a number per tab id, nothing else; a closed tab's entry goes); without a factor it reads. A tab may forward four more shortcut names: `app-menu`, `zoom-in`, `zoom-out`, `zoom-reset`. The titlebar shows a zoom chip only while the pane in front is not at 100%.

create-waybetter: `tab_zoom` in the shell capability list; the template says which panel sections it lacks (store, updates) and how to add menu rows.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
CRTkafa 2026-09-30 21:52:51 +07:00
parent eed6bdd8f4
commit e5d43afffc
27 changed files with 1587 additions and 18 deletions

View file

@ -493,6 +493,8 @@ async fn tabs_sync(webview: Webview, app: AppHandle, items: Vec<TabLayout>, view
if shell_is_raised() {
host::raise_shell(&webview, true);
}
// A new webview starts at 100%: this tab's remembered page zoom.
host::restore_tab_zoom(&app, &tab);
tab
}
Err(error) => {
@ -517,6 +519,7 @@ async fn tabs_sync(webview: Webview, app: AppHandle, items: Vec<TabLayout>, view
if let Ok(mut data) = profiles(&app) {
data.tab_profiles.remove(&label);
}
host::forget_tab_zoom(&app, id);
hooks.tab_closed(&app, &label, TabClosed::Removed);
}
}
@ -545,6 +548,15 @@ async fn tab_action(webview: Webview, app: AppHandle, id: String, action: String
host::tab_action(&app, &id, &action)
}
/// The page zoom of tab `id` (the app menu's zoom row, Ctrl with + / - / 0): sets it to `factor`
/// (clamped to 25%..500%, remembered per tab in app data `zoom.json`), or only reads it without
/// one. Returns the factor in effect. The engine's own page zoom; nothing is injected into the page.
#[tauri::command]
async fn tab_zoom(webview: Webview, app: AppHandle, id: String, factor: Option<f64>) -> Result<f64, String> {
shell_only(&webview)?;
host::tab_zoom(&app, &id, factor)
}
/// Gives keyboard focus back to the shell (e.g. Ctrl+L pressed inside a tab).
#[tauri::command]
async fn shell_focus(webview: Webview) -> Result<(), String> {
@ -900,6 +912,8 @@ fn tab_builder(app: &AppHandle, hooks: &Arc<dyn SiteHooks>, tab: &NewTab, url: U
let finished = matches!(payload.event(), PageLoadEvent::Finished);
if !finished {
load_hooks.page_started(app, &tab);
// An engine that resets page zoom on navigation still shows this tab's.
host::restore_tab_zoom(app, &tab);
}
emit_tab_state(app, TabState { id: load_id.clone(), url: Some(payload.url().to_string()), loading: Some(!finished), ..Default::default() });
if finished && site.is_origin(payload.url()) {
@ -957,6 +971,7 @@ fn host_handler() -> impl Fn(tauri::ipc::Invoke<Wry>) -> bool + Send + Sync + 's
tabs_sync,
tab_navigate,
tab_action,
tab_zoom,
open_external_url,
shell_focus,
shell_ready,