Compare commits
2 Commits
94b8b8559c
...
cecba34979
Author | SHA1 | Date | |
---|---|---|---|
cecba34979 | |||
0b7ba06e9e |
@ -9,6 +9,7 @@ android {
|
|||||||
|
|
||||||
apply from: "../capacitor-cordova-android-plugins/cordova.variables.gradle"
|
apply from: "../capacitor-cordova-android-plugins/cordova.variables.gradle"
|
||||||
dependencies {
|
dependencies {
|
||||||
|
implementation project(':capacitor-community-keep-awake')
|
||||||
implementation project(':capacitor-community-native-audio')
|
implementation project(':capacitor-community-native-audio')
|
||||||
implementation project(':capacitor-community-sqlite')
|
implementation project(':capacitor-community-sqlite')
|
||||||
implementation project(':capacitor-community-text-to-speech')
|
implementation project(':capacitor-community-text-to-speech')
|
||||||
|
@ -2,6 +2,9 @@
|
|||||||
include ':capacitor-android'
|
include ':capacitor-android'
|
||||||
project(':capacitor-android').projectDir = new File('../node_modules/@capacitor/android/capacitor')
|
project(':capacitor-android').projectDir = new File('../node_modules/@capacitor/android/capacitor')
|
||||||
|
|
||||||
|
include ':capacitor-community-keep-awake'
|
||||||
|
project(':capacitor-community-keep-awake').projectDir = new File('../node_modules/@capacitor-community/keep-awake/android')
|
||||||
|
|
||||||
include ':capacitor-community-native-audio'
|
include ':capacitor-community-native-audio'
|
||||||
project(':capacitor-community-native-audio').projectDir = new File('../node_modules/@capacitor-community/native-audio/android')
|
project(':capacitor-community-native-audio').projectDir = new File('../node_modules/@capacitor-community/native-audio/android')
|
||||||
|
|
||||||
|
3
bun.lock
3
bun.lock
@ -4,6 +4,7 @@
|
|||||||
"": {
|
"": {
|
||||||
"name": "librenav",
|
"name": "librenav",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@capacitor-community/keep-awake": "^7.1.0",
|
||||||
"@capacitor-community/native-audio": "^7.0.0",
|
"@capacitor-community/native-audio": "^7.0.0",
|
||||||
"@capacitor-community/sqlite": "^7.0.0",
|
"@capacitor-community/sqlite": "^7.0.0",
|
||||||
"@capacitor-community/text-to-speech": "^6.0.0",
|
"@capacitor-community/text-to-speech": "^6.0.0",
|
||||||
@ -54,6 +55,8 @@
|
|||||||
|
|
||||||
"@babel/runtime": ["@babel/runtime@7.27.3", "", {}, "sha512-7EYtGezsdiDMyY80+65EzwiGmcJqpmcZCojSXaRgdrBaGtWTgDZKq69cPIVped6MkIM78cTQ2GOiEYjwOlG4xw=="],
|
"@babel/runtime": ["@babel/runtime@7.27.3", "", {}, "sha512-7EYtGezsdiDMyY80+65EzwiGmcJqpmcZCojSXaRgdrBaGtWTgDZKq69cPIVped6MkIM78cTQ2GOiEYjwOlG4xw=="],
|
||||||
|
|
||||||
|
"@capacitor-community/keep-awake": ["@capacitor-community/keep-awake@7.1.0", "", { "peerDependencies": { "@capacitor/core": ">=7.0.0" } }, "sha512-4Hj6OKnBd/DAOeiMnqBy74tg1rwC+qLYWQbWJmysMZm2e2nptz43hxaKu22Xlyyw5O71CwwskLCM0skDFMPpQQ=="],
|
||||||
|
|
||||||
"@capacitor-community/native-audio": ["@capacitor-community/native-audio@7.0.0", "", { "peerDependencies": { "@capacitor/core": ">=7.0.0" } }, "sha512-wi2l68tU6KDLJWKL6I0lPUKOdB+hNxlvF7RMe/jfkKOMZnd1eUq7kszmbMqyGFZFIxdNG/GMiZrEztZHDypf8A=="],
|
"@capacitor-community/native-audio": ["@capacitor-community/native-audio@7.0.0", "", { "peerDependencies": { "@capacitor/core": ">=7.0.0" } }, "sha512-wi2l68tU6KDLJWKL6I0lPUKOdB+hNxlvF7RMe/jfkKOMZnd1eUq7kszmbMqyGFZFIxdNG/GMiZrEztZHDypf8A=="],
|
||||||
|
|
||||||
"@capacitor-community/sqlite": ["@capacitor-community/sqlite@7.0.0", "", { "dependencies": { "jeep-sqlite": "^2.7.2" }, "peerDependencies": { "@capacitor/core": ">=7.0.0" } }, "sha512-GSHxLEiyuhPoWwpMLOwfaOhLpfZglhfI1sqEgA5bSbtIYt1I+iK02b/ymonaghB176NhA5wuGd+spOIaL0kgHw=="],
|
"@capacitor-community/sqlite": ["@capacitor-community/sqlite@7.0.0", "", { "dependencies": { "jeep-sqlite": "^2.7.2" }, "peerDependencies": { "@capacitor/core": ">=7.0.0" } }, "sha512-GSHxLEiyuhPoWwpMLOwfaOhLpfZglhfI1sqEgA5bSbtIYt1I+iK02b/ymonaghB176NhA5wuGd+spOIaL0kgHw=="],
|
||||||
|
@ -33,6 +33,7 @@
|
|||||||
},
|
},
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@capacitor-community/keep-awake": "^7.1.0",
|
||||||
"@capacitor-community/native-audio": "^7.0.0",
|
"@capacitor-community/native-audio": "^7.0.0",
|
||||||
"@capacitor-community/sqlite": "^7.0.0",
|
"@capacitor-community/sqlite": "^7.0.0",
|
||||||
"@capacitor-community/text-to-speech": "^6.0.0",
|
"@capacitor-community/text-to-speech": "^6.0.0",
|
||||||
|
1003
public/style.json
1003
public/style.json
File diff suppressed because one or more lines are too long
@ -27,9 +27,7 @@
|
|||||||
const DEBUG_POINTS = false; // Set to true to show debug points on the map
|
const DEBUG_POINTS = false; // Set to true to show debug points on the map
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Protocol
|
<Protocol scheme="tiles" loadFn={protocol} />
|
||||||
scheme="tiles"
|
|
||||||
loadFn={protocol} />
|
|
||||||
|
|
||||||
<!-- <Protocol
|
<!-- <Protocol
|
||||||
scheme="tiles"
|
scheme="tiles"
|
||||||
|
@ -212,7 +212,7 @@
|
|||||||
variant="outline"
|
variant="outline"
|
||||||
onclick={async () => {
|
onclick={async () => {
|
||||||
const url = prompt("URL?");
|
const url = prompt("URL?");
|
||||||
if(!url) return;
|
if (!url) return;
|
||||||
await test(url);
|
await test(url);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
@ -1,4 +1,8 @@
|
|||||||
import { CapacitorSQLite, SQLiteConnection, SQLiteDBConnection } from "@capacitor-community/sqlite";
|
import {
|
||||||
|
CapacitorSQLite,
|
||||||
|
SQLiteConnection,
|
||||||
|
SQLiteDBConnection,
|
||||||
|
} from "@capacitor-community/sqlite";
|
||||||
import initSqlJs from "sql.js";
|
import initSqlJs from "sql.js";
|
||||||
import { Buffer } from "buffer";
|
import { Buffer } from "buffer";
|
||||||
import { Capacitor } from "@capacitor/core";
|
import { Capacitor } from "@capacitor/core";
|
||||||
@ -9,8 +13,8 @@ let db: SQLiteDBConnection;
|
|||||||
|
|
||||||
export async function downloadMBTiles(url: string): Promise<Uint8Array> {
|
export async function downloadMBTiles(url: string): Promise<Uint8Array> {
|
||||||
return fetch(url)
|
return fetch(url)
|
||||||
.then(res => res.arrayBuffer())
|
.then((res) => res.arrayBuffer())
|
||||||
.then(ab => new Uint8Array(ab))
|
.then((ab) => new Uint8Array(ab));
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function copyMBTiles(data: Uint8Array) {
|
export async function copyMBTiles(data: Uint8Array) {
|
||||||
@ -37,13 +41,18 @@ export async function copyMBTiles(data: Uint8Array) {
|
|||||||
const total = res[0].values.length;
|
const total = res[0].values.length;
|
||||||
for (const [idx, row] of res[0].values.entries()) {
|
for (const [idx, row] of res[0].values.entries()) {
|
||||||
const [z, x, y, data] = row;
|
const [z, x, y, data] = row;
|
||||||
await db.run(`INSERT OR REPLACE INTO tiles (z, x, y, data) VALUES (?, ?, ?, ?)`, [
|
await db.run(
|
||||||
z,
|
`INSERT OR REPLACE INTO tiles (z, x, y, data) VALUES (?, ?, ?, ?)`,
|
||||||
x,
|
[
|
||||||
y,
|
z,
|
||||||
Buffer.from(data as Uint8Array) // Convert Uint8Array to Buffer
|
x,
|
||||||
]);
|
y,
|
||||||
console.log(`Inserted tile z=${z}, x=${x}, y=${y}. Item ${idx + 1} of ${total}`);
|
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`);
|
console.log(`Copied ${res[0].values.length} tiles from MBTiles data`);
|
||||||
}
|
}
|
||||||
@ -55,7 +64,7 @@ export async function test(url: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function initDB() {
|
export async function initDB() {
|
||||||
if(!Capacitor.isNativePlatform()) {
|
if (!Capacitor.isNativePlatform()) {
|
||||||
throw new Error("initDB is only available on native platforms");
|
throw new Error("initDB is only available on native platforms");
|
||||||
}
|
}
|
||||||
console.log("Initializing SQLite database for tiles");
|
console.log("Initializing SQLite database for tiles");
|
||||||
@ -69,11 +78,13 @@ export async function initDB() {
|
|||||||
data BLOB NOT NULL,
|
data BLOB NOT NULL,
|
||||||
PRIMARY KEY (z, x, y)
|
PRIMARY KEY (z, x, y)
|
||||||
)`);
|
)`);
|
||||||
await db.execute(`CREATE INDEX IF NOT EXISTS idx_tiles_zxy ON tiles (z, x, y)`);
|
await db.execute(
|
||||||
|
`CREATE INDEX IF NOT EXISTS idx_tiles_zxy ON tiles (z, x, y)`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function deleteDB() {
|
async function deleteDB() {
|
||||||
if(!Capacitor.isNativePlatform()) {
|
if (!Capacitor.isNativePlatform()) {
|
||||||
throw new Error("deleteDB is only available on native platforms");
|
throw new Error("deleteDB is only available on native platforms");
|
||||||
}
|
}
|
||||||
await db.execute(`DROP TABLE IF EXISTS tiles`);
|
await db.execute(`DROP TABLE IF EXISTS tiles`);
|
||||||
@ -86,8 +97,15 @@ window.deleteDB = deleteDB;
|
|||||||
// @ts-expect-error aaaaa
|
// @ts-expect-error aaaaa
|
||||||
window.initDB = initDB;
|
window.initDB = initDB;
|
||||||
|
|
||||||
export async function getTile(z: number, x: number, y: number): Promise<Uint8Array | null> {
|
export async function getTile(
|
||||||
const res = await db.query(`SELECT data FROM tiles WHERE z = ? AND x = ? AND y = ?`, [z, x, y]);
|
z: number,
|
||||||
|
x: number,
|
||||||
|
y: number,
|
||||||
|
): Promise<Uint8Array | null> {
|
||||||
|
const res = await db.query(
|
||||||
|
`SELECT data FROM tiles WHERE z = ? AND x = ? AND y = ?`,
|
||||||
|
[z, x, y],
|
||||||
|
);
|
||||||
if (!res.values || res.values.length === 0) {
|
if (!res.values || res.values.length === 0) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -99,22 +117,25 @@ export async function getTile(z: number, x: number, y: number): Promise<Uint8Arr
|
|||||||
window.getTile = getTile;
|
window.getTile = getTile;
|
||||||
|
|
||||||
async function decompressGzip(blob: Uint8Array): Promise<Uint8Array> {
|
async function decompressGzip(blob: Uint8Array): Promise<Uint8Array> {
|
||||||
// const ds = new DecompressionStream("gzip");
|
// const ds = new DecompressionStream("gzip");
|
||||||
// const decompressedStream = new Blob([blob]).stream().pipeThrough(ds);
|
// const decompressedStream = new Blob([blob]).stream().pipeThrough(ds);
|
||||||
// return new Uint8Array(await new Response(decompressedStream).arrayBuffer());
|
// return new Uint8Array(await new Response(decompressedStream).arrayBuffer());
|
||||||
return ungzip(blob);
|
return ungzip(blob);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function protocol(params: {
|
||||||
export async function protocol(params: { url: string }): Promise<{ data: Uint8Array }> {
|
url: string;
|
||||||
|
}): Promise<{ data: Uint8Array }> {
|
||||||
console.log("Protocol called with params:", params);
|
console.log("Protocol called with params:", params);
|
||||||
const url = new URL(params.url);
|
const url = new URL(params.url);
|
||||||
const pathname = url.pathname.replace(/^\//, ""); // Remove leading slash
|
const pathname = url.pathname.replace(/^\//, ""); // Remove leading slash
|
||||||
const z = parseInt(pathname.split("/")[0]);
|
const z = parseInt(pathname.split("/")[0]);
|
||||||
const x = parseInt(pathname.split("/")[1]);
|
const x = parseInt(pathname.split("/")[1]);
|
||||||
const y = parseInt(pathname.split("/")[2]);
|
const y = parseInt(pathname.split("/")[2]);
|
||||||
if(!Capacitor.isNativePlatform()) {
|
if (!Capacitor.isNativePlatform()) {
|
||||||
const t = await fetch(`https://tiles.openfreemap.org/planet/20250528_001001_pt/${z}/${x}/${y}.pbf`);
|
const t = await fetch(
|
||||||
|
`https://tiles.openfreemap.org/planet/20250528_001001_pt/${z}/${x}/${y}.pbf`,
|
||||||
|
);
|
||||||
if (t.status == 200) {
|
if (t.status == 200) {
|
||||||
const buffer = await t.arrayBuffer();
|
const buffer = await t.arrayBuffer();
|
||||||
return { data: new Uint8Array(buffer) };
|
return { data: new Uint8Array(buffer) };
|
||||||
@ -122,7 +143,7 @@ export async function protocol(params: { url: string }): Promise<{ data: Uint8Ar
|
|||||||
throw new Error(`Tile fetch error: ${t.statusText}`);
|
throw new Error(`Tile fetch error: ${t.statusText}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(!db) {
|
if (!db) {
|
||||||
await initDB();
|
await initDB();
|
||||||
}
|
}
|
||||||
const tmsY = (1 << z) - 1 - y; // Invert y for TMS
|
const tmsY = (1 << z) - 1 - y; // Invert y for TMS
|
||||||
@ -131,8 +152,8 @@ export async function protocol(params: { url: string }): Promise<{ data: Uint8Ar
|
|||||||
if (!data) {
|
if (!data) {
|
||||||
console.warn(`Tile not found: z=${z}, x=${x}, y=${y}`);
|
console.warn(`Tile not found: z=${z}, x=${x}, y=${y}`);
|
||||||
return {
|
return {
|
||||||
data: new Uint8Array() // Return empty array if tile not found
|
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: await fetch("/0.pbf").then(res => res.arrayBuffer()).then(ab => new Uint8Array(ab)) };
|
||||||
return { data };
|
return { data };
|
||||||
|
@ -4,6 +4,8 @@ import say from "./TTS";
|
|||||||
import type { ValhallaRequest } from "./ValhallaRequest";
|
import type { ValhallaRequest } from "./ValhallaRequest";
|
||||||
import type { LngLatBoundsLike } from "maplibre-gl";
|
import type { LngLatBoundsLike } from "maplibre-gl";
|
||||||
import { generateVoiceGuidance } from "./VoiceGuidance";
|
import { generateVoiceGuidance } from "./VoiceGuidance";
|
||||||
|
import { Capacitor } from "@capacitor/core";
|
||||||
|
import { KeepAwake } from "@capacitor-community/keep-awake";
|
||||||
|
|
||||||
export const routing = $state({
|
export const routing = $state({
|
||||||
geojson: {
|
geojson: {
|
||||||
@ -128,6 +130,9 @@ function drawCurrentTrip() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function startRoute(trip: Trip) {
|
export async function startRoute(trip: Trip) {
|
||||||
|
if (Capacitor.isNativePlatform()) {
|
||||||
|
await KeepAwake.keepAwake();
|
||||||
|
}
|
||||||
routing.currentTrip = trip;
|
routing.currentTrip = trip;
|
||||||
removeAllRoutes();
|
removeAllRoutes();
|
||||||
routing.geojson.route = tripToGeoJSON(trip);
|
routing.geojson.route = tripToGeoJSON(trip);
|
||||||
@ -266,6 +271,9 @@ export function stopNavigation() {
|
|||||||
routing.currentTrip = null;
|
routing.currentTrip = null;
|
||||||
map.updateMapPadding(); // TODO: REMOVE
|
map.updateMapPadding(); // TODO: REMOVE
|
||||||
removeAllRoutes();
|
removeAllRoutes();
|
||||||
|
if (Capacitor.isNativePlatform()) {
|
||||||
|
KeepAwake.allowSleep();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// function getUserLocation(): WorldLocation {
|
// function getUserLocation(): WorldLocation {
|
||||||
|
Reference in New Issue
Block a user