wip
This commit is contained in:
		
							parent
							
								
									f1e8d88add
								
							
						
					
					
						commit
						fff4fdea81
					
				
					 8 changed files with 317 additions and 214 deletions
				
			
		
							
								
								
									
										202
									
								
								Cargo.lock
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										202
									
								
								Cargo.lock
									
										
									
										generated
									
									
									
								
							|  | @ -17,18 +17,6 @@ version = "0.2.3" | |||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "ee2a4ec343196209d6594e19543ae87a39f96d5534d7174822a3ad825dd6ed7e" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "anyhow" | ||||
| version = "1.0.48" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "62e1f47f7dc0422027a4e370dd4548d4d66b26782e513e98dca1e689e058a80e" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "anymap" | ||||
| version = "0.12.1" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "33954243bd79057c2de7338850b85983a44588021f8a5fee574a8888c6de4344" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "assert_approx_eq" | ||||
| version = "1.1.0" | ||||
|  | @ -55,15 +43,6 @@ dependencies = [ | |||
|  "rustc-demangle", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "bincode" | ||||
| version = "1.3.3" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" | ||||
| dependencies = [ | ||||
|  "serde", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "boolinator" | ||||
| version = "2.4.0" | ||||
|  | @ -76,12 +55,6 @@ version = "3.4.0" | |||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "2e8c087f005730276d1096a652e92a8bacee2e2472bcc9715a74d2bec38b5820" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "bytes" | ||||
| version = "1.1.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "cfg-if" | ||||
| version = "0.1.10" | ||||
|  | @ -94,12 +67,6 @@ version = "1.0.0" | |||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "cfg-match" | ||||
| version = "0.2.1" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "8100e46ff92eb85bf6dc2930c73f2a4f7176393c84a9446b3d501e1b354e7b34" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "chrono" | ||||
| version = "0.4.19" | ||||
|  | @ -132,12 +99,6 @@ dependencies = [ | |||
|  "backtrace", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "fnv" | ||||
| version = "1.0.7" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "geo-types" | ||||
| version = "0.4.3" | ||||
|  | @ -155,22 +116,39 @@ checksum = "f6503fe142514ca4799d4c26297c4248239fe8838d827db6bd6065c6ed29a6ce" | |||
| 
 | ||||
| [[package]] | ||||
| name = "gloo" | ||||
| version = "0.2.1" | ||||
| version = "0.4.2" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "68ce6f2dfa9f57f15b848efa2aade5e1850dc72986b87a2b0752d44ca08f4967" | ||||
| checksum = "23947965eee55e3e97a5cd142dd4c10631cc349b48cecca0ed230fd296f568cd" | ||||
| dependencies = [ | ||||
|  "gloo-console-timer", | ||||
|  "gloo-console", | ||||
|  "gloo-dialogs", | ||||
|  "gloo-events", | ||||
|  "gloo-file", | ||||
|  "gloo-render", | ||||
|  "gloo-storage", | ||||
|  "gloo-timers", | ||||
|  "gloo-utils", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "gloo-console-timer" | ||||
| name = "gloo-console" | ||||
| version = "0.2.1" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "3907f786f65bbb4f419e918b0c5674175ef1c231ecda93b2dbd65fd1e8882637" | ||||
| dependencies = [ | ||||
|  "js-sys", | ||||
|  "serde", | ||||
|  "wasm-bindgen", | ||||
|  "web-sys", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "gloo-dialogs" | ||||
| version = "0.1.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "b48675544b29ac03402c6dffc31a912f716e38d19f7e74b78b7e900ec3c941ea" | ||||
| checksum = "4ffb557a2ea2ed283f1334423d303a336fad55fb8572d51ae488f828b1464b40" | ||||
| dependencies = [ | ||||
|  "wasm-bindgen", | ||||
|  "web-sys", | ||||
| ] | ||||
| 
 | ||||
|  | @ -186,9 +164,9 @@ dependencies = [ | |||
| 
 | ||||
| [[package]] | ||||
| name = "gloo-file" | ||||
| version = "0.1.0" | ||||
| version = "0.2.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "8f9fecfe46b5dc3cc46f58e98ba580cc714f2c93860796d002eb3527a465ef49" | ||||
| checksum = "d31ba1f51868ae10a0b665c6dccd5ed967486e7c17055d1c889596ee983be493" | ||||
| dependencies = [ | ||||
|  "gloo-events", | ||||
|  "js-sys", | ||||
|  | @ -196,6 +174,31 @@ dependencies = [ | |||
|  "web-sys", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "gloo-render" | ||||
| version = "0.1.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "5b4cda6e149df3bb4a3c6a343873903e5bcc2448a9877d61bb8274806ad67f6e" | ||||
| dependencies = [ | ||||
|  "wasm-bindgen", | ||||
|  "web-sys", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "gloo-storage" | ||||
| version = "0.2.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "1b5057761927af1b1929d02b1f49cf83553dd347a473ee7c8bb08420f2673ffc" | ||||
| dependencies = [ | ||||
|  "gloo-utils", | ||||
|  "js-sys", | ||||
|  "serde", | ||||
|  "serde_json", | ||||
|  "thiserror", | ||||
|  "wasm-bindgen", | ||||
|  "web-sys", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "gloo-timers" | ||||
| version = "0.2.1" | ||||
|  | @ -207,6 +210,17 @@ dependencies = [ | |||
|  "web-sys", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "gloo-utils" | ||||
| version = "0.1.1" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "3d77d28d9a6f7c384d9e40293fa11f05558bf928a993208e12528ee6633cb415" | ||||
| dependencies = [ | ||||
|  "js-sys", | ||||
|  "wasm-bindgen", | ||||
|  "web-sys", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "gpx" | ||||
| version = "0.8.1" | ||||
|  | @ -225,10 +239,11 @@ name = "gpx-web-utils" | |||
| version = "0.0.1" | ||||
| dependencies = [ | ||||
|  "console_error_panic_hook", | ||||
|  "gloo-file", | ||||
|  "gpx", | ||||
|  "js-sys", | ||||
|  "wasm-bindgen", | ||||
|  "wasm-bindgen-test", | ||||
|  "web-sys", | ||||
|  "yew", | ||||
| ] | ||||
| 
 | ||||
|  | @ -238,17 +253,6 @@ version = "0.11.2" | |||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "http" | ||||
| version = "0.2.5" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "1323096b05d41827dadeaee54c9981958c0f94e670bc94ed80037d1a7b8b186b" | ||||
| dependencies = [ | ||||
|  "bytes", | ||||
|  "fnv", | ||||
|  "itoa", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "indexmap" | ||||
| version = "1.7.0" | ||||
|  | @ -330,6 +334,30 @@ version = "0.22.0" | |||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "8d3b63360ec3cb337817c2dbd47ab4a0f170d285d8e5a2064600f3def1402397" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "proc-macro-error" | ||||
| version = "1.0.4" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" | ||||
| dependencies = [ | ||||
|  "proc-macro-error-attr", | ||||
|  "proc-macro2", | ||||
|  "quote", | ||||
|  "syn", | ||||
|  "version_check", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "proc-macro-error-attr" | ||||
| version = "1.0.4" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" | ||||
| dependencies = [ | ||||
|  "proc-macro2", | ||||
|  "quote", | ||||
|  "version_check", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "proc-macro2" | ||||
| version = "1.0.24" | ||||
|  | @ -361,10 +389,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
| checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "scoped-tls" | ||||
| version = "1.0.0" | ||||
| name = "scoped-tls-hkt" | ||||
| version = "0.1.2" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2" | ||||
| checksum = "c2e9d7eaddb227e8fbaaa71136ae0e1e913ca159b86c7da82f3e8f0044ad3a63" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "serde" | ||||
|  | @ -451,6 +479,12 @@ version = "0.2.1" | |||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "version_check" | ||||
| version = "0.9.3" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "wasi" | ||||
| version = "0.10.0+wasi-snapshot-preview1" | ||||
|  | @ -464,6 +498,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
| checksum = "1ac64ead5ea5f05873d7c12b545865ca2b8d28adfc50a49b84770a3a97265d42" | ||||
| dependencies = [ | ||||
|  "cfg-if 0.1.10", | ||||
|  "serde", | ||||
|  "serde_json", | ||||
|  "wasm-bindgen-macro", | ||||
| ] | ||||
| 
 | ||||
|  | @ -523,30 +559,6 @@ version = "0.2.68" | |||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "1d649a3145108d7d3fbcde896a468d1bd636791823c9921135218ad89be08307" | ||||
| 
 | ||||
| [[package]] | ||||
| name = "wasm-bindgen-test" | ||||
| version = "0.3.18" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "34d1cdc8b98a557f24733d50a1199c4b0635e465eecba9c45b214544da197f64" | ||||
| dependencies = [ | ||||
|  "console_error_panic_hook", | ||||
|  "js-sys", | ||||
|  "scoped-tls", | ||||
|  "wasm-bindgen", | ||||
|  "wasm-bindgen-futures", | ||||
|  "wasm-bindgen-test-macro", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "wasm-bindgen-test-macro" | ||||
| version = "0.3.18" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "e8fb9c67be7439ee8ab1b7db502a49c05e51e2835b66796c705134d9b8e1a585" | ||||
| dependencies = [ | ||||
|  "proc-macro2", | ||||
|  "quote", | ||||
| ] | ||||
| 
 | ||||
| [[package]] | ||||
| name = "web-sys" | ||||
| version = "0.3.45" | ||||
|  | @ -588,25 +600,15 @@ checksum = "b07db065a5cf61a7e4ba64f29e67db906fb1787316516c4e6e5ff0fea1efcd8a" | |||
| [[package]] | ||||
| name = "yew" | ||||
| version = "0.18.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "e4d5154faef86dddd2eb333d4755ea5643787d20aca683e58759b0e53351409f" | ||||
| source = "git+https://github.com/yewstack/yew.git#996bf5b41ac30d7ada14fdc2f419de7659e94613" | ||||
| dependencies = [ | ||||
|  "anyhow", | ||||
|  "anymap", | ||||
|  "bincode", | ||||
|  "cfg-if 1.0.0", | ||||
|  "cfg-match", | ||||
|  "console_error_panic_hook", | ||||
|  "gloo", | ||||
|  "http", | ||||
|  "gloo-utils", | ||||
|  "indexmap", | ||||
|  "js-sys", | ||||
|  "log", | ||||
|  "ryu", | ||||
|  "serde", | ||||
|  "serde_json", | ||||
|  "scoped-tls-hkt", | ||||
|  "slab", | ||||
|  "thiserror", | ||||
|  "wasm-bindgen", | ||||
|  "wasm-bindgen-futures", | ||||
|  "web-sys", | ||||
|  | @ -616,11 +618,11 @@ dependencies = [ | |||
| [[package]] | ||||
| name = "yew-macro" | ||||
| version = "0.18.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "d6e23bfe3dc3933fbe9592d149c9985f3047d08c637a884b9344c21e56e092ef" | ||||
| source = "git+https://github.com/yewstack/yew.git#996bf5b41ac30d7ada14fdc2f419de7659e94613" | ||||
| dependencies = [ | ||||
|  "boolinator", | ||||
|  "lazy_static", | ||||
|  "proc-macro-error", | ||||
|  "proc-macro2", | ||||
|  "quote", | ||||
|  "syn", | ||||
|  |  | |||
							
								
								
									
										20
									
								
								Cargo.toml
									
										
									
									
									
								
							
							
						
						
									
										20
									
								
								Cargo.toml
									
										
									
									
									
								
							|  | @ -8,16 +8,24 @@ repository = "git://pingo.thermokar.st/gpx-web-utils" | |||
| license = "MIT" | ||||
| 
 | ||||
| [dependencies] | ||||
| wasm-bindgen = "0.2.63" | ||||
| js-sys = "0.3.45" | ||||
| wasm-bindgen = "0.2" | ||||
| js-sys = "0.3" | ||||
| gpx = "0.8.1" | ||||
| yew = "0.18" | ||||
| # TODO | ||||
| # yew = "0.19" | ||||
| yew = { git = "https://github.com/yewstack/yew.git" } | ||||
| gloo-file = "0.2" | ||||
| 
 | ||||
| console_error_panic_hook = { version = "0.1.6", optional = true } | ||||
| 
 | ||||
| [dev-dependencies] | ||||
| wasm-bindgen-test = "0.3.13" | ||||
| 
 | ||||
| [profile.release] | ||||
| opt-level = 3 | ||||
| lto = true | ||||
| 
 | ||||
| [profile.dev] | ||||
| opt-level = 3 | ||||
| lto = true | ||||
| 
 | ||||
| [dependencies.web-sys] | ||||
| version = "0.3" | ||||
| features = ["File", "Blob", "Element", "MouseEvent", "EventTarget", "Url", "Event"] | ||||
|  |  | |||
							
								
								
									
										11
									
								
								README.md
									
										
									
									
									
								
							
							
						
						
									
										11
									
								
								README.md
									
										
									
									
									
								
							|  | @ -2,8 +2,9 @@ | |||
| 
 | ||||
| ## quickstart | ||||
| 
 | ||||
| 1. install [wasm-pack](https://rustwasm.github.io/wasm-pack/installer/) | ||||
| 2. `wasm-pack build` | ||||
| 3. `cd www` | ||||
| 4. `npm install` | ||||
| 5. `npm run start` | ||||
| ```bash | ||||
| cargo install --locked trunk | ||||
| cargo install wasm-bindgen-cli | ||||
| rustup target add wasm32-unknown-unknown | ||||
| trunk serve | ||||
| ``` | ||||
|  |  | |||
							
								
								
									
										46
									
								
								src/app.rs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								src/app.rs
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,46 @@ | |||
| use super::loader::Loader; | ||||
| 
 | ||||
| use yew::{html, Component, Context, Html}; | ||||
| 
 | ||||
| pub struct App; | ||||
| 
 | ||||
| impl Component for App { | ||||
|     type Message = (); | ||||
|     type Properties = (); | ||||
| 
 | ||||
|     fn create(_ctx: &Context<Self>) -> Self { | ||||
|         Self | ||||
|     } | ||||
| 
 | ||||
|     fn view(&self, _ctx: &Context<Self>) -> Html { | ||||
|         html! { | ||||
|           <> | ||||
|             <h1> | ||||
|               <a href="/">{"gpx.thermokar.st"}</a> | ||||
|             </h1> | ||||
| 
 | ||||
|             <p> | ||||
|               {"This client-side tool is for merging "} | ||||
|               <a href="https://www.topografix.com/gpx.asp">{"GPX files"}</a> | ||||
|               {". Please note, this has only been tested on GPX files produced by "} | ||||
|               <a href="https://www.garmin.com">{"Garmin"}</a> | ||||
|               {" and "} | ||||
|               <a href="https://www.strava.com">{"Strava"}</a> | ||||
|               {" - your mileage may vary."} | ||||
|             </p> | ||||
| 
 | ||||
|             <Loader /> | ||||
| 
 | ||||
|             <hr/> | ||||
| 
 | ||||
|             <p> | ||||
|               <small> | ||||
|                 <a href="https://github.com/thermokarst/gpx-web-utils"> | ||||
|                   {"https://github.com/thermokarst/gpx-web-utils"} | ||||
|                 </a> | ||||
|               </small> | ||||
|             </p> | ||||
|           </> | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										30
									
								
								src/lib.rs
									
										
									
									
									
								
							
							
						
						
									
										30
									
								
								src/lib.rs
									
										
									
									
									
								
							|  | @ -1,17 +1,17 @@ | |||
| mod utils; | ||||
| 
 | ||||
| use wasm_bindgen::prelude::*; | ||||
| 
 | ||||
| #[cfg(feature = "wee_alloc")] | ||||
| #[global_allocator] | ||||
| static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT; | ||||
| 
 | ||||
| #[wasm_bindgen] | ||||
| pub fn merge(files: js_sys::Array) -> wasm_bindgen::JsValue { | ||||
|     utils::set_panic_hook(); | ||||
|     let files: Vec<String> = utils::translate_js_to_rust(files); | ||||
|     let merged: gpx::Gpx = utils::join_gpx_files(files); | ||||
|     let out_vec: Vec<u8> = utils::write_gpx_to_buffer(merged); | ||||
| 
 | ||||
|     JsValue::from_str(&String::from_utf8(out_vec).unwrap()) | ||||
| } | ||||
| // use wasm_bindgen::prelude::*;
 | ||||
| // 
 | ||||
| // #[cfg(feature = "wee_alloc")]
 | ||||
| // #[global_allocator]
 | ||||
| // static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT;
 | ||||
| // 
 | ||||
| // #[wasm_bindgen]
 | ||||
| // pub fn merge(files: js_sys::Array) -> wasm_bindgen::JsValue {
 | ||||
| //     utils::set_panic_hook();
 | ||||
| //     let files: Vec<String> = utils::translate_js_to_rust(files);
 | ||||
| //     let merged: gpx::Gpx = utils::join_gpx_files(files);
 | ||||
| //     let out_vec: Vec<u8> = utils::write_gpx_to_buffer(merged);
 | ||||
| // 
 | ||||
| //     JsValue::from_str(&String::from_utf8(out_vec).unwrap())
 | ||||
| // }
 | ||||
|  |  | |||
							
								
								
									
										115
									
								
								src/loader.rs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										115
									
								
								src/loader.rs
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,115 @@ | |||
| use std::collections::HashMap; | ||||
| 
 | ||||
| use gloo_file::callbacks::FileReader; | ||||
| use gloo_file::File; | ||||
| use web_sys::{Event, HtmlInputElement, Url, MouseEvent}; | ||||
| use yew::{html, html::TargetCast, Component, Context, Html}; | ||||
| 
 | ||||
| use super::utils; | ||||
| 
 | ||||
| pub enum Msg { | ||||
|     FileLoaded(String, String), | ||||
|     Files(Vec<File>), | ||||
|     FilesLoaded, | ||||
|     Reset, | ||||
| } | ||||
| 
 | ||||
| pub struct Loader { | ||||
|     readers: HashMap<String, FileReader>, | ||||
|     files: Vec<String>, | ||||
|     count: usize, | ||||
| } | ||||
| 
 | ||||
| impl Component for Loader { | ||||
|     type Message = Msg; | ||||
|     type Properties = (); | ||||
| 
 | ||||
|     fn create(_ctx: &Context<Self>) -> Self { | ||||
|         Self { | ||||
|             readers: HashMap::default(), | ||||
|             files: vec![], | ||||
|             count: 0, | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     fn update(&mut self, ctx: &Context<Self>, msg: Self::Message) -> bool { | ||||
|         match msg { | ||||
|             Msg::FileLoaded(filename, data) => { | ||||
|                 self.files.push(data); | ||||
|                 self.readers.remove(&filename); | ||||
|                 if self.files.len() == self.count { | ||||
|                     ctx.link().send_message(Msg::FilesLoaded); | ||||
|                 } | ||||
|                 true | ||||
|             } | ||||
| 
 | ||||
|             Msg::Files(files) => { | ||||
|                 self.count = files.len(); | ||||
|                 for file in files.into_iter() { | ||||
|                     let file_name = file.name(); | ||||
|                     let task = { | ||||
|                         let file_name = file_name.clone(); | ||||
|                         let link = ctx.link().clone(); | ||||
| 
 | ||||
|                         gloo_file::callbacks::read_as_text(&file, move |res| { | ||||
|                             link.send_message(Msg::FileLoaded( | ||||
|                                 file_name, | ||||
|                                 res.unwrap_or_else(|e| e.to_string()), | ||||
|                             )) | ||||
|                         }) | ||||
|                     }; | ||||
|                     self.readers.insert(file_name, task); | ||||
|                 } | ||||
|                 true | ||||
|             } | ||||
| 
 | ||||
|             Msg::FilesLoaded => { | ||||
|                 let merged = utils::merge(&self.files); | ||||
| 
 | ||||
|                 let window = web_sys::window().expect("no global `window` exists"); | ||||
|                 let document = window.document().expect("should have a document on window"); | ||||
|                 let anchor_element = document.create_element("a").unwrap(); | ||||
| 
 | ||||
|                 let url = Url::create_object_url_with_blob(&merged).unwrap(); | ||||
| 
 | ||||
|                 anchor_element.set_attribute("href", &url).unwrap(); | ||||
|                 anchor_element.set_attribute("download", "merged.gpx").unwrap(); | ||||
| 
 | ||||
|                 let event = MouseEvent::new("click").unwrap(); | ||||
|                 anchor_element.dispatch_event(&event).unwrap(); | ||||
| 
 | ||||
|                 true | ||||
|             } | ||||
| 
 | ||||
|             Msg::Reset => { | ||||
|                 self.readers = HashMap::default(); | ||||
|                 self.files = vec![]; | ||||
|                 self.count = 0; | ||||
|                 true | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     fn view(&self, ctx: &Context<Self>) -> Html { | ||||
|         let link = ctx.link(); | ||||
|         html! { | ||||
|             <> | ||||
|                 <input type="file" multiple=true onchange={link.callback(move |e: Event| { | ||||
|                     let mut result = Vec::new(); | ||||
|                     let input: HtmlInputElement = e.target_unchecked_into(); | ||||
| 
 | ||||
|                     if let Some(files) = input.files() { | ||||
|                         let files = js_sys::try_iter(&files) | ||||
|                             .unwrap() | ||||
|                             .unwrap() | ||||
|                             .map(|v| web_sys::File::from(v.unwrap())) | ||||
|                             .map(File::from); | ||||
|                         result.extend(files); | ||||
|                     } | ||||
|                     Msg::Files(result) | ||||
|                     })} | ||||
|                 /> | ||||
|             </> | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										79
									
								
								src/main.rs
									
										
									
									
									
								
							
							
						
						
									
										79
									
								
								src/main.rs
									
										
									
									
									
								
							|  | @ -1,78 +1,7 @@ | |||
| use yew::prelude::*; | ||||
| 
 | ||||
| enum Msg { | ||||
|     AddOne, | ||||
|     SubOne, | ||||
| } | ||||
| 
 | ||||
| struct Model { | ||||
|     link: ComponentLink<Self>, | ||||
|     value: i64, | ||||
| } | ||||
| 
 | ||||
| impl Component for Model { | ||||
|     type Message = Msg; | ||||
|     type Properties = (); | ||||
| 
 | ||||
|     fn create(_props: Self::Properties, link: ComponentLink<Self>) -> Self { | ||||
|         Self { | ||||
|             link, | ||||
|             value: 0, | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     fn update(&mut self, msg: Self::Message) -> ShouldRender { | ||||
|         match msg { | ||||
|             Msg::AddOne => { | ||||
|                 self.value += 1; | ||||
|                 true | ||||
|             } | ||||
|             Msg::SubOne => { | ||||
|                 self.value -= 1; | ||||
|                 true | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     fn change(&mut self, _props: Self::Properties) -> ShouldRender { | ||||
|         false | ||||
|     } | ||||
| 
 | ||||
|     fn view(&self) -> Html { | ||||
|         html! { | ||||
|           <> | ||||
|             <h1> | ||||
|               <a href="/">{"gpx.thermokar.st"}</a> | ||||
|             </h1> | ||||
| 
 | ||||
|             <p> | ||||
|               {"This client-side tool is for merging "} | ||||
|               <a href="https://www.topografix.com/gpx.asp">{"GPX files"}</a> | ||||
|               {". Please note, this has only been tested on GPX files produced by "} | ||||
|               <a href="https://www.garmin.com">{"Garmin"}</a> | ||||
|               {" and "} | ||||
|               <a href="https://www.strava.com">{"Strava"}</a> | ||||
|               {" - your mileage may vary."} | ||||
|             </p> | ||||
| 
 | ||||
|             <button onclick=self.link.callback(|_| Msg::SubOne)>{ "-1" }</button> | ||||
|             <button onclick=self.link.callback(|_| Msg::AddOne)>{ "+1" }</button> | ||||
|             <p>{ self.value }</p> | ||||
| 
 | ||||
|             <hr/> | ||||
| 
 | ||||
|             <p> | ||||
|               <small> | ||||
|                 <a href="https://github.com/thermokarst/gpx-web-utils"> | ||||
|                   {"https://github.com/thermokarst/gpx-web-utils"} | ||||
|                 </a> | ||||
|               </small> | ||||
|             </p> | ||||
|           </> | ||||
|         } | ||||
|     } | ||||
| } | ||||
| mod app; | ||||
| mod loader; | ||||
| mod utils; | ||||
| 
 | ||||
| fn main() { | ||||
|     yew::start_app::<Model>(); | ||||
|     yew::start_app::<app::App>(); | ||||
| } | ||||
|  |  | |||
							
								
								
									
										28
									
								
								src/utils.rs
									
										
									
									
									
								
							
							
						
						
									
										28
									
								
								src/utils.rs
									
										
									
									
									
								
							|  | @ -1,14 +1,6 @@ | |||
| pub fn set_panic_hook() { | ||||
|     #[cfg(feature = "console_error_panic_hook")] | ||||
|     console_error_panic_hook::set_once(); | ||||
| } | ||||
| use web_sys::Blob; | ||||
| 
 | ||||
| pub fn translate_js_to_rust(files: js_sys::Array) -> Vec<String> { | ||||
|     // https://github.com/rustwasm/wasm-bindgen/issues/111
 | ||||
|     files.iter().map(|f| f.as_string().unwrap()).collect() | ||||
| } | ||||
| 
 | ||||
| pub fn join_gpx_files(files: Vec<String>) -> gpx::Gpx { | ||||
| fn join_gpx_files(files: &Vec<String>) -> gpx::Gpx { | ||||
|     let mut merged_gpx: gpx::Gpx = Default::default(); | ||||
|     let mut merged_track: gpx::Track = gpx::Track::new(); | ||||
| 
 | ||||
|  | @ -46,10 +38,20 @@ pub fn join_gpx_files(files: Vec<String>) -> gpx::Gpx { | |||
| 
 | ||||
|     merged_gpx | ||||
| } | ||||
| 
 | ||||
| pub fn write_gpx_to_buffer(gpx: gpx::Gpx) -> Vec<u8> { | ||||
| fn write_gpx_to_buffer(gpx: gpx::Gpx) -> js_sys::Array { | ||||
|     let mut buffer = Vec::new(); | ||||
|     gpx::write(&gpx, &mut buffer).unwrap(); | ||||
| 
 | ||||
|     buffer | ||||
|     let uint8arr = js_sys::Uint8Array::new(&unsafe { js_sys::Uint8Array::view(&buffer) }.into()); | ||||
|     let array = js_sys::Array::new(); | ||||
|     array.push(&uint8arr.buffer()); | ||||
| 
 | ||||
|     array | ||||
| } | ||||
| 
 | ||||
| pub fn merge(files: &Vec<String>) -> Blob { | ||||
|     let merged: gpx::Gpx = join_gpx_files(files); | ||||
|     let out_vec = write_gpx_to_buffer(merged); | ||||
| 
 | ||||
|     Blob::new_with_u8_array_sequence(&out_vec).unwrap() | ||||
| } | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue