From 0288e6f5a0d9ee2cf3a15a148606c68236d460ee Mon Sep 17 00:00:00 2001 From: Cfp Date: Mon, 11 Aug 2025 13:57:33 +0200 Subject: [PATCH] feat: replace capacitor components --- bun.lock | 3 + package.json | 1 + src/lib/services/DuckPlugin.ts | 19 -- src/lib/services/OfflineTiles-Cap.ts | 173 ------------------ src/lib/services/navigation/TTS.ts | 6 +- src/lib/services/navigation/routing.svelte.ts | 8 - 6 files changed, 7 insertions(+), 203 deletions(-) delete mode 100644 src/lib/services/DuckPlugin.ts delete mode 100644 src/lib/services/OfflineTiles-Cap.ts diff --git a/bun.lock b/bun.lock index 4728f5d..b5377f8 100644 --- a/bun.lock +++ b/bun.lock @@ -26,6 +26,7 @@ "pmtiles": "^4.3.0", "sql.js": "^1.13.0", "svelte-maplibre-gl": "^0.1.8", + "tauri-plugin-duck-api": "^0.1.1", "tauri-plugin-keep-screen-on-api": "^0.1.4", "typescript-eslint": "^8.34.1", }, @@ -926,6 +927,8 @@ "tar": ["tar@6.2.1", "", { "dependencies": { "chownr": "^2.0.0", "fs-minipass": "^2.0.0", "minipass": "^5.0.0", "minizlib": "^2.1.1", "mkdirp": "^1.0.3", "yallist": "^4.0.0" } }, "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A=="], + "tauri-plugin-duck-api": ["tauri-plugin-duck-api@0.1.1", "", { "dependencies": { "@tauri-apps/api": ">=2.0.0-beta.6" } }, "sha512-1mhz1SI2Lu8bHmgF5dmvutHmYpY78qITR0cMQbS5Tbk3NlW+e6WGew6ujUepqQvL6/WdWcPi7XNM0Lfd4haDNQ=="], + "tauri-plugin-keep-screen-on-api": ["tauri-plugin-keep-screen-on-api@0.1.4", "", { "dependencies": { "@tauri-apps/api": ">=2.0.0-beta.6" } }, "sha512-uFY2EKWiKQ3xmwpMYfjaXgYr5USSNS0/Nz8h75lnG0bgttsEcUs4soP0fHPpE7tL3BKbzJdyTycusirkS9aKkA=="], "terra-draw": ["terra-draw@1.6.2", "", {}, "sha512-U5vHQ8CPOM52cHcHUrCewuQnmaUWRXF2g3UJV2IDLyVtzeOBbkBXl2ZNXD4AhA3roEDwYi5wZ5ZbB6pKuC62Kw=="], diff --git a/package.json b/package.json index 0443c93..f00092e 100644 --- a/package.json +++ b/package.json @@ -59,6 +59,7 @@ "pmtiles": "^4.3.0", "sql.js": "^1.13.0", "svelte-maplibre-gl": "^0.1.8", + "tauri-plugin-duck-api": "^0.1.1", "tauri-plugin-keep-screen-on-api": "^0.1.4", "typescript-eslint": "^8.34.1" } diff --git a/src/lib/services/DuckPlugin.ts b/src/lib/services/DuckPlugin.ts deleted file mode 100644 index 4b0444b..0000000 --- a/src/lib/services/DuckPlugin.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { registerPlugin, WebPlugin } from "@capacitor/core"; - -export interface DuckPlugin { - duck: () => void; - unduck: () => void; -} - -class DuckWeb extends WebPlugin implements DuckPlugin { - // eslint-disable-next-line @typescript-eslint/no-empty-function - duck(): void {} - // eslint-disable-next-line @typescript-eslint/no-empty-function - unduck(): void {} -} - -const Duck = registerPlugin("Duck", { - web: new DuckWeb(), -}); - -export default Duck; diff --git a/src/lib/services/OfflineTiles-Cap.ts b/src/lib/services/OfflineTiles-Cap.ts deleted file mode 100644 index f723721..0000000 --- a/src/lib/services/OfflineTiles-Cap.ts +++ /dev/null @@ -1,173 +0,0 @@ -import { - CapacitorSQLite, - SQLiteConnection, - SQLiteDBConnection, -} from "@capacitor-community/sqlite"; -import initSqlJs from "sql.js"; -import { Buffer } from "buffer"; -import { Capacitor } from "@capacitor/core"; -import { ungzip } from "pako"; - -let sqlite: SQLiteConnection; -let db: SQLiteDBConnection; - -export async function downloadMBTiles(url: string): Promise { - return fetch(url) - .then((res) => res.arrayBuffer()) - .then((ab) => new Uint8Array(ab)); -} - -export async function copyMBTiles(data: Uint8Array) { - if (!db) { - await initDB(); - } - const SQL = await initSqlJs(); - const mdb = new SQL.Database(data); - const res = mdb.exec("SELECT * FROM tiles"); - //// const chunkSize = 10; // Adjust chunk size as needed - //// const values = res[0].values; - //// for (let i = 0; i < values.length; i += chunkSize) { - //// const chunk = values.slice(i, i + chunkSize); - //// const statements = chunk.map(row => { - //// const [z, x, y, data] = row; - //// return { - //// statement: `INSERT OR REPLACE INTO tiles (z, x, y, data) VALUES (?, ?, ?, ?)`, - //// values: [z, x, y, Buffer.from(data as Uint8Array)] - //// }; - //// }); - //// await db.executeSet(statements); - //// console.log(`Inserted chunk ${i / chunkSize + 1} of ${Math.ceil(values.length / chunkSize)}: z=${chunk[0][0]}, x=${chunk[0][1]}, y=${chunk[0][2]}`); - //// } - const total = res[0].values.length; - for (const [idx, row] of res[0].values.entries()) { - const [z, x, y, data] = row; - await db.run( - `INSERT OR REPLACE INTO tiles (z, x, y, data) VALUES (?, ?, ?, ?)`, - [ - z, - x, - y, - Buffer.from(data as Uint8Array), // Convert Uint8Array to Buffer - ], - ); - console.log( - `Inserted tile z=${z}, x=${x}, y=${y}. Item ${idx + 1} of ${total}`, - ); - } - console.log(`Copied ${res[0].values.length} tiles from MBTiles data`); -} - -export async function test(url: string) { - const res = await downloadMBTiles(url); - console.log("Downloaded MBTiles data"); - await copyMBTiles(res); -} - -export async function initDB() { - if (!Capacitor.isNativePlatform()) { - throw new Error("initDB is only available on native platforms"); - } - console.log("Initializing SQLite database for tiles"); - sqlite = new SQLiteConnection(CapacitorSQLite); - db = await sqlite.createConnection("tiles", false, "no-encryption", 1, false); - await db.open(); - await db.execute(`CREATE TABLE IF NOT EXISTS tiles ( - z INTEGER NOT NULL, - x INTEGER NOT NULL, - y INTEGER NOT NULL, - data BLOB NOT NULL, - PRIMARY KEY (z, x, y) - )`); - await db.execute( - `CREATE INDEX IF NOT EXISTS idx_tiles_zxy ON tiles (z, x, y)`, - ); -} - -async function deleteDB() { - if (!Capacitor.isNativePlatform()) { - throw new Error("deleteDB is only available on native platforms"); - } - await db.execute(`DROP TABLE IF EXISTS tiles`); - await initDB(); -} - -// @ts-expect-error aaaaa -window.deleteDB = deleteDB; - -// @ts-expect-error aaaaa -window.initDB = initDB; - -export async function getTile( - z: number, - x: number, - y: number, - signal?: AbortSignal -): Promise { - if (signal?.aborted) { - throw new DOMException("Aborted", "AbortError"); - } - const abortPromise = new Promise((_, reject) => { - if (signal) { - signal.addEventListener("abort", () => { - reject(new DOMException("Aborted", "AbortError")); - }, { once: true }); - } - }); - const queryPromise = db.query( - `SELECT data FROM tiles WHERE z = ? AND x = ? AND y = ?`, - [z, x, y], - ); - const res = await Promise.race([queryPromise, abortPromise]); - if (!res.values || res.values.length === 0) { - return null; - } - console.log(res); - return await decompressGzip(res.values[0].data as Uint8Array); -} - -// @ts-expect-error aaaaa -window.getTile = getTile; - -async function decompressGzip(blob: Uint8Array): Promise { - // const ds = new DecompressionStream("gzip"); - // const decompressedStream = new Blob([blob]).stream().pipeThrough(ds); - // return new Uint8Array(await new Response(decompressedStream).arrayBuffer()); - return ungzip(blob); -} - -export async function protocol(params: { - url: string; -}, { signal }: AbortController): Promise<{ data: Uint8Array }> { - console.log("Protocol called with params:", params); - const url = new URL(params.url); - const pathname = url.pathname.replace(/^\//, ""); // Remove leading slash - const z = parseInt(pathname.split("/")[0]); - const x = parseInt(pathname.split("/")[1]); - const y = parseInt(pathname.split("/")[2]); - if (!Capacitor.isNativePlatform()) { - const t = await fetch( - `https://tiles.openfreemap.org/planet/20250528_001001_pt/${z}/${x}/${y}.pbf`, - { signal } - ); - if (t.status == 200) { - const buffer = await t.arrayBuffer(); - return { data: new Uint8Array(buffer) }; - } else { - throw new Error(`Tile fetch error: ${t.statusText}`); - } - } - if (!db) { - await initDB(); - } - const tmsY = (1 << z) - 1 - y; // Invert y for TMS - console.log(`Fetching tile: z=${z}, x=${x}, y=${y}, tmsY=${tmsY}`); - const data = await getTile(z, x, tmsY, signal); - if (!data) { - console.warn(`Tile not found: z=${z}, x=${x}, y=${y}`); - return { - data: new Uint8Array(), // Return empty array if tile not found - }; - } - // return { data: await fetch("/0.pbf").then(res => res.arrayBuffer()).then(ab => new Uint8Array(ab)) }; - return { data }; -} diff --git a/src/lib/services/navigation/TTS.ts b/src/lib/services/navigation/TTS.ts index 0dacbab..ccd3ba1 100644 --- a/src/lib/services/navigation/TTS.ts +++ b/src/lib/services/navigation/TTS.ts @@ -1,6 +1,6 @@ import type { TextToSpeechPlugin } from "@capacitor-community/text-to-speech"; import { Capacitor } from "@capacitor/core"; -import Duck from "../DuckPlugin"; +import { duck, unduck } from "tauri-plugin-duck-api"; export let tts: TextToSpeechPlugin | "web" | null = null; @@ -21,7 +21,7 @@ export default async function say(text: string) { await initTTS(); // return; } - Duck.duck(); + duck(); if (tts !== "web") { try { await tts?.speak({ @@ -37,5 +37,5 @@ export default async function say(text: string) { utterance.lang = "de-DE"; window.speechSynthesis.speak(utterance); } - Duck.unduck(); + unduck(); } diff --git a/src/lib/services/navigation/routing.svelte.ts b/src/lib/services/navigation/routing.svelte.ts index 099f830..3bbd9b0 100644 --- a/src/lib/services/navigation/routing.svelte.ts +++ b/src/lib/services/navigation/routing.svelte.ts @@ -5,8 +5,6 @@ import type { ValhallaRequest } from "./ValhallaRequest"; import type { LngLatBoundsLike } from "maplibre-gl"; import { generateVoiceGuidance } from "./VoiceGuidance"; import { keepScreenOn } from "tauri-plugin-keep-screen-on-api"; -// import { Capacitor } from "@capacitor/core"; -// import { KeepAwake } from "@capacitor-community/keep-awake"; export const routing = $state({ geojson: { @@ -131,9 +129,6 @@ function drawCurrentTrip() { } export async function startRoute(trip: Trip) { - /* if (Capacitor.isNativePlatform()) { - await KeepAwake.keepAwake(); - } */ if(window.__TAURI__) { await keepScreenOn(true); } @@ -275,9 +270,6 @@ export function stopNavigation() { routing.currentTrip = null; map.updateMapPadding(); // TODO: REMOVE removeAllRoutes(); - //if (Capacitor.isNativePlatform()) { - // KeepAwake.allowSleep(); - //} if(window.__TAURI__) { keepScreenOn(false); }