mirror of
https://github.com/gpxstudio/gpx.studio.git
synced 2026-09-24 08:27:37 +00:00
wasm first steps
This commit is contained in:
@@ -0,0 +1,2 @@
|
|||||||
|
target/
|
||||||
|
pkg/
|
||||||
Generated
+114
@@ -0,0 +1,114 @@
|
|||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
version = 4
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bumpalo"
|
||||||
|
version = "3.20.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cfg-if"
|
||||||
|
version = "1.0.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "gpx-rs"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"wasm-bindgen",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "once_cell"
|
||||||
|
version = "1.21.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro2"
|
||||||
|
version = "1.0.106"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quote"
|
||||||
|
version = "1.0.46"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dfbc457d0c7a0759a614551b11a6409e5951f6c7537be1f1b7682b9ae9230368"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustversion"
|
||||||
|
version = "1.0.23"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cf54715a573b99ac80df0bc206da022bcd442c974952c7b9720069370852e21f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "syn"
|
||||||
|
version = "2.0.118"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1b9ae57f904213ebb649ce6895b8a66c66f0203b9319718f69a5612a065b1422"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-ident"
|
||||||
|
version = "1.0.24"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-bindgen"
|
||||||
|
version = "0.2.126"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4b067c0c11094aef6b7a801c1e34a26affafdf3d051dba08456b868789aaf9a4"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"once_cell",
|
||||||
|
"rustversion",
|
||||||
|
"wasm-bindgen-macro",
|
||||||
|
"wasm-bindgen-shared",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-bindgen-macro"
|
||||||
|
version = "0.2.126"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "167ce5e579f6bcf889c4f7175a8a5a585de84e8ff93976ce393efa5f2837aab1"
|
||||||
|
dependencies = [
|
||||||
|
"quote",
|
||||||
|
"wasm-bindgen-macro-support",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-bindgen-macro-support"
|
||||||
|
version = "0.2.126"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f3997c7839262f4ef12cf90b818d6340c18e80f263f1a94bf157d0ec4420380e"
|
||||||
|
dependencies = [
|
||||||
|
"bumpalo",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
"wasm-bindgen-shared",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-bindgen-shared"
|
||||||
|
version = "0.2.126"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dc1b4cb0cc549fcf58d7dfc081778139b3d283a081644e833e84682ad71cea24"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
[package]
|
||||||
|
name = "gpx-rs"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2024"
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
crate-type = ["cdylib"]
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
wasm-bindgen = "0.2"
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
use wasm_bindgen::prelude::*;
|
||||||
|
|
||||||
|
use crate::{stack::Stack, types::GPXFile};
|
||||||
|
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub struct Controller {
|
||||||
|
stack: Stack,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[wasm_bindgen]
|
||||||
|
impl Controller {
|
||||||
|
#[wasm_bindgen(constructor)]
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
stack: Stack::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub fn create_file(&mut self, name: &str) {
|
||||||
|
let id = self.stack.get_new_file_id();
|
||||||
|
let file = Rc::new(GPXFile::new(id, name));
|
||||||
|
self.stack.update(&[file]);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
mod controller;
|
||||||
|
mod stack;
|
||||||
|
mod types;
|
||||||
@@ -0,0 +1,101 @@
|
|||||||
|
use std::{collections::HashMap, rc::Rc};
|
||||||
|
|
||||||
|
use crate::types::{GPXFile, GPXFileId};
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct Stack {
|
||||||
|
entries: Vec<StackEntry>,
|
||||||
|
index: Option<usize>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Stack {
|
||||||
|
pub fn current(&self) -> Option<&StackEntry> {
|
||||||
|
match self.index {
|
||||||
|
Some(i) => Some(&self.entries[i]),
|
||||||
|
None => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_new_file_id(&self) -> GPXFileId {
|
||||||
|
if let Some(current) = self.current() {
|
||||||
|
for id in 0..current.len() {
|
||||||
|
if !current.contains_key(&id) {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
current.len() as GPXFileId
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn update(&mut self, files: &[Rc<GPXFile>]) {
|
||||||
|
let mut next = match self.current() {
|
||||||
|
Some(current) => current.clone(),
|
||||||
|
None => StackEntry::default(),
|
||||||
|
};
|
||||||
|
for file in files {
|
||||||
|
next.insert(file.id, file.clone());
|
||||||
|
}
|
||||||
|
self.push(next);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn delete(&mut self, files: &[GPXFileId]) {
|
||||||
|
if let Some(current) = self.current() {
|
||||||
|
let mut next = current.clone();
|
||||||
|
for file in files {
|
||||||
|
next.remove(file);
|
||||||
|
}
|
||||||
|
self.push(next);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn can_undo(&self) -> bool {
|
||||||
|
self.index.is_some()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn can_redo(&self) -> bool {
|
||||||
|
match self.index {
|
||||||
|
Some(i) => i + 1 < self.entries.len(),
|
||||||
|
None => !self.entries.is_empty(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn undo(&mut self) {
|
||||||
|
if let Some(i) = self.index {
|
||||||
|
if i == 0 {
|
||||||
|
self.index = None;
|
||||||
|
} else {
|
||||||
|
self.index = Some(i - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn redo(&mut self) {
|
||||||
|
match self.index {
|
||||||
|
Some(i) => {
|
||||||
|
if i + 1 < self.entries.len() {
|
||||||
|
self.index = Some(i + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
if !self.entries.is_empty() {
|
||||||
|
self.index = Some(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn push(&mut self, entry: StackEntry) {
|
||||||
|
if let Some(i) = self.index {
|
||||||
|
if i + 1 < self.entries.len() {
|
||||||
|
self.entries.truncate(i + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.entries.push(entry);
|
||||||
|
self.index = Some(self.entries.len() - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type StackEntry = HashMap<GPXFileId, Rc<GPXFile>>;
|
||||||
@@ -0,0 +1,106 @@
|
|||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
pub type GPXFileId = usize;
|
||||||
|
|
||||||
|
pub struct GPXFile {
|
||||||
|
pub id: GPXFileId,
|
||||||
|
pub info: Rc<GPXFileInfo>,
|
||||||
|
pub trk: Vec<Track>,
|
||||||
|
pub wpt: Vec<Rc<WaypointChunk>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GPXFile {
|
||||||
|
pub fn new(id: GPXFileId, name: &str) -> Self {
|
||||||
|
Self {
|
||||||
|
id,
|
||||||
|
info: Rc::new(GPXFileInfo::new(name)),
|
||||||
|
trk: Vec::new(),
|
||||||
|
wpt: Vec::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct GPXFileInfo {
|
||||||
|
pub name: String,
|
||||||
|
pub desc: Option<String>,
|
||||||
|
pub author: Option<Author>,
|
||||||
|
pub link: Option<Link>,
|
||||||
|
pub time: Option<i64>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GPXFileInfo {
|
||||||
|
pub fn new(name: &str) -> Self {
|
||||||
|
Self {
|
||||||
|
name: name.to_owned(),
|
||||||
|
desc: None,
|
||||||
|
author: None,
|
||||||
|
link: None,
|
||||||
|
time: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Author {
|
||||||
|
pub name: Option<String>,
|
||||||
|
pub email: Option<String>,
|
||||||
|
pub link: Option<Link>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Link {
|
||||||
|
pub href: String,
|
||||||
|
pub text: Option<String>,
|
||||||
|
pub type_: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Track {
|
||||||
|
pub info: Rc<TrackInfo>,
|
||||||
|
pub trkseg: Vec<TrackSegment>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct TrackInfo {
|
||||||
|
name: Option<String>,
|
||||||
|
cmt: Option<String>,
|
||||||
|
desc: Option<String>,
|
||||||
|
src: Option<String>,
|
||||||
|
link: Option<Link>,
|
||||||
|
type_: Option<String>,
|
||||||
|
color: Option<String>,
|
||||||
|
opacity: Option<f64>,
|
||||||
|
width: Option<f64>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct TrackSegment {
|
||||||
|
pub trkpt: Vec<Rc<TrackPointChunk>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type TrackPointChunk = Vec<TrackPoint>;
|
||||||
|
|
||||||
|
pub struct TrackPoint {
|
||||||
|
pub coordinates: LngLat,
|
||||||
|
pub ele: f64,
|
||||||
|
pub time: Option<i64>,
|
||||||
|
pub hr: Option<u16>,
|
||||||
|
pub cad: Option<u16>,
|
||||||
|
pub power: Option<u16>,
|
||||||
|
pub atemp: Option<i16>,
|
||||||
|
// TODO OSM data? or store intervals at a higher level?
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type WaypointChunk = Vec<Waypoint>;
|
||||||
|
|
||||||
|
pub struct Waypoint {
|
||||||
|
pub coordinates: LngLat,
|
||||||
|
pub ele: f64,
|
||||||
|
pub time: Option<i64>,
|
||||||
|
pub name: Option<String>,
|
||||||
|
pub cmt: Option<String>,
|
||||||
|
pub desc: Option<String>,
|
||||||
|
pub link: Option<Link>,
|
||||||
|
pub sym: Option<String>,
|
||||||
|
pub type_: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct LngLat {
|
||||||
|
pub lng: f64,
|
||||||
|
pub lat: f64,
|
||||||
|
}
|
||||||
Generated
+21
-1
@@ -17,6 +17,7 @@
|
|||||||
"dexie": "^4.0.11",
|
"dexie": "^4.0.11",
|
||||||
"file-saver": "^2.0.5",
|
"file-saver": "^2.0.5",
|
||||||
"gpx": "file:../gpx",
|
"gpx": "file:../gpx",
|
||||||
|
"gpx-rs": "file:../gpx-rs/pkg",
|
||||||
"immer": "^10.1.1",
|
"immer": "^10.1.1",
|
||||||
"jszip": "^3.10.1",
|
"jszip": "^3.10.1",
|
||||||
"mapillary-js": "^4.1.2",
|
"mapillary-js": "^4.1.2",
|
||||||
@@ -70,7 +71,8 @@
|
|||||||
"tw-animate-css": "^1.4.0",
|
"tw-animate-css": "^1.4.0",
|
||||||
"typescript": "^5.8.3",
|
"typescript": "^5.8.3",
|
||||||
"vaul-svelte": "^1.0.0-next.7",
|
"vaul-svelte": "^1.0.0-next.7",
|
||||||
"vite": "^6.3.5"
|
"vite": "^6.3.5",
|
||||||
|
"vite-plugin-wasm": "^3.6.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"../gpx": {
|
"../gpx": {
|
||||||
@@ -89,6 +91,10 @@
|
|||||||
"typescript": "^5.6.2"
|
"typescript": "^5.6.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"../gpx-rs/pkg": {
|
||||||
|
"name": "gpx-rs",
|
||||||
|
"version": "0.1.0"
|
||||||
|
},
|
||||||
"../gpx/node_modules/@cspotcode/source-map-support": {
|
"../gpx/node_modules/@cspotcode/source-map-support": {
|
||||||
"version": "0.8.1",
|
"version": "0.8.1",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
@@ -5492,6 +5498,10 @@
|
|||||||
"resolved": "../gpx",
|
"resolved": "../gpx",
|
||||||
"link": true
|
"link": true
|
||||||
},
|
},
|
||||||
|
"node_modules/gpx-rs": {
|
||||||
|
"resolved": "../gpx-rs/pkg",
|
||||||
|
"link": true
|
||||||
|
},
|
||||||
"node_modules/graceful-fs": {
|
"node_modules/graceful-fs": {
|
||||||
"version": "4.2.11",
|
"version": "4.2.11",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
@@ -7716,6 +7726,16 @@
|
|||||||
"node": ">=18.0.0"
|
"node": ">=18.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/vite-plugin-wasm": {
|
||||||
|
"version": "3.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/vite-plugin-wasm/-/vite-plugin-wasm-3.6.0.tgz",
|
||||||
|
"integrity": "sha512-mL/QPziiIA4RAA6DkaZZzOstdwbW5jO4Vz7Zenj0wieKWBlNvIvX5L5ljum9lcUX0ShNfBgCNLKTjNkRVVqcsw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"peerDependencies": {
|
||||||
|
"vite": "^2 || ^3 || ^4 || ^5 || ^6 || ^7 || ^8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/vite/node_modules/@esbuild/aix-ppc64": {
|
"node_modules/vite/node_modules/@esbuild/aix-ppc64": {
|
||||||
"version": "0.25.12",
|
"version": "0.25.12",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz",
|
||||||
|
|||||||
@@ -59,7 +59,8 @@
|
|||||||
"tw-animate-css": "^1.4.0",
|
"tw-animate-css": "^1.4.0",
|
||||||
"typescript": "^5.8.3",
|
"typescript": "^5.8.3",
|
||||||
"vaul-svelte": "^1.0.0-next.7",
|
"vaul-svelte": "^1.0.0-next.7",
|
||||||
"vite": "^6.3.5"
|
"vite": "^6.3.5",
|
||||||
|
"vite-plugin-wasm": "^3.6.0"
|
||||||
},
|
},
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -72,6 +73,7 @@
|
|||||||
"dexie": "^4.0.11",
|
"dexie": "^4.0.11",
|
||||||
"file-saver": "^2.0.5",
|
"file-saver": "^2.0.5",
|
||||||
"gpx": "file:../gpx",
|
"gpx": "file:../gpx",
|
||||||
|
"gpx-rs": "file:../gpx-rs/pkg",
|
||||||
"immer": "^10.1.1",
|
"immer": "^10.1.1",
|
||||||
"jszip": "^3.10.1",
|
"jszip": "^3.10.1",
|
||||||
"mapillary-js": "^4.1.2",
|
"mapillary-js": "^4.1.2",
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
import { getURLForGoogleDriveFile } from '$lib/components/embedding/embedding';
|
import { getURLForGoogleDriveFile } from '$lib/components/embedding/embedding';
|
||||||
import { db } from '$lib/db';
|
import { db } from '$lib/db';
|
||||||
import { fileStateCollection } from '$lib/logic/file-state';
|
import { fileStateCollection } from '$lib/logic/file-state';
|
||||||
|
import { browser } from '$app/environment';
|
||||||
|
|
||||||
const {
|
const {
|
||||||
treeFileView,
|
treeFileView,
|
||||||
@@ -36,6 +37,14 @@
|
|||||||
);
|
);
|
||||||
|
|
||||||
onMount(async () => {
|
onMount(async () => {
|
||||||
|
if (browser) {
|
||||||
|
const wasm = await import('gpx-rs');
|
||||||
|
const controller = new wasm.Controller();
|
||||||
|
|
||||||
|
console.log(controller);
|
||||||
|
|
||||||
|
controller.create_file();
|
||||||
|
}
|
||||||
settings.connectToDatabase(db);
|
settings.connectToDatabase(db);
|
||||||
fileStateCollection.connectToDatabase(db).then(() => {
|
fileStateCollection.connectToDatabase(db).then(() => {
|
||||||
let files: string[] = JSON.parse(page.url.searchParams.get('files') || '[]');
|
let files: string[] = JSON.parse(page.url.searchParams.get('files') || '[]');
|
||||||
|
|||||||
@@ -2,10 +2,11 @@ import { sveltekit } from '@sveltejs/kit/vite';
|
|||||||
import { enhancedImages } from '@sveltejs/enhanced-img';
|
import { enhancedImages } from '@sveltejs/enhanced-img';
|
||||||
import { defineConfig } from 'vite';
|
import { defineConfig } from 'vite';
|
||||||
import tailwindcss from '@tailwindcss/vite';
|
import tailwindcss from '@tailwindcss/vite';
|
||||||
|
import wasm from 'vite-plugin-wasm';
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
ssr: {
|
ssr: {
|
||||||
noExternal: ['gpx'],
|
noExternal: ['gpx'],
|
||||||
},
|
},
|
||||||
plugins: [enhancedImages(), tailwindcss(), sveltekit()],
|
plugins: [enhancedImages(), tailwindcss(), wasm(), sveltekit()],
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user