mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-07-08 05:45:10 +02:00
Make settings menu a regular window (#113)
This commit is contained in:
@@ -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
|
||||||
|
|||||||
@@ -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 @@
|
|||||||
{"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
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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(() => {
|
||||||
|
|||||||
@@ -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]);
|
||||||
|
|
||||||
|
|||||||
@@ -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',
|
||||||
|
|||||||
@@ -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));
|
||||||
@@ -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],
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -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 });
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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'
|
||||||
|
|||||||
Reference in New Issue
Block a user