From f8002c4550ed7d368e87f566ecce8161f3196367 Mon Sep 17 00:00:00 2001
From: Trent Larson
Date: Wed, 20 Dec 2023 20:40:00 -0700
Subject: [PATCH 1/9] add DB logging for service-worker events
---
sw_scripts/additional-scripts.js | 37 +++++++++++++++++++++---------
sw_scripts/safari-notifications.js | 25 ++++++++++++++++++++
2 files changed, 51 insertions(+), 11 deletions(-)
diff --git a/sw_scripts/additional-scripts.js b/sw_scripts/additional-scripts.js
index fe16c18..5ecb1ed 100644
--- a/sw_scripts/additional-scripts.js
+++ b/sw_scripts/additional-scripts.js
@@ -4,8 +4,22 @@ importScripts(
"https://storage.googleapis.com/workbox-cdn/releases/6.4.1/workbox-sw.js",
);
+function logDbOrConsole(self, message, arg1, arg2) {
+ let fullMessage = `${new Date().toISOString()} ${message}`;
+ if (arg1) {
+ fullMessage += `: ${JSON.stringify(arg1)}`;
+ }
+ if (arg2) {
+ fullMessage += ` -- ${JSON.stringify(arg2)}`;
+ }
+ const logged = self.logMessage(fullMessage);
+ if (!logged) {
+ console.log(`$new Date().toISOString()} ${message}`, arg1, arg2);
+ }
+}
+
self.addEventListener("install", (event) => {
- console.log(new Date().toISOString(), "Installing service worker:", event);
+ logDbOrConsole(self, "Installing service worker:", event);
importScripts(
"safari-notifications.js",
"nacl.js",
@@ -15,7 +29,7 @@ self.addEventListener("install", (event) => {
});
self.addEventListener("push", function (event) {
- console.log(new Date().toISOString(), "Received push event:", event);
+ logDbOrConsole(self, "Received push event:", event);
event.waitUntil(
(async () => {
try {
@@ -32,40 +46,41 @@ self.addEventListener("push", function (event) {
badge: payload ? payload.badge : "badge.png",
};
await self.registration.showNotification(title, options);
- console.log(new Date().toISOString(), "Notified user:", options);
+ logDbOrConsole(self, "Notified user:", options);
} else {
- console.log(new Date().toISOString(), "No notification message.");
+ logDbOrConsole(self, "No notification message.");
}
} catch (error) {
- console.error(new Date().toISOString(), "Error with push event", event, " - ", error);
+ logDbOrConsole(self, "Error with push event", event, error);
}
})(),
);
});
self.addEventListener("message", (event) => {
- console.log(new Date().toISOString(), "Service worker message:", event);
+ logDbOrConsole(self, "Service worker message:", event);
if (event.data && event.data.type === "SEND_LOCAL_DATA") {
self.secret = event.data.data;
event.ports[0].postMessage({ success: true });
}
- console.log(new Date().toISOString(), "Service worker posted message.");
+ logDbOrConsole(self, "Service worker posted message.");
});
self.addEventListener("activate", (event) => {
- console.log(new Date().toISOString(), "Service worker activating...", event);
+ logDbOrConsole(self, "Service worker activating...", event);
// see https://developer.mozilla.org/en-US/docs/Web/API/Clients/claim
// and https://web.dev/articles/service-worker-lifecycle#clientsclaim
event.waitUntil(clients.claim());
- console.log(new Date().toISOString(), "Service worker activated.");
+ logDbOrConsole(self, "Service worker activated.");
});
self.addEventListener("fetch", (event) => {
- console.log(new Date().toISOString(), "Got fetch event:", event);
+ logDbOrConsole(self, "Got fetch event:", event);
});
self.addEventListener("error", (event) => {
- console.error(new Date().toISOString(), "Error in Service Worker:", event);
+ logDbOrConsole(self, "Error in Service Worker:", event);
+ console.error("Full Error:", event);
console.error("Message:", event.message);
console.error("File:", event.filename);
console.error("Line:", event.lineno);
diff --git a/sw_scripts/safari-notifications.js b/sw_scripts/safari-notifications.js
index 32c12e0..16969ad 100644
--- a/sw_scripts/safari-notifications.js
+++ b/sw_scripts/safari-notifications.js
@@ -404,6 +404,27 @@ async function setMostRecentNotified(id) {
}
}
+async function logMessage(message) {
+ try {
+ const db = await openIndexedDB("TimeSafari");
+ const transaction = db.transaction("worker_log", "readwrite");
+ const store = transaction.objectStore("worker_log");
+ // will only keep one day's worth of logs
+ let data = await getRecord(store, new Date().toDateString());
+ if (!data) {
+ await store.clear(); // clear out anything older than today
+ }
+ data = data || "";
+ data += `\n${message}`;
+ await updateRecord(store, data);
+ transaction.oncomplete = () => db.close();
+ return true;
+ } catch (error) {
+ console.error("IndexedDB logMessage error:", error);
+ return false;
+ }
+}
+
function openIndexedDB(dbName) {
return new Promise((resolve, reject) => {
const request = indexedDB.open(dbName);
@@ -420,6 +441,7 @@ function getRecord(store, key) {
});
}
+// Note that this assumes there is only one record in the store.
function updateRecord(store, data) {
return new Promise((resolve, reject) => {
const request = store.put(data);
@@ -437,6 +459,9 @@ async function fetchAllAccounts() {
if (!db.objectStoreNames.contains("accounts")) {
db.createObjectStore("accounts", { keyPath: "id" });
}
+ if (!db.objectStoreNames.contains("worker_log")) {
+ db.createObjectStore("worker_log");
+ }
};
openRequest.onsuccess = function (event) {
From d7f4acb70253bd7d957d734a5d661c638d1ffad4 Mon Sep 17 00:00:00 2001
From: Trent Larson
Date: Thu, 21 Dec 2023 20:50:35 -0700
Subject: [PATCH 2/9] make more adjustments to try and get logging to work
---
README.md | 4 +--
package.json | 2 +-
src/App.vue | 4 +--
src/components/TopMessage.vue | 2 +-
src/db/index.ts | 14 ++++++++--
src/db/tables/contacts.ts | 2 +-
src/db/tables/logs.ts | 7 +++++
sw_scripts/additional-scripts.js | 45 ++++++++++++++++--------------
sw_scripts/safari-notifications.js | 13 +++++----
9 files changed, 55 insertions(+), 38 deletions(-)
create mode 100644 src/db/tables/logs.ts
diff --git a/README.md b/README.md
index 861a86d..34a169a 100644
--- a/README.md
+++ b/README.md
@@ -30,7 +30,7 @@ If you are deploying in a subdirectory, add it to `publicPath` in vue.config.js,
* Tag wth the new version: `git tag 0.1.0`.
-* If production, change src/constants/app.ts DEFAULT_*_SERVER to be PROD.
+* If production, change src/constants/app.ts DEFAULT_*_SERVER to be PROD and package.json to not be _Test.
* `npm run build`
@@ -40,7 +40,7 @@ If you are deploying in a subdirectory, add it to `publicPath` in vue.config.js,
* `rsync -azvu -e "ssh -i ~/.ssh/..." dist ubuntu@endorser.ch:time-safari`
-* Revert src/constants/app.ts, increment version, add "-beta", `npm install`, and commit.
+* Revert src/constants/app.ts and/or package.json, edit package.json to increment version & add "-beta", `npm install`, and commit.
diff --git a/package.json b/package.json
index a24cb46..1d35ad2 100644
--- a/package.json
+++ b/package.json
@@ -1,5 +1,5 @@
{
- "name": "TimeSafari",
+ "name": "TimeSafari_Test",
"version": "0.1.8-beta",
"private": true,
"scripts": {
diff --git a/src/App.vue b/src/App.vue
index 05bbe0a..b69bbd0 100644
--- a/src/App.vue
+++ b/src/App.vue
@@ -462,9 +462,7 @@ export default class App extends Vue {
"An error occurred setting notification permissions:",
error,
);
- alert(
- "Some error occurred setting notification permissions. See logs.",
- );
+ alert("Some error occurred setting notification permissions.");
});
}
diff --git a/src/components/TopMessage.vue b/src/components/TopMessage.vue
index 8433741..bccc2fe 100644
--- a/src/components/TopMessage.vue
+++ b/src/components/TopMessage.vue
@@ -50,7 +50,7 @@ export default class TopMessage extends Vue {
title: "Error Detecting Server",
text: JSON.stringify(err),
},
- 10000,
+ -1,
);
}
}
diff --git a/src/db/index.ts b/src/db/index.ts
index 37d6cf5..644f813 100644
--- a/src/db/index.ts
+++ b/src/db/index.ts
@@ -1,7 +1,8 @@
import BaseDexie, { Table } from "dexie";
import { encrypted, Encryption } from "@pvermeer/dexie-encrypted-addon";
import { Account, AccountsSchema } from "./tables/accounts";
-import { Contact, ContactsSchema } from "./tables/contacts";
+import { Contact, ContactSchema } from "./tables/contacts";
+import { Log, LogSchema } from "@/db/tables/logs";
import {
MASTER_SETTINGS_KEY,
Settings,
@@ -13,6 +14,7 @@ import { AppString } from "@/constants/app";
type SensitiveTables = { accounts: Table };
type NonsensitiveTables = {
contacts: Table;
+ logs: Table;
settings: Table;
};
@@ -26,7 +28,11 @@ export const accountsDB = new BaseDexie("TimeSafariAccounts") as SensitiveDexie;
const SensitiveSchemas = { ...AccountsSchema };
export const db = new BaseDexie("TimeSafari") as NonsensitiveDexie;
-const NonsensitiveSchemas = { ...ContactsSchema, ...SettingsSchema };
+const NonsensitiveSchemas = {
+ ...ContactSchema,
+ ...LogSchema,
+ ...SettingsSchema,
+};
// Manage the encryption key. If not present in localStorage, create and store it.
const secret =
@@ -38,7 +44,9 @@ encrypted(accountsDB, { secretKey: secret });
// Define the schema for our databases
accountsDB.version(1).stores(SensitiveSchemas);
-db.version(1).stores(NonsensitiveSchemas);
+// v1 was contacts & settings
+// v2 added logs
+db.version(2).stores(NonsensitiveSchemas);
// Event handler to initialize the non-sensitive database with default settings
db.on("populate", () => {
diff --git a/src/db/tables/contacts.ts b/src/db/tables/contacts.ts
index b684505..8ffd2fb 100644
--- a/src/db/tables/contacts.ts
+++ b/src/db/tables/contacts.ts
@@ -6,6 +6,6 @@ export interface Contact {
registered?: boolean;
}
-export const ContactsSchema = {
+export const ContactSchema = {
contacts: "&did, name, publicKeyBase64, registered, seesMe",
};
diff --git a/src/db/tables/logs.ts b/src/db/tables/logs.ts
new file mode 100644
index 0000000..2dd99f7
--- /dev/null
+++ b/src/db/tables/logs.ts
@@ -0,0 +1,7 @@
+export interface Log {
+ message: string;
+}
+
+export const LogSchema = {
+ logs: "message",
+};
diff --git a/sw_scripts/additional-scripts.js b/sw_scripts/additional-scripts.js
index 5ecb1ed..5defa97 100644
--- a/sw_scripts/additional-scripts.js
+++ b/sw_scripts/additional-scripts.js
@@ -4,7 +4,19 @@ importScripts(
"https://storage.googleapis.com/workbox-cdn/releases/6.4.1/workbox-sw.js",
);
+self.addEventListener("install", (event) => {
+ console.log("Service worker scripts importing...", event);
+ importScripts(
+ "safari-notifications.js",
+ "nacl.js",
+ "noble-curves.js",
+ "noble-hashes.js",
+ );
+ console.log("Service worker scripts imported.");
+});
+
function logDbOrConsole(self, message, arg1, arg2) {
+ console.log(`${new Date().toISOString()} ${message}`, arg1, arg2);
let fullMessage = `${new Date().toISOString()} ${message}`;
if (arg1) {
fullMessage += `: ${JSON.stringify(arg1)}`;
@@ -12,24 +24,15 @@ function logDbOrConsole(self, message, arg1, arg2) {
if (arg2) {
fullMessage += ` -- ${JSON.stringify(arg2)}`;
}
- const logged = self.logMessage(fullMessage);
- if (!logged) {
- console.log(`$new Date().toISOString()} ${message}`, arg1, arg2);
- }
+ // const logged =
+ self.logMessage(fullMessage);
+ // if (logged || !logged) {
+ // console.log(`${new Date().toISOString()} ${message}`, arg1, arg2);
+ // }
}
-self.addEventListener("install", (event) => {
- logDbOrConsole(self, "Installing service worker:", event);
- importScripts(
- "safari-notifications.js",
- "nacl.js",
- "noble-curves.js",
- "noble-hashes.js",
- );
-});
-
self.addEventListener("push", function (event) {
- logDbOrConsole(self, "Received push event:", event);
+ logDbOrConsole(this, "Received push event:", event);
event.waitUntil(
(async () => {
try {
@@ -58,28 +61,28 @@ self.addEventListener("push", function (event) {
});
self.addEventListener("message", (event) => {
- logDbOrConsole(self, "Service worker message:", event);
+ logDbOrConsole(this, "Service worker message:", event);
if (event.data && event.data.type === "SEND_LOCAL_DATA") {
self.secret = event.data.data;
event.ports[0].postMessage({ success: true });
}
- logDbOrConsole(self, "Service worker posted message.");
+ logDbOrConsole(this, "Service worker posted message.");
});
self.addEventListener("activate", (event) => {
- logDbOrConsole(self, "Service worker activating...", event);
+ logDbOrConsole(this, "Service worker activating...", event);
// see https://developer.mozilla.org/en-US/docs/Web/API/Clients/claim
// and https://web.dev/articles/service-worker-lifecycle#clientsclaim
event.waitUntil(clients.claim());
- logDbOrConsole(self, "Service worker activated.");
+ logDbOrConsole(this, "Service worker activated.");
});
self.addEventListener("fetch", (event) => {
- logDbOrConsole(self, "Got fetch event:", event);
+ logDbOrConsole(this, "Got fetch event:", event);
});
self.addEventListener("error", (event) => {
- logDbOrConsole(self, "Error in Service Worker:", event);
+ logDbOrConsole(this, "Error in Service Worker:", event);
console.error("Full Error:", event);
console.error("Message:", event.message);
console.error("File:", event.filename);
diff --git a/sw_scripts/safari-notifications.js b/sw_scripts/safari-notifications.js
index 16969ad..e2f6fe0 100644
--- a/sw_scripts/safari-notifications.js
+++ b/sw_scripts/safari-notifications.js
@@ -407,16 +407,17 @@ async function setMostRecentNotified(id) {
async function logMessage(message) {
try {
const db = await openIndexedDB("TimeSafari");
- const transaction = db.transaction("worker_log", "readwrite");
- const store = transaction.objectStore("worker_log");
+ const transaction = db.transaction("logs", "readwrite");
+ const store = transaction.objectStore("logs");
// will only keep one day's worth of logs
- let data = await getRecord(store, new Date().toDateString());
+ const todayKey = new Date().toDateString();
+ let data = await getRecord(store, todayKey);
if (!data) {
await store.clear(); // clear out anything older than today
}
data = data || "";
data += `\n${message}`;
- await updateRecord(store, data);
+ await updateRecord(store, { message: data }, todayKey);
transaction.oncomplete = () => db.close();
return true;
} catch (error) {
@@ -442,9 +443,9 @@ function getRecord(store, key) {
}
// Note that this assumes there is only one record in the store.
-function updateRecord(store, data) {
+function updateRecord(store, data, key) {
return new Promise((resolve, reject) => {
- const request = store.put(data);
+ const request = key ? store.put(data, key) : store.put(data);
request.onsuccess = () => resolve(request.result);
request.onerror = () => reject(request.error);
});
From 8d873b51bdc34003daec8eb663eee9889c3d0cfb Mon Sep 17 00:00:00 2001
From: Trent Larson
Date: Thu, 21 Dec 2023 21:03:47 -0700
Subject: [PATCH 3/9] doc: update tasks
---
project.task.yaml | 26 ++++++++++----------------
1 file changed, 10 insertions(+), 16 deletions(-)
diff --git a/project.task.yaml b/project.task.yaml
index a80de78..1ccd004 100644
--- a/project.task.yaml
+++ b/project.task.yaml
@@ -2,29 +2,19 @@
tasks:
- 08 notifications :
- - make the app behave correctly when App Notifications are turned off
- - write troubleshooting docs for notifications
- - hide the "App Notifications" toggle when they switch notifications
- - prompt user to install on their home screen https://developer.mozilla.org/en-US/docs/Web/API/Navigator/getInstalledRelatedApps
+ - get the rest of our Android devices to work... and insert tooling (exportable logs?) so that we can see problems and troubleshoot as we onboard
+ - prompt user to install on their home screen https://benborgers.com/posts/pwa-detect-installed
- warn if they're using the web (android only?)
https://developer.mozilla.org/en-US/docs/Web/API/Navigator/getInstalledRelatedApps
https://web.dev/articles/get-installed-related-apps
- - add windows & mac help at OS & browser level
+ - add windows & mac help at OS & browser level, in HelpNotificationsView.vue (linked from account page)
-- back-and-forth on discovery & project pages led to "You need an identity to load your projects." error on product page when I had an identity
-- fix the projects on /discover to show the issuer (currently all "Someone Anonymous")
+- .2 fix the projects on /discover to show the issuer (currently all "Someone Anonymous")
- .3 bug - make or edit a project, choose "Include location", and see the map display shows on top of the bottom icons assignee-group:ui
-- Got error adding on Firefox user #0 as contact for themselves
- .5 If notifications are not enabled, add message to front page with link/button to enable
-- 01 server - show all claim details when issued by the issuer
-- enhance help page instructions for friends to get notifications, for debugging notifications
-- add way to test a push notification
-- help instructions for PWA install problems (secret failed, must reinstall)
-- look at other examples for better UI friend.tech
-
- show VC details... somehow:
- 01 show my VCs - most interesting, or via search
- 01 allow download of each VC (& confirmations, to show that they actually own their data)
@@ -44,9 +34,13 @@ tasks:
- Other features - donation vs give, show offers, show give & outstanding totals, show network view, restrict registration, connect to contacts
blocks: ref:https://raw.githubusercontent.com/trentlarson/lives-of-gifts/master/project.yaml#kickstarter%20for%20time
-- 01 send visibility signal as a VC and store it
-- remove 'rowid' references (that are sqlite-specific)
- make identicons for contacts into more-memorable faces (and maybe change project identicons, too)
+- 01 server - show all claim details when issued by the issuer
+- bug - got error adding on Firefox user #0 as contact for themselves
+- bug - back-and-forth on discovery & project pages led to "You need an identity to load your projects." error on product page when I had an identity
+- 01 send visibility signal as a VC and store it
+- 04 remove 'rowid' references (that are sqlite-specific); may involve server
+- 04 look at other examples for better UI friend.tech
- 01 make the prod build copy the sw_scripts
- .5 Add start date to project
- .3 check that Android shows "back" buttons on screens without bottom tray
From e739d0be7ccb3f3d85720ae600b0cfe89df67875 Mon Sep 17 00:00:00 2001
From: Trent Larson
Date: Fri, 22 Dec 2023 09:19:36 -0700
Subject: [PATCH 4/9] update error messages to be less... confusing
---
src/components/GiftedDialog.vue | 4 +---
src/components/OfferDialog.vue | 4 +---
src/views/ContactAmountsView.vue | 3 ++-
src/views/ContactGiftingView.vue | 3 ++-
src/views/HomeView.vue | 3 ++-
5 files changed, 8 insertions(+), 9 deletions(-)
diff --git a/src/components/GiftedDialog.vue b/src/components/GiftedDialog.vue
index 1dfb153..e236246 100644
--- a/src/components/GiftedDialog.vue
+++ b/src/components/GiftedDialog.vue
@@ -123,9 +123,7 @@ export default class GiftedDialog extends Vue {
group: "alert",
type: "danger",
title: "Error",
- text:
- err.message ||
- "There was an error retrieving the latest sweet, sweet action.",
+ text: err.message || "There was an error retrieving your settings.",
},
-1,
);
diff --git a/src/components/OfferDialog.vue b/src/components/OfferDialog.vue
index 0ab3700..b61bde8 100644
--- a/src/components/OfferDialog.vue
+++ b/src/components/OfferDialog.vue
@@ -105,9 +105,7 @@ export default class OfferDialog extends Vue {
group: "alert",
type: "danger",
title: "Error",
- text:
- err.message ||
- "There was an error retrieving the latest sweet, sweet action.",
+ text: err.message || "There was an error retrieving your settings.",
},
-1,
);
diff --git a/src/views/ContactAmountsView.vue b/src/views/ContactAmountsView.vue
index a3dfc73..52412ae 100644
--- a/src/views/ContactAmountsView.vue
+++ b/src/views/ContactAmountsView.vue
@@ -178,6 +178,7 @@ export default class ContactAmountssView extends Vue {
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
} catch (err: any) {
+ console.log("Error retrieving settings or gives.", err);
this.$notify(
{
group: "alert",
@@ -185,7 +186,7 @@ export default class ContactAmountssView extends Vue {
title: "Error",
text:
err.userMessage ||
- "There was an error retrieving the latest sweet, sweet action.",
+ "There was an error retrieving your settings and/or contacts and/or gives.",
},
-1,
);
diff --git a/src/views/ContactGiftingView.vue b/src/views/ContactGiftingView.vue
index 2d2bcb8..35bec25 100644
--- a/src/views/ContactGiftingView.vue
+++ b/src/views/ContactGiftingView.vue
@@ -145,6 +145,7 @@ export default class ContactGiftingView extends Vue {
this.allContacts = await db.contacts.toArray();
// eslint-disable-next-line @typescript-eslint/no-explicit-any
} catch (err: any) {
+ console.log("Error retrieving settings & contacts:", err);
this.$notify(
{
group: "alert",
@@ -152,7 +153,7 @@ export default class ContactGiftingView extends Vue {
title: "Error",
text:
err.message ||
- "There was an error retrieving the latest sweet, sweet action.",
+ "There was an error retrieving your settings and/or contacts.",
},
-1,
);
diff --git a/src/views/HomeView.vue b/src/views/HomeView.vue
index 3c973b3..daf47c4 100644
--- a/src/views/HomeView.vue
+++ b/src/views/HomeView.vue
@@ -234,6 +234,7 @@ export default class HomeView extends Vue {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
} catch (err: any) {
+ console.log("Error retrieving settings and/or feed.", err);
this.$notify(
{
group: "alert",
@@ -241,7 +242,7 @@ export default class HomeView extends Vue {
title: "Error",
text:
err.userMessage ||
- "There was an error retrieving the latest sweet, sweet action.",
+ "There was an error retrieving your settings and/or the latest activity.",
},
-1,
);
From 7fe256dc9efd3c01bfc24978d65e9be67e948be7 Mon Sep 17 00:00:00 2001
From: Trent Larson
Date: Fri, 22 Dec 2023 12:51:18 -0700
Subject: [PATCH 5/9] log service worker messages to the DB (now works)
---
README.md | 16 ++++++-------
project.task.yaml | 1 +
src/App.vue | 1 +
src/db/tables/logs.ts | 5 ++++-
sw_scripts/additional-scripts.js | 36 +++++++++++++-----------------
sw_scripts/safari-notifications.js | 32 ++++++++++++++++----------
6 files changed, 50 insertions(+), 41 deletions(-)
diff --git a/README.md b/README.md
index 34a169a..4a8392d 100644
--- a/README.md
+++ b/README.md
@@ -22,10 +22,6 @@ npm run lint
If you are deploying in a subdirectory, add it to `publicPath` in vue.config.js, eg: `publicPath: "/app/time-tracker/",`
-* `npx prettier --write ./sw_scripts/`
-
-...to make sure the service worker scripts are in proper form
-
* Update the CHANGELOG.md & the version in package.json, run `npm install`, and commit.
* Tag wth the new version: `git tag 0.1.0`.
@@ -34,6 +30,10 @@ If you are deploying in a subdirectory, add it to `publicPath` in vue.config.js,
* `npm run build`
+* `npx prettier --write ./sw_scripts/`
+
+...to make sure the service worker scripts are in proper form
+
* `cp sw_scripts/[ns]* dist/`
... to copy the contents of the `sw_scripts` folder to the `dist` folder - except additional_scripts.js.
@@ -112,10 +112,10 @@ To add an icon, add to main.ts and reference with `fa` element and `icon` attrib
### Clear/Reset data & restart
-* Clear cache for site. (In Chrome, go to `chrome://settings/cookies` and "all site data and permissions"; in Firefox, go to `about:preferences` and search for "cache" then "Manage Data".)
-* Unregister service worker (in Chrome, go to `chrome://serviceworker-internals/`; in Firefox, go to `about:serviceworkers`).
-* Clear notification permission (in Chrome, go to `chrome://settings/content/notifications`; in Firefox, go to `about:preferences` and search for "notifications").
-* Clear Cache Storage (in Chrome, in dev tools under Application; in Firefox, in dev tools under Storage).
+* Clear cache for site. (In Chrome, go to `chrome://settings/cookies` and "all site data and permissions"; in Firefox, go to `about:preferences` and search for "cache" then "Manage Data", and also manually remove the IndexedDB data if the DBs still show.)
+* Clear notification permission. (in Chrome, go to `chrome://settings/content/notifications`; in Firefox, go to `about:preferences` and search for "notifications".)
+* Unregister service worker. (in Chrome, go to `chrome://serviceworker-internals/`; in Firefox, go to `about:serviceworkers`.)
+* Clear Cache Storage. (in Chrome, in dev tools under Application; in Firefox, in dev tools under Storage.)
diff --git a/project.task.yaml b/project.task.yaml
index 1ccd004..5ba2e88 100644
--- a/project.task.yaml
+++ b/project.task.yaml
@@ -3,6 +3,7 @@ tasks:
- 08 notifications :
- get the rest of our Android devices to work... and insert tooling (exportable logs?) so that we can see problems and troubleshoot as we onboard
+ - get an error registering notifications on Firefox and subscription info is null
- prompt user to install on their home screen https://benborgers.com/posts/pwa-detect-installed
- warn if they're using the web (android only?)
https://developer.mozilla.org/en-US/docs/Web/API/Navigator/getInstalledRelatedApps
diff --git a/src/App.vue b/src/App.vue
index b69bbd0..2c20d32 100644
--- a/src/App.vue
+++ b/src/App.vue
@@ -373,6 +373,7 @@ export default class App extends Vue {
}
private askPermission(): Promise {
+ console.log("Requesting permission for notifications:", navigator);
if (!("serviceWorker" in navigator && navigator.serviceWorker.controller)) {
return Promise.reject("Service worker not available.");
}
diff --git a/src/db/tables/logs.ts b/src/db/tables/logs.ts
index 2dd99f7..9207a2f 100644
--- a/src/db/tables/logs.ts
+++ b/src/db/tables/logs.ts
@@ -3,5 +3,8 @@ export interface Log {
}
export const LogSchema = {
- logs: "message",
+ // Currently keyed by "date" because A) today's log data is what we need so we append, and
+ // B) we don't want it to grow so we remove everything if this is the first entry today.
+ // See safari-notifications.js logMessage for the associated logic.
+ logs: "date, message",
};
diff --git a/sw_scripts/additional-scripts.js b/sw_scripts/additional-scripts.js
index 5defa97..3582bfc 100644
--- a/sw_scripts/additional-scripts.js
+++ b/sw_scripts/additional-scripts.js
@@ -5,34 +5,30 @@ importScripts(
);
self.addEventListener("install", (event) => {
- console.log("Service worker scripts importing...", event);
+ console.log("Service worker got install. Importing scripts...", event);
importScripts(
"safari-notifications.js",
"nacl.js",
"noble-curves.js",
"noble-hashes.js",
);
- console.log("Service worker scripts imported.");
+ console.log("Service worker imported scripts.");
});
-function logDbOrConsole(self, message, arg1, arg2) {
+function logConsoleAndDb(message, arg1, arg2) {
console.log(`${new Date().toISOString()} ${message}`, arg1, arg2);
let fullMessage = `${new Date().toISOString()} ${message}`;
if (arg1) {
- fullMessage += `: ${JSON.stringify(arg1)}`;
+ fullMessage += `\n${JSON.stringify(arg1)}`;
}
if (arg2) {
- fullMessage += ` -- ${JSON.stringify(arg2)}`;
+ fullMessage += `\n${JSON.stringify(arg2)}`;
}
- // const logged =
- self.logMessage(fullMessage);
- // if (logged || !logged) {
- // console.log(`${new Date().toISOString()} ${message}`, arg1, arg2);
- // }
+ self.appendDailyLog(fullMessage);
}
self.addEventListener("push", function (event) {
- logDbOrConsole(this, "Received push event:", event);
+ logConsoleAndDb("Service worker received a push event.", event);
event.waitUntil(
(async () => {
try {
@@ -49,40 +45,40 @@ self.addEventListener("push", function (event) {
badge: payload ? payload.badge : "badge.png",
};
await self.registration.showNotification(title, options);
- logDbOrConsole(self, "Notified user:", options);
+ logConsoleAndDb("Notified user:", options);
} else {
- logDbOrConsole(self, "No notification message.");
+ logConsoleAndDb("No notification message.");
}
} catch (error) {
- logDbOrConsole(self, "Error with push event", event, error);
+ logConsoleAndDb("Error with push event", event, error);
}
})(),
);
});
self.addEventListener("message", (event) => {
- logDbOrConsole(this, "Service worker message:", event);
+ logConsoleAndDb("Service worker got a message...", event);
if (event.data && event.data.type === "SEND_LOCAL_DATA") {
self.secret = event.data.data;
event.ports[0].postMessage({ success: true });
}
- logDbOrConsole(this, "Service worker posted message.");
+ logConsoleAndDb("Service worker posted a message.");
});
self.addEventListener("activate", (event) => {
- logDbOrConsole(this, "Service worker activating...", event);
+ logConsoleAndDb("Service worker activating...", event);
// see https://developer.mozilla.org/en-US/docs/Web/API/Clients/claim
// and https://web.dev/articles/service-worker-lifecycle#clientsclaim
event.waitUntil(clients.claim());
- logDbOrConsole(this, "Service worker activated.");
+ logConsoleAndDb("Service worker is activated.");
});
self.addEventListener("fetch", (event) => {
- logDbOrConsole(this, "Got fetch event:", event);
+ logConsoleAndDb("Service worker got fetch event.", event);
});
self.addEventListener("error", (event) => {
- logDbOrConsole(this, "Error in Service Worker:", event);
+ logConsoleAndDb("Service worker error", event);
console.error("Full Error:", event);
console.error("Message:", event.message);
console.error("File:", event.filename);
diff --git a/sw_scripts/safari-notifications.js b/sw_scripts/safari-notifications.js
index e2f6fe0..22dcf99 100644
--- a/sw_scripts/safari-notifications.js
+++ b/sw_scripts/safari-notifications.js
@@ -395,33 +395,41 @@ async function setMostRecentNotified(id) {
data["lastNotifiedClaimId"] = id;
await updateRecord(store, data);
} else {
- console.error("IndexedDB settings record not found.");
+ console.error(
+ "safari-notifications setMostRecentNotified IndexedDB settings record not found",
+ );
}
transaction.oncomplete = () => db.close();
} catch (error) {
- console.error("IndexedDB error:", error);
+ console.error(
+ "safari-notifications setMostRecentNotified IndexedDB error",
+ error,
+ );
}
}
-async function logMessage(message) {
+async function appendDailyLog(message) {
try {
const db = await openIndexedDB("TimeSafari");
const transaction = db.transaction("logs", "readwrite");
const store = transaction.objectStore("logs");
// will only keep one day's worth of logs
const todayKey = new Date().toDateString();
- let data = await getRecord(store, todayKey);
- if (!data) {
+ const previous = await getRecord(store, todayKey);
+ if (!previous) {
await store.clear(); // clear out anything older than today
}
- data = data || "";
- data += `\n${message}`;
- await updateRecord(store, { message: data }, todayKey);
+ let fullMessage = (previous && previous.message) || "";
+ if (fullMessage) {
+ fullMessage += "\n";
+ }
+ fullMessage += message;
+ await updateRecord(store, { date: todayKey, message: fullMessage });
transaction.oncomplete = () => db.close();
return true;
} catch (error) {
- console.error("IndexedDB logMessage error:", error);
+ console.error("safari-notifications logMessage IndexedDB error", error);
return false;
}
}
@@ -443,9 +451,9 @@ function getRecord(store, key) {
}
// Note that this assumes there is only one record in the store.
-function updateRecord(store, data, key) {
+function updateRecord(store, data) {
return new Promise((resolve, reject) => {
- const request = key ? store.put(data, key) : store.put(data);
+ const request = store.put(data);
request.onsuccess = () => resolve(request.result);
request.onerror = () => reject(request.error);
});
@@ -547,7 +555,7 @@ async function getNotificationCount() {
await setMostRecentNotified(most_recent_notified);
} else {
console.error(
- "The service worker got a bad response status when fetching claims:",
+ "safari-notifications getNotificationsCount got a bad response status when fetching claims",
response.status,
response,
);
From 44cfe0d88e125733c271b1dad882c5c309cb38db Mon Sep 17 00:00:00 2001
From: Trent Larson
Date: Fri, 22 Dec 2023 14:22:13 -0700
Subject: [PATCH 6/9] allow notifications even without an ID
---
project.task.yaml | 5 +
src/views/HelpNotificationsView.vue | 7 +-
sw_scripts/safari-notifications.js | 140 ++++++++++++++--------------
3 files changed, 81 insertions(+), 71 deletions(-)
diff --git a/project.task.yaml b/project.task.yaml
index 5ba2e88..df49f3e 100644
--- a/project.task.yaml
+++ b/project.task.yaml
@@ -4,6 +4,11 @@ tasks:
- 08 notifications :
- get the rest of our Android devices to work... and insert tooling (exportable logs?) so that we can see problems and troubleshoot as we onboard
- get an error registering notifications on Firefox and subscription info is null
+ - if navigator.serviceWorker is null, then tell the user to wait
+ - Android DuckDuckGo asked for my permissions, got error, won't download DB
+ - Android Chrome won't ask permission, will download log but always empty
+ -
+ - Chrome will get notification permissions but still complain when I reload (maybe I reload too soon?)
- prompt user to install on their home screen https://benborgers.com/posts/pwa-detect-installed
- warn if they're using the web (android only?)
https://developer.mozilla.org/en-US/docs/Web/API/Navigator/getInstalledRelatedApps
diff --git a/src/views/HelpNotificationsView.vue b/src/views/HelpNotificationsView.vue
index c734ba4..a7c125b 100644
--- a/src/views/HelpNotificationsView.vue
+++ b/src/views/HelpNotificationsView.vue
@@ -22,7 +22,7 @@
-
Here are things to try to get notifications working.
+
Here are things to get notifications working.
Test
Somehow call the service-worker self.showNotification
@@ -54,7 +54,10 @@
Make sure your OS (above) supports it.
Mobile Phone - Android
-
Chrome requires version 50.
+
+ Chrome requires version 50. Hold icon, select "App info", and enable
+ notifications.
+
diff --git a/sw_scripts/safari-notifications.js b/sw_scripts/safari-notifications.js
index 22dcf99..a50980f 100644
--- a/sw_scripts/safari-notifications.js
+++ b/sw_scripts/safari-notifications.js
@@ -461,10 +461,10 @@ function updateRecord(store, data) {
async function fetchAllAccounts() {
return new Promise((resolve, reject) => {
- let openRequest = indexedDB.open("TimeSafariAccounts");
+ const openRequest = indexedDB.open("TimeSafariAccounts");
openRequest.onupgradeneeded = function (event) {
- let db = event.target.result;
+ const db = event.target.result;
if (!db.objectStoreNames.contains("accounts")) {
db.createObjectStore("accounts", { keyPath: "id" });
}
@@ -474,10 +474,10 @@ async function fetchAllAccounts() {
};
openRequest.onsuccess = function (event) {
- let db = event.target.result;
- let transaction = db.transaction("accounts", "readonly");
- let objectStore = transaction.objectStore("accounts");
- let getAllRequest = objectStore.getAll();
+ const db = event.target.result;
+ const transaction = db.transaction("accounts", "readonly");
+ const objectStore = transaction.objectStore("accounts");
+ const getAllRequest = objectStore.getAll();
getAllRequest.onsuccess = function () {
resolve(getAllRequest.result);
@@ -494,76 +494,78 @@ async function fetchAllAccounts() {
}
async function getNotificationCount() {
- let secret = null;
let accounts = [];
let result = null;
- if ("secret" in self) {
- secret = self.secret;
- const secretUint8Array = self.decodeBase64(secret);
- // 1 is our master settings ID; see MASTER_SETTINGS_KEY
- const settings = await getSettingById(1);
- let lastNotifiedClaimId = null;
- if ("lastNotifiedClaimId" in settings) {
- lastNotifiedClaimId = settings["lastNotifiedClaimId"];
+ // 1 is our master settings ID; see MASTER_SETTINGS_KEY
+ const settings = await getSettingById(1);
+ let lastNotifiedClaimId = null;
+ if ("lastNotifiedClaimId" in settings) {
+ lastNotifiedClaimId = settings["lastNotifiedClaimId"];
+ }
+ const activeDid = settings["activeDid"];
+ console.log("safari-not getNotificationsCount last", lastNotifiedClaimId);
+ accounts = await fetchAllAccounts();
+ let activeAccount = null;
+ for (let i = 0; i < accounts.length; i++) {
+ if (accounts[i]["did"] == activeDid) {
+ activeAccount = accounts[i];
+ break;
}
- const activeDid = settings["activeDid"];
- accounts = await fetchAllAccounts();
- let did = null;
- for (var i = 0; i < accounts.length; i++) {
- let account = accounts[i];
- let did = account["did"];
- if (did == activeDid) {
- let publicKeyHex = account["publicKeyHex"];
- let identity = account["identity"];
- const messageWithNonceAsUint8Array = self.decodeBase64(identity);
- const nonce = messageWithNonceAsUint8Array.slice(0, 24);
- const message = messageWithNonceAsUint8Array.slice(24, identity.length);
- const decoder = new TextDecoder("utf-8");
- const decrypted = self.secretbox.open(message, nonce, secretUint8Array);
-
- const msg = decoder.decode(decrypted);
- const identifier = JSON.parse(JSON.parse(msg));
-
- const headers = {
- "Content-Type": "application/json",
- };
-
- headers["Authorization"] = "Bearer " + (await accessToken(identifier));
-
- let response = await fetch(
- settings["apiServer"] + "/api/v2/report/claims",
- {
- method: "GET",
- headers: headers,
- },
- );
- if (response.status == 200) {
- let json = await response.json();
- let claims = json["data"];
- let newClaims = 0;
- for (var i = 0; i < claims.length; i++) {
- let claim = claims[i];
- if (claim["id"] === lastNotifiedClaimId) {
- break;
- }
- newClaims++;
- }
- if (newClaims > 0) {
- result = `There are ${newClaims} new activities on TimeSafari`;
- }
- const most_recent_notified = claims[0]["id"];
- await setMostRecentNotified(most_recent_notified);
- } else {
- console.error(
- "safari-notifications getNotificationsCount got a bad response status when fetching claims",
- response.status,
- response,
- );
- }
+ }
+
+ const headers = {
+ "Content-Type": "application/json",
+ };
+
+ const identity = activeAccount && activeAccount["identity"];
+ if (identity && "secret" in self) {
+ const secret = self.secret;
+ const secretUint8Array = self.decodeBase64(secret);
+ const messageWithNonceAsUint8Array = self.decodeBase64(identity);
+ const nonce = messageWithNonceAsUint8Array.slice(0, 24);
+ const message = messageWithNonceAsUint8Array.slice(24, identity.length);
+ const decoder = new TextDecoder("utf-8");
+ const decrypted = self.secretbox.open(message, nonce, secretUint8Array);
+ const msg = decoder.decode(decrypted);
+ const identifier = JSON.parse(JSON.parse(msg));
+
+ headers["Authorization"] = "Bearer " + (await accessToken(identifier));
+ }
+
+ console.log("safari-not getNotificationsCount fetch", headers);
+ const response = await fetch(
+ settings["apiServer"] + "/api/v2/report/claims",
+ {
+ method: "GET",
+ headers: headers,
+ },
+ );
+ console.log("safari-not getNotificationsCount json", response);
+ if (response.status == 200) {
+ const json = await response.json();
+ console.log("safari-not getNotificationsCount json", json);
+ const claims = json["data"];
+ let newClaims = 0;
+ for (let i = 0; i < claims.length; i++) {
+ const claim = claims[i];
+ if (claim["id"] === lastNotifiedClaimId) {
break;
}
+ newClaims++;
+ }
+ if (newClaims > 0) {
+ result = `There are ${newClaims} new activities on Time Safari`;
}
+ const most_recent_notified = claims[0]["id"];
+ await setMostRecentNotified(most_recent_notified);
+ } else {
+ console.error(
+ "safari-notifications getNotificationsCount got a bad response status when fetching claims",
+ response.status,
+ response,
+ );
}
+
return result;
}
From 853eb3c623dacd6bd1c8de7ed055d16587d6f2d0 Mon Sep 17 00:00:00 2001
From: Trent Larson
Date: Sat, 23 Dec 2023 19:34:26 -0700
Subject: [PATCH 7/9] include the data in the logged info for a service worker
"push"
---
sw_scripts/additional-scripts.js | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/sw_scripts/additional-scripts.js b/sw_scripts/additional-scripts.js
index 3582bfc..0e2d326 100644
--- a/sw_scripts/additional-scripts.js
+++ b/sw_scripts/additional-scripts.js
@@ -28,13 +28,17 @@ function logConsoleAndDb(message, arg1, arg2) {
}
self.addEventListener("push", function (event) {
- logConsoleAndDb("Service worker received a push event.", event);
+ let text = null;
+ if (event.data) {
+ text = event.data.text();
+ }
+ logConsoleAndDb("Service worker received a push event.", text, event);
event.waitUntil(
(async () => {
try {
let payload;
- if (event.data) {
- payload = JSON.parse(event.data.text());
+ if (text) {
+ payload = JSON.parse(text);
}
const message = await self.getNotificationCount();
if (message) {
From 05c6ddda02553ae43559d7aaeb8c3f226ec0abab Mon Sep 17 00:00:00 2001
From: Trent Larson
Date: Sun, 24 Dec 2023 21:24:51 -0700
Subject: [PATCH 8/9] allow a test notification from the notification help
screen
---
README.md | 4 +-
project.task.yaml | 14 +++-
src/App.vue | 14 ++--
src/constants/app.ts | 12 ++-
src/db/index.ts | 4 +-
src/views/AccountViewView.vue | 18 +---
src/views/HelpNotificationsView.vue | 125 ++++++++++++++++++++++++++++
src/views/HelpView.vue | 9 ++
sw_scripts/additional-scripts.js | 24 +++++-
sw_scripts/safari-notifications.js | 4 -
10 files changed, 183 insertions(+), 45 deletions(-)
diff --git a/README.md b/README.md
index 4a8392d..0e943d1 100644
--- a/README.md
+++ b/README.md
@@ -26,13 +26,13 @@ If you are deploying in a subdirectory, add it to `publicPath` in vue.config.js,
* Tag wth the new version: `git tag 0.1.0`.
-* If production, change src/constants/app.ts DEFAULT_*_SERVER to be PROD and package.json to not be _Test.
+* If production, change src/constants/app.ts DEFAULT_*_SERVER to be "PROD" and package.json to remove "_Test".
* `npm run build`
* `npx prettier --write ./sw_scripts/`
-...to make sure the service worker scripts are in proper form
+...to make sure the service worker scripts are in proper form. It's only important if you changed something in that directory.
* `cp sw_scripts/[ns]* dist/`
diff --git a/project.task.yaml b/project.task.yaml
index df49f3e..36808bf 100644
--- a/project.task.yaml
+++ b/project.task.yaml
@@ -2,18 +2,23 @@
tasks:
- 08 notifications :
- - get the rest of our Android devices to work... and insert tooling (exportable logs?) so that we can see problems and troubleshoot as we onboard
+ - get the rest of our Android devices to work
+ - insert tooling (exportable logs?) so that we can see problems and troubleshoot as we onboard
- get an error registering notifications on Firefox and subscription info is null
- if navigator.serviceWorker is null, then tell the user to wait
- Android DuckDuckGo asked for my permissions, got error, won't download DB
- Android Chrome won't ask permission, will download log but always empty
- -
- - Chrome will get notification permissions but still complain when I reload (maybe I reload too soon?)
+ - Firefox works
+ - Local install works after cleared out cache in Chrome
+ - create troubleshooting notification:
+ - server gets signal to send a normal notification back immediately
+ - add windows & mac help at OS & browser level, in HelpNotificationsView.vue (linked from account page)
+ maybe tell them to pause, after first turn-on and after test
+ maybe Google Play permissions
- prompt user to install on their home screen https://benborgers.com/posts/pwa-detect-installed
- warn if they're using the web (android only?)
https://developer.mozilla.org/en-US/docs/Web/API/Navigator/getInstalledRelatedApps
https://web.dev/articles/get-installed-related-apps
- - add windows & mac help at OS & browser level, in HelpNotificationsView.vue (linked from account page)
- .2 fix the projects on /discover to show the issuer (currently all "Someone Anonymous")
@@ -83,6 +88,7 @@ tasks:
- 24 Move to Vite
- 32 accept images for projects
- 32 accept images for contacts
+- import project interactions from GitHub/GitLab and manage signing
- linking between projects or plans :
- show total time given to & from a project
diff --git a/src/App.vue b/src/App.vue
index 2c20d32..7b41d47 100644
--- a/src/App.vue
+++ b/src/App.vue
@@ -281,7 +281,7 @@ interface VapidResponse {
};
}
-import { AppString } from "@/constants/app";
+import { DEFAULT_PUSH_SERVER } from "@/constants/app";
import { db } from "@/db/index";
import { MASTER_SETTINGS_KEY } from "@/db/tables/settings";
@@ -302,7 +302,7 @@ export default class App extends Vue {
try {
await db.open();
const settings = await db.settings.get(MASTER_SETTINGS_KEY);
- let pushUrl: string = AppString.DEFAULT_PUSH_SERVER;
+ let pushUrl = DEFAULT_PUSH_SERVER;
if (settings?.webPushServer) {
pushUrl = settings.webPushServer;
}
@@ -446,7 +446,9 @@ export default class App extends Vue {
}
})
.then(() => {
- console.log("Subscription data sent to server.");
+ console.log(
+ "Subscription data sent to server and all finished successfully.",
+ );
})
.catch((error) => {
console.error(
@@ -510,11 +512,7 @@ export default class App extends Vue {
resolve();
})
.catch((error) => {
- console.error(
- "Subscription or server communication failed:",
- error,
- options,
- );
+ console.error("Push subscription failed:", error, options);
// Inform the user about the issue
alert(
diff --git a/src/constants/app.ts b/src/constants/app.ts
index c92709b..1675806 100644
--- a/src/constants/app.ts
+++ b/src/constants/app.ts
@@ -4,22 +4,20 @@
* See also ../libs/veramo/setup.ts
*/
export enum AppString {
- APP_NAME = "Time Safari",
-
PROD_ENDORSER_API_SERVER = "https://api.endorser.ch",
TEST_ENDORSER_API_SERVER = "https://test-api.endorser.ch",
LOCAL_ENDORSER_API_SERVER = "http://localhost:3000",
- DEFAULT_ENDORSER_API_SERVER = TEST_ENDORSER_API_SERVER,
-
- // eslint-disable-next-line @typescript-eslint/no-duplicate-enum-values
PROD_PUSH_SERVER = "https://timesafari.app",
TEST1_PUSH_SERVER = "https://test.timesafari.app",
TEST2_PUSH_SERVER = "https://timesafari-pwa.anomalistlabs.com",
-
- DEFAULT_PUSH_SERVER = TEST1_PUSH_SERVER,
}
+export const DEFAULT_ENDORSER_API_SERVER = AppString.TEST_ENDORSER_API_SERVER;
+
+export const DEFAULT_PUSH_SERVER =
+ window.location.protocol + "//" + window.location.host;
+
/**
* The possible values for "group" and "type" are in App.vue.
* From the notiwind package
diff --git a/src/db/index.ts b/src/db/index.ts
index 644f813..c15f6c9 100644
--- a/src/db/index.ts
+++ b/src/db/index.ts
@@ -8,7 +8,7 @@ import {
Settings,
SettingsSchema,
} from "./tables/settings";
-import { AppString } from "@/constants/app";
+import { DEFAULT_ENDORSER_API_SERVER } from "@/constants/app";
// Define types for tables that hold sensitive and non-sensitive data
type SensitiveTables = { accounts: Table };
@@ -52,6 +52,6 @@ db.version(2).stores(NonsensitiveSchemas);
db.on("populate", () => {
db.settings.add({
id: MASTER_SETTINGS_KEY,
- apiServer: AppString.DEFAULT_ENDORSER_API_SERVER,
+ apiServer: DEFAULT_ENDORSER_API_SERVER,
});
});
diff --git a/src/views/AccountViewView.vue b/src/views/AccountViewView.vue
index f459c0e..1a19d05 100644
--- a/src/views/AccountViewView.vue
+++ b/src/views/AccountViewView.vue
@@ -133,6 +133,9 @@
Notification status may have changed. Revisit this page to see the
latest setting.
+
+ Troubleshoot notifications here.
+
Data
@@ -306,13 +309,6 @@
Switch Identity
-
- Show Subscription from Web Push Server
-
-
Claim Server
diff --git a/src/views/HelpNotificationsView.vue b/src/views/HelpNotificationsView.vue
index a7c125b..12c055f 100644
--- a/src/views/HelpNotificationsView.vue
+++ b/src/views/HelpNotificationsView.vue
@@ -69,12 +69,34 @@
Auto-detection
Show results of auto-detection whether they're turned on
+
+
+ Show Subscription from Web Push Server
+
+
+
+ Send Myself a Test Web Push Message
+
diff --git a/src/views/HelpView.vue b/src/views/HelpView.vue
index 6caae30..53ea284 100644
--- a/src/views/HelpView.vue
+++ b/src/views/HelpView.vue
@@ -182,6 +182,15 @@
different page.
+
+ Where do I get help with notifications?
+
+
+ Here.
+
+
How do I access even more functionality?
diff --git a/sw_scripts/additional-scripts.js b/sw_scripts/additional-scripts.js
index 0e2d326..b96f5f2 100644
--- a/sw_scripts/additional-scripts.js
+++ b/sw_scripts/additional-scripts.js
@@ -38,11 +38,29 @@ self.addEventListener("push", function (event) {
try {
let payload;
if (text) {
- payload = JSON.parse(text);
+ try {
+ payload = JSON.parse(text);
+ } catch (e) {
+ // don't use payload since it is not JSON
+ }
+ }
+
+ // This should be a constant shared with the notification-test code. See TEST_PUSH_TITLE in HelpNotificationsView.vue
+ // Use something other than "Daily Update" https://gitea.anomalistdesign.com/trent_larson/py-push-server/src/commit/3c0e196c11bc98060ec5934e99e7dbd591b5da4d/app.py#L213
+ const DIRECT_PUSH_TITLE = "DIRECT_NOTIFICATION";
+
+ let title = "Generic Notification";
+ let message = "Got some empty message.";
+ if (payload && payload.title == DIRECT_PUSH_TITLE) {
+ // skip any search logic and show the message directly
+ title = "Direct Message";
+ message = payload.message || "No details were provided.";
+ } else {
+ title =
+ payload && payload.title ? payload.title : "Unknown Notification";
+ message = await self.getNotificationCount();
}
- const message = await self.getNotificationCount();
if (message) {
- const title = payload && payload.title ? payload.title : "Message";
const options = {
body: message,
icon: payload ? payload.icon : "icon.png",
diff --git a/sw_scripts/safari-notifications.js b/sw_scripts/safari-notifications.js
index a50980f..0d0eb9c 100644
--- a/sw_scripts/safari-notifications.js
+++ b/sw_scripts/safari-notifications.js
@@ -503,7 +503,6 @@ async function getNotificationCount() {
lastNotifiedClaimId = settings["lastNotifiedClaimId"];
}
const activeDid = settings["activeDid"];
- console.log("safari-not getNotificationsCount last", lastNotifiedClaimId);
accounts = await fetchAllAccounts();
let activeAccount = null;
for (let i = 0; i < accounts.length; i++) {
@@ -532,7 +531,6 @@ async function getNotificationCount() {
headers["Authorization"] = "Bearer " + (await accessToken(identifier));
}
- console.log("safari-not getNotificationsCount fetch", headers);
const response = await fetch(
settings["apiServer"] + "/api/v2/report/claims",
{
@@ -540,10 +538,8 @@ async function getNotificationCount() {
headers: headers,
},
);
- console.log("safari-not getNotificationsCount json", response);
if (response.status == 200) {
const json = await response.json();
- console.log("safari-not getNotificationsCount json", json);
const claims = json["data"];
let newClaims = 0;
for (let i = 0; i < claims.length; i++) {
From fd8877900b7ec9c5756ccb183e95547b11713d24 Mon Sep 17 00:00:00 2001
From: Trent Larson
Date: Mon, 25 Dec 2023 12:51:06 -0700
Subject: [PATCH 9/9] add another alert message & test button
---
project.task.yaml | 1 +
src/App.vue | 9 ++++++
src/views/HelpNotificationsView.vue | 44 +++++++++++++++++++++++++++--
sw_scripts/additional-scripts.js | 2 +-
4 files changed, 52 insertions(+), 4 deletions(-)
diff --git a/project.task.yaml b/project.task.yaml
index 36808bf..ba36658 100644
--- a/project.task.yaml
+++ b/project.task.yaml
@@ -46,6 +46,7 @@ tasks:
blocks: ref:https://raw.githubusercontent.com/trentlarson/lives-of-gifts/master/project.yaml#kickstarter%20for%20time
- make identicons for contacts into more-memorable faces (and maybe change project identicons, too)
+- 04 split out notification logic & tests from web-push-subscription logic & tests
- 01 server - show all claim details when issued by the issuer
- bug - got error adding on Firefox user #0 as contact for themselves
- bug - back-and-forth on discovery & project pages led to "You need an identity to load your projects." error on product page when I had an identity
diff --git a/src/App.vue b/src/App.vue
index 7b41d47..85489c8 100644
--- a/src/App.vue
+++ b/src/App.vue
@@ -449,6 +449,15 @@ export default class App extends Vue {
console.log(
"Subscription data sent to server and all finished successfully.",
);
+ this.$notify(
+ {
+ group: "alert",
+ type: "success",
+ title: "Notifications Turned On",
+ text: "Notifications are on. You should see one on your device; if not, see the 'Troubleshoot' page.",
+ },
+ -1,
+ );
})
.catch((error) => {
console.error(
diff --git a/src/views/HelpNotificationsView.vue b/src/views/HelpNotificationsView.vue
index 12c055f..77b284b 100644
--- a/src/views/HelpNotificationsView.vue
+++ b/src/views/HelpNotificationsView.vue
@@ -22,10 +22,16 @@
-
Here are things to get notifications working.
+
Here are ways to get notifications working.
Test
Somehow call the service-worker self.showNotification
+
+ See a Test Notification
+
Check OS-level permissions
@@ -150,7 +156,7 @@ export default class HelpNotificationsView extends Vue {
pushUrl = settings.webPushServer;
}
- // This should be a constant shared with the service worker. See TEST_PUSH_TITLE in additional-scripts.js
+ // This is shared with the service worker and should be a constant. Look for the same name in additional-scripts.js
// Use something other than "Daily Update" https://gitea.anomalistdesign.com/trent_larson/py-push-server/src/commit/3c0e196c11bc98060ec5934e99e7dbd591b5da4d/app.py#L213
const DIRECT_PUSH_TITLE = "DIRECT_NOTIFICATION";
@@ -172,7 +178,7 @@ export default class HelpNotificationsView extends Vue {
auth: authB64,
p256dh: p256dhB64,
},
- message: "This is a test message, hopefully triggered by you.",
+ message: "This is a test message, triggered by you.",
title: DIRECT_PUSH_TITLE,
};
console.log("Sending a test web push message:", newPayload);
@@ -211,5 +217,37 @@ export default class HelpNotificationsView extends Vue {
);
}
}
+
+ showTestNotification() {
+ navigator.serviceWorker.ready
+ .then((registration) => {
+ return registration.showNotification("It Worked", {
+ body: "This is your test notification.",
+ });
+ })
+ .then(() => {
+ this.$notify(
+ {
+ group: "alert",
+ type: "success",
+ title: "Sent",
+ text: "A notification was triggered, so one should show on your device soon.",
+ },
+ 5000,
+ );
+ })
+ .catch((error) => {
+ console.error("Got a notification error:", error);
+ this.$notify(
+ {
+ group: "alert",
+ type: "danger",
+ title: "Failed",
+ text: "Got an error sending a notification.",
+ },
+ -1,
+ );
+ });
+ }
}
diff --git a/sw_scripts/additional-scripts.js b/sw_scripts/additional-scripts.js
index b96f5f2..79b42a7 100644
--- a/sw_scripts/additional-scripts.js
+++ b/sw_scripts/additional-scripts.js
@@ -45,7 +45,7 @@ self.addEventListener("push", function (event) {
}
}
- // This should be a constant shared with the notification-test code. See TEST_PUSH_TITLE in HelpNotificationsView.vue
+ // This is shared with the notification-test code and should be a constant. Look for the same name in HelpNotificationsView.vue
// Use something other than "Daily Update" https://gitea.anomalistdesign.com/trent_larson/py-push-server/src/commit/3c0e196c11bc98060ec5934e99e7dbd591b5da4d/app.py#L213
const DIRECT_PUSH_TITLE = "DIRECT_NOTIFICATION";