From e038f9664a403dfaa592ff44091076aa14dfc5ee Mon Sep 17 00:00:00 2001 From: Lukas Potthast Date: Wed, 4 Oct 2023 17:35:52 +0200 Subject: [PATCH] WIP: Add use_service_worker --- CHANGELOG.md | 6 + Cargo.toml | 5 + docs/book/src/SUMMARY.md | 1 + docs/book/src/browser/use_service_worker.md | 3 + examples/Cargo.toml | 1 + examples/use_service_worker/Cargo.toml | 16 + examples/use_service_worker/README.md | 23 ++ examples/use_service_worker/Trunk.toml | 7 + examples/use_service_worker/index.html | 10 + examples/use_service_worker/input.css | 3 + examples/use_service_worker/manifest.json | 54 ++++ examples/use_service_worker/post_build.sh | 56 ++++ .../res/icon/maskable_icon_x128.png | Bin 0 -> 4308 bytes .../res/icon/maskable_icon_x192.png | Bin 0 -> 6145 bytes .../res/icon/maskable_icon_x384.png | Bin 0 -> 14111 bytes .../res/icon/maskable_icon_x48.png | Bin 0 -> 1341 bytes .../res/icon/maskable_icon_x512.png | Bin 0 -> 22051 bytes .../res/icon/maskable_icon_x72.png | Bin 0 -> 2408 bytes .../res/icon/maskable_icon_x96.png | Bin 0 -> 2865 bytes examples/use_service_worker/res/icon/pwa.png | Bin 0 -> 50089 bytes examples/use_service_worker/res/icon/pwa.svg | 9 + .../use_service_worker/rust-toolchain.toml | 2 + examples/use_service_worker/service-worker.js | 82 +++++ examples/use_service_worker/src/main.rs | 61 ++++ examples/use_service_worker/style/output.css | 294 ++++++++++++++++++ .../use_service_worker/tailwind.config.js | 15 + src/lib.rs | 2 + src/use_service_worker.rs | 269 ++++++++++++++++ 28 files changed, 919 insertions(+) create mode 100644 docs/book/src/browser/use_service_worker.md create mode 100644 examples/use_service_worker/Cargo.toml create mode 100644 examples/use_service_worker/README.md create mode 100644 examples/use_service_worker/Trunk.toml create mode 100644 examples/use_service_worker/index.html create mode 100644 examples/use_service_worker/input.css create mode 100644 examples/use_service_worker/manifest.json create mode 100755 examples/use_service_worker/post_build.sh create mode 100644 examples/use_service_worker/res/icon/maskable_icon_x128.png create mode 100644 examples/use_service_worker/res/icon/maskable_icon_x192.png create mode 100644 examples/use_service_worker/res/icon/maskable_icon_x384.png create mode 100644 examples/use_service_worker/res/icon/maskable_icon_x48.png create mode 100644 examples/use_service_worker/res/icon/maskable_icon_x512.png create mode 100644 examples/use_service_worker/res/icon/maskable_icon_x72.png create mode 100644 examples/use_service_worker/res/icon/maskable_icon_x96.png create mode 100644 examples/use_service_worker/res/icon/pwa.png create mode 100644 examples/use_service_worker/res/icon/pwa.svg create mode 100644 examples/use_service_worker/rust-toolchain.toml create mode 100644 examples/use_service_worker/service-worker.js create mode 100644 examples/use_service_worker/src/main.rs create mode 100644 examples/use_service_worker/style/output.css create mode 100644 examples/use_service_worker/tailwind.config.js create mode 100644 src/use_service_worker.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index 65d75ca..213701a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,12 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [Unreleased] - + +### New Functions 🚀 + +- `use_service_worker` + ## [0.7.1] - 2023-10-02 ### New Function 🚀 diff --git a/Cargo.toml b/Cargo.toml index 2747c15..0031e6d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,6 +15,7 @@ homepage = "https://leptos-use.rs" [dependencies] leptos = "0.5" wasm-bindgen = "0.2" +wasm-bindgen-futures = "0.4" js-sys = "0.3" default-struct-builder = "0.5" num = { version = "0.4", optional = true } @@ -69,6 +70,10 @@ features = [ "ResizeObserverSize", "ScrollBehavior", "ScrollToOptions", + "ServiceWorker", + "ServiceWorkerContainer", + "ServiceWorkerRegistration", + "ServiceWorkerState", "Storage", "Touch", "TouchEvent", diff --git a/docs/book/src/SUMMARY.md b/docs/book/src/SUMMARY.md index dbb23c8..955db99 100644 --- a/docs/book/src/SUMMARY.md +++ b/docs/book/src/SUMMARY.md @@ -38,6 +38,7 @@ - [use_media_query](browser/use_media_query.md) - [use_preferred_contrast](browser/use_preferred_contrast.md) - [use_preferred_dark](browser/use_preferred_dark.md) +- [use_service_worker](browser/use_service_worker.md) # Sensors diff --git a/docs/book/src/browser/use_service_worker.md b/docs/book/src/browser/use_service_worker.md new file mode 100644 index 0000000..93f8a0a --- /dev/null +++ b/docs/book/src/browser/use_service_worker.md @@ -0,0 +1,3 @@ +# use_service_worker + + diff --git a/examples/Cargo.toml b/examples/Cargo.toml index 930d976..6fcf5b6 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml @@ -35,6 +35,7 @@ members = [ "use_resize_observer", "use_round", "use_scroll", + "use_service_worker", "use_sorted", "use_storage", "use_throttle_fn", diff --git a/examples/use_service_worker/Cargo.toml b/examples/use_service_worker/Cargo.toml new file mode 100644 index 0000000..878fa9a --- /dev/null +++ b/examples/use_service_worker/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "use_service_worker" +version = "0.1.0" +edition = "2021" + +[dependencies] +leptos = { version = "0.5", features = ["nightly", "csr"] } +console_error_panic_hook = "0.1" +console_log = "1" +log = "0.4" +leptos-use = { path = "../..", features = ["docs"] } +web-sys = "0.3" + +[dev-dependencies] +wasm-bindgen = "0.2" +wasm-bindgen-test = "0.3.0" diff --git a/examples/use_service_worker/README.md b/examples/use_service_worker/README.md new file mode 100644 index 0000000..a4e333d --- /dev/null +++ b/examples/use_service_worker/README.md @@ -0,0 +1,23 @@ +A simple example for `use_service_worker`. + +If you don't have it installed already, install [Trunk](https://trunkrs.dev/) and [Tailwind](https://tailwindcss.com/docs/installation) +as well as the nightly toolchain for Rust and the wasm32-unknown-unknown target: + +```bash +cargo install trunk +npm install -D tailwindcss @tailwindcss/forms +rustup toolchain install nightly +rustup target add wasm32-unknown-unknown +``` + +Then, open two terminals. In the first one, run: + +``` +npx tailwindcss -i ./input.css -o ./style/output.css --watch +``` + +In the second one, run: + +```bash +trunk serve --open +``` \ No newline at end of file diff --git a/examples/use_service_worker/Trunk.toml b/examples/use_service_worker/Trunk.toml new file mode 100644 index 0000000..241fda5 --- /dev/null +++ b/examples/use_service_worker/Trunk.toml @@ -0,0 +1,7 @@ +[build] +public_url = "/demo/" + +[[hooks]] +stage = "post_build" +command = "bash" +command_arguments = ["-c", "./post_build.sh"] diff --git a/examples/use_service_worker/index.html b/examples/use_service_worker/index.html new file mode 100644 index 0000000..c3733f9 --- /dev/null +++ b/examples/use_service_worker/index.html @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/examples/use_service_worker/input.css b/examples/use_service_worker/input.css new file mode 100644 index 0000000..bd6213e --- /dev/null +++ b/examples/use_service_worker/input.css @@ -0,0 +1,3 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; \ No newline at end of file diff --git a/examples/use_service_worker/manifest.json b/examples/use_service_worker/manifest.json new file mode 100644 index 0000000..8b720cf --- /dev/null +++ b/examples/use_service_worker/manifest.json @@ -0,0 +1,54 @@ +{ + "name": "Demo", + "short_name": "Demo", + "icons": [ + { + "src": "./res/icon/maskable_icon_x48.png", + "sizes": "48x48", + "type": "image/png", + "purpose": "maskable" + }, + { + "src": "./res/icon/maskable_icon_x72.png", + "sizes": "72x72", + "type": "image/png", + "purpose": "maskable" + }, + { + "src": "./res/icon/maskable_icon_x96.png", + "sizes": "96x96", + "type": "image/png", + "purpose": "maskable" + }, + { + "src": "./res/icon/maskable_icon_x128.png", + "sizes": "128x128", + "type": "image/png", + "purpose": "maskable" + }, + { + "src": "./res/icon/maskable_icon_x192.png", + "sizes": "192x192", + "type": "image/png", + "purpose": "maskable" + }, + { + "src": "./res/icon/maskable_icon_x384.png", + "sizes": "384x384", + "type": "image/png", + "purpose": "maskable" + }, + { + "src": "./res/icon/maskable_icon_x512.png", + "sizes": "512x512", + "type": "image/png", + "purpose": "maskable" + } + ], + "lang": "en-US", + "id": "/demo/", + "start_url": "/demo/", + "display": "standalone", + "background_color": "#e52320", + "theme_color": "#e52320" +} \ No newline at end of file diff --git a/examples/use_service_worker/post_build.sh b/examples/use_service_worker/post_build.sh new file mode 100755 index 0000000..202a47b --- /dev/null +++ b/examples/use_service_worker/post_build.sh @@ -0,0 +1,56 @@ +#!/bin/bash +set -e + +appName="use_service_worker" +stylePrefix="output" +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/examples/use_service_worker/res/icon/maskable_icon_x128.png b/examples/use_service_worker/res/icon/maskable_icon_x128.png new file mode 100644 index 0000000000000000000000000000000000000000..f730574311af028829811f53861f5e48fa6c6a4a GIT binary patch literal 4308 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 BFv$P_ literal 0 HcmV?d00001 diff --git a/examples/use_service_worker/res/icon/maskable_icon_x384.png b/examples/use_service_worker/res/icon/maskable_icon_x384.png new file mode 100644 index 0000000000000000000000000000000000000000..3041f5251b8a194f2134d25135d6a43eeda26675 GIT binary patch literal 14111 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 literal 0 HcmV?d00001 diff --git a/examples/use_service_worker/res/icon/maskable_icon_x512.png b/examples/use_service_worker/res/icon/maskable_icon_x512.png new file mode 100644 index 0000000000000000000000000000000000000000..d1e37b91f6555a30dee14a5071adcdede261fabe GIT binary patch literal 22051 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 literal 0 HcmV?d00001 diff --git a/examples/use_service_worker/res/icon/maskable_icon_x72.png b/examples/use_service_worker/res/icon/maskable_icon_x72.png new file mode 100644 index 0000000000000000000000000000000000000000..41968977044d3238d36eca7a01d2f1ffbc63df5f GIT binary patch literal 2408 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 BNp=7L literal 0 HcmV?d00001 diff --git a/examples/use_service_worker/res/icon/pwa.png b/examples/use_service_worker/res/icon/pwa.png new file mode 100644 index 0000000000000000000000000000000000000000..b5a31afb6b877cba9004090531e3db55f6105cd3 GIT binary patch literal 50089 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 literal 0 HcmV?d00001 diff --git a/examples/use_service_worker/res/icon/pwa.svg b/examples/use_service_worker/res/icon/pwa.svg new file mode 100644 index 0000000..55264a9 --- /dev/null +++ b/examples/use_service_worker/res/icon/pwa.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/examples/use_service_worker/rust-toolchain.toml b/examples/use_service_worker/rust-toolchain.toml new file mode 100644 index 0000000..271800c --- /dev/null +++ b/examples/use_service_worker/rust-toolchain.toml @@ -0,0 +1,2 @@ +[toolchain] +channel = "nightly" \ No newline at end of file diff --git a/examples/use_service_worker/service-worker.js b/examples/use_service_worker/service-worker.js new file mode 100644 index 0000000..511a41b --- /dev/null +++ b/examples/use_service_worker/service-worker.js @@ -0,0 +1,82 @@ +var buildVersion = "{{buildVersion}}" +var cssBuildVersion = "{{cssBuildVersion}}" +var cacheName = "demo"; +var filesToCache = [ + './', + './index.html', + './manifest.json', + './use_service_worker-' + buildVersion + '_bg.wasm', + './use_service_worker-' + buildVersion + '.js', + './output-' + cssBuildVersion + '.css', + './res/icon/maskable_icon_x48.png', + './res/icon/maskable_icon_x72.png', + './res/icon/maskable_icon_x96.png', + './res/icon/maskable_icon_x128.png', + './res/icon/maskable_icon_x192.png', + './res/icon/maskable_icon_x384.png', + './res/icon/maskable_icon_x512.png', + + // 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/examples/use_service_worker/src/main.rs b/examples/use_service_worker/src/main.rs new file mode 100644 index 0000000..2df2dcd --- /dev/null +++ b/examples/use_service_worker/src/main.rs @@ -0,0 +1,61 @@ +use leptos::*; +use leptos_use::docs::demo_or_body; +use leptos_use::{use_service_worker, use_window}; +use web_sys::HtmlMetaElement; + +#[component] +fn Demo() -> impl IntoView { + let build = load_meta_element("version") + .map(|meta| meta.content()) + .expect("'version' meta element"); + + let sw = use_service_worker(); + + view! { +

"Current build: "{build}

+ +
+ +

"registration: "{move || format!("{:#?}", sw.registration.get())}

+

"installing: "{move || sw.installing.get()}

+

"waiting: "{move || sw.waiting.get()}

+

"active: "{move || sw.active.get()}

+ +
+ + + } +} + +fn main() { + _ = console_log::init_with_level(log::Level::Debug); + console_error_panic_hook::set_once(); + + mount_to(demo_or_body(), || { + view! { } + }) +} + +fn load_meta_element>(name: S) -> Result { + use wasm_bindgen::JsCast; + use_window() + .as_ref() + .ok_or_else(|| "No window instance!".to_owned()) + .and_then(|window| { + window + .document() + .ok_or_else(|| "No document instance!".to_owned()) + }) + .and_then(|document| { + document + .query_selector(format!("meta[name=\"{}\"]", name.as_ref()).as_str()) + .ok() + .flatten() + .ok_or_else(|| format!("Unable to find meta element with name 'version'.")) + }) + .and_then(|element| { + element.dyn_into::().map_err(|err| { + format!("Unable to cast element to HtmlMetaElement. Err: '{err:?}'.") + }) + }) +} diff --git a/examples/use_service_worker/style/output.css b/examples/use_service_worker/style/output.css new file mode 100644 index 0000000..1c83da6 --- /dev/null +++ b/examples/use_service_worker/style/output.css @@ -0,0 +1,294 @@ +[type='text'],input:where(:not([type])),[type='email'],[type='url'],[type='password'],[type='number'],[type='date'],[type='datetime-local'],[type='month'],[type='search'],[type='tel'],[type='time'],[type='week'],[multiple],textarea,select { + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + background-color: #fff; + border-color: #6b7280; + border-width: 1px; + border-radius: 0px; + padding-top: 0.5rem; + padding-right: 0.75rem; + padding-bottom: 0.5rem; + padding-left: 0.75rem; + font-size: 1rem; + line-height: 1.5rem; + --tw-shadow: 0 0 #0000; +} + +[type='text']:focus, input:where(:not([type])):focus, [type='email']:focus, [type='url']:focus, [type='password']:focus, [type='number']:focus, [type='date']:focus, [type='datetime-local']:focus, [type='month']:focus, [type='search']:focus, [type='tel']:focus, [type='time']:focus, [type='week']:focus, [multiple]:focus, textarea:focus, select:focus { + outline: 2px solid transparent; + outline-offset: 2px; + --tw-ring-inset: var(--tw-empty,/*!*/ /*!*/); + --tw-ring-offset-width: 0px; + --tw-ring-offset-color: #fff; + --tw-ring-color: #2563eb; + --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color); + --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color); + box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow); + border-color: #2563eb; +} + +input::-moz-placeholder, textarea::-moz-placeholder { + color: #6b7280; + opacity: 1; +} + +input::placeholder,textarea::placeholder { + color: #6b7280; + opacity: 1; +} + +::-webkit-datetime-edit-fields-wrapper { + padding: 0; +} + +::-webkit-date-and-time-value { + min-height: 1.5em; + text-align: inherit; +} + +::-webkit-datetime-edit { + display: inline-flex; +} + +::-webkit-datetime-edit,::-webkit-datetime-edit-year-field,::-webkit-datetime-edit-month-field,::-webkit-datetime-edit-day-field,::-webkit-datetime-edit-hour-field,::-webkit-datetime-edit-minute-field,::-webkit-datetime-edit-second-field,::-webkit-datetime-edit-millisecond-field,::-webkit-datetime-edit-meridiem-field { + padding-top: 0; + padding-bottom: 0; +} + +select { + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 8l4 4 4-4'/%3e%3c/svg%3e"); + background-position: right 0.5rem center; + background-repeat: no-repeat; + background-size: 1.5em 1.5em; + padding-right: 2.5rem; + -webkit-print-color-adjust: exact; + print-color-adjust: exact; +} + +[multiple],[size]:where(select:not([size="1"])) { + background-image: initial; + background-position: initial; + background-repeat: unset; + background-size: initial; + padding-right: 0.75rem; + -webkit-print-color-adjust: unset; + print-color-adjust: unset; +} + +[type='checkbox'],[type='radio'] { + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + padding: 0; + -webkit-print-color-adjust: exact; + print-color-adjust: exact; + display: inline-block; + vertical-align: middle; + background-origin: border-box; + -webkit-user-select: none; + -moz-user-select: none; + user-select: none; + flex-shrink: 0; + height: 1rem; + width: 1rem; + color: #2563eb; + background-color: #fff; + border-color: #6b7280; + border-width: 1px; + --tw-shadow: 0 0 #0000; +} + +[type='checkbox'] { + border-radius: 0px; +} + +[type='radio'] { + border-radius: 100%; +} + +[type='checkbox']:focus,[type='radio']:focus { + outline: 2px solid transparent; + outline-offset: 2px; + --tw-ring-inset: var(--tw-empty,/*!*/ /*!*/); + --tw-ring-offset-width: 2px; + --tw-ring-offset-color: #fff; + --tw-ring-color: #2563eb; + --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color); + --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color); + box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow); +} + +[type='checkbox']:checked,[type='radio']:checked { + border-color: transparent; + background-color: currentColor; + background-size: 100% 100%; + background-position: center; + background-repeat: no-repeat; +} + +[type='checkbox']:checked { + background-image: url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M12.207 4.793a1 1 0 010 1.414l-5 5a1 1 0 01-1.414 0l-2-2a1 1 0 011.414-1.414L6.5 9.086l4.293-4.293a1 1 0 011.414 0z'/%3e%3c/svg%3e"); +} + +[type='radio']:checked { + background-image: url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3ccircle cx='8' cy='8' r='3'/%3e%3c/svg%3e"); +} + +[type='checkbox']:checked:hover,[type='checkbox']:checked:focus,[type='radio']:checked:hover,[type='radio']:checked:focus { + border-color: transparent; + background-color: currentColor; +} + +[type='checkbox']:indeterminate { + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 16 16'%3e%3cpath stroke='white' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M4 8h8'/%3e%3c/svg%3e"); + border-color: transparent; + background-color: currentColor; + background-size: 100% 100%; + background-position: center; + background-repeat: no-repeat; +} + +[type='checkbox']:indeterminate:hover,[type='checkbox']:indeterminate:focus { + border-color: transparent; + background-color: currentColor; +} + +[type='file'] { + background: unset; + border-color: inherit; + border-width: 0; + border-radius: 0; + padding: 0; + font-size: unset; + line-height: inherit; +} + +[type='file']:focus { + outline: 1px solid ButtonText; + outline: 1px auto -webkit-focus-ring-color; +} + +*, ::before, ::after { + --tw-border-spacing-x: 0; + --tw-border-spacing-y: 0; + --tw-translate-x: 0; + --tw-translate-y: 0; + --tw-rotate: 0; + --tw-skew-x: 0; + --tw-skew-y: 0; + --tw-scale-x: 1; + --tw-scale-y: 1; + --tw-pan-x: ; + --tw-pan-y: ; + --tw-pinch-zoom: ; + --tw-scroll-snap-strictness: proximity; + --tw-gradient-from-position: ; + --tw-gradient-via-position: ; + --tw-gradient-to-position: ; + --tw-ordinal: ; + --tw-slashed-zero: ; + --tw-numeric-figure: ; + --tw-numeric-spacing: ; + --tw-numeric-fraction: ; + --tw-ring-inset: ; + --tw-ring-offset-width: 0px; + --tw-ring-offset-color: #fff; + --tw-ring-color: rgb(59 130 246 / 0.5); + --tw-ring-offset-shadow: 0 0 #0000; + --tw-ring-shadow: 0 0 #0000; + --tw-shadow: 0 0 #0000; + --tw-shadow-colored: 0 0 #0000; + --tw-blur: ; + --tw-brightness: ; + --tw-contrast: ; + --tw-grayscale: ; + --tw-hue-rotate: ; + --tw-invert: ; + --tw-saturate: ; + --tw-sepia: ; + --tw-drop-shadow: ; + --tw-backdrop-blur: ; + --tw-backdrop-brightness: ; + --tw-backdrop-contrast: ; + --tw-backdrop-grayscale: ; + --tw-backdrop-hue-rotate: ; + --tw-backdrop-invert: ; + --tw-backdrop-opacity: ; + --tw-backdrop-saturate: ; + --tw-backdrop-sepia: ; +} + +::backdrop { + --tw-border-spacing-x: 0; + --tw-border-spacing-y: 0; + --tw-translate-x: 0; + --tw-translate-y: 0; + --tw-rotate: 0; + --tw-skew-x: 0; + --tw-skew-y: 0; + --tw-scale-x: 1; + --tw-scale-y: 1; + --tw-pan-x: ; + --tw-pan-y: ; + --tw-pinch-zoom: ; + --tw-scroll-snap-strictness: proximity; + --tw-gradient-from-position: ; + --tw-gradient-via-position: ; + --tw-gradient-to-position: ; + --tw-ordinal: ; + --tw-slashed-zero: ; + --tw-numeric-figure: ; + --tw-numeric-spacing: ; + --tw-numeric-fraction: ; + --tw-ring-inset: ; + --tw-ring-offset-width: 0px; + --tw-ring-offset-color: #fff; + --tw-ring-color: rgb(59 130 246 / 0.5); + --tw-ring-offset-shadow: 0 0 #0000; + --tw-ring-shadow: 0 0 #0000; + --tw-shadow: 0 0 #0000; + --tw-shadow-colored: 0 0 #0000; + --tw-blur: ; + --tw-brightness: ; + --tw-contrast: ; + --tw-grayscale: ; + --tw-hue-rotate: ; + --tw-invert: ; + --tw-saturate: ; + --tw-sepia: ; + --tw-drop-shadow: ; + --tw-backdrop-blur: ; + --tw-backdrop-brightness: ; + --tw-backdrop-contrast: ; + --tw-backdrop-grayscale: ; + --tw-backdrop-hue-rotate: ; + --tw-backdrop-invert: ; + --tw-backdrop-opacity: ; + --tw-backdrop-saturate: ; + --tw-backdrop-sepia: ; +} + +.static { + position: static; +} + +.text-\[--brand-color\] { + color: var(--brand-color); +} + +.text-green-600 { + --tw-text-opacity: 1; + color: rgb(22 163 74 / var(--tw-text-opacity)); +} + +.opacity-75 { + opacity: 0.75; +} + +@media (prefers-color-scheme: dark) { + .dark\:text-green-500 { + --tw-text-opacity: 1; + color: rgb(34 197 94 / var(--tw-text-opacity)); + } +} \ No newline at end of file diff --git a/examples/use_service_worker/tailwind.config.js b/examples/use_service_worker/tailwind.config.js new file mode 100644 index 0000000..bc09f5e --- /dev/null +++ b/examples/use_service_worker/tailwind.config.js @@ -0,0 +1,15 @@ +/** @type {import('tailwindcss').Config} */ +module.exports = { + content: { + files: ["*.html", "./src/**/*.rs", "../../src/docs/**/*.rs"], + }, + theme: { + extend: {}, + }, + corePlugins: { + preflight: false, + }, + plugins: [ + require('@tailwindcss/forms'), + ], +} \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index c3384c8..4d2d979 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -25,6 +25,7 @@ mod is_none; mod is_ok; mod is_some; mod on_click_outside; +mod use_service_worker; mod signal_debounced; mod signal_throttled; mod use_active_element; @@ -74,6 +75,7 @@ pub use is_none::*; pub use is_ok::*; pub use is_some::*; pub use on_click_outside::*; +pub use use_service_worker::*; pub use signal_debounced::*; pub use signal_throttled::*; pub use use_active_element::*; diff --git a/src/use_service_worker.rs b/src/use_service_worker.rs new file mode 100644 index 0000000..17f77c3 --- /dev/null +++ b/src/use_service_worker.rs @@ -0,0 +1,269 @@ +use default_struct_builder::DefaultBuilder; +use leptos::*; +use std::borrow::Cow; +use wasm_bindgen::{prelude::Closure, JsCast, JsValue}; +use web_sys::ServiceWorkerRegistration; + +use crate::use_window; + +/// +/// +/// ## Demo +/// +/// [Link to Demo](https://github.com/Synphonyte/leptos-use/tree/main/examples/use_service_worker) +/// +/// ## Usage +/// +/// ``` +/// # use leptos::*; +/// # use leptos_use::use_service_worker; +/// # +/// # #[component] +/// # fn Demo() -> impl IntoView { +/// # let sw = use_service_worker_with_options(UseServiceWorkerOptions { +/// # script_url: "service-worker.js".into(), +/// # skip_waiting_message: "skipWaiting".into(), +/// # ..UseServiceWorkerOptions::default() +/// # }); +/// # +/// # view! { } +/// # } +/// ``` +pub fn use_service_worker() -> UseServiceWorkerReturn { + use_service_worker_with_options(UseServiceWorkerOptions::default()) +} + +/// Version of [`use_service_worker`] that takes a `UseServiceWorkerOptions`. See [`use_service_worker`] for how to use. +pub fn use_service_worker_with_options(options: UseServiceWorkerOptions) -> UseServiceWorkerReturn { + // Reload the page whenever a new ServiceWorker is installed. + if let Some(navigator) = use_window().navigator() { + let on_controller_change = options.on_controller_change.clone(); + let reload = Closure::wrap(Box::new(move |_event: JsValue| { + on_controller_change.call(()); + }) as Box) + .into_js_value(); + navigator + .service_worker() + .set_oncontrollerchange(Some(reload.as_ref().unchecked_ref())); + } + + // Create async actions. + let create_or_update_registration = create_action_create_or_update_sw_registration(); + let get_registration = create_action_get_sw_registration(); + let update_action = create_action_update_sw(); + + // Immediately create or update the SW registration. + create_or_update_registration.dispatch(ServiceWorkerScriptUrl(options.script_url.to_string())); + + // And parse the result into individual signals. + let registration: Signal> = + Signal::derive(move || { + let a = get_registration.value().get(); + let b = create_or_update_registration.value().get(); + // We only dispatch create_or_update_registration once. Whenever we manually re-fetched the registration, the result of that has precedence! + match a { + Some(res) => res.map_err(ServiceWorkerRegistrationError::Js), + None => match b { + Some(res) => res.map_err(ServiceWorkerRegistrationError::Js), + None => Err(ServiceWorkerRegistrationError::NeverQueried), + }, + } + }); + + let fetch_registration = Closure::wrap(Box::new(move |_event: JsValue| { + get_registration.dispatch(()); + }) as Box) + .into_js_value(); + + // Handle a changing registration state. + // Notify to developer if SW registration or retrieval fails. + create_effect(move |_| { + registration.with(|reg| match reg { + Ok(registration) => { + // We must be informed when an updated SW is available. + registration.set_onupdatefound(Some(fetch_registration.as_ref().unchecked_ref())); + + // Trigger a check to see IF an updated SW is available. + update_action.dispatch(registration.clone()); + + // If a SW is installing, we must be notified if its state changes! + if let Some(sw) = registration.installing() { + sw.set_onstatechange(Some(fetch_registration.as_ref().unchecked_ref())); + } + } + Err(err) => match err { + ServiceWorkerRegistrationError::Js(err) => { + tracing::warn!("ServiceWorker registration failed: {err:?}") + } + ServiceWorkerRegistrationError::NeverQueried => {} + }, + }) + }); + + UseServiceWorkerReturn { + registration, + installing: Signal::derive(move || { + registration.with(|reg| { + reg.as_ref() + .map(|reg| reg.installing().is_some()) + .unwrap_or_default() + }) + }), + waiting: Signal::derive(move || { + registration.with(|reg| { + reg.as_ref() + .map(|reg| reg.waiting().is_some()) + .unwrap_or_default() + }) + }), + active: Signal::derive(move || { + registration.with(|reg| { + reg.as_ref() + .map(|reg| reg.active().is_some()) + .unwrap_or_default() + }) + }), + check_for_update: Callback::new(move |()| { + registration.with(|reg| { + if let Ok(reg) = reg { + update_action.dispatch(reg.clone()) + } + }) + }), + skip_waiting: Callback::new(move |()| { + registration.with_untracked(|reg| if let Ok(reg) = reg { + match reg.waiting() { + Some(sw) => { + tracing::info!("Updating to newly installed SW..."); + sw.post_message(&JsValue::from_str(&options.skip_waiting_message)).expect("post message"); + }, + None => { + tracing::warn!("You tried to update the SW while no new SW was waiting. This is probably a bug."); + }, + } + }); + }), + } +} + +/// Options for [`use_service_worker_with_options`]. +#[derive(DefaultBuilder)] +pub struct UseServiceWorkerOptions { + /// The name of your service-worker. + /// You will most likely deploy the service-worker JS fiel alongside your app. + /// A typical name is 'service-worker.js'. + pub script_url: Cow<'static, str>, + + /// The message sent to a waiting ServiceWorker when you call the `skip_waiting` callback. + pub skip_waiting_message: Cow<'static, str>, + + /// What should happen when a new service worker was activated? + /// The default implementation reloads the current page. + pub on_controller_change: Callback<()>, +} + +impl Default for UseServiceWorkerOptions { + fn default() -> Self { + Self { + script_url: "service-worker.js".into(), + skip_waiting_message: "skipWaiting".into(), + on_controller_change: Callback::new(move |()| { + use std::ops::Deref; + if let Some(window) = use_window().deref() { + match window.location().reload() { + Ok(()) => {} + Err(err) => tracing::warn!( + "Detected a ServiceWorkerController change but the page reload failed! Error: {err:?}" + ), + } + } + }), + } + } +} + +/// Return type of [`use_service_worker`]. +pub struct UseServiceWorkerReturn { + /// The current registration state. + pub registration: Signal>, + + /// Whether a SW is currently installing. + pub installing: Signal, + + /// Whether a SW was installed and is now awaiting activation. + pub waiting: Signal, + + /// Whether a SW is active. + pub active: Signal, + + /// Check for ServiceWorker update. + pub check_for_update: Callback<()>, + + /// Call this to activate a new ("waiting") SW if one is available. + pub skip_waiting: Callback<()>, +} + +struct ServiceWorkerScriptUrl(pub String); + +#[derive(Debug, Clone)] +pub enum ServiceWorkerRegistrationError { + Js(JsValue), + NeverQueried, +} + +/// A leptos action which asynchronously checks for ServiceWorker updates, given an existing ServiceWorkerRegistration. +fn create_action_update_sw( +) -> Action> { + create_action(move |registration: &ServiceWorkerRegistration| { + let registration = registration.clone(); + async move { + let update_promise = registration.update().expect("update to not fail"); + wasm_bindgen_futures::JsFuture::from(update_promise) + .await + .map(|ok| { + ok.dyn_into::() + .expect("conversion into ServiceWorkerRegistration") + }) + } + }) +} + +/// A leptos action which asynchronously creates or updates and than retrieves the ServiceWorkerRegistration. +fn create_action_create_or_update_sw_registration( +) -> Action> { + create_action(move |script_url: &ServiceWorkerScriptUrl| { + let script_url = script_url.0.to_owned(); + async move { + if let Some(navigator) = use_window().navigator() { + let promise = navigator.service_worker().register(script_url.as_str()); + wasm_bindgen_futures::JsFuture::from(promise) + .await + .map(|ok| { + ok.dyn_into::() + .expect("conversion into ServiceWorkerRegistration") + }) + } else { + Err(JsValue::from_str("no navigator")) + } + } + }) +} + +/// A leptos action which asynchronously fetches the current ServiceWorkerRegistration. +fn create_action_get_sw_registration() -> Action<(), Result> { + create_action(move |(): &()| { + async move { + if let Some(navigator) = use_window().navigator() { + let promise = navigator.service_worker().get_registration(); // Could take a scope like "/app"... + wasm_bindgen_futures::JsFuture::from(promise) + .await + .map(|ok| { + ok.dyn_into::() + .expect("conversion into ServiceWorkerRegistration") + }) + } else { + Err(JsValue::from_str("no navigator")) + } + } + }) +}