diff --git a/src/components/GiftedDialog.vue b/src/components/GiftedDialog.vue index 2ad08b0e6..9dd8f011a 100644 --- a/src/components/GiftedDialog.vue +++ b/src/components/GiftedDialog.vue @@ -15,7 +15,7 @@ class="rounded-l border border-r-0 border-slate-400 bg-slate-200 text-center text-blue-500 px-2 py-2 w-20" @click="changeUnitCode()" > - {{ libsUtil.UNIT_SHORT[unitCode] }} + {{ libsUtil.UNIT_SHORT[unitCode] || unitCode }}
- +
@@ -60,7 +60,10 @@ Upload
-
+
-
-
- ... and those without your image see this (if you let them see your - activity): +
+
+ People without your image see this: +
+ (if you've let them see your activity)
Import - +
+ +
+

Share Image

+ Populates the "shared-photo" view as if they used "share_target". + + + Go to Shared Page + +
diff --git a/sw_scripts/additional-scripts.js b/sw_scripts/additional-scripts.js index 07e5d2d20..196e9909b 100644 --- a/sw_scripts/additional-scripts.js +++ b/sw_scripts/additional-scripts.js @@ -81,7 +81,7 @@ self.addEventListener("push", function (event) { } else { title = payload.title || "Update"; } - // getNotificationCount is injected from safari-notifications.js at build time by the vue.config.js configureWebpack apply plugin + // getNotificationCount is injected from safari-notifications.js at build time by the sw_combine.js script // eslint-disable-next-line no-undef message = await getNotificationCount(); } @@ -131,8 +131,27 @@ self.addEventListener("notificationclick", (event) => { ); }); +// This is invoked when the user chooses this as a share_target, mapped to share-target in the manifest. self.addEventListener("fetch", (event) => { logConsoleAndDb("Service worker got fetch event.", event); + + // Regular requests not related to Web Share Target. + if (event.request.method !== "POST") { + event.respondWith(fetch(event.request)); + return; + } + + // Requests related to Web Share share-target Target. + event.respondWith( + (async () => { + const formData = await event.request.formData(); + const photo = formData.get("photo"); + // savePhoto is injected from safari-notifications.js at build time by the sw_combine.js script + // eslint-disable-next-line no-undef + await savePhoto(photo); + return Response.redirect("/shared-photo", 303); + })(), + ); }); self.addEventListener("error", (event) => { diff --git a/sw_scripts/safari-notifications.js b/sw_scripts/safari-notifications.js index 7803e6f00..0103f5beb 100644 --- a/sw_scripts/safari-notifications.js +++ b/sw_scripts/safari-notifications.js @@ -566,6 +566,20 @@ async function getNotificationCount() { return result; } +// Store the image blob and go immediate to a page to upload it. +// @param photo - image Blob to store for later retrieval after redirect +async function savePhoto(photo) { + try { + const db = await openIndexedDB("TimeSafari"); + const transaction = db.transaction("temp", "readwrite"); + const store = transaction.objectStore("temp"); + await updateRecord(store, { id: "shared-photo", blob: photo }); + transaction.oncomplete = () => db.close(); + } catch (error) { + console.error("safari-notifications logMessage IndexedDB error", error); + } +} + self.appendDailyLog = appendDailyLog; self.getNotificationCount = getNotificationCount; self.decodeBase64 = decodeBase64; diff --git a/vite.config.mjs b/vite.config.mjs index 4e59d462e..3964ac325 100644 --- a/vite.config.mjs +++ b/vite.config.mjs @@ -17,6 +17,27 @@ export default defineConfig({ filename: 'sw_scripts-combined.js', manifest: { name: process.env.TIME_SAFARI_APP_TITLE || require('./package.json').name, + short_name: process.env.TIME_SAFARI_APP_TITLE || require('./package.json').name, + // 192x192 and 512x512 are important for Chrome to show that it's installable + "icons":[ + {"src":"./img/icons/android-chrome-192x192.png","sizes":"192x192","type":"image/png"}, + {"src":"./img/icons/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}, + {"src":"./img/icons/android-chrome-maskable-192x192.png","sizes":"192x192","type":"image/png","purpose":"maskable"}, + {"src":"./img/icons/android-chrome-maskable-512x512.png","sizes":"512x512","type":"image/png","purpose":"maskable"} + ], + share_target: { + action: '/share-target', + method: 'POST', + enctype: 'multipart/form-data', + params: { + files: [ + { + name: 'photo', + accept: ['image/jpg', 'image/jpeg', 'image/png'], + }, + ], + }, + }, }, }), ],