Update files

This commit is contained in:
Mohamed Boudra
2026-02-05 22:35:43 +07:00
parent 29bca7e7b9
commit b1b0be7b56
5 changed files with 80 additions and 26 deletions
+48 -25
View File
@@ -14,21 +14,38 @@ async function getTauriWindow() {
if (tauriWindow) return tauriWindow; if (tauriWindow) return tauriWindow;
// Double-check: both environment check AND platform check // Double-check: both environment check AND platform check
if (!isTauriEnvironment() || !getIsTauriMac()) { if (!isTauriEnvironment()) {
return null; return null;
} }
try { try {
// Avoid emitting `import()` syntax into the Hermes bundle (it fails to parse), // When `app.withGlobalTauri` is enabled, Tauri exposes its JS APIs on `window.__TAURI__`.
// while still loading the Tauri module at runtime in the WebView. // We must use that here because importing `@tauri-apps/api/*` would be bundled into
const dynamicImport = new Function( // the native (Hermes) builds and break parsing/runtime on mobile.
"moduleName", const tauri = (window as any).__TAURI__ as any;
"return import(moduleName)"
) as (moduleName: string) => Promise<any>;
const { getCurrentWindow } = await dynamicImport("@tauri-apps/api/window"); // Prefer the public global window module.
tauriWindow = getCurrentWindow(); const windowModule = tauri?.window;
return tauriWindow; if (windowModule && typeof windowModule.getCurrentWindow === "function") {
tauriWindow = windowModule.getCurrentWindow();
return tauriWindow;
}
// Fallback: core invoke (should exist when withGlobalTauri is enabled).
// We assume the main window label is "main" (default in Tauri when not specified).
const invoke = tauri?.core?.invoke;
if (typeof invoke === "function") {
tauriWindow = {
label: "main",
startDragging: () => invoke("plugin:window|start_dragging", { label: "main" }),
toggleMaximize: () => invoke("plugin:window|toggle_maximize", { label: "main" }),
isFullscreen: () => invoke("plugin:window|is_fullscreen", { label: "main" }),
onResized: (handler: (e: unknown) => void) => tauri?.event?.listen?.("tauri://resize", handler),
};
return tauriWindow;
}
return null;
} catch { } catch {
return null; return null;
} }
@@ -37,43 +54,49 @@ async function getTauriWindow() {
export async function startDragging() { export async function startDragging() {
const win = await getTauriWindow(); const win = await getTauriWindow();
if (win) { if (win) {
await win.startDragging(); try {
await win.startDragging();
} catch (error) {
console.warn("[TauriWindow] startDragging failed", error);
}
} }
} }
export async function toggleMaximize() { export async function toggleMaximize() {
const win = await getTauriWindow(); const win = await getTauriWindow();
if (win) { if (win) {
await win.toggleMaximize(); try {
await win.toggleMaximize();
} catch (error) {
console.warn("[TauriWindow] toggleMaximize failed", error);
}
} }
} }
// Returns event handlers for drag region behavior // Returns event handlers for drag region behavior
export function useTauriDragHandlers() { export function useTauriDragHandlers() {
if (Platform.OS !== "web" || !getIsTauriMac()) { // Dragging should work on any desktop OS when running under Tauri.
if (Platform.OS !== "web" || !isTauriEnvironment()) {
return {}; return {};
} }
return { return {
onMouseDown: (e: React.MouseEvent) => { onMouseDown: (e: React.MouseEvent) => {
// Only handle left click, ignore if clicking on interactive elements // Only handle primary button, ignore if clicking on interactive elements.
if (e.button !== 0) return; // Tauri docs recommend using `e.detail` on mousedown for double-click maximize.
if (typeof e.buttons === "number" ? e.buttons !== 1 : e.button !== 0) return;
const target = e.target as HTMLElement; const target = e.target as HTMLElement;
if (target.closest("button, a, input, [role='button']")) return; if (target.closest("button, a, input, [role='button']")) return;
// Prevent text selection when dragging // Prevent text selection when dragging
e.preventDefault(); e.preventDefault();
// Start dragging on mouse down // Double click to maximize, otherwise drag.
startDragging(); if (e.detail === 2) {
}, toggleMaximize();
onDoubleClick: (e: React.MouseEvent) => { } else {
// Ignore if clicking on interactive elements startDragging();
const target = e.target as HTMLElement; }
if (target.closest("button, a, input, [role='button']")) return;
e.preventDefault();
toggleMaximize();
}, },
}; };
} }
+16
View File
@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleIdentifier</key>
<string>dev.paseo.desktop</string>
<key>CFBundleName</key>
<string>Paseo</string>
<key>CFBundleShortVersionString</key>
<string>0.1.0</string>
<key>CFBundleVersion</key>
<string>0.1.0</string>
<key>NSMicrophoneUsageDescription</key>
<string>Paseo needs access to your microphone for voice dictation and voice mode.</string>
</dict>
</plist>
@@ -2,6 +2,12 @@
"$schema": "../gen/schemas/desktop-schema.json", "$schema": "../gen/schemas/desktop-schema.json",
"identifier": "default", "identifier": "default",
"description": "enables the default permissions", "description": "enables the default permissions",
"remote": {
"urls": [
"http://localhost:8081/*",
"http://127.0.0.1:8081/*"
]
},
"windows": [ "windows": [
"main" "main"
], ],
+6
View File
@@ -1,6 +1,12 @@
// Prevents additional console window on Windows in release, DO NOT REMOVE!! // Prevents additional console window on Windows in release, DO NOT REMOVE!!
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
// `tauri dev` runs the raw executable (`target/debug/Paseo`) on macOS (not the .app bundle),
// so we must embed an Info.plist containing `NSMicrophoneUsageDescription` for WebKit
// microphone access to trigger the OS permission prompt in dev.
#[cfg(all(target_os = "macos", debug_assertions))]
tauri::embed_plist::embed_info_plist!("../Info.plist");
fn main() { fn main() {
paseo_lib::run(); paseo_lib::run();
} }
+4 -1
View File
@@ -36,6 +36,9 @@
"icons/128x128@2x.png", "icons/128x128@2x.png",
"icons/icon.icns", "icons/icon.icns",
"icons/icon.ico" "icons/icon.ico"
] ],
"macOS": {
"infoPlist": "Info.plist"
}
} }
} }