allow a test notification from the notification help screen
This commit is contained in:
@@ -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/`
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
14
src/App.vue
14
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(
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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<Account> };
|
||||
@@ -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,
|
||||
});
|
||||
});
|
||||
|
||||
@@ -133,6 +133,9 @@
|
||||
Notification status may have changed. Revisit this page to see the
|
||||
latest setting.
|
||||
</div>
|
||||
<router-link class="px-4 text-sm text-blue-500" to="/help-notifications">
|
||||
Troubleshoot notifications here.
|
||||
</router-link>
|
||||
</div>
|
||||
|
||||
<h3 class="text-sm uppercase font-semibold mb-3">Data</h3>
|
||||
@@ -306,13 +309,6 @@
|
||||
Switch Identity
|
||||
</router-link>
|
||||
|
||||
<button
|
||||
@click="alertWebPushSubscription()"
|
||||
class="block w-full text-center text-md uppercase bg-slate-500 text-white px-1.5 py-2 rounded-md mb-2"
|
||||
>
|
||||
Show Subscription from Web Push Server
|
||||
</button>
|
||||
|
||||
<div class="flex py-4">
|
||||
<h2 class="text-slate-500 text-sm font-bold mb-2">Claim Server</h2>
|
||||
<input
|
||||
@@ -1048,13 +1044,5 @@ export default class AccountViewView extends Vue {
|
||||
-1,
|
||||
);
|
||||
}
|
||||
|
||||
alertWebPushSubscription() {
|
||||
console.log(
|
||||
"Web push subscription:",
|
||||
JSON.parse(JSON.stringify(this.subscription)), // gives more info than plain console logging
|
||||
);
|
||||
alert(JSON.stringify(this.subscription));
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -69,12 +69,34 @@
|
||||
|
||||
<h2 class="text-xl font-semibold">Auto-detection</h2>
|
||||
<p>Show results of auto-detection whether they're turned on</p>
|
||||
|
||||
<button
|
||||
@click="alertWebPushSubscription()"
|
||||
class="block w-full text-center text-md uppercase bg-slate-500 text-white px-1.5 py-2 rounded-md mb-2"
|
||||
>
|
||||
Show Subscription from Web Push Server
|
||||
</button>
|
||||
|
||||
<button
|
||||
@click="sendTestWebPushMessage()"
|
||||
class="block w-full text-center text-md uppercase bg-slate-500 text-white px-1.5 py-2 rounded-md mb-2"
|
||||
>
|
||||
Send Myself a Test Web Push Message
|
||||
</button>
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import axios from "axios";
|
||||
import { Component, Vue } from "vue-facing-decorator";
|
||||
|
||||
import QuickNav from "@/components/QuickNav.vue";
|
||||
import { db } from "@/db/index";
|
||||
import { MASTER_SETTINGS_KEY } from "@/db/tables/settings";
|
||||
import { DEFAULT_PUSH_SERVER } from "@/constants/app";
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
const Buffer = require("buffer/").Buffer;
|
||||
|
||||
interface Notification {
|
||||
group: string;
|
||||
@@ -86,5 +108,108 @@ interface Notification {
|
||||
@Component({ components: { QuickNav } })
|
||||
export default class HelpNotificationsView extends Vue {
|
||||
$notify!: (notification: Notification, timeout?: number) => void;
|
||||
|
||||
subscription: PushSubscription | null = null;
|
||||
|
||||
async mounted() {
|
||||
try {
|
||||
const registration = await navigator.serviceWorker.ready;
|
||||
this.subscription = await registration.pushManager.getSubscription();
|
||||
} catch (error) {
|
||||
console.error("Mount error:", error);
|
||||
}
|
||||
}
|
||||
|
||||
alertWebPushSubscription() {
|
||||
console.log(
|
||||
"Web push subscription:",
|
||||
JSON.parse(JSON.stringify(this.subscription)), // gives more info than plain console logging
|
||||
);
|
||||
alert(JSON.stringify(this.subscription));
|
||||
}
|
||||
|
||||
async sendTestWebPushMessage() {
|
||||
if (!this.subscription) {
|
||||
this.$notify(
|
||||
{
|
||||
group: "alert",
|
||||
type: "danger",
|
||||
title: "Not Subscribed",
|
||||
text: "You must enable notifications before testing the web push.",
|
||||
},
|
||||
-1,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await db.open();
|
||||
const settings = await db.settings.get(MASTER_SETTINGS_KEY);
|
||||
let pushUrl: string = DEFAULT_PUSH_SERVER as string;
|
||||
if (settings?.webPushServer) {
|
||||
pushUrl = settings.webPushServer;
|
||||
}
|
||||
|
||||
// This should be a constant shared with the service worker. See TEST_PUSH_TITLE 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";
|
||||
|
||||
const auth = Buffer.from(this.subscription.getKey("auth"));
|
||||
const authB64 = auth
|
||||
.toString("base64")
|
||||
.replace(/\+/g, "-")
|
||||
.replace(/\//g, "_")
|
||||
.replace(/=+$/, "");
|
||||
const p256dh = Buffer.from(this.subscription.getKey("p256dh"));
|
||||
const p256dhB64 = p256dh
|
||||
.toString("base64")
|
||||
.replace(/\+/g, "-")
|
||||
.replace(/\//g, "_")
|
||||
.replace(/=+$/, "");
|
||||
const newPayload = {
|
||||
endpoint: this.subscription.endpoint,
|
||||
keys: {
|
||||
auth: authB64,
|
||||
p256dh: p256dhB64,
|
||||
},
|
||||
message: "This is a test message, hopefully triggered by you.",
|
||||
title: DIRECT_PUSH_TITLE,
|
||||
};
|
||||
console.log("Sending a test web push message:", newPayload);
|
||||
const payloadStr = JSON.stringify(newPayload);
|
||||
const response = await axios.post(
|
||||
pushUrl + "/web-push/send-test",
|
||||
payloadStr,
|
||||
{
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
console.log("Got response from web push server:", response);
|
||||
|
||||
this.$notify(
|
||||
{
|
||||
group: "alert",
|
||||
type: "success",
|
||||
title: "Test Web Push Sent",
|
||||
text: "Check your device for the test web push message.",
|
||||
},
|
||||
-1,
|
||||
);
|
||||
} catch (error) {
|
||||
console.error("Got an error sending test notification:", error);
|
||||
this.$notify(
|
||||
{
|
||||
group: "alert",
|
||||
type: "danger",
|
||||
title: "Error Sending Test",
|
||||
text: "Got an error sending the test web push notification.",
|
||||
},
|
||||
-1,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -182,6 +182,15 @@
|
||||
different page.
|
||||
</p>
|
||||
|
||||
<h2 class="text-xl font-semibold">
|
||||
Where do I get help with notifications?
|
||||
</h2>
|
||||
<p>
|
||||
<router-link class="text-blue-500" to="/help-notifications"
|
||||
>Here.</router-link
|
||||
>
|
||||
</p>
|
||||
|
||||
<h2 class="text-xl font-semibold">
|
||||
How do I access even more functionality?
|
||||
</h2>
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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++) {
|
||||
|
||||
Reference in New Issue
Block a user