From a0aae68a977c32b29fdc860fcca3b31c437c3eff Mon Sep 17 00:00:00 2001 From: Bill Thiede Date: Sat, 18 Feb 2023 19:00:03 -0800 Subject: [PATCH] Canvas based zoomable image with good logging. --- Cargo.lock | 434 ++++++++++++++++------------------------------------- Cargo.toml | 12 +- index.css | 4 + index.html | 1 + src/lib.rs | 287 ++++++++++++++++++++++++++++++++--- 5 files changed, 407 insertions(+), 331 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index dcefbce..94708d2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,12 +17,6 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" -[[package]] -name = "base-x" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4521f3e3d031370679b3b140beb36dfe4801b09ac77e30c61941f97df3ef28b" - [[package]] name = "bitflags" version = "1.2.1" @@ -41,12 +35,6 @@ version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" -[[package]] -name = "cfg-if" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" - [[package]] name = "cfg-if" version = "1.0.0" @@ -80,29 +68,33 @@ dependencies = [ [[package]] name = "console_error_panic_hook" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8d976903543e0c48546a91908f21588a680a8c8f984df9a5d69feccb2b2a211" +checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc" dependencies = [ - "cfg-if 0.1.10", + "cfg-if", "wasm-bindgen", ] [[package]] -name = "const_fn" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "076a6803b0dacd6a88cfe64deba628b01533ff5ef265687e6938280c1afd0a28" +name = "console_log" +version = "0.1.0" +source = "git+http://git.z.xinu.tv/wathiede/console_log#1c235d5a7bae685dfff05bc9162abb049beefb7d" +dependencies = [ + "log", + "wasm-bindgen", + "web-sys", +] [[package]] name = "cookie" -version = "0.14.4" +version = "0.16.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03a5d7b21829bc7b4bf4754a978a241ae54ea55a40f92bb20216e54096f4b951" +checksum = "e859cd57d0710d9e06c381b550c06e76992472a8c6d527aecd2fc673dcc231fb" dependencies = [ "percent-encoding", - "time 0.2.26", - "version_check 0.9.3", + "time 0.3.19", + "version_check 0.9.4", ] [[package]] @@ -164,12 +156,6 @@ dependencies = [ "version_check 0.1.5", ] -[[package]] -name = "discard" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "212d0f5754cb6769937f4501cc0e67f4f4483c8d2c3e1e922ee9edbe4ab4c7c0" - [[package]] name = "enclose" version = "1.1.8" @@ -178,9 +164,9 @@ checksum = "1056f553da426e9c025a662efa48b52e62e0a3a7648aa2d15aeaaf7f0d329357" [[package]] name = "futures" -version = "0.3.13" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f55667319111d593ba876406af7c409c0ebb44dc4be6132a783ccf163ea14c1" +checksum = "13e2792b0ff0340399d58445b88fd9770e3489eff258a4cbc1523418f12abf84" dependencies = [ "futures-channel", "futures-core", @@ -193,9 +179,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.13" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c2dd2df839b57db9ab69c2c9d8f3e8c81984781937fe2807dc6dcf3b2ad2939" +checksum = "2e5317663a9089767a1ec00a487df42e0ca174b61b4483213ac24448e4664df5" dependencies = [ "futures-core", "futures-sink", @@ -203,15 +189,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.13" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15496a72fabf0e62bdc3df11a59a3787429221dd0710ba8ef163d6f7a9112c94" +checksum = "ec90ff4d0fe1f57d600049061dc6bb68ed03c7d2fbd697274c41805dcb3f8608" [[package]] name = "futures-executor" -version = "0.3.13" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "891a4b7b96d84d5940084b2a37632dd65deeae662c114ceaa2c879629c9c0ad1" +checksum = "e8de0a35a6ab97ec8869e32a2473f4b1324459e14c29275d14b10cb1fd19b50e" dependencies = [ "futures-core", "futures-task", @@ -220,17 +206,16 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.13" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71c2c65c57704c32f5241c1223167c2c3294fd34ac020c807ddbe6db287ba59" +checksum = "bfb8371b6fb2aeb2d280374607aeabfc99d95c72edfe51692e42d3d7f0d08531" [[package]] name = "futures-macro" -version = "0.3.13" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea405816a5139fb39af82c2beb921d52143f556038378d6db21183a5c37fbfb7" +checksum = "95a73af87da33b5acf53acfebdc339fe592ecf5357ac7c0a7734ab9d8c876a70" dependencies = [ - "proc-macro-hack", "proc-macro2", "quote", "syn", @@ -238,21 +223,21 @@ dependencies = [ [[package]] name = "futures-sink" -version = "0.3.13" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85754d98985841b7d4f5e8e6fbfa4a4ac847916893ec511a2917ccd8525b8bb3" +checksum = "f310820bb3e8cfd46c80db4d7fb8353e15dfff853a127158425f31e0be6c8364" [[package]] name = "futures-task" -version = "0.3.13" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa189ef211c15ee602667a6fcfe1c1fd9e07d42250d2156382820fba33c9df80" +checksum = "dcf79a1bf610b10f42aea489289c5a2c478a786509693b80cd39c44ccd936366" [[package]] name = "futures-util" -version = "0.3.13" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1812c7ab8aedf8d6f2701a43e1243acdbcc2b36ab26e2ad421eb99ac963d96d1" +checksum = "9c1d6de3acfef38d2be4b1f543f553131788603495be83da675e180c8d6b7bd1" dependencies = [ "futures-channel", "futures-core", @@ -263,43 +248,19 @@ dependencies = [ "memchr", "pin-project-lite", "pin-utils", - "proc-macro-hack", - "proc-macro-nested", "slab", ] -[[package]] -name = "getopts" -version = "0.2.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5" -dependencies = [ - "unicode-width", -] - [[package]] name = "getrandom" -version = "0.1.16" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" +checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "js-sys", "libc", - "wasi 0.9.0+wasi-snapshot-preview1", - "wasm-bindgen", -] - -[[package]] -name = "getrandom" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9495705279e7140bf035dde1f6e750c162df8b625267cd52cc44e0b156732c8" -dependencies = [ - "cfg-if 1.0.0", - "js-sys", - "libc", - "wasi 0.10.0+wasi-snapshot-preview1", + "wasi 0.11.0+wasi-snapshot-preview1", "wasm-bindgen", ] @@ -315,9 +276,9 @@ dependencies = [ [[package]] name = "gloo-file" -version = "0.1.0" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f9fecfe46b5dc3cc46f58e98ba580cc714f2c93860796d002eb3527a465ef49" +checksum = "a8d5564e570a38b43d78bdc063374a0c3098c4f0d64005b12f9bbe87e869b6d7" dependencies = [ "futures-channel", "gloo-events", @@ -328,22 +289,34 @@ dependencies = [ [[package]] name = "gloo-timers" -version = "0.2.1" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47204a46aaff920a1ea58b11d03dec6f704287d27561724a4631e450654a891f" +checksum = "9b995a66bb87bebce9a0f4a95aed01daca4872c050bfcb21653361c03bc35e5c" dependencies = [ "futures-channel", "futures-core", "js-sys", "wasm-bindgen", +] + +[[package]] +name = "gloo-utils" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8e8fc851e9c7b9852508bc6e3f690f452f474417e8545ec9857b7f7377036b5" +dependencies = [ + "js-sys", + "serde", + "serde_json", + "wasm-bindgen", "web-sys", ] [[package]] name = "hashbrown" -version = "0.9.1" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" [[package]] name = "humantime" @@ -377,9 +350,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "1.6.2" +version = "1.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "824845a0bf897a9042383849b02c1bc219c2383772efcd5c6f9766fa4b81aef3" +checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399" dependencies = [ "autocfg", "hashbrown", @@ -391,30 +364,24 @@ version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", ] [[package]] name = "itoa" -version = "0.4.7" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736" +checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440" [[package]] name = "js-sys" -version = "0.3.50" +version = "0.3.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d99f9e3e84b8f67f846ef5b4cbbc3b1c29f6c759fcbce6f01aa0e73d932a24c" +checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730" dependencies = [ "wasm-bindgen", ] -[[package]] -name = "lazy_static" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" - [[package]] name = "libc" version = "0.2.139" @@ -442,11 +409,11 @@ dependencies = [ [[package]] name = "log" -version = "0.4.14" +version = "0.4.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" +checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", ] [[package]] @@ -497,7 +464,7 @@ version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "instant", "libc", "redox_syscall", @@ -529,18 +496,6 @@ version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" -[[package]] -name = "proc-macro-hack" -version = "0.5.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" - -[[package]] -name = "proc-macro-nested" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc881b2c22681370c6a780e47af9840ef841837bc98118431d4e1868bd0c1086" - [[package]] name = "proc-macro2" version = "1.0.51" @@ -550,18 +505,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "pulldown-cmark" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffade02495f22453cd593159ea2f59827aae7f53fa8323f756799b670881dcf8" -dependencies = [ - "bitflags", - "getopts", - "memchr", - "unicase", -] - [[package]] name = "quote" version = "1.0.9" @@ -573,23 +516,20 @@ dependencies = [ [[package]] name = "rand" -version = "0.7.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ - "getrandom 0.1.16", "libc", "rand_chacha", "rand_core", - "rand_hc", - "rand_pcg", ] [[package]] name = "rand_chacha" -version = "0.2.2" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", "rand_core", @@ -597,29 +537,11 @@ dependencies = [ [[package]] name = "rand_core" -version = "0.5.1" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.1.16", -] - -[[package]] -name = "rand_hc" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" -dependencies = [ - "rand_core", -] - -[[package]] -name = "rand_pcg" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16abd0c1b639e9eb4d7c50c0b8100b0d0f849be2349829c740fe8e6eb4816429" -dependencies = [ - "rand_core", + "getrandom", ] [[package]] @@ -631,15 +553,6 @@ dependencies = [ "bitflags", ] -[[package]] -name = "rustc_version" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" -dependencies = [ - "semver", -] - [[package]] name = "ryu" version = "1.0.5" @@ -666,45 +579,31 @@ checksum = "ddccb15bcce173023b3fedd9436f882a0739b8dfb45e4f6b6002bee5929f61b2" [[package]] name = "seed" -version = "0.8.0" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b599be9cc57456f4b7fc99b8abfb154d4819f7b6c147e80be5580663dad4536" +checksum = "9352d75dd253803ce05722fe3acaafffc461d4faeaf0ebe0d8bf831059482e21" dependencies = [ "console_error_panic_hook", "cookie", "dbg", "enclose", "futures", + "getrandom", "gloo-file", "gloo-timers", + "gloo-utils", "indexmap", "js-sys", - "pulldown-cmark", "rand", "serde", "serde_json", "uuid", - "version_check 0.9.3", + "version_check 0.9.4", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", ] -[[package]] -name = "semver" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" -dependencies = [ - "semver-parser", -] - -[[package]] -name = "semver-parser" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" - [[package]] name = "serde" version = "1.0.152" @@ -727,21 +626,15 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.64" +version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "799e97dc9fdae36a5c8b8f2cae9ce2ee9fdce2058c57a93e6099d919fd982f79" +checksum = "cad406b69c91885b5107daf2c29572f6c8cdb3c66826821e286c533490c0bc76" dependencies = [ "itoa", "ryu", "serde", ] -[[package]] -name = "sha1" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d" - [[package]] name = "slab" version = "0.4.2" @@ -754,64 +647,6 @@ version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" -[[package]] -name = "standback" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e113fb6f3de07a243d434a56ec6f186dfd51cb08448239fe7bcae73f87ff28ff" -dependencies = [ - "version_check 0.9.3", -] - -[[package]] -name = "stdweb" -version = "0.4.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d022496b16281348b52d0e30ae99e01a73d737b2f45d38fed4edf79f9325a1d5" -dependencies = [ - "discard", - "rustc_version", - "stdweb-derive", - "stdweb-internal-macros", - "stdweb-internal-runtime", - "wasm-bindgen", -] - -[[package]] -name = "stdweb-derive" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c87a60a40fccc84bef0652345bbbbbe20a605bf5d0ce81719fc476f5c03b50ef" -dependencies = [ - "proc-macro2", - "quote", - "serde", - "serde_derive", - "syn", -] - -[[package]] -name = "stdweb-internal-macros" -version = "0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58fa5ff6ad0d98d1ffa8cb115892b6e69d67799f6763e162a1c9db421dc22e11" -dependencies = [ - "base-x", - "proc-macro2", - "quote", - "serde", - "serde_derive", - "serde_json", - "sha1", - "syn", -] - -[[package]] -name = "stdweb-internal-runtime" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "213701ba3370744dcd1a12960caa4843b3d68b4d1c0a5d575e0d65b2ee9d16c0" - [[package]] name = "syn" version = "1.0.107" @@ -865,40 +700,29 @@ dependencies = [ [[package]] name = "time" -version = "0.2.26" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08a8cbfbf47955132d0202d1662f49b2423ae35862aee471f3ba4b133358f372" +checksum = "53250a3b3fed8ff8fd988587d8925d26a83ac3845d9e03b220b37f34c2b8d6c2" dependencies = [ - "const_fn", - "libc", - "standback", - "stdweb", + "itoa", + "serde", + "time-core", "time-macros", - "version_check 0.9.3", - "winapi", ] +[[package]] +name = "time-core" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e153e1f1acaef8acc537e68b44906d2db6436e2b35ac2c6b42640fff91f00fd" + [[package]] name = "time-macros" -version = "0.1.1" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "957e9c6e26f12cb6d0dd7fc776bb67a706312e7299aed74c8dd5b17ebb27e2f1" +checksum = "a460aeb8de6dcb0f381e1ee05f1cd56fcf5a5f6eb8187ff3d8f0b11078d38b7c" dependencies = [ - "proc-macro-hack", - "time-macros-impl", -] - -[[package]] -name = "time-macros-impl" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5c3be1edfad6027c69f5491cf4cb310d1a71ecd6af742788c6ff8bced86b8fa" -dependencies = [ - "proc-macro-hack", - "proc-macro2", - "quote", - "standback", - "syn", + "time-core", ] [[package]] @@ -906,21 +730,15 @@ name = "tracerviewer" version = "0.1.0" dependencies = [ "chrono", + "console_log", "humantime", + "log", "seed", "serde", "thiserror", "wasm-bindgen-test", "wasm-timer", -] - -[[package]] -name = "unicase" -version = "2.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" -dependencies = [ - "version_check 0.9.3", + "web-sys", ] [[package]] @@ -937,11 +755,11 @@ checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3" [[package]] name = "uuid" -version = "0.8.2" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" +checksum = "1674845326ee10d37ca60470760d4288a6f80f304007d92e5c53bab78c9cfd79" dependencies = [ - "getrandom 0.2.2", + "getrandom", ] [[package]] @@ -952,15 +770,9 @@ checksum = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" [[package]] name = "version_check" -version = "0.9.3" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe" - -[[package]] -name = "wasi" -version = "0.9.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "wasi" @@ -969,12 +781,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" [[package]] -name = "wasm-bindgen" -version = "0.2.73" +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83240549659d187488f91f33c0f8547cbfef0b2088bc470c116d1d260ef623d9" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.84" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "serde", "serde_json", "wasm-bindgen-macro", @@ -982,13 +800,13 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.73" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae70622411ca953215ca6d06d3ebeb1e915f0f6613e3b495122878d7ebec7dae" +checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9" dependencies = [ "bumpalo", - "lazy_static", "log", + "once_cell", "proc-macro2", "quote", "syn", @@ -997,11 +815,11 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.23" +version = "0.4.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81b8b767af23de6ac18bf2168b690bed2902743ddf0fb39252e36f9e2bfc63ea" +checksum = "f219e0d211ba40266969f6dbdd90636da12f75bee4fc9d6c23d1260dadb51454" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "js-sys", "wasm-bindgen", "web-sys", @@ -1009,9 +827,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.73" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e734d91443f177bfdb41969de821e15c516931c3c3db3d318fa1b68975d0f6f" +checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1019,9 +837,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.73" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d53739ff08c8a68b0fdbcd54c372b8ab800b1449ab3c9d706503bc7dd1621b2c" +checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6" dependencies = [ "proc-macro2", "quote", @@ -1032,9 +850,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.73" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9a543ae66aa233d14bb765ed9af4a33e81b8b58d1584cf1b47ff8cd0b9e4489" +checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d" [[package]] name = "wasm-bindgen-test" @@ -1077,9 +895,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.50" +version = "0.3.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a905d57e488fec8861446d3393670fb50d27a262344013181c2cdf9fff5481be" +checksum = "e33b99f4b23ba3eec1a53ac264e35a755f00e966e0065077d6027c0f575b0b97" dependencies = [ "js-sys", "wasm-bindgen", diff --git a/Cargo.toml b/Cargo.toml index 0bc127e..41c2245 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,12 +17,22 @@ wasm-bindgen-test = "0.3.18" [dependencies] chrono = "0.4.23" +console_log = {git = "http://git.z.xinu.tv/wathiede/console_log"} humantime = "2.1.0" -seed = "0.8.0" +log = "0.4.17" +seed = "0.9.2" serde = "1.0.152" thiserror = "1.0.38" wasm-timer = "0.2.5" +[dependencies.web-sys] +version = "0.3.58" +features = [ + "CanvasRenderingContext2d", + "HtmlImageElement", + "ImageData", +] + [profile.release] lto = true opt-level = 'z' diff --git a/index.css b/index.css index 2815869..fec8417 100644 --- a/index.css +++ b/index.css @@ -21,3 +21,7 @@ html, body, #root { .fresh { color: #4f4; } + +.image { + width: 100%; +} diff --git a/index.html b/index.html index 0b426df..665c1ce 100644 --- a/index.html +++ b/index.html @@ -2,6 +2,7 @@ + Traceviewer diff --git a/src/lib.rs b/src/lib.rs index ed186e1..e43d3dd 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,19 +3,21 @@ // but some rules are too "annoying" or are not applicable for your case.) #![allow(clippy::wildcard_imports)] -use std::{sync::Arc, time::Duration}; +use std::time::Duration; -use chrono::{DateTime, Local, NaiveDateTime, TimeZone}; +use chrono::{Local, NaiveDateTime, TimeZone}; +use log::Level; use seed::{prelude::*, *}; use thiserror::Error; use wasm_timer::{SystemTime, UNIX_EPOCH}; +use web_sys::{HtmlCanvasElement, HtmlImageElement}; const ROOT_URL: &'static str = "/www/tracer/"; #[derive(Clone, Error, Debug)] pub enum AppError { - #[error("fetch error")] - FetchError(Arc), + #[error("fetch error: {0}")] + FetchError(String), } // ------ ------ @@ -25,10 +27,15 @@ pub enum AppError { // `init` describes what should happen when your app started. fn init(_: Url, orders: &mut impl Orders) -> Model { let timer_handle = orders.stream_with_handle(streams::interval(1000, || Msg::OnCheck)); + orders.after_next_render(|_| Msg::Rendered); Model { timer_handle, data: None, error: None, + image_canvas: ElRef::::default(), + image_ref: ElRef::::default(), + zoom: 1.0, + offset: [0., 0.], } } @@ -41,19 +48,26 @@ struct Model { timer_handle: StreamHandle, data: Option, error: Option, + image_canvas: ElRef, + image_ref: ElRef, + zoom: f64, + offset: [f64; 2], } // ------ ------ // Update // ------ ------ -// (Remove the line below once any of your `Msg` variants doesn't implement `Copy`.) #[derive(Clone)] // `Msg` describes the different events you can modify state with. enum Msg { OnCheck, OnError(AppError), + Rendered, Received(Data), + Reset, + Zoom(f64, [i32; 2]), + Move([f64; 2]), } // `update` describes how to handle each `Msg`. @@ -76,16 +90,57 @@ fn update(msg: Msg, model: &mut Model, orders: &mut impl Orders) { match response .check_status() // ensure we've got 2xx status - .expect("status check failed") - .json::() - .await - { - Ok(data) => Msg::Received(data), - Err(e) => Msg::OnError(AppError::FetchError(Arc::new(e))), - } + {Ok(data)=> + match data + .json::() + .await + { + Ok(data) => Msg::Received(data), + Err(e) => Msg::OnError(AppError::FetchError(format!("{:?}",e))), + }, + Err(e) => Msg::OnError(AppError::FetchError(format!("{:?}",e))), + } }); } - Msg::Received(data) => model.data = Some(data), + Msg::Received(data) => { + if let Some(d) = &model.data { + if d.timestamp != data.timestamp { + model.data = Some(data); + } + } else { + model.data = Some(data); + } + } + Msg::Rendered => { + draw( + &model.image_canvas, + &model.image_ref, + model.zoom, + model.offset, + ); + // We want to call `.skip` to prevent infinite loop. + // (However infinite loops are useful for animations.) + // TODO(wathiede): can this be done less often? + orders.after_next_render(|_| Msg::Rendered).skip(); + } + Msg::Reset => { + model.zoom = 1.; + model.offset = [0., 0.]; + } + Msg::Zoom(scale, at) => { + let old_zoom = model.zoom; + model.zoom += scale; + if model.zoom < 0.1 { + model.zoom = 0.1; + } + let z_rat = model.zoom / old_zoom; + let at = [at[0] as f64, at[1] as f64]; + model.offset = [ + at[0] - (z_rat) * (at[0] - model.offset[0]), + at[1] - (z_rat) * (at[1] - model.offset[1]), + ]; + } + Msg::Move(delta) => model.offset = [model.offset[0] + delta[0], model.offset[1] + delta[1]], } } use serde::{Deserialize, Serialize}; @@ -173,34 +228,215 @@ fn view_metadata_table(data: &Data) -> Node { ] } -fn view_image(im: &ImageMetadata) -> Node { +fn draw( + canvas: &ElRef, + image: &ElRef, + zoom: f64, + offset: [f64; 2], +) { + let (canvas, image) = match (canvas.get(), image.get()) { + (Some(canvas), Some(image)) => (canvas, image), + _ => { + return; + } + }; + + #[derive(Serialize)] + struct ContextOptions { + #[serde(rename = "willReadFrequently")] + will_read_frequently: bool, + } + let ctx = canvas + .get_context_with_context_options( + "2d", + &wasm_bindgen::JsValue::from_serde(&ContextOptions { + will_read_frequently: true, + }) + .unwrap(), + ) + .expect("Problem getting canvas context") + .expect("The canvas context is empty") + .dyn_into::() + .expect("Problem casting as web_sys::CanvasRenderingContext2d"); + + let width = canvas.width(); + let height = canvas.height(); + let dw = width as f64; + let dh = height as f64; + // clear canvas + ctx.begin_path(); + ctx.clear_rect(0., 0., dw, dh); + let sx = 0.; + let sy = 0.; + let sw = image.width() as f64; + let sh = image.height() as f64; + let dx = offset[0]; + let dy = offset[1]; + let dw = dw * zoom; + let dh = dh * zoom; + ctx.draw_image_with_html_image_element_and_sw_and_sh_and_dx_and_dy_and_dw_and_dh( + &image, sx, sy, sw, sh, dx, dy, dw, dh, + ) + .unwrap(); + + //let color = ctx.get_image_data(10.0, 10.0, 11.0, 11.0).unwrap().data(); +} +fn view_image( + im: &ImageMetadata, + image_canvas: &ElRef, + image_ref: &ElRef, +) -> Node { let url = format!("{ROOT_URL}/{}", im.image); + let attrs = if let Some(canvas) = image_canvas.get() { + Some(attrs![ + At::Width => px(canvas.client_width()), + At::Height => px(canvas.client_height()), + ]) + } else { + None + }; div![ - a![attrs! {At::Href => url}, p![&im.name]], - a![attrs! {At::Href => url}, img![attrs! { At::Src => url}]] + C!["image"], + canvas![ + el_ref(image_canvas), + C!["image"], + attrs, + attrs! { + At::Draggable=>AtValue::None, + }, + mouse_ev(Ev::MouseMove, |e| { + if e.buttons() != 0 { + Msg::Move([e.movement_x() as f64, e.movement_y() as f64]) + } else { + Msg::Move([0., 0.]) + } + }), + wheel_ev(Ev::Wheel, |event| { + let delta_y = event.delta_y(); + (delta_y != 0.0).then(|| { + event.prevent_default(); + let at = [event.offset_x(), event.offset_y()]; + let delta_y = -delta_y / 1000.; + Msg::Zoom(delta_y, at) + }) + }), + ], + img![ + el_ref(image_ref), + attrs! { + At::Src => url + }, + style! { + St::Display => "none", + } + ] ] } -fn view_data(data: &Data) -> Node { +fn view_data( + data: &Data, + image_canvas: &ElRef, + image_ref: &ElRef, + zoom: f64, + offset: [f64; 2], +) -> Node { + let mut width = 128; + let mut height = 128; + if let Some(c) = image_canvas.get() { + width = c.width() as i32; + height = c.height() as i32; + } + let zoom_in = 0.1; + let zoom_out = -0.1; div![ C!["columns"], - div![C!["column", "is-narrow"], view_metadata_table(data),], + div![ + C!["column", "is-narrow"], + view_metadata_table(data), + p![format!( + "Z: {:.4} Off: {:.2}x{:.2}", + zoom, offset[0], offset[1] + )], + p![format!("Mid {}x{}", width / 2, height / 2)], + p![format!("Max {}x{}", width, height)], + button![ev(Ev::Click, |_| Msg::Reset), "Reset",], + div![ + button![ + ev(Ev::Click, move |_| Msg::Zoom(zoom_in, [0, 0])), + "+ @ 0x0", + ], + button![ + ev(Ev::Click, move |_| Msg::Zoom(zoom_out, [0, 0])), + "- @ 0x0", + ], + ], + div![ + button![ + ev(Ev::Click, move |_| Msg::Zoom( + zoom_in, + [width / 2, height / 2] + )), + "+ @ mid", + ], + button![ + ev(Ev::Click, move |_| Msg::Zoom( + zoom_out, + [width / 2, height / 2] + )), + "- @ mid", + ], + ], + div![ + button![ + ev(Ev::Click, move |_| Msg::Zoom(zoom_in, [width, height])), + "+ @ max", + ], + button![ + ev(Ev::Click, move |_| Msg::Zoom(zoom_out, [width, height])), + "- @ max", + ], + ], + ], div![ C!["column"], - data.image_metadata.iter().map(|im| view_image(im)) + div![ + C!["tabs"], + ul![data.image_metadata.iter().map(|im| li![a![&im.name]])] + ], + data.image_metadata + .iter() + .nth(0) + .map(|im| view_image(im, image_canvas, image_ref)) ] ] } // `view` describes what to display. fn view(model: &Model) -> Node { + let error: Option> = if let Some(error) = &model.error { + Some(div![C!["error"], "Errors:", pre![error.to_string()]]) + } else { + None + }; div![ match &model.data { - Some(data) => view_data(data), + Some(data) => view_data( + data, + &model.image_canvas, + &model.image_ref, + model.zoom, + model.offset + ), None => h1!["Loading...."], }, - "Data", - pre![format!("{:#?}", model.data)], + error, + div![ + style! { + St::Display => "none", + }, + "Data", + pre![format!("{:#?}", model.data)] + ], ] } @@ -211,6 +447,13 @@ fn view(model: &Model) -> Node { // (This function is invoked by `init` function in `index.html`.) #[wasm_bindgen(start)] pub fn start() { + // This provides better error messages in debug mode. + // It's disabled in release mode so it doesn't bloat up the file size. + #[cfg(debug_assertions)] + console_error_panic_hook::set_once(); + + let lvl = Level::Info; + console_log::init_with_level(lvl).expect("failed to initialize console logging"); // Mount the `app` to the element with the `id` "app". App::start("app", init, update, view); }