Update files
This commit is contained in:
@@ -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();
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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"
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user