update the notification-help to remove push-notification info, and other minor fixes

This commit is contained in:
2026-03-05 20:58:49 -07:00
parent 6825bd5214
commit 94f31faacc
5 changed files with 92 additions and 595 deletions

View File

@@ -143,29 +143,6 @@
</button>
</div>
</div>
<!-- Dev/test only: 10-minute rollover for rapid testing (Reminder Notifications) -->
<label
v-if="isNotProdServer"
class="flex items-center justify-between cursor-pointer mt-3 py-2"
@click="toggleReminderFastRollover"
>
<span class="text-sm text-slate-600">
Use 10-minute rollover (testing)
</span>
<div class="relative ml-2">
<input
:checked="reminderFastRolloverForTesting"
type="checkbox"
class="sr-only"
readonly
@click.stop.prevent
/>
<div class="block bg-slate-500 w-14 h-8 rounded-full"></div>
<div
class="dot absolute left-1 top-1 bg-slate-400 w-6 h-6 rounded-full transition"
></div>
</div>
</label>
<div v-if="false" class="mt-4 flex items-center justify-between">
<!-- label -->
<div>

View File

@@ -1,34 +1,3 @@
<!--
HelpNotificationsView.vue - Push Notification Help & Testing Component
User support component that provides comprehensive help and testing functionality
for push notifications. Critical for users experiencing notification issues.
Key Features:
- Push notification testing with multiple test scenarios
- Comprehensive troubleshooting guide for notification issues
- System permission checks for various platforms and browsers
- Web push subscription management and diagnostics
- Direct device testing without push server dependency
User Experience Impact:
- High priority for users having notification issues
- Primary troubleshooting resource for notification problems
- Platform-specific guidance for iOS, Android, Mac, Windows
- Technical diagnostic tools for developers and support
Database Operations:
- Settings updates for notification preferences via PlatformServiceMixin
- Simple key-value updates for notification configuration
- No complex queries or data relationships
Security Considerations:
- No sensitive data exposure in notifications or logs
- Safe diagnostic information display
- Secure push subscription handling
@author Matthew Raymer
-->
<template>
<QuickNav />
@@ -57,576 +26,140 @@
</router-link>
</div>
<!-- eslint-disable prettier/prettier -->
<div>
<p>Here are ways to test notifications and get them working.</p>
<p class="mt-2 font-medium">Quick checklist:</p>
<ul class="list-disc ml-4 mt-1">
<li>
Notifications are turned on for
<strong>{{ AppString.APP_NAME_NO_SPACES }}</strong>
(or the browser you use for the app) in system Settings.
</li>
<li>
Battery and background settings are not restricting the app (see
"Battery &amp; background" under Check App Permissions).
</li>
<li>
You're not in Focus or Do Not Disturb, or the app is allowed in that
mode.
</li>
<li>Run the <strong>Full Test</strong> below.</li>
</ul>
<h2 class="text-xl font-semibold mt-4">Full Test</h2>
<div>
<p>
If this works then you're all set.
<button
:class="primaryTestButtonClass"
@click="sendTestWebPushMessage(true)"
>
Send Yourself a Test Web Push Message (Through Push Server but
Skipping Client Filter)
</button>
</p>
</div>
<h2 class="text-xl font-semibold mt-4">Android Users</h2>
<div>
<p>
Note that you may not receive notifications when the app is in the
background. When you're done working, close the app, and then you'll
get the reminder notifications.
</p>
</div>
<h2 class="text-xl font-semibold mt-4">
If this app doesn't support notifications...
<!-- Note that that exact verbiage shows in a message elsewhere. -->
</h2>
<div>
<p>
To be notified of interesting updates, install this app on your device
(as opposed to using it inside the browser app). In Chrome, it may prompt
you, and you can also look for the "Install" command in the browser
settings.
</p>
</div>
<h2 class="text-xl font-semibold mt-4">
If you must enable notifications...
<!-- Note that that exact verbiage shows in a message elsewhere. -->
</h2>
<div>
<p>
<button class="text-blue-500" @click="showNotificationChoice()">
Click here.
</button>
<PushNotificationPermission ref="pushNotificationPermission" />
</p>
</div>
<h2 class="text-xl font-semibold mt-4">
If you're waiting for system initialization...
<!-- Note that that exact verbiage shows in a message elsewhere. -->
</h2>
<div>
<p>
... and it never stops, then there is a problem with the underlying
service worker or push server mechanism in your browser. Your best bet
is to follow the "Reinstall" steps below or use a different browser.
</p>
</div>
<h2 class="text-xl font-semibold mt-4">Check App Permissions</h2>
<div>
<p>
If you use <strong>Focus</strong> (iOS) or <strong>Do Not
Disturb</strong> (Android), notifications may be silenced. Check that
{{ AppString.APP_NAME }} is allowed in that mode, or temporarily turn
it off to test.
</p>
<p>
In Apple iOS, check "Settings" -> "Notifications" and look for
<strong>{{ AppString.APP_NAME_NO_SPACES }}</strong>
(the app name in system Settings). If you added the app from a browser
(e.g. "Add to Home Screen"), you may see
the browser (e.g. Safari) instead ensure notifications are enabled
for that and for the site if listed separately. Make sure notifications
are enabled.
</p>
<p>
In Android, go to "Settings" -> "Notifications" and look for
<strong>{{ AppString.APP_NAME_NO_SPACES }}</strong>
(or Chrome if you installed from Chrome). Alternatively, long-press
the app icon, select "App Info", then
"Notifications" and make sure they're enabled. If it's still a problem
then go further:
</p>
<p>
If you installed the app with Chrome, make sure there are no other
tabs with it open. Here are some ways to clear caches that can mess
things up (and note that this clears out data from the installed app
-- which is good to do while the app is installed):
</p>
<ul>
<li class="list-disc ml-4">
Go to Chrome "App Info", then "Storage & Cache" and "Clear Storage".
</li>
<li class="list-disc ml-4">
Go to Chrome "Settings", then "Privacy and Security" and "Clear
browsing data", then "Cookies and site data". Make sure the "Time
Range" at the top shows "All time".
</li>
</ul>
<p>
On a Mac, go to "Settings" and check "Notifications".
<img
src="../assets/help/mac-installed-app-settings.png"
alt="Mac app settings"
class="ml-4"
/>
</p>
<h3 class="text-lg font-semibold mt-4">Battery &amp; background</h3>
<p>
Notifications (especially scheduled reminders) can be blocked by
battery or background settings. Check the following:
</p>
<ul class="list-disc ml-4">
<li>
<strong>iOS</strong>: In Settings Battery, ensure Low Power Mode
is off (it can delay background activity). In Settings General
Background App Refresh, ensure it's on and that
<strong>{{ AppString.APP_NAME_NO_SPACES }}</strong>
(or Safari if you use the app from Safari) is allowed.
</li>
<li>
<strong>Android</strong>: In Settings → Apps →
{{ AppString.APP_NAME_NO_SPACES }} (or Chrome if you use the PWA),
open Battery and set to "Unrestricted" or "Don't
optimize" so the app can run in the background. Battery Saver or
Adaptive Battery can also limit notifications — try disabling them or
adding an exception for the app.
</li>
</ul>
</div>
<h2 class="text-xl font-semibold mt-4">Check Browser Permissions</h2>
<div>
<p>In Apple iOS, check Settings -> Notifications.</p>
<p>In Android, check Settings -> Notifications.</p>
You can find more details about compatibility
<a
href="https://developer.mozilla.org/en-US/docs/Web/API/Push_API#browser_compatibility"
class="text-blue-500"
target="_blank"
>
here <font-awesome icon="arrow-up-right-from-square" class="fa-fw" />
</a>
</div>
<h2 class="text-xl font-semibold mt-4">
Check Operating System (OS) Permissions
</h2>
<div class="px-2">
<div>
<h3 class="text-lg font-semibold">Mobile Phone - Apple iOS</h3>
<div>
Notifications require iOS 16.4 or higher. To check your iOS version,
go to Settings > General > About > Software Version.
</div>
<h3 class="text-lg font-semibold">Mobile Phone - Google Android</h3>
<div>
We recommend Chrome. It must be version 42 or higher. Check your
version under Settings -> About Chrome.
</div>
<h3 class="text-lg font-semibold">Desktop - Mac</h3>
<div>
<span>
See "System Settings" -> "Notifications" and make sure it is
enabled for the browser you're using. Note that these
notifications require Mac OS 13; see your macOS version under
Apple -> "About This Mac".
</span>
</div>
<h3 class="text-lg font-semibold">Desktop - Windows</h3>
In Windows, check "Settings" -> "Notifications".
<img
src="../assets/help/windows-system-enable-notifications.png"
alt="Windows system settings"
class="ml-4"
<label
class="flex items-center justify-between cursor-pointer mt-3 py-2"
@click="toggleReminderFastRollover"
>
<span class="text-sm text-slate-600">
Use 10-minute rollover (testing)
</span>
<div class="relative ml-2">
<input
:checked="reminderFastRolloverForTesting"
type="checkbox"
class="sr-only"
readonly
@click.stop.prevent
/>
<div class="block bg-slate-500 w-14 h-8 rounded-full"></div>
<div
class="dot absolute left-1 top-1 bg-slate-400 w-6 h-6 rounded-full transition"
></div>
</div>
<div>
You can find more details about compatibility
<a
href="https://developer.mozilla.org/en-US/docs/Web/API/Push_API#browser_compatibility"
class="text-blue-500"
target="_blank"
>
here <font-awesome icon="arrow-up-right-from-square" class="fa-fw" />
</a>
</div>
</div>
<h2 class="text-xl font-semibold mt-4">Reinstall</h2>
<div>
<p>
If all else fails, it's best to start over.
</p>
<p>
Of course, you'll want to back up all your data first -- all seeds as
well as the contacts & settings -- on the Profile
<font-awesome icon="circle-user" /> page.
</p>
<p>
Here are instructions to uninstall the app and clear out caches and
storage. Note that you should first ensure that browser tabs with
{{ AppString.APP_NAME }} are closed. (If any are open then that will
interfere with your refresh.)
</p>
<ul class="ml-4 list-disc">
<li>
Clear cache.
<ul>
<li>
In mobile, look for the browser app settings. This is true even
for an installed app: go to the browser which you used to
initially visit timesafari.app, because those settings affect
the app. Look for "Delete browsing data" in the "Settings",
under "Privacy and Security".
</li>
<li>
In Chrome, go to `chrome://settings/cookies` and "all site data
and permissions" for timesafari.app; in Firefox, go to
`about:preferences` and search for "cache" then "Manage Data"
for timesafari.app. Also manually remove the IndexedDB data if
the DBs still show.)
</li>
</ul>
</li>
<li>
Clear notification permission. (In Chrome, go to
`chrome://settings/content/notifications`; in Firefox, go to
`about:preferences` and search for "notifications".)
</li>
<li>
Unregister service worker. (In Chrome, go to
`chrome://serviceworker-internals/`; in Firefox, go to
`about:serviceworkers`.)
</li>
<li>
Clear "Cache Storage". (In Chrome, in dev tools under "Application";
in Firefox, in dev tools under "Storage".)
</li>
</ul>
<p>Then reinstall the app.</p>
</div>
<h2 class="text-xl font-semibold mt-4">Tests</h2>
<button
:class="testButtonClass"
@click="showTestNotification()"
>
Send Test Notification Directly to Device (Not Through Push Server)
</button>
<p>
If that didn't show a notification on your device, the problem is that
your browser or your operating system are not allowing notifications
through. See "Check App Permissions" and "Check Browser Permissions" and
"Check Operating System (OS) Permissions" above.
</p>
<button
:class="testButtonClass"
@click="alertWebPushSubscription()"
>
Show Web Push Subscription Info
</button>
<p>
If that showed "null" then the notification is not active.
<button class="text-blue-500" @click="showNotificationChoice()">
Click here.
</button>
</p>
<button
:class="testButtonClass"
@click="sendTestWebPushMessage(true)"
>
Send Yourself a Test Web Push Message (Through Push Server but Skipping
Client Filter)
</button>
<p>
If that didn't show a notification on your device, there is a problem
getting to the push server. Disable notifications and then enable them
again.
</p>
<button
:class="testButtonClass"
@click="sendTestWebPushMessage()"
>
Send Yourself a Test Web Push Message (Through Push Server and Client
Filter)
</button>
<p>
If you don't see a message, it could be that there is nothing new for
you to see. If the previous test worked, then things should work fine.
If you notice a full 24 hours where you get no notification and you know
that there are new items that should show, gather as many details as
possible and go to the bottom of
<router-link to="help" class="text-blue-500"> this page </router-link>
for ways to contact us.
</p>
</label>
</div>
<!-- eslint-enable -->
</section>
</template>
<script lang="ts">
import { Component, Vue } from "vue-facing-decorator";
import { Capacitor } from "@capacitor/core";
import QuickNav from "../components/QuickNav.vue";
import { AppString, NotificationIface } from "../constants/app";
import { DIRECT_PUSH_TITLE, sendTestThroughPushServer } from "../libs/util";
import PushNotificationPermission from "../components/PushNotificationPermission.vue";
import { NotificationIface } from "../constants/app";
import { PlatformServiceMixin } from "../utils/PlatformServiceMixin";
import { createNotifyHelpers, TIMEOUTS } from "../utils/notify";
import {
NOTIFY_PUSH_NOT_SUBSCRIBED,
NOTIFY_TEST_WEB_PUSH_SUCCESS,
NOTIFY_TEST_WEB_PUSH_ERROR,
NOTIFY_TEST_NOTIFICATION_SUCCESS,
NOTIFY_TEST_NOTIFICATION_ERROR,
} from "../constants/notifications";
import { NotificationService } from "@/services/notifications";
import { Router } from "vue-router";
import { logger } from "../utils/logger";
/**
* HelpNotificationsView Component
*
* User support component that provides comprehensive help and testing functionality
* for push notifications. Critical for users experiencing notification issues.
*
* Key features:
* - Push notification testing with multiple test scenarios
* - Comprehensive troubleshooting guide for notification issues
* - System permission checks for various platforms and browsers
* - Web push subscription management and diagnostics
* - Direct device testing without push server dependency
*
* User Experience Impact:
* - High priority for users having notification issues
* - Primary troubleshooting resource for notification problems
* - Platform-specific guidance for iOS, Android, Mac, Windows
* - Technical diagnostic tools for developers and support
*
* Database Operations:
* - Settings updates for notification preferences via PlatformServiceMixin
* - Simple key-value updates for notification configuration
* - No complex queries or data relationships
*
* Security Features:
* - No sensitive data exposure in notifications or logs
* - Safe diagnostic information display
* - Secure push subscription handling
* - Proper error handling without data leakage
*
* @author Matthew Raymer
*/
@Component({
components: { PushNotificationPermission, QuickNav },
components: { QuickNav },
mixins: [PlatformServiceMixin],
})
export default class HelpNotificationsView extends Vue {
$notify!: (notification: NotificationIface, timeout?: number) => void;
$router!: Router;
subscriptionJSON?: PushSubscriptionJSON;
apiServer: string = "";
notifyingReminder = false;
notifyingReminderMessage = "";
notifyingReminderTime = "";
reminderFastRolloverForTesting: boolean = false;
// Expose app name constants for template (Settings label vs product name)
AppString = AppString;
// Notification helper system
notify!: ReturnType<typeof createNotifyHelpers>;
/**
* Computed property for consistent button styling
* Used for all test buttons in the notification help interface
*/
get buttonClass(): string {
return "block w-full text-center text-md bg-gradient-to-b from-slate-400 to-slate-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white px-1.5 py-2 rounded-md";
}
/**
* Computed property for test button styling with margins
* Used for test buttons in the Tests section
*/
get testButtonClass(): string {
return this.buttonClass + " mt-4 mb-2";
}
/**
* Computed property for primary test button styling
* Used for the main test button with bottom margin
*/
get primaryTestButtonClass(): string {
return this.buttonClass + " mb-2";
}
/**
* Vue mounted lifecycle hook
*
* Initializes the component by setting up push subscription information.
* Retrieves the current push subscription from the service worker and stores
* it for display and testing purposes.
*
* Handles errors gracefully with proper logging without exposing sensitive data.
*/
async mounted() {
// Initialize notification helpers
this.notify = createNotifyHelpers(this.$notify);
try {
const registration = await navigator.serviceWorker?.ready;
const fullSub = await registration?.pushManager.getSubscription();
this.subscriptionJSON = fullSub?.toJSON();
const settings = await this.$settings();
this.apiServer = settings.apiServer || "";
this.notifyingReminder = !!settings.notifyingReminderTime;
this.notifyingReminderMessage = settings.notifyingReminderMessage || "";
this.notifyingReminderTime = settings.notifyingReminderTime || "";
this.reminderFastRolloverForTesting =
!!settings.reminderFastRolloverForTesting;
} catch (error) {
logger.error("Mount error:", error);
}
}
/**
* Navigates back to the previous page
* Provides consistent navigation behavior for the back button
*/
goBack(): void {
this.$router.back();
}
/**
* Displays web push subscription information
*
* Shows the current push subscription details to the user for diagnostic purposes.
* Useful for troubleshooting push notification issues and verifying subscription status.
*/
alertWebPushSubscription() {
alert(JSON.stringify(this.subscriptionJSON));
}
async toggleReminderFastRollover(): Promise<void> {
const next = !this.reminderFastRolloverForTesting;
await this.$saveSettings({
reminderFastRolloverForTesting: next,
});
this.reminderFastRolloverForTesting = next;
/**
* Sends test web push message through push server
*
* Sends a test notification through the push server to verify the complete
* notification pipeline. Can skip client-side filtering for testing purposes.
*
* @param skipFilter - Whether to skip client-side message filtering
*/
async sendTestWebPushMessage(skipFilter: boolean = false) {
if (!this.subscriptionJSON) {
this.notify.error(NOTIFY_PUSH_NOT_SUBSCRIBED.message, TIMEOUTS.STANDARD);
return;
}
try {
await sendTestThroughPushServer(this.subscriptionJSON, skipFilter);
this.notify.success(
this.getTestWebPushSuccessMessage(skipFilter),
TIMEOUTS.STANDARD,
);
} catch (error) {
logger.error("Got an error sending test notification:", error);
this.notify.error(NOTIFY_TEST_WEB_PUSH_ERROR.message, TIMEOUTS.STANDARD);
}
}
/**
* Shows test notification directly to device
*
* Displays a test notification directly through the service worker without
* using the push server. Useful for testing local notification capabilities.
*/
showTestNotification() {
const TEST_NOTIFICATION_TITLE = "It Worked";
navigator.serviceWorker?.ready
.then((registration) => {
return registration.showNotification(TEST_NOTIFICATION_TITLE, {
body: "This is your test notification.",
});
})
.then(() => {
this.notify.success(
this.getTestNotificationSuccessMessage(TEST_NOTIFICATION_TITLE),
TIMEOUTS.STANDARD,
);
})
.catch((error) => {
logger.error("Got a notification error:", error);
this.notify.error(
NOTIFY_TEST_NOTIFICATION_ERROR.message,
TIMEOUTS.STANDARD,
);
});
}
/**
* Shows notification permission choice dialog
*
* Opens the notification permission dialog to allow users to enable
* notifications. Updates notification settings upon successful permission grant.
*/
showNotificationChoice() {
(this.$refs.pushNotificationPermission as PushNotificationPermission).open(
DIRECT_PUSH_TITLE,
async (success: boolean, timeText: string, message?: string) => {
if (success) {
await this.$updateSettings({
notifyingReminderMessage: message,
notifyingReminderTime: timeText,
});
this.notifyingReminder = true;
this.notifyingReminderMessage = message || "";
this.notifyingReminderTime = timeText;
if (this.notifyingReminder) {
try {
const service = NotificationService.getInstance();
if (Capacitor.getPlatform() !== "android") {
await service.cancelDailyNotification();
}
},
);
const time24h = this.parseTimeTo24Hour(this.notifyingReminderTime);
const title = "Daily Reminder";
const body =
this.notifyingReminderMessage ||
"Click to share some gratitude with the world -- even if they're unnamed.";
await service.scheduleDailyNotification({
time: time24h,
title,
body,
priority: "normal",
...(next ? { rolloverIntervalMinutes: 10 } : {}),
});
this.notify.success(
next
? "Reminder will repeat every 10 minutes (testing)."
: "Reminder will repeat daily (24h).",
TIMEOUTS.STANDARD,
);
} catch (err) {
logger.error(
"[HelpNotificationsView] Reschedule after fast-rollover toggle failed:",
err,
);
this.notify.error(
"Failed to update reminder interval. Please try again.",
TIMEOUTS.STANDARD,
);
}
}
}
/**
* Generates test web push success message
*
* Creates a dynamic success message based on whether client filtering is skipped.
*
* @param skipFilter - Whether client-side message filtering was skipped
* @returns Formatted success message string
*/
private getTestWebPushSuccessMessage(skipFilter: boolean): string {
return (
NOTIFY_TEST_WEB_PUSH_SUCCESS.message +
(skipFilter ? "." : " if there are new items in your feed.")
);
}
private parseTimeTo24Hour(timeStr: string): string {
const timeMatch = timeStr.match(/(\d+):(\d+)\s*(AM|PM)/i);
if (!timeMatch) {
return "09:00";
}
/**
* Generates test notification success message
*
* Creates a dynamic success message with the notification title inserted.
*
* @param title - The title of the test notification
* @returns Formatted success message string
*/
private getTestNotificationSuccessMessage(title: string): string {
return NOTIFY_TEST_NOTIFICATION_SUCCESS.message.replace("{title}", title);
let hour = parseInt(timeMatch[1], 10);
const minute = timeMatch[2];
const isAm = timeMatch[3].toUpperCase() === "AM";
if (isAm && hour === 12) {
hour = 0;
} else if (!isAm && hour !== 12) {
hour = hour + 12;
}
return `${hour.toString().padStart(2, "0")}:${minute}`;
}
}
</script>

View File

@@ -4,20 +4,7 @@ This directory contains the automated end-to-end test suite for Time Safari usin
## Test Structure
Tests are organized by feature area and numbered for execution order:
- `00-noid-tests.spec.ts` - Tests for unregistered users
- `05-invite.spec.ts` - Contact invitation functionality
- `10-check-usage-limits.spec.ts` - Usage limit verification
- `20-create-project.spec.ts` - Project creation
- `25-create-project-x10.spec.ts` - Bulk project creation
- `30-record-gift.spec.ts` - Gift recording
- `33-record-gift-x10.spec.ts` - Bulk gift recording
- `35-record-gift-from-image-share.spec.ts` - Gift recording from shared images
- `37-record-gift-on-project.spec.ts` - Project-specific gift recording
- `40-add-contact.spec.ts` - Contact management
- `50-record-offer.spec.ts` - Offer recording
- `60-new-activity.spec.ts` - Activity feed updates
Tests are organized by feature area and numbered for execution order.
## Key Files

View File

@@ -138,12 +138,12 @@ await page.waitForFunction(() => {
3. If you find yourself wanting to see the testing process try something like this:
```
npx playwright test -c playwright.config-local.ts test-playwright/60-new-activity.spec.ts --grep "New offers for another user" --headed
npx playwright test -c playwright.config-local.ts test-playwright/40-add-contact.spec.ts --grep "New offers for another user" --headed
```
This command allows you to:
- **Run a specific test file**: `test-playwright/60-new-activity.spec.ts`
- **Run a specific test file**: `test-playwright/40-add-contact.spec.ts`
- **Filter to a specific test**: `--grep "New offers for another user"` runs only tests with that name
- **See the browser**: `--headed` opens the browser window so you can watch the test execute
- **Use local config**: `-c playwright.config-local.ts` uses the local configuration file