aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xbun.lockbbin120851 -> 120851 bytes
-rw-r--r--src/app.html1
-rw-r--r--src/locales/en.json2
-rw-r--r--src/routes/(app)/[username]/(profile)/+layout.svelte6
-rw-r--r--src/routes/(app)/[username]/(profile)/+page.svelte28
-rw-r--r--src/routes/+layout.svelte17
-rw-r--r--src/service-worker.js83
-rw-r--r--static/home.pngbin0 -> 260144 bytes
-rw-r--r--static/manifest.webmanifest66
-rw-r--r--static/receive.pngbin0 -> 247776 bytes
-rw-r--r--static/screenshot.pngbin219558 -> 0 bytes
-rw-r--r--svelte.config.js3
12 files changed, 188 insertions, 18 deletions
diff --git a/bun.lockb b/bun.lockb
index 406ad71b..38d329c9 100755
--- a/bun.lockb
+++ b/bun.lockb
Binary files differ
diff --git a/src/app.html b/src/app.html
index 9d7e2fdb..728900ed 100644
--- a/src/app.html
+++ b/src/app.html
@@ -9,6 +9,7 @@
/>
<meta name="description" content="The easiest raysway to get started with bitcoin" />
<meta name="keywords" content="open source bitcoin lightning web wallet" />
+ <meta name="theme-color" content="#fff"/>
<link rel="manifest" href="/manifest.webmanifest" />
%sveltekit.head%
</head>
diff --git a/src/locales/en.json b/src/locales/en.json
index f29c8d29..93affb7f 100644
--- a/src/locales/en.json
+++ b/src/locales/en.json
@@ -155,7 +155,7 @@
"subheader": "Latest Updates"
},
"user": {
- "details": "Details",
+ "info": "Info",
"noMessages": "You have not sent or received any messages yet",
"profilePage": "Profile page",
"nostrPubkey": "Nostr pubkey",
diff --git a/src/routes/(app)/[username]/(profile)/+layout.svelte b/src/routes/(app)/[username]/(profile)/+layout.svelte
index 5752491b..11e33dbf 100644
--- a/src/routes/(app)/[username]/(profile)/+layout.svelte
+++ b/src/routes/(app)/[username]/(profile)/+layout.svelte
@@ -168,14 +168,16 @@
</a>
{/if}
+ {#if user.username !== subject.username}
<button
type="button"
on:click={toggleDetails}
class="rounded-2xl border py-5 px-6 font-bold hover:opacity-80 flex justify-center w-full"
>
- <Icon icon="edit" style="w-8 mr-2" />
- <div class="mt-1">{$t("user.details")}</div>
+ <Icon icon="profile" style="w-8 mr-2" />
+ <div class="mt-1">{$t("user.info")}</div>
</button>
+ {/if}
{#if user?.admin && user.username !== subject.username}
<form class="w-full flex" on:submit|preventDefault={reset}>
diff --git a/src/routes/(app)/[username]/(profile)/+page.svelte b/src/routes/(app)/[username]/(profile)/+page.svelte
index f0ab743a..9443c063 100644
--- a/src/routes/(app)/[username]/(profile)/+page.svelte
+++ b/src/routes/(app)/[username]/(profile)/+page.svelte
@@ -102,6 +102,21 @@
let reset = () =>
(dragDisabled =
user?.username !== subject?.username || window.innerWidth < 768);
+
+ let installPrompt;
+ onMount(() => {
+ if (!browser) return;
+ window.addEventListener("beforeinstallprompt", (event) => {
+ event.preventDefault();
+ installPrompt = event;
+ });
+ });
+
+ let install = async () => {
+ if (!installPrompt) return;
+ await installPrompt.prompt();
+ installPrompt = null;
+ };
</script>
<svelte:window on:resize={reset} />
@@ -148,18 +163,17 @@
</button>
</a>
- <a href={`/${user.username}/items/create`} class="contents">
+ {#if installPrompt}
<button
- class="rounded-2xl border py-5 px-6 font-bold hover:opacity-80 flex bg-primary grow basis-full"
+ class="rounded-2xl border py-5 px-6 font-bold hover:opacity-80 flex bg-black text-white grow basis-full fixed bottom-16"
+ on:click={install}
>
<div class="mx-auto flex gap-2">
- <Icon icon="plus" style="w-8 mx-auto" />
- <div class="my-auto text-xl whitespace-nowrap">
- {$t("items.add")}
- </div>
+ <Icon icon="save" style="w-8 mx-auto invert" />
+ <div class="my-auto text-xl whitespace-nowrap">Install app</div>
</div>
</button>
- </a>
+ {/if}
</div>
{/if}
diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte
index 545018ed..43e573ef 100644
--- a/src/routes/+layout.svelte
+++ b/src/routes/+layout.svelte
@@ -2,6 +2,23 @@
import { PUBLIC_DOMAIN } from "$env/static/public";
import "../app.css";
import { loading, t } from "$lib/translations";
+ import { onMount } from "svelte";
+ import { dev } from "$app/environment";
+
+ onMount(() => {
+ if ("serviceWorker" in navigator) {
+ navigator.serviceWorker
+ .register("/service-worker.js", {
+ type: dev ? "module" : "classic",
+ })
+ .then((registration) => {
+ console.log("SW registered: ", registration);
+ })
+ .catch((registrationError) => {
+ console.log("SW registration failed: ", registrationError);
+ });
+ }
+ });
export let data;
let { pathname } = data;
diff --git a/src/service-worker.js b/src/service-worker.js
new file mode 100644
index 00000000..a95ff268
--- /dev/null
+++ b/src/service-worker.js
@@ -0,0 +1,83 @@
+/// <reference types="@sveltejs/kit" />
+import { build, files, version } from "$service-worker";
+
+// Create a unique cache name for this deployment
+const CACHE = `cache-${version}`;
+
+const ASSETS = [
+ ...build, // the app itself
+ ...files, // everything in `static`
+];
+
+self.addEventListener("install", (event) => {
+ console.log("SW installed");
+
+ // Create a new cache and add all files to it
+ async function addFilesToCache() {
+ const cache = await caches.open(CACHE);
+ await cache.addAll(ASSETS);
+ }
+
+ event.waitUntil(addFilesToCache());
+});
+
+self.addEventListener("activate", (event) => {
+ // Remove previous cached data from disk
+ async function deleteOldCaches() {
+ for (const key of await caches.keys()) {
+ if (key !== CACHE) await caches.delete(key);
+ }
+ }
+
+ event.waitUntil(deleteOldCaches());
+});
+
+self.addEventListener("fetch", (event) => {
+ console.log("FETCH")
+ // ignore POST requests etc
+ if (event.request.method !== "GET") return;
+
+ async function respond() {
+ const url = new URL(event.request.url);
+ const cache = await caches.open(CACHE);
+
+ // `build`/`files` can always be served from the cache
+ if (ASSETS.includes(url.pathname)) {
+ const response = await cache.match(url.pathname);
+
+ if (response) {
+ return response;
+ }
+ }
+
+ // for everything else, try the network first, but
+ // fall back to the cache if we're offline
+ try {
+ const response = await fetch(event.request);
+
+ // if we're offline, fetch can return a value that is not a Response
+ // instead of throwing - and we can't pass this non-Response to respondWith
+ if (!(response instanceof Response)) {
+ throw new Error("invalid response from fetch");
+ }
+
+ if (response.status === 200) {
+ cache.put(event.request, response.clone());
+ }
+
+ return response;
+ } catch (err) {
+ const response = await cache.match(event.request);
+
+ if (response) {
+ return response;
+ }
+
+ // if there's no cache, then just error out
+ // as there is nothing we can do to respond to this request
+ throw err;
+ }
+ }
+
+ event.respondWith(respond());
+});
diff --git a/static/home.png b/static/home.png
new file mode 100644
index 00000000..e6ba1b85
--- /dev/null
+++ b/static/home.png
Binary files differ
diff --git a/static/manifest.webmanifest b/static/manifest.webmanifest
index d09b8090..15f55603 100644
--- a/static/manifest.webmanifest
+++ b/static/manifest.webmanifest
@@ -11,30 +11,80 @@
{
"src": "/icon-192x192.png",
"sizes": "192x192",
- "type": "image/png"
+ "type": "image/png",
+ "purpose": "maskable"
},
{
"src": "/icon-256x256.png",
"sizes": "256x256",
- "type": "image/png"
+ "type": "image/png",
+ "purpose": "maskable"
},
{
"src": "/icon-384x384.png",
"sizes": "384x384",
- "type": "image/png"
+ "type": "image/png",
+ "purpose": "maskable"
},
{
"src": "/icon-512x512.png",
"sizes": "512x512",
- "type": "image/png"
+ "type": "image/png",
+ "purpose": "maskable"
+ },
+ {
+ "src": "/icon-192x192.png",
+ "sizes": "192x192",
+ "type": "image/png",
+ "purpose": "any"
+ },
+ {
+ "src": "/icon-256x256.png",
+ "sizes": "256x256",
+ "type": "image/png",
+ "purpose": "any"
+ },
+ {
+ "src": "/icon-384x384.png",
+ "sizes": "384x384",
+ "type": "image/png",
+ "purpose": "any"
+ },
+ {
+ "src": "/icon-512x512.png",
+ "sizes": "512x512",
+ "type": "image/png",
+ "purpose": "any"
}
],
"screenshots": [
{
- "src": "/screenshot.png",
- "sizes": "632x701",
- "type": "image/gif",
- "label": "Homepage"
+ "src": "/home.png",
+ "sizes": "801x920",
+ "type": "image/png",
+ "label": "Homepage",
+ "form_factor": "wide"
+ },
+ {
+ "src": "/receive.png",
+ "sizes": "801x920",
+ "type": "image/png",
+ "label": "Receive",
+ "form_factor": "wide"
+ },
+ {
+ "src": "/home.png",
+ "sizes": "801x920",
+ "type": "image/png",
+ "label": "Homepage",
+ "form_factor": "narrow"
+ },
+ {
+ "src": "/receive.png",
+ "sizes": "801x920",
+ "type": "image/png",
+ "label": "Receive",
+ "form_factor": "narrow"
}
],
"protocol_handlers": [
diff --git a/static/receive.png b/static/receive.png
new file mode 100644
index 00000000..8151e52c
--- /dev/null
+++ b/static/receive.png
Binary files differ
diff --git a/static/screenshot.png b/static/screenshot.png
deleted file mode 100644
index e10fbd19..00000000
--- a/static/screenshot.png
+++ /dev/null
Binary files differ
diff --git a/svelte.config.js b/svelte.config.js
index bc89e810..ccd77e7d 100644
--- a/svelte.config.js
+++ b/svelte.config.js
@@ -17,6 +17,9 @@ const config = {
crawl: false,
entries: [],
},
+ serviceWorker: {
+ register: false
+ }
},
onwarn: (warning, handler) => {
if (warning.code.includes("caption") || warning.filename.includes("Toast"))