From 72304b8fb936417c802f215b57a1aa1f812f2f1e Mon Sep 17 00:00:00 2001 From: elsirion Date: Sun, 19 Nov 2023 22:04:15 +0100 Subject: [PATCH] feat: add service worker so PWA can be installed --- Cargo.lock | 29 ++++----- Cargo.toml | 2 +- Trunk.toml | 3 + favicon.ico | Bin 0 -> 1150 bytes index.html | 4 ++ assets/manifest.json => manifest.json | 0 post_build.sh | 56 ++++++++++++++++++ service-worker.js | 81 ++++++++++++++++++++++++++ src/components/app.rs | 9 ++- src/components/mod.rs | 1 + src/components/service_worker.rs | 23 ++++++++ 11 files changed, 192 insertions(+), 16 deletions(-) create mode 100644 Trunk.toml create mode 100644 favicon.ico rename assets/manifest.json => manifest.json (100%) create mode 100755 post_build.sh create mode 100644 service-worker.js create mode 100644 src/components/service_worker.rs diff --git a/Cargo.lock b/Cargo.lock index 2e0d11b..7043513 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -774,6 +774,7 @@ dependencies = [ "tracing-wasm", "wasm-bindgen", "wasm-bindgen-futures", + "web-sys", ] [[package]] @@ -1540,9 +1541,9 @@ checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" [[package]] name = "js-sys" -version = "0.3.64" +version = "0.3.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" +checksum = "54c0c35952f67de54bb584e9fd912b3023117cbafc0a77d8f3dee1fb5f572fe8" dependencies = [ "wasm-bindgen", ] @@ -3385,9 +3386,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.87" +version = "0.2.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" +checksum = "7daec296f25a1bae309c0cd5c29c4b260e510e6d813c286b19eaadf409d40fce" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -3395,9 +3396,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.87" +version = "0.2.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" +checksum = "e397f4664c0e4e428e8313a469aaa58310d302159845980fd23b0f22a847f217" dependencies = [ "bumpalo", "log", @@ -3422,9 +3423,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.87" +version = "0.2.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" +checksum = "5961017b3b08ad5f3fe39f1e79877f8ee7c23c5e5fd5eb80de95abc41f1f16b2" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -3432,9 +3433,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.87" +version = "0.2.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" +checksum = "c5353b8dab669f5e10f5bd76df26a9360c748f054f862ff5f3f8aae0c7fb3907" dependencies = [ "proc-macro2", "quote", @@ -3445,15 +3446,15 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.87" +version = "0.2.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" +checksum = "0d046c5d029ba91a1ed14da14dca44b68bf2f124cfbaf741c54151fdb3e0750b" [[package]] name = "web-sys" -version = "0.3.64" +version = "0.3.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b" +checksum = "5db499c5f66323272151db0e666cd34f78617522fb0c1604d31a27c50c206a85" dependencies = [ "js-sys", "wasm-bindgen", diff --git a/Cargo.toml b/Cargo.toml index 61e153d..763eaea 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -38,7 +38,7 @@ tokio = { version = "1.28.2", features = [ "rt", "sync", "time" ] } tokio-stream = "0.1.14" wasm-bindgen = "0.2.87" wasm-bindgen-futures = "0.4.37" - +web-sys = { version = "0.3.65", features = [ "Navigator", "Window", "ServiceWorkerContainer" ] } gloo-storage = "0.3.0" [patch.crates-io] diff --git a/Trunk.toml b/Trunk.toml new file mode 100644 index 0000000..d73f1f7 --- /dev/null +++ b/Trunk.toml @@ -0,0 +1,3 @@ +[[hooks]] +stage = "post_build" +command = "./post_build.sh" diff --git a/favicon.ico b/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..9045e40f4e59fd8f168da82339cec014840e9895 GIT binary patch literal 1150 zcmZ{kPe@cz6vof^lol2VLKuTJlICEV|FhCS6cJ60f=ttmAW|y@nKp&FiIyc&n}|RX z@gF6b)Iu0cg|Ze78k2-cOE-#&xlm5u_vT%=ATs>kx%WHYciw%EnGx~flawU52IOA6 z$SDyC0!UC|I*JH-k9T9Zd+(w@YsDiA^%u}1Sbo+sJ{Ylhea8%al^w8_ZS%Cw3 z!9Fm)1FUU~P7l4zxaUA^1e?HkzF^(r>Fl+FIbizqQfK}u;B%SYD%O_{A~iDF7<2|| z(;cp%m4H8%j~QlvSlSlWceiG$WaV{f&Em6?53>&oCO+TKsr>h~nlpF~dd$6;wP(In zz3m_ySbljWy6~h}r@M0XeQQ=^@Op+{wIv?@AuG@9h_!#G`p6e~e!1-X)8d_QC{HKb zF6dCh`OP;K=ZaK&;^3XI{LFR(zGt2(s=w<}=6ecL!lC?ykL}qyd^1y#o$bp`P1e=A z)9{#g#SF9MU;{AEXDi*9u9T^coWk)t!Ty2j^uAYRX&2Y0D){`@z&4b zz^{KBBn{sXKhU*$X6btYjE@;=31H09c`o)s;Ecxu)Ma3vlQWoMma{v-9x$_6>5Y2W zIrivfhFOvbZh=o=7ua*`HGA~X%Z&XS;GE;&2ABjpz+}0m#vVQHeciBiF*@oA&;-7D iG<({i+}bgbup`pzixF3jzlne~6ia(=e9Y~g75NWJONO=p literal 0 HcmV?d00001 diff --git a/index.html b/index.html index c6d8420..a2b9626 100644 --- a/index.html +++ b/index.html @@ -1,9 +1,13 @@ + + + + diff --git a/assets/manifest.json b/manifest.json similarity index 100% rename from assets/manifest.json rename to manifest.json diff --git a/post_build.sh b/post_build.sh new file mode 100755 index 0000000..c9c609a --- /dev/null +++ b/post_build.sh @@ -0,0 +1,56 @@ +#!/usr/bin/env bash +set -e + +appName="fedimint-leptos-test" +stylePrefix="index" +styleFormat="css" + +# Extract build version +indexJsFile=$(find ./dist/.stage -iname "${appName}-*.js") +echo "Extracting build version from file: ${indexJsFile}" +regex="(.*)${appName}-(.*).js" +_src="${indexJsFile}" +while [[ "${_src}" =~ ${regex} ]]; do + buildVersion="${BASH_REMATCH[2]}" + _i=${#BASH_REMATCH} + _src=${_src:_i} +done +if [ -z "${buildVersion}" ]; then + echo "Could not determine build version!" + exit 1 +fi +echo "Build-Version is: ${buildVersion}" + +# Replace placeholder in service-worker.js +serviceWorkerJsFile=$(find ./dist/.stage -iname "service-worker.js") +echo "Replacing {{buildVersion}} placeholder in: ${serviceWorkerJsFile}" +sed "s/{{buildVersion}}/${buildVersion}/g" "${serviceWorkerJsFile}" > "${serviceWorkerJsFile}.modified" +mv -f "${serviceWorkerJsFile}.modified" "${serviceWorkerJsFile}" + +# Replace placeholder in index.html +indexHtmlFile=$(find ./dist/.stage -iname "index.html") +echo "Replacing {{buildVersion}} placeholder in: ${indexHtmlFile}" +sed "s/{{buildVersion}}/${buildVersion}/g" "${indexHtmlFile}" > "${indexHtmlFile}.modified" +mv -f "${indexHtmlFile}.modified" "${indexHtmlFile}" + +# Extract CSS build version +indexJsFile=$(find ./dist/.stage -iname "${stylePrefix}-*.${styleFormat}") +echo "Extracting style build version from file: ${indexJsFile}" +regex="(.*)${stylePrefix}-(.*).${styleFormat}" +_src="${indexJsFile}" +while [[ "${_src}" =~ ${regex} ]]; do + cssBuildVersion="${BASH_REMATCH[2]}" + _i=${#BASH_REMATCH} + _src=${_src:_i} +done +if [ -z "${cssBuildVersion}" ]; then + echo "Could not determine style build version!" + exit 1 +fi +echo "CSS Build-Version is: ${cssBuildVersion}" + +# Replace placeholder in service-worker.js +serviceWorkerJsFile=$(find ./dist/.stage -iname "service-worker.js") +echo "Replacing {{cssBuildVersion}} placeholder in: ${serviceWorkerJsFile}" +sed "s/{{cssBuildVersion}}/${cssBuildVersion}/g" "${serviceWorkerJsFile}" > "${serviceWorkerJsFile}.modified" +mv -f "${serviceWorkerJsFile}.modified" "${serviceWorkerJsFile}" diff --git a/service-worker.js b/service-worker.js new file mode 100644 index 0000000..9bccd90 --- /dev/null +++ b/service-worker.js @@ -0,0 +1,81 @@ +var buildVersion = "{{buildVersion}}" +var cssBuildVersion = "{{cssBuildVersion}}" +var cacheName = "webimint"; + +var filesToCache = [ + './', + './index.html', + './manifest.json', + './fedimint-leptos-test-' + buildVersion + '_bg.wasm', + './fedimint-leptos-test-' + buildVersion + '.js', + './index-' + cssBuildVersion + '.css', + './assets/icons/android-icon-192x192.png', + './assets/icons/favicon-32x32.png', + './assets/icons/favicon-96x96.png', + './assets/icons/favicon-16x16.png', + './favicon.ico', + + // TODO: Add files you want the SW to cache. Rename entries to match your build output! +]; + +/* Start the service worker and cache all of the app's content */ +self.addEventListener('install', function (event) { + console.log("Installing service-worker for build", buildVersion); + const preCache = async () => { + get_cache().then(function (cache) { + // We clear the whole cache, as we do not know which resources were updated! + cache.keys().then(function (requests) { + for (let request of requests) { + cache.delete(request); + } + }); + cache.addAll(filesToCache.map(url => new Request(url, { credentials: 'same-origin' }))); + }) + }; + event.waitUntil(preCache); +}); + +self.addEventListener('message', function (messageEvent) { + if (messageEvent.data === "skipWaiting") { + console.log("Service-worker received skipWaiting event", buildVersion); + self.skipWaiting(); + } +}); + +self.addEventListener('fetch', function (e) { + e.respondWith(cache_then_network(e.request)); +}); + +async function get_cache() { + return caches.open(cacheName); +} + +async function cache_then_network(request) { + const cache = await get_cache(); + return cache.match(request).then( + (cache_response) => { + if (!cache_response) { + return fetch_from_network(request, cache); + } else { + return cache_response; + } + }, + (reason) => { + return fetch_from_network(request, cache); + } + ); +} + +function fetch_from_network(request, cache) { + return fetch(request).then( + (net_response) => { + return net_response; + }, + (reason) => { + console.error("Network fetch rejected. Falling back to ./index.html. Reason: ", reason); + return cache.match("./index.html").then(function (cache_root_response) { + return cache_root_response; + }); + } + ) +} diff --git a/src/components/app.rs b/src/components/app.rs index 3077add..636d9ee 100644 --- a/src/components/app.rs +++ b/src/components/app.rs @@ -6,12 +6,17 @@ use crate::utils::empty_view; use anyhow::anyhow; use leptos::*; use leptos_meta::{Title, Meta, Link}; +use leptos::SignalGet; +use tracing::info; +use crate::components::service_worker::ServiceWorker; // // App component // #[component] pub fn App(cx: Scope) -> impl IntoView { + info!("Starting app..."); + let client = ClientRpc::new(); provide_client_context(cx, client.clone()); @@ -54,13 +59,15 @@ pub fn App(cx: Scope) -> impl IntoView { }; view! { cx, + + <Meta name="viewport" content="width=device-width, initial-scale=0.75, user-scalable=0, interactive-widget=overlays-content" /> <Link rel="icon" type_="image/png" sizes="192x192" href="/assets/icons/android-icon-192x192.png" /> <Link rel="icon" type_="image/png" sizes="32x32" href="/assets/icons/favicon-32x32.png" /> <Link rel="icon" type_="image/png" sizes="96x96" href="/assets/icons/favicon-96x96.png" /> <Link rel="icon" type_="image/png" sizes="16x16" href="/assets/icons/favicon-16x16.png" /> - <Link rel="manifest" href="/assets/manifest.json" /> + <Link rel="manifest" href="/manifest.json" /> <Meta name="theme-color" content="#ffffff" /> <div class="h-[100dvh]"> diff --git a/src/components/mod.rs b/src/components/mod.rs index d8d2b06..b2e96bf 100644 --- a/src/components/mod.rs +++ b/src/components/mod.rs @@ -14,6 +14,7 @@ pub mod submit_button; pub mod submit_form; pub mod tx_list; pub mod wallet_selector; +pub mod service_worker; pub use app::*; pub use balance::*; diff --git a/src/components/service_worker.rs b/src/components/service_worker.rs new file mode 100644 index 0000000..cd1ab12 --- /dev/null +++ b/src/components/service_worker.rs @@ -0,0 +1,23 @@ +use leptos::{component, create_action, IntoView, Scope, window}; +use tracing::{info, warn}; +use crate::utils::empty_view; + +#[component] +pub fn ServiceWorker(cx: Scope, #[prop(into)] path: String) -> impl IntoView { + let register_action = create_action(cx, move |script_url: &String| { + let script_url = script_url.to_owned(); + async move { + info!("Registering service worker: {}", script_url); + let promise = window().navigator().service_worker().register(script_url.as_str()); + if let Err(e) = wasm_bindgen_futures::JsFuture::from(promise) + .await { + warn!("Service worker registration failed: {:?}", e); + } + info!("Service worker registered"); + } + }); + + register_action.dispatch(path); + + empty_view() +} \ No newline at end of file