diff --git a/apps/desktop/src-tauri/src/commands.rs b/apps/desktop/src-tauri/src/commands.rs index 5cdb1cbf..41d8a12f 100644 --- a/apps/desktop/src-tauri/src/commands.rs +++ b/apps/desktop/src-tauri/src/commands.rs @@ -12,6 +12,7 @@ pub fn open_settings(window: WebviewWindow, update: bool) { let app = window.app_handle(); let settings_windows = app.get_webview_window(SETTINGS_WINDOW_NAME); if let Some(settings_windows) = settings_windows { + let _ = settings_windows.unminimize(); settings_windows.show(); settings_windows.set_focus(); if update { @@ -47,12 +48,18 @@ pub fn toggle_pin(window: WebviewWindow, pin: State, menu: State()); - _set_pin(value, &window, pin, menu); + // Always target the main overlay window so pinning from other windows + // (e.g., settings) does not affect those windows. + if let Some(main_win) = app.get_webview_window(MAIN_WINDOW_NAME) { + _set_pin(value, &main_win, pin, menu); + } } #[tauri::command] pub fn set_pin(window: WebviewWindow, pin: State, menu: State, value: bool) { - _set_pin(value, &window, pin, menu); + if let Some(main_win) = window.app_handle().get_webview_window(MAIN_WINDOW_NAME) { + _set_pin(value, &main_win, pin, menu); + } } impl Deref for Pinned { @@ -75,9 +82,20 @@ fn _set_pin(value: bool, window: &WebviewWindow, pinned: State, menu: St // @d0nutptr cooked here pinned.store(value, std::sync::atomic::Ordering::Relaxed); - // let the client know + // emit to the main window and also broadcast to all webviews so other + // windows (like settings) can react to the change. window.emit(TRAY_TOGGLE_PIN, value).unwrap(); + // Broadcast the pin change to all webviews so other + // windows (like settings) can react to the change. + let app_handle = window.app_handle(); + if let Some(main_win) = app_handle.get_webview_window(MAIN_WINDOW_NAME) { + let _ = main_win.emit(TRAY_TOGGLE_PIN, value); + } + if let Some(settings_win) = app_handle.get_webview_window(SETTINGS_WINDOW_NAME) { + let _ = settings_win.emit(TRAY_TOGGLE_PIN, value); + } + // invert the label for the tray if let Some(toggle_pin_menu_item) = menu.lock().ok().and_then(|m| m.get(TRAY_TOGGLE_PIN)) { let enable_or_disable = if value { "Unpin" } else { "Pin" }; diff --git a/apps/desktop/src-tauri/src/main.rs b/apps/desktop/src-tauri/src/main.rs index 8f844c23..fe8f5706 100644 --- a/apps/desktop/src-tauri/src/main.rs +++ b/apps/desktop/src-tauri/src/main.rs @@ -152,6 +152,9 @@ fn main() { width: SETTINGS_WINDOW_WIDTH, height: SETTINGS_WINDOW_HEIGHT, }); + // Start the settings window minimized so it's available but not intrusive + // The `show` call from the UI will restore/unminimize it. + settings.minimize().ok(); Ok(()) }) @@ -168,22 +171,39 @@ fn main() { .build(tauri::generate_context!()) .expect("An error occured while running the app!") .run(|app, event| { + use tauri::WindowEvent as WEvent; + if let tauri::RunEvent::WindowEvent { - event: tauri::WindowEvent::CloseRequested { api, .. }, - label, - .. + event: we, label, .. } = event { - if label == SETTINGS_WINDOW_NAME { - let win = app.get_webview_window(label.as_str()).unwrap(); - win.hide().unwrap(); - } - - if label == MAIN_WINDOW_NAME { - app.save_window_state(StateFlags::POSITION | StateFlags::SIZE); - std::process::exit(0); - } else { - api.prevent_close(); + match we { + WEvent::CloseRequested { api, .. } => { + if label == SETTINGS_WINDOW_NAME { + let win = app.get_webview_window(label.as_str()).unwrap(); + // Minimize the settings window instead of hiding/closing it when + // the user clicks the X so it remains available to restore. + win.minimize().ok(); + } + + if label == MAIN_WINDOW_NAME { + // Save state on close + app.save_window_state(StateFlags::POSITION | StateFlags::SIZE); + std::process::exit(0); + } else { + api.prevent_close(); + } + } + + WEvent::Resized(_) | WEvent::Moved(_) => { + if label == MAIN_WINDOW_NAME { + // Also save state whenever the main window is moved or resized so + // we persist the latest bounds even if the process is terminated + app.save_window_state(StateFlags::POSITION | StateFlags::SIZE); + } + } + + _ => {} } } }); diff --git a/apps/desktop/src-tauri/tauri.conf.json b/apps/desktop/src-tauri/tauri.conf.json index d1a5fe66..ca70b57f 100644 --- a/apps/desktop/src-tauri/tauri.conf.json +++ b/apps/desktop/src-tauri/tauri.conf.json @@ -52,7 +52,7 @@ "transparent": true, "decorations": true, "resizable": false, - "visible": false, + "visible": true, "label": "settings", "url": "#settings", "title": "Overlayed - Settings", diff --git a/apps/desktop/src/App.tsx b/apps/desktop/src/App.tsx index b95c2aa4..ea5db09d 100644 --- a/apps/desktop/src/App.tsx +++ b/apps/desktop/src/App.tsx @@ -1,4 +1,4 @@ -import { Routes, Route } from "react-router-dom"; +import { Routes, Route, useLocation } from "react-router-dom"; import { MainView } from "./views/main"; import { ChannelView } from "./views/channel"; @@ -30,12 +30,15 @@ function App() { const { pin } = usePin(); const { horizontal, setHorizontalDirection } = useAlign(); const visibleClass = visible ? "opacity-100" : "opacity-0"; + const location = useLocation(); + const isSettingsWindow = location.pathname === "/settings"; return (
{!pin && ( @@ -48,10 +51,10 @@ function App() { )} - + } /> } /> } /> - + } />
); diff --git a/apps/desktop/src/components/nav-bar.tsx b/apps/desktop/src/components/nav-bar.tsx index 48f7eb05..63a1282b 100644 --- a/apps/desktop/src/components/nav-bar.tsx +++ b/apps/desktop/src/components/nav-bar.tsx @@ -16,6 +16,7 @@ import { useState } from "react"; import { CHANNEL_TYPES } from "@/constants"; import { Metric, track } from "@/metrics"; import { invoke } from "@tauri-apps/api/core"; +import { emit } from "@tauri-apps/api/event"; const mapping = { left: 0, center: 1, @@ -64,6 +65,11 @@ export const NavBar = ({ const [channelName, setChannelName] = useState(); const [currentAlignment, setCurrentAlignment] = useState(mapping[alignDirection]); + // keep local currentAlignment in sync when the prop changes (e.g., loaded from config) + useEffect(() => { + setCurrentAlignment(mapping[alignDirection] ?? mapping.right); + }, [alignDirection]); + const opacity = pin && location.pathname === "/channel" ? "opacity-0" : "opacity-100"; const IconComponent = horizontalAlignments[currentAlignment]?.icon || ArrowLeftToLine; const showUpdateButton = location.pathname !== "/settings" && isUpdateAvailable; @@ -87,7 +93,7 @@ export const NavBar = ({
logo {!canary && showUpdateButton && ( - )} - - +
{ @@ -167,7 +187,7 @@ export const Account = () => { open={showLogoutDialog} > - @@ -208,7 +228,7 @@ export const Account = () => { open={showQuitDialog} > - diff --git a/apps/desktop/src/views/settings/configuration.tsx b/apps/desktop/src/views/settings/configuration.tsx index 7da168ff..0e913e5b 100644 --- a/apps/desktop/src/views/settings/configuration.tsx +++ b/apps/desktop/src/views/settings/configuration.tsx @@ -1,4 +1,4 @@ -import { Input } from "@/components/ui/input"; +import { Slider } from "@/components/ui/slider"; import { Switch } from "@/components/ui/switch"; import Config from "@/config"; import { useConfigValue } from "@/hooks/use-config-value"; @@ -7,13 +7,18 @@ import { emit } from "@tauri-apps/api/event"; export const Configuration = () => { const { value: showOnlyTalkingUsers } = useConfigValue("showOnlyTalkingUsers"); const { value: opacity } = useConfigValue("opacity"); + const { value: opacityTarget } = useConfigValue("opacityTarget"); + const { value: vertical } = useConfigValue("vertical"); + const { value: horizontal } = useConfigValue("horizontal"); + const { value: maxUsernameLength } = useConfigValue("maxUsernameLength"); + const { value: userScale } = useConfigValue("userScale"); return (
-
+
@@ -28,27 +33,164 @@ export const Configuration = () => { }} />
-
+
- +
+ { + const newVal = val[0] ?? maxUsernameLength; + await Config.set("maxUsernameLength", Number(newVal)); + await emit("config_update", await Config.getConfig()); + }} + /> +
+
+ {maxUsernameLength} +
+
+
+
+ + +
+
+ + +
+
+ + +
+
+ +
+
+ { + const newVal = val[0] ?? opacity; + await Config.set("opacity", Number(newVal)); + await emit("config_update", await Config.getConfig()); + }} + /> +
+
+ {opacity} % +
+
+
+
+ +
+
+ { + const newVal = val[0] ?? userScale; + await Config.set("userScale", Number(newVal)); + await emit("config_update", await Config.getConfig()); + }} + /> +
+
+ {userScale} % +
+
);