mirror of
https://gitlab.com/ArkHost/HelixNotes.git
synced 2026-07-24 07:45:57 +02:00
Fix #63: decide layout from compile-time platform, not the webview user-agent
This commit is contained in:
@@ -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';
|
||||
|
||||
@@ -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');
|
||||
|
||||
@@ -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<HTMLCanvasElement>(null!);
|
||||
let loading = $state(true);
|
||||
let searchQuery = $state('');
|
||||
|
||||
@@ -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[] }[] = [
|
||||
|
||||
@@ -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<TrashNotebookEntry[]>([]);
|
||||
let trashBusy = $state<string | null>(null);
|
||||
|
||||
@@ -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<SearchResult[]>([]);
|
||||
@@ -83,8 +84,6 @@
|
||||
return str.replace(/&/g, '&').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);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script lang="ts">
|
||||
import { showSettings, theme, appConfig, updateAvailable as globalUpdateAvailable, updateObj as globalUpdateObj, installType, settingsTab, vaultReady, androidApkUrl, checkForUpdateMobile, notebookSortMode, isManagedInstall } from '$lib/stores/app';
|
||||
import { setTheme, setAccentColor, setFontSize, setFontFamily, setLineHeight, setUiScale, setContentWidth, setGeneralSettings, importObsidian, createBackup, listBackups, restoreBackup, deleteBackup, setBackupSettings, setAiSettings, testAiConnection, setSyncSettings, testSyncConnection, syncNow } from '$lib/api';
|
||||
import { darkThemes } from '$lib/platform';
|
||||
import { darkThemes, isMobile } from '$lib/platform';
|
||||
import { open as openDialog } from '@tauri-apps/plugin-dialog';
|
||||
import { listen } from '@tauri-apps/api/event';
|
||||
import { getVersion } from '@tauri-apps/api/app';
|
||||
@@ -9,7 +9,6 @@
|
||||
import { openUrl } from '$lib/api';
|
||||
import type { ImportResult, BackupEntry } from '$lib/types';
|
||||
|
||||
const isMobile = /android|iphone|ipad|ipod/i.test(navigator.userAgent);
|
||||
const modKey = navigator.platform.startsWith('Mac') ? '⌘' : 'Ctrl';
|
||||
|
||||
type Tab = 'general' | 'editor' | 'styling' | 'import' | 'backup' | 'ai' | 'sync' | 'updates';
|
||||
|
||||
@@ -26,13 +26,13 @@
|
||||
import { readFile } from '@tauri-apps/plugin-fs';
|
||||
import { convertFileSrc } from '@tauri-apps/api/core';
|
||||
import type { NotebookEntry } from '$lib/types';
|
||||
import { isMobile } from '$lib/platform';
|
||||
|
||||
let { onViewChanged = () => {} }: {
|
||||
onViewChanged?: () => void;
|
||||
} = $props();
|
||||
|
||||
const modKey = navigator.platform.startsWith('Mac') ? '⌘' : 'Ctrl';
|
||||
const isMobile = /android|iphone|ipad|ipod/i.test(navigator.userAgent);
|
||||
|
||||
// Whether any top nav item (All Notes, Quick Access, Tasks, Daily Notes, Trash) is visible.
|
||||
// When all are hidden we drop the empty <nav> and its divider so the tree sits flush.
|
||||
|
||||
+14
-5
@@ -1,10 +1,19 @@
|
||||
// Centralized platform detection. iOS WebViews report iPhone/iPad/iPod in the user
|
||||
// agent (not the literal "ios"), so they must be matched explicitly.
|
||||
// Platform is the compile-time build target, injected by the backend into
|
||||
// window.__HELIX_PLATFORM__ before app scripts run (see src-tauri/src/lib.rs). The UA is only a
|
||||
// fallback when that global is absent (SSR/prerender, plain-browser dev): some desktop WebKitGTK
|
||||
// builds report a mobile-looking user-agent. (#63)
|
||||
type HelixPlatform = { mobile: boolean; android: boolean; ios: boolean };
|
||||
|
||||
const injected: HelixPlatform | undefined =
|
||||
typeof window !== 'undefined'
|
||||
? (window as unknown as { __HELIX_PLATFORM__?: HelixPlatform }).__HELIX_PLATFORM__
|
||||
: undefined;
|
||||
|
||||
const ua = typeof navigator !== 'undefined' ? navigator.userAgent : '';
|
||||
|
||||
export const isAndroid = /android/i.test(ua);
|
||||
export const isIOS = /iphone|ipad|ipod/i.test(ua);
|
||||
export const isMobile = isAndroid || isIOS;
|
||||
export const isAndroid = injected ? injected.android : /android/i.test(ua);
|
||||
export const isIOS = injected ? injected.ios : /iphone|ipad|ipod/i.test(ua);
|
||||
export const isMobile = injected ? injected.mobile : isAndroid || isIOS;
|
||||
|
||||
// Themes that use the dark color scheme. Used by applyTheme() to toggle the
|
||||
// `dark` class on the root element. Keep this in sync when adding new themes.
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { writable, derived, get } from "svelte/store";
|
||||
import { isMobile } from "$lib/platform";
|
||||
import type {
|
||||
AppConfig,
|
||||
NoteEntry,
|
||||
@@ -87,11 +88,8 @@ export const updateAvailable = writable<{
|
||||
} | null>(null);
|
||||
export const updateObj = writable<any>(null);
|
||||
export const installType = writable<string>("native");
|
||||
// True only on the Android/iOS build. Defaults to a user-agent guess for the first paint, then
|
||||
// gets the authoritative compile-time value from the backend at startup (see +layout). (#63)
|
||||
export const platformIsMobile = writable<boolean>(
|
||||
typeof navigator !== "undefined" && /android|iphone|ipad|ipod/i.test(navigator.userAgent),
|
||||
);
|
||||
// True only on the Android/iOS build. Reconfirmed from the backend at startup (see +layout). (#63)
|
||||
export const platformIsMobile = writable<boolean>(isMobile);
|
||||
export const androidApkUrl = writable<string | null>(null);
|
||||
|
||||
// Install types that handle their own updates (in-app auto-updater, or a
|
||||
|
||||
Reference in New Issue
Block a user