Make settings menu a regular window (#113)

This commit is contained in:
Gregory Schier
2024-09-25 12:52:12 -07:00
committed by GitHub
parent 2be45d6101
commit b19748c42e
13 changed files with 201 additions and 111 deletions
+1 -1
View File
@@ -1,5 +1,5 @@
# Generated by Cargo # Generated by Cargo
# will have compiled files and executables # will have compiled files and executables
/target/ target/
vendored vendored
+2 -2
View File
@@ -35,12 +35,12 @@
"core:window:allow-is-fullscreen", "core:window:allow-is-fullscreen",
"core:window:allow-maximize", "core:window:allow-maximize",
"core:window:allow-minimize", "core:window:allow-minimize",
"core:window:allow-toggle-maximize",
"core:window:allow-set-decorations", "core:window:allow-set-decorations",
"core:window:allow-set-title", "core:window:allow-set-title",
"core:window:allow-start-dragging", "core:window:allow-start-dragging",
"core:window:allow-unmaximize",
"core:window:allow-theme", "core:window:allow-theme",
"core:window:allow-toggle-maximize",
"core:window:allow-unmaximize",
"clipboard-manager:allow-read-text", "clipboard-manager:allow-read-text",
"clipboard-manager:allow-write-text" "clipboard-manager:allow-write-text"
] ]
+1 -1
View File
@@ -1 +1 @@
{"main":{"identifier":"main","description":"Main permissions","local":true,"windows":["*"],"permissions":["core:event:allow-emit","core:event:allow-listen","core:event:allow-unlisten","os:allow-os-type","clipboard-manager:allow-clear","clipboard-manager:allow-write-text","clipboard-manager:allow-read-text","dialog:allow-open","dialog:allow-save","fs:allow-read-file","fs:allow-read-text-file",{"identifier":"fs:scope","allow":[{"path":"$APPDATA"},{"path":"$APPDATA/**"}]},"shell:allow-open","core:webview:allow-set-webview-zoom","core:window:allow-close","core:window:allow-is-fullscreen","core:window:allow-maximize","core:window:allow-minimize","core:window:allow-toggle-maximize","core:window:allow-set-decorations","core:window:allow-set-title","core:window:allow-start-dragging","core:window:allow-unmaximize","core:window:allow-theme","clipboard-manager:allow-read-text","clipboard-manager:allow-write-text"]}} {"main":{"identifier":"main","description":"Main permissions","local":true,"windows":["*"],"permissions":["core:event:allow-emit","core:event:allow-listen","core:event:allow-unlisten","os:allow-os-type","clipboard-manager:allow-clear","clipboard-manager:allow-write-text","clipboard-manager:allow-read-text","dialog:allow-open","dialog:allow-save","fs:allow-read-file","fs:allow-read-text-file",{"identifier":"fs:scope","allow":[{"path":"$APPDATA"},{"path":"$APPDATA/**"}]},"shell:allow-open","core:webview:allow-set-webview-zoom","core:window:allow-close","core:window:allow-is-fullscreen","core:window:allow-maximize","core:window:allow-minimize","core:window:allow-set-decorations","core:window:allow-set-title","core:window:allow-start-dragging","core:window:allow-theme","core:window:allow-toggle-maximize","core:window:allow-unmaximize","clipboard-manager:allow-read-text","clipboard-manager:allow-write-text"]}}
+140 -70
View File
@@ -2,13 +2,13 @@ extern crate core;
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
extern crate objc; extern crate objc;
use std::collections::{BTreeMap}; use std::collections::BTreeMap;
use std::fs;
use std::fs::{create_dir_all, read_to_string, File}; use std::fs::{create_dir_all, read_to_string, File};
use std::path::PathBuf; use std::path::PathBuf;
use std::process::exit; use std::process::exit;
use std::str::FromStr; use std::str::FromStr;
use std::time::Duration; use std::time::Duration;
use std::{fs, panic};
use base64::prelude::BASE64_STANDARD; use base64::prelude::BASE64_STANDARD;
use base64::Engine; use base64::Engine;
@@ -83,7 +83,9 @@ const DEFAULT_WINDOW_HEIGHT: f64 = 600.0;
const MIN_WINDOW_WIDTH: f64 = 300.0; const MIN_WINDOW_WIDTH: f64 = 300.0;
const MIN_WINDOW_HEIGHT: f64 = 300.0; const MIN_WINDOW_HEIGHT: f64 = 300.0;
const MAIN_WINDOW_PREFIX: &str = "main_"; const MAIN_WINDOW_PREFIX: &str = "main_";
const OTHER_WINDOW_PREFIX: &str = "other_";
#[derive(serde::Serialize)] #[derive(serde::Serialize)]
#[serde(default, rename_all = "camelCase")] #[serde(default, rename_all = "camelCase")]
@@ -1649,19 +1651,83 @@ async fn cmd_list_workspaces(w: WebviewWindow) -> Result<Vec<Workspace>, String>
} }
#[tauri::command] #[tauri::command]
async fn cmd_new_window(app_handle: AppHandle, url: &str) -> Result<(), String> { async fn cmd_new_child_window(
create_window(&app_handle, url); parent_window: WebviewWindow,
url: &str,
label: &str,
title: &str,
inner_size: (f64, f64),
) -> Result<(), String> {
let app_handle = parent_window.app_handle();
let label = format!("{OTHER_WINDOW_PREFIX}_{label}");
let scale_factor = parent_window.scale_factor().unwrap();
let current_pos = parent_window
.inner_position()
.unwrap()
.to_logical::<f64>(scale_factor);
let current_size = parent_window
.inner_size()
.unwrap()
.to_logical::<f64>(scale_factor);
// Position the new window in the middle of the parent
let position = (
current_pos.x + current_size.width / 2.0 - inner_size.0 / 2.0,
current_pos.y + current_size.height / 2.0 - inner_size.1 / 2.0,
);
let config = CreateWindowConfig {
label: label.as_str(),
title,
url,
inner_size,
position,
};
let child_window = create_window(&app_handle, config);
// NOTE: These listeners will remain active even when the windows close. Unfortunately,
// there's no way to unlisten to events for now, so we just have to be defensive.
{
let parent_window = parent_window.clone();
let child_window = child_window.clone();
child_window.clone().on_window_event(move |e| match e {
// When the new window is destroyed, bring the other up behind it
WindowEvent::Destroyed => {
if let Some(w) = parent_window.get_webview_window(child_window.label()) {
w.set_focus().unwrap();
}
}
_ => {}
});
}
{
let parent_window = parent_window.clone();
let child_window = child_window.clone();
parent_window.clone().on_window_event(move |e| match e {
// When the parent window is closed, close the child
WindowEvent::CloseRequested { .. } => child_window.destroy().unwrap(),
// When the parent window is focused, bring the child above
WindowEvent::Focused(focus) => {
if *focus {
if let Some(w) = parent_window.get_webview_window(child_window.label()) {
w.set_focus().unwrap();
};
}
}
_ => {}
});
}
Ok(()) Ok(())
} }
#[tauri::command] #[tauri::command]
async fn cmd_new_nested_window( async fn cmd_new_main_window(app_handle: AppHandle, url: &str) -> Result<(), String> {
window: WebviewWindow, create_main_window(&app_handle, url);
url: &str,
label: &str,
title: &str,
) -> Result<(), String> {
create_nested_window(&window, label, url, title);
Ok(()) Ok(())
} }
@@ -1721,7 +1787,18 @@ pub fn run() {
.build(), .build(),
) )
.plugin(tauri_plugin_clipboard_manager::init()) .plugin(tauri_plugin_clipboard_manager::init())
.plugin(tauri_plugin_window_state::Builder::default().build()) .plugin(
tauri_plugin_window_state::Builder::default()
.with_denylist(&["ignored"])
.map_label(|label| {
if label.starts_with(OTHER_WINDOW_PREFIX) {
"ignored"
} else {
label
}
})
.build(),
)
.plugin(tauri_plugin_shell::init()) .plugin(tauri_plugin_shell::init())
.plugin(tauri_plugin_updater::Builder::default().build()) .plugin(tauri_plugin_updater::Builder::default().build())
.plugin(tauri_plugin_dialog::init()) .plugin(tauri_plugin_dialog::init())
@@ -1810,8 +1887,8 @@ pub fn run() {
cmd_list_plugins, cmd_list_plugins,
cmd_list_workspaces, cmd_list_workspaces,
cmd_metadata, cmd_metadata,
cmd_new_nested_window, cmd_new_child_window,
cmd_new_window, cmd_new_main_window,
cmd_parse_template, cmd_parse_template,
cmd_plugin_info, cmd_plugin_info,
cmd_reload_plugins, cmd_reload_plugins,
@@ -1844,7 +1921,7 @@ pub fn run() {
.run(|app_handle, event| { .run(|app_handle, event| {
match event { match event {
RunEvent::Ready => { RunEvent::Ready => {
let w = create_window(app_handle, "/"); let w = create_main_window(app_handle, "/");
tauri::async_runtime::spawn(async move { tauri::async_runtime::spawn(async move {
let info = analytics::track_launch_event(&w).await; let info = analytics::track_launch_event(&w).await;
debug!("Launched Yaak {:?}", info); debug!("Launched Yaak {:?}", info);
@@ -1866,7 +1943,9 @@ pub fn run() {
tauri::async_runtime::spawn(async move { tauri::async_runtime::spawn(async move {
let val: State<'_, Mutex<YaakUpdater>> = h.state(); let val: State<'_, Mutex<YaakUpdater>> = h.state();
let update_mode = get_update_mode(&h).await; let update_mode = get_update_mode(&h).await;
_ = val.lock().await.check(&h, update_mode).await; if let Err(e) = val.lock().await.check(&h, update_mode).await {
warn!("Failed to check for updates {e:?}");
};
}); });
let h = app_handle.clone(); let h = app_handle.clone();
@@ -1897,47 +1976,31 @@ fn is_dev() -> bool {
} }
} }
fn create_nested_window( fn create_main_window(handle: &AppHandle, url: &str) -> WebviewWindow {
window: &WebviewWindow, let label = format!("{MAIN_WINDOW_PREFIX}{}", handle.webview_windows().len());
label: &str, let config = CreateWindowConfig {
url: &str, url,
title: &str, label: label.as_str(),
) -> WebviewWindow { title: "Yaak",
info!("Create new nested window label={label}"); inner_size: (DEFAULT_WINDOW_WIDTH, DEFAULT_WINDOW_HEIGHT),
let mut win_builder = tauri::WebviewWindowBuilder::new( position: (
window, // Offset by random amount so it's easier to differentiate
format!("nested_{}_{}", window.label(), label), 100.0 + random::<f64>() * 20.0,
WebviewUrl::App(url.into()), 100.0 + random::<f64>() * 20.0,
) ),
.resizable(true) };
.fullscreen(false) create_window(handle, config)
.disable_drag_drop_handler() // Required for frontend Dnd on windows
.title(title)
.parent(&window)
.unwrap()
.min_inner_size(MIN_WINDOW_WIDTH, MIN_WINDOW_HEIGHT)
.inner_size(DEFAULT_WINDOW_WIDTH * 0.7, DEFAULT_WINDOW_HEIGHT * 0.9);
// Add macOS-only things
#[cfg(target_os = "macos")]
{
win_builder = win_builder
.hidden_title(true)
.title_bar_style(TitleBarStyle::Overlay);
}
// Add non-macOS things
#[cfg(not(target_os = "macos"))]
{
win_builder = win_builder.decorations(false);
}
let win = win_builder.build().expect("failed to build window");
win
} }
fn create_window(handle: &AppHandle, url: &str) -> WebviewWindow { struct CreateWindowConfig<'s> {
url: &'s str,
label: &'s str,
title: &'s str,
inner_size: (f64, f64),
position: (f64, f64),
}
fn create_window(handle: &AppHandle, config: CreateWindowConfig) -> WebviewWindow {
#[allow(unused_variables)] #[allow(unused_variables)]
let menu = app_menu(handle).unwrap(); let menu = app_menu(handle).unwrap();
@@ -1945,22 +2008,17 @@ fn create_window(handle: &AppHandle, url: &str) -> WebviewWindow {
#[cfg(not(target_os = "linux"))] #[cfg(not(target_os = "linux"))]
handle.set_menu(menu).expect("Failed to set app menu"); handle.set_menu(menu).expect("Failed to set app menu");
let window_num = handle.webview_windows().len(); info!("Create new window label={}", config.label);
let label = format!("{MAIN_WINDOW_PREFIX}{window_num}");
info!("Create new window label={label}");
let mut win_builder = let mut win_builder =
tauri::WebviewWindowBuilder::new(handle, label, WebviewUrl::App(url.into())) tauri::WebviewWindowBuilder::new(handle, config.label, WebviewUrl::App(config.url.into()))
.title(config.title)
.resizable(true) .resizable(true)
.fullscreen(false) .fullscreen(false)
.disable_drag_drop_handler() // Required for frontend Dnd on windows .disable_drag_drop_handler() // Required for frontend Dnd on windows
.inner_size(DEFAULT_WINDOW_WIDTH, DEFAULT_WINDOW_HEIGHT) .inner_size(config.inner_size.0, config.inner_size.1)
.position( .position(config.position.0, config.position.1)
// Randomly offset so windows don't stack exactly .min_inner_size(MIN_WINDOW_WIDTH, MIN_WINDOW_HEIGHT);
100.0 + random::<f64>() * 30.0,
100.0 + random::<f64>() * 30.0,
)
.min_inner_size(MIN_WINDOW_WIDTH, MIN_WINDOW_HEIGHT)
.title(handle.package_info().name.to_string());
// Add macOS-only things // Add macOS-only things
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
@@ -1977,7 +2035,16 @@ fn create_window(handle: &AppHandle, url: &str) -> WebviewWindow {
win_builder = win_builder.decorations(false); win_builder = win_builder.decorations(false);
} }
let win = win_builder.build().expect("failed to build window"); if let Some(w) = handle.webview_windows().get(config.label) {
info!(
"Webview with label {} already exists. Focusing existing",
config.label
);
w.set_focus().unwrap();
return w.to_owned();
}
let win = win_builder.build().unwrap();
let webview_window = win.clone(); let webview_window = win.clone();
win.on_menu_event(move |w, event| { win.on_menu_event(move |w, event| {
@@ -1994,10 +2061,13 @@ fn create_window(handle: &AppHandle, url: &str) -> WebviewWindow {
"zoom_out" => w.emit("zoom_out", true).unwrap(), "zoom_out" => w.emit("zoom_out", true).unwrap(),
"settings" => w.emit("settings", true).unwrap(), "settings" => w.emit("settings", true).unwrap(),
"open_feedback" => { "open_feedback" => {
_ = webview_window if let Err(e) = webview_window
.app_handle() .app_handle()
.shell() .shell()
.open("https://yaak.app/roadmap", None) .open("https://yaak.app/feedback", None)
{
warn!("Failed to open feedback {e:?}")
}
} }
// Commands for development // Commands for development
+6 -2
View File
@@ -2,7 +2,11 @@ use hex_color::HexColor;
use log::warn; use log::warn;
use objc::{msg_send, sel, sel_impl}; use objc::{msg_send, sel, sel_impl};
use rand::{distributions::Alphanumeric, Rng}; use rand::{distributions::Alphanumeric, Rng};
use tauri::{plugin::{Builder, TauriPlugin}, Manager, Runtime, Window, WindowEvent, Emitter, Listener}; use tauri::{
plugin::{Builder, TauriPlugin},
Emitter, Listener, Manager, Runtime, Window, WindowEvent,
};
use crate::MAIN_WINDOW_PREFIX;
const WINDOW_CONTROL_PAD_X: f64 = 13.0; const WINDOW_CONTROL_PAD_X: f64 = 13.0;
const WINDOW_CONTROL_PAD_Y: f64 = 18.0; const WINDOW_CONTROL_PAD_Y: f64 = 18.0;
@@ -127,7 +131,7 @@ fn update_window_theme<R: Runtime>(window: Window<R>, color: HexColor) {
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
fn position_traffic_lights(ns_window_handle: UnsafeWindowHandle, x: f64, y: f64, label: String) { fn position_traffic_lights(ns_window_handle: UnsafeWindowHandle, x: f64, y: f64, label: String) {
if label.starts_with("nested_") { if !label.starts_with(MAIN_WINDOW_PREFIX) {
return; return;
} }
+5 -14
View File
@@ -1,11 +1,10 @@
import classNames from 'classnames'; import classNames from 'classnames';
import { search } from 'fast-fuzzy'; import { search } from 'fast-fuzzy';
import type { KeyboardEvent, ReactNode } from 'react'; import type { KeyboardEvent, ReactNode } from 'react';
import { useEffect, useRef, useCallback, useMemo, useState } from 'react'; import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { useActiveCookieJar } from '../hooks/useActiveCookieJar'; import { useActiveCookieJar } from '../hooks/useActiveCookieJar';
import { useActiveEnvironment } from '../hooks/useActiveEnvironment'; import { useActiveEnvironment } from '../hooks/useActiveEnvironment';
import { useActiveRequest } from '../hooks/useActiveRequest'; import { useActiveRequest } from '../hooks/useActiveRequest';
import { useActiveWorkspace } from '../hooks/useActiveWorkspace';
import { useAppRoutes } from '../hooks/useAppRoutes'; import { useAppRoutes } from '../hooks/useAppRoutes';
import { useCreateEnvironment } from '../hooks/useCreateEnvironment'; import { useCreateEnvironment } from '../hooks/useCreateEnvironment';
import { useCreateGrpcRequest } from '../hooks/useCreateGrpcRequest'; import { useCreateGrpcRequest } from '../hooks/useCreateGrpcRequest';
@@ -17,6 +16,7 @@ import { useEnvironments } from '../hooks/useEnvironments';
import type { HotkeyAction } from '../hooks/useHotKey'; import type { HotkeyAction } from '../hooks/useHotKey';
import { useHotKey } from '../hooks/useHotKey'; import { useHotKey } from '../hooks/useHotKey';
import { useHttpRequestActions } from '../hooks/useHttpRequestActions'; import { useHttpRequestActions } from '../hooks/useHttpRequestActions';
import { useOpenSettings } from '../hooks/useOpenSettings';
import { useOpenWorkspace } from '../hooks/useOpenWorkspace'; import { useOpenWorkspace } from '../hooks/useOpenWorkspace';
import { useRecentEnvironments } from '../hooks/useRecentEnvironments'; import { useRecentEnvironments } from '../hooks/useRecentEnvironments';
import { useRecentRequests } from '../hooks/useRecentRequests'; import { useRecentRequests } from '../hooks/useRecentRequests';
@@ -28,7 +28,6 @@ import { useSendAnyHttpRequest } from '../hooks/useSendAnyHttpRequest';
import { useSidebarHidden } from '../hooks/useSidebarHidden'; import { useSidebarHidden } from '../hooks/useSidebarHidden';
import { useWorkspaces } from '../hooks/useWorkspaces'; import { useWorkspaces } from '../hooks/useWorkspaces';
import { fallbackRequestName } from '../lib/fallbackRequestName'; import { fallbackRequestName } from '../lib/fallbackRequestName';
import { invokeCmd } from '../lib/tauri';
import { CookieDialog } from './CookieDialog'; import { CookieDialog } from './CookieDialog';
import { Button } from './core/Button'; import { Button } from './core/Button';
import { Heading } from './core/Heading'; import { Heading } from './core/Heading';
@@ -74,11 +73,11 @@ export function CommandPalette({ onClose }: { onClose: () => void }) {
const createGrpcRequest = useCreateGrpcRequest(); const createGrpcRequest = useCreateGrpcRequest();
const createEnvironment = useCreateEnvironment(); const createEnvironment = useCreateEnvironment();
const dialog = useDialog(); const dialog = useDialog();
const workspace = useActiveWorkspace();
const sendRequest = useSendAnyHttpRequest(); const sendRequest = useSendAnyHttpRequest();
const renameRequest = useRenameRequest(activeRequest?.id ?? null); const renameRequest = useRenameRequest(activeRequest?.id ?? null);
const deleteRequest = useDeleteRequest(activeRequest?.id ?? null); const deleteRequest = useDeleteRequest(activeRequest?.id ?? null);
const [, setSidebarHidden] = useSidebarHidden(); const [, setSidebarHidden] = useSidebarHidden();
const openSettings = useOpenSettings();
const workspaceCommands = useMemo<CommandPaletteItem[]>(() => { const workspaceCommands = useMemo<CommandPaletteItem[]>(() => {
const commands: CommandPaletteItem[] = [ const commands: CommandPaletteItem[] = [
@@ -86,14 +85,7 @@ export function CommandPalette({ onClose }: { onClose: () => void }) {
key: 'settings.open', key: 'settings.open',
label: 'Open Settings', label: 'Open Settings',
action: 'settings.show', action: 'settings.show',
onSelect: async () => { onSelect: openSettings.mutate,
if (workspace == null) return;
await invokeCmd('cmd_new_nested_window', {
url: routes.paths.workspaceSettings({ workspaceId: workspace.id }),
label: 'settings',
title: 'Yaak Settings',
});
},
}, },
{ {
key: 'app.create', key: 'app.create',
@@ -195,11 +187,10 @@ export function CommandPalette({ onClose }: { onClose: () => void }) {
deleteRequest.mutate, deleteRequest.mutate,
dialog, dialog,
httpRequestActions, httpRequestActions,
openSettings.mutate,
renameRequest.mutate, renameRequest.mutate,
routes.paths,
sendRequest, sendRequest,
setSidebarHidden, setSidebarHidden,
workspace,
]); ]);
const sortedRequests = useMemo(() => { const sortedRequests = useMemo(() => {
+1 -2
View File
@@ -160,9 +160,8 @@ export function GlobalHooks() {
return; return;
} }
const { interfaceScale, interfaceFontSize, editorFontSize } = settings; const { interfaceScale, editorFontSize } = settings;
getCurrentWebviewWindow().setZoom(interfaceScale).catch(console.error); getCurrentWebviewWindow().setZoom(interfaceScale).catch(console.error);
document.documentElement.style.setProperty('font-size', `${interfaceFontSize}px`);
document.documentElement.style.setProperty('--editor-font-size', `${editorFontSize}px`); document.documentElement.style.setProperty('--editor-font-size', `${editorFontSize}px`);
}, [settings]); }, [settings]);
+4 -16
View File
@@ -1,13 +1,11 @@
import { open } from '@tauri-apps/plugin-shell'; import { open } from '@tauri-apps/plugin-shell';
import { useRef } from 'react'; import { useRef } from 'react';
import { useActiveWorkspace } from '../hooks/useActiveWorkspace';
import { useAppInfo } from '../hooks/useAppInfo'; import { useAppInfo } from '../hooks/useAppInfo';
import { useAppRoutes } from '../hooks/useAppRoutes';
import { useCheckForUpdates } from '../hooks/useCheckForUpdates'; import { useCheckForUpdates } from '../hooks/useCheckForUpdates';
import { useExportData } from '../hooks/useExportData'; import { useExportData } from '../hooks/useExportData';
import { useImportData } from '../hooks/useImportData'; import { useImportData } from '../hooks/useImportData';
import { useListenToTauriEvent } from '../hooks/useListenToTauriEvent'; import { useListenToTauriEvent } from '../hooks/useListenToTauriEvent';
import { invokeCmd } from '../lib/tauri'; import { useOpenSettings } from '../hooks/useOpenSettings';
import type { DropdownRef } from './core/Dropdown'; import type { DropdownRef } from './core/Dropdown';
import { Dropdown } from './core/Dropdown'; import { Dropdown } from './core/Dropdown';
import { Icon } from './core/Icon'; import { Icon } from './core/Icon';
@@ -22,19 +20,9 @@ export function SettingsDropdown() {
const dropdownRef = useRef<DropdownRef>(null); const dropdownRef = useRef<DropdownRef>(null);
const dialog = useDialog(); const dialog = useDialog();
const checkForUpdates = useCheckForUpdates(); const checkForUpdates = useCheckForUpdates();
const routes = useAppRoutes(); const openSettings = useOpenSettings();
const workspace = useActiveWorkspace();
const showSettings = async () => { useListenToTauriEvent('settings', () => openSettings.mutate());
if (!workspace) return;
await invokeCmd('cmd_new_nested_window', {
url: routes.paths.workspaceSettings({ workspaceId: workspace.id }),
label: 'settings',
title: 'Yaak Settings',
});
};
useListenToTauriEvent('settings', showSettings);
return ( return (
<Dropdown <Dropdown
@@ -45,7 +33,7 @@ export function SettingsDropdown() {
label: 'Settings', label: 'Settings',
hotKeyAction: 'settings.show', hotKeyAction: 'settings.show',
leftSlot: <Icon icon="settings" />, leftSlot: <Icon icon="settings" />,
onSelect: showSettings, onSelect: openSettings.mutate,
}, },
{ {
key: 'hotkeys', key: 'hotkeys',
+15
View File
@@ -0,0 +1,15 @@
// Listen for settings changes, the re-compute theme
import { listen } from '@tauri-apps/api/event';
import type { ModelPayload } from './components/GlobalHooks';
import { getSettings } from './lib/store';
function setFontSizeOnDocument(fontSize: number) {
document.documentElement.style.fontSize = `${fontSize}px`;
}
listen<ModelPayload>('upserted_model', async (event) => {
if (event.payload.model.model !== 'settings') return;
setFontSizeOnDocument(event.payload.model.interfaceFontSize);
}).catch(console.error);
getSettings().then((settings) => setFontSizeOnDocument(settings.interfaceFontSize));
+22
View File
@@ -0,0 +1,22 @@
import { useMutation } from '@tanstack/react-query';
import { invokeCmd } from '../lib/tauri';
import { useActiveWorkspace } from './useActiveWorkspace';
import { useAppRoutes } from './useAppRoutes';
export function useOpenSettings() {
const routes = useAppRoutes();
const workspace = useActiveWorkspace();
return useMutation({
mutationKey: ['open_settings'],
mutationFn: async () => {
if (workspace == null) return;
await invokeCmd('cmd_new_child_window', {
url: routes.paths.workspaceSettings({ workspaceId: workspace.id }),
label: 'settings',
title: 'Yaak Settings',
innerSize: [600, 550],
});
},
});
}
+1 -1
View File
@@ -26,7 +26,7 @@ export function useOpenWorkspace() {
requestId != null requestId != null
? routes.paths.request({ ...baseArgs, requestId }) ? routes.paths.request({ ...baseArgs, requestId })
: routes.paths.workspace({ ...baseArgs }); : routes.paths.workspace({ ...baseArgs });
await invokeCmd('cmd_new_window', { url: path }); await invokeCmd('cmd_new_main_window', { url: path });
} else { } else {
if (requestId != null) { if (requestId != null) {
routes.navigate('request', { ...baseArgs, requestId }); routes.navigate('request', { ...baseArgs, requestId });
+1
View File
@@ -27,6 +27,7 @@
<div id="react-portal"></div> <div id="react-portal"></div>
<div id="radix-portal" class="cm-portal"></div> <div id="radix-portal" class="cm-portal"></div>
<script type="module" src="/theme.ts"></script> <script type="module" src="/theme.ts"></script>
<script type="module" src="/font-size.ts"></script>
<script type="module" src="/main.tsx"></script> <script type="module" src="/main.tsx"></script>
</body> </body>
</html> </html>
+2 -2
View File
@@ -51,8 +51,8 @@ type TauriCmd =
| 'cmd_list_plugins' | 'cmd_list_plugins'
| 'cmd_list_workspaces' | 'cmd_list_workspaces'
| 'cmd_metadata' | 'cmd_metadata'
| 'cmd_new_nested_window' | 'cmd_new_main_window'
| 'cmd_new_window' | 'cmd_new_child_window'
| 'cmd_parse_template' | 'cmd_parse_template'
| 'cmd_plugin_info' | 'cmd_plugin_info'
| 'cmd_render_template' | 'cmd_render_template'