diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 364fe54..63ca13b 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -38,7 +38,21 @@ pub fn run() { let close_to_tray = config.close_to_tray && show_tray; let app_state = AppState::new(config); + // Inject the compile-time platform so the frontend never sniffs the (sometimes + // mobile-looking) WebKitGTK user-agent. (#63) + let platform_init = format!( + "window.__HELIX_PLATFORM__={{mobile:{},android:{},ios:{}}};", + cfg!(mobile), + cfg!(target_os = "android"), + cfg!(target_os = "ios"), + ); + let mut builder = tauri::Builder::default() + .plugin( + tauri::plugin::Builder::::new("helix-platform") + .js_init_script(platform_init) + .build(), + ) .plugin(tauri_plugin_dialog::init()) .plugin(tauri_plugin_fs::init()) .plugin(tauri_plugin_opener::init()) diff --git a/src/lib/components/AppLayout.svelte b/src/lib/components/AppLayout.svelte index 6035d1c..8a92e4e 100644 --- a/src/lib/components/AppLayout.svelte +++ b/src/lib/components/AppLayout.svelte @@ -58,9 +58,8 @@ const appWindow = getCurrentWindow(); const isMac = navigator.platform.startsWith('Mac'); const isMobile = $derived($platformIsMobile); - const isAndroid = /android/i.test(navigator.userAgent); import { loadVaultState, saveVaultState, readNote, createDailyNote, createBackup, getPendingOpenFile, addQuickAccess, removeQuickAccess, getQuickAccess, setTheme, syncNow, setTaskDone, setTaskPriority, setTaskDue } from '$lib/api'; - import { darkThemes } from '$lib/platform'; + import { darkThemes, isAndroid } from '$lib/platform'; import { debounce } from '$lib/utils/debounce'; import { openNoteWindow } from '$lib/utils/window'; import { get } from 'svelte/store'; diff --git a/src/lib/components/Editor.svelte b/src/lib/components/Editor.svelte index 0407aa1..432c85f 100644 --- a/src/lib/components/Editor.svelte +++ b/src/lib/components/Editor.svelte @@ -49,9 +49,9 @@ import { wrapTextareaSelection } from '$lib/editor/source/selectionPairs'; import GraphView from './GraphView.svelte'; import TagSuggestInput from './TagSuggestInput.svelte'; + import { isMobile, isAndroid } from '$lib/platform'; const modKey = navigator.platform.startsWith('Mac') ? '⌘' : 'Ctrl'; - const isMobile = /android|iphone|ipad|ipod/i.test(navigator.userAgent); // Track virtual keyboard height on mobile via visualViewport let keyboardHeight = $state(0); @@ -1028,7 +1028,6 @@ function addToolbar(container: HTMLElement, source: string) { const toolbar = document.createElement('div'); toolbar.className = 'mermaid-render-toolbar'; - const isAndroid = /android/i.test(navigator.userAgent); if (!isAndroid) { const copyBtn = document.createElement('button'); diff --git a/src/lib/components/GraphView.svelte b/src/lib/components/GraphView.svelte index 9a0a44f..5191011 100644 --- a/src/lib/components/GraphView.svelte +++ b/src/lib/components/GraphView.svelte @@ -2,14 +2,13 @@ import { onDestroy } from 'svelte'; import { getGraphData } from '$lib/api'; import { activeNotePath, appConfig } from '$lib/stores/app'; + import { isMobile } from '$lib/platform'; let { onclose, onnavigate }: { onclose: () => void; onnavigate: (path: string, title: string) => void; } = $props(); - const isMobile = /android|iphone|ipad|ipod/i.test(navigator.userAgent); - let canvas = $state(null!); let loading = $state(true); let searchQuery = $state(''); diff --git a/src/lib/components/InfoPanel.svelte b/src/lib/components/InfoPanel.svelte index 0df984d..6adf445 100644 --- a/src/lib/components/InfoPanel.svelte +++ b/src/lib/components/InfoPanel.svelte @@ -15,9 +15,9 @@ bindingsEqual, type ActionDef, } from '$lib/keybindings'; + import { isMobile } from '$lib/platform'; const modKey = navigator.platform.startsWith('Mac') ? '⌘' : 'Ctrl'; - const isMobile = /android|iphone|ipad|ipod/i.test(navigator.userAgent); // Customizable shortcuts, grouped for display. const actionGroups: { title: string; actions: ActionDef[] }[] = [ diff --git a/src/lib/components/NoteList.svelte b/src/lib/components/NoteList.svelte index 22385d4..e2c8b83 100644 --- a/src/lib/components/NoteList.svelte +++ b/src/lib/components/NoteList.svelte @@ -43,6 +43,7 @@ import type { NoteEntry, TrashNotebookEntry, SortMode, TaskItem } from '$lib/types'; import TasksView from './TasksView.svelte'; import TagSuggestInput from './TagSuggestInput.svelte'; + import { isMobile, isAndroid } from '$lib/platform'; let { onNoteSelected = (_path: string, _content: string) => {}, onNoteMoved = () => {}, onBeforeNoteSwitch = () => {}, onNoteCreated = () => {}, onToggleTask = async (_t: TaskItem) => {}, onSetTaskPriority = async (_t: TaskItem, _p: string | null) => {}, onSetTaskDue = async (_t: TaskItem, _d: string | null) => {} }: { onNoteSelected?: (path: string, content: string) => void; @@ -55,8 +56,6 @@ } = $props(); const modKey = navigator.platform.startsWith('Mac') ? '⌘' : 'Ctrl'; - const isMobile = /android|iphone|ipad|ipod/i.test(navigator.userAgent); - const isAndroid = /android/i.test(navigator.userAgent); let multiSelectMode = $state(false); let trashNotebooks = $state([]); let trashBusy = $state(null); diff --git a/src/lib/components/SearchPanel.svelte b/src/lib/components/SearchPanel.svelte index 0e00f77..1909a61 100644 --- a/src/lib/components/SearchPanel.svelte +++ b/src/lib/components/SearchPanel.svelte @@ -3,6 +3,7 @@ import { searchNotes, readNote } from '$lib/api'; import { debounce } from '$lib/utils/debounce'; import type { SearchResult } from '$lib/types'; + import { isMobile } from '$lib/platform'; let query = $state(''); let results = $state([]); @@ -83,8 +84,6 @@ return str.replace(/&/g, '&').replace(//g, '>'); } - const isMobile = /android|iphone|ipad|ipod/i.test(navigator.userAgent); - async function openResult(result: SearchResult) { try { const content = await readNote(result.path); diff --git a/src/lib/components/SettingsPanel.svelte b/src/lib/components/SettingsPanel.svelte index 31ba7a0..c5caf31 100644 --- a/src/lib/components/SettingsPanel.svelte +++ b/src/lib/components/SettingsPanel.svelte @@ -1,7 +1,7 @@