Skip to content

Commit

Permalink
fix: sync native PushSubscription to store, localizations, misc fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
th0rgall committed Oct 5, 2023
1 parent 5891663 commit 0fe53cc
Show file tree
Hide file tree
Showing 13 changed files with 171 additions and 74 deletions.
17 changes: 16 additions & 1 deletion src/lib/api/push-registrations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,11 @@ import {
type FirebasePushRegistration,
type LocalPushRegistration
} from '$lib/types/PushRegistration';
import { loadedPushRegistrations, pushRegistrations } from '$lib/stores/pushRegistrations';
import {
currentNativeSubStore,
loadedPushRegistrations,
pushRegistrations
} from '$lib/stores/pushRegistrations';
import removeUndefined from '$lib/util/remove-undefined';
import { get } from 'svelte/store';
import isFirebaseError from '$lib/util/types/isFirebaseError';
Expand Down Expand Up @@ -64,6 +68,7 @@ const unsubscribeNativePushRegistration = async () => {
const success = await fullNativeSub?.unsubscribe();
if (success) {
console.log('Unregistered (in FB) local native PushSubscription sucessfully unsubscribed.');
currentNativeSubStore.set(null);
return true;
} else {
console.warn(
Expand Down Expand Up @@ -203,8 +208,10 @@ export const getCurrentNativeSubscription = async () => {
);
// Empirically: iOS Safari may give an empty object, instead of null, when no registration exists.
if (isEmpty(sub)) {
currentNativeSubStore.set(null);
return null;
}
currentNativeSubStore.set(sub);
return sub;
};

Expand Down Expand Up @@ -340,6 +347,7 @@ const subscribeOrRefreshMessaging = async () => {
// Endpoints should uniquely identify a subscription.
// https://stackoverflow.com/questions/63767889/is-it-safe-to-use-the-p256dh-or-endpoint-keys-values-of-the-push-notificatio/63769192#63769192
const subscriptionObject = await getSubscriptionFromSW(serviceWorkerRegistration);
currentNativeSubStore.set(subscriptionObject);
if (!subscriptionObject) {
throw new Error(
'Could unexpectedly not retrieve the native Push Subscription object of an existing FCM registration'
Expand Down Expand Up @@ -480,6 +488,7 @@ export const deletePushRegistration = async (pushRegistration: LocalPushRegistra
if (success) {
try {
console.log('Successfully deleted/unsubscribed the current FCM registration.');
currentNativeSubStore.set(null);
await deletePushRegistrationDoc(pushRegistration);
return true;
} catch (e) {
Expand Down Expand Up @@ -508,6 +517,12 @@ export const deletePushRegistration = async (pushRegistration: LocalPushRegistra
}
};

export const isOnIDevicePWA = () => {
const { isIDevice, iDeviceVersion } = iDeviceInfo!;
// The last version check is probably redundant
return hasNotificationSupportNow() && isIDevice && iDeviceVersion! >= 16.4;
};

/**
* @returns a PushRegistrationJSON object if one exists, null if none exists
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,12 @@
then we'd also get the fade-out effect
-->
<Modal center on:close={() => close()}>
<h3 slot="title">{$_('push-notifications.prompt.ios-installed-title')}</h3>
<div slot="body">
<p>{@html $_('banners.notifications.ios-installed')}</p>
<p>{@html $_('push-notifications.prompt.ios-installed')}</p>
<div class="buttons">
<Button xsmall on:click={action}>
{$_('banners.notifications.btn-yes')}
<Button small fullWidth on:click={action}>
{$_('push-notifications.prompt.btn-turn-on')}
</Button>
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
<!-- If the device is not clearly a mobile or tablet device,
show instructions on how to proceed -->
<!-- https://github.com/faisalman/ua-parser-js/issues/182#issuecomment-263115448 -->
{@html $_('push-notifications.prompt.garden-follow-up-desktop')}
{@html $_('push-notifications.prompt.follow-up-desktop')}
{:else if is_16_4_OrAboveIDevice && !hasNotificationSupportNow()}
<!-- State that mobile notifications are definitely possible -->
<IosBrowserSteps />
Expand Down Expand Up @@ -65,10 +65,6 @@
</Modal>

<style>
section {
padding: 4rem 2rem;
}
.upgrade-btns > :global(*:first-child) {
margin-top: 1rem;
margin-bottom: 1rem;
Expand Down
8 changes: 5 additions & 3 deletions src/lib/stores/pushRegistrations.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import type { LocalPushRegistration } from '$lib/types/PushRegistration';
import type { PushSubscriptionPOJO } from '$lib/api/push-registrations';
import { writable } from 'svelte/store';

export const pushRegistrations = writable<LocalPushRegistration[]>([]);
export const loadedPushRegistrations = writable(false);
export const currentNativeSubStore = writable<PushSubscriptionPOJO | null>(null);

export const resetPushRegistrationStores = () => {
pushRegistrations.set([])
loadedPushRegistrations.set(false)
}
pushRegistrations.set([]);
loadedPushRegistrations.set(false);
};
4 changes: 3 additions & 1 deletion src/lib/util/uaInfo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,13 @@ import { UAParser } from 'ua-parser-js';

export const uaInfo = browser ? UAParser(navigator.userAgent) : undefined;

export const isIDeviceF = (osName: string) => /iOS|iPadOS/.test(osName);

export const iDeviceInfo = browser
? (() => {
// TODO: wasn't the iPad Pro masquerading as a Mac?
const ua = uaInfo!;
const isIDevice = /iOS|iPadOS/.test(ua.os.name ?? '');
const isIDevice = isIDeviceF(ua.os.name ?? '');
const versionString = ua.os.version ?? ua.browser.version ?? null;
const iDeviceVersion = versionString ? Number.parseFloat(versionString) : null;
// note: os.name is not reliable
Expand Down
30 changes: 13 additions & 17 deletions src/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -1029,8 +1029,11 @@
"delete": "Delete",
"turn-on": "Turn on notifications",
"unknown": "unknown",
"current": "Current",
"last-seen": "Last seen on"
"current": "Current device",
"last-seen": "Last seen on",
"unsupported": "It looks like this device doesn't support Web Push, which is required for mobile WTMG notifications. On Android you can try a different or newer browser. On iOS you can check {link} to iOS/iPadOS 16.4 or higher.",
"ios16-check": "if you can update your device",
"ios16-link": "https://support.apple.com/en-us/HT213411"
}
},
"auth": {
Expand Down Expand Up @@ -1485,26 +1488,19 @@
"donate": "Donate"
}
},
"banners": {
"notifications": {
"show-how": "Show me how",
"title": "Get a mobile notification when you receive a message",
"ios-installed": "<p>It looks like you added WTMG to your home screen, nice!</p><p>Now you can turn on notifications.</p>",
"btn-yes": "Yes, turn on notifications",
"btn-no": "No thanks"
},
"tip": "Tip from WTMG"
},
"push-notifications": {
"registration-success": "Notifications were successfully enabled!",
"registration-success": "Notifications were successfully turned on",
"prompt": {
"title": "Want to receive notifications on your phone?",
"title": "Get a mobile notification when you receive a message",
"garden-intro": "You will automatically receive an email for each new request to stay in your garden",
"garden-follow-up-desktop": ". Would you also like to receive <strong>mobile notifications</strong> for new chat messages?",
"garden-follow-up": ", and you can also get <strong>mobile notifications</strong>.",
"garden-enable": "Would you also like to receive <strong>mobile notifications</strong> for new chat messages?",
"garden-ios-home": "To turn on just <strong>add</strong> the <strong>WTMG</strong> website to your <strong>home screen</strong> in a few easy steps.",
"btn-show-me": "Show me how"
"ios-installed": "<p>It looks like you added WTMG to your home screen, nice!</p><p>Now you can turn on notifications.</p>",
"ios-installed-title": "Almost there!",
"btn-show-me": "Show me how",
"btn-turn-on": "Turn on notifications",
"follow-up-desktop": "Would yo like to receive <strong>mobile notifications</strong> for new chat messages?"
},
"how-to": {
"title": "How to turn on notifications",
Expand All @@ -1524,7 +1520,7 @@
"1-firefox": "Click on the <em>menu</em> {burgerIcon} (the small icon from Firefox, <em>not</em> the bigger WTMG menu) → “<em>Share</em>” {shareIcon} → “<em>Add to your Home Screen</em>” {plusSquareIcon}."
},
"questions": "Any questions? Check our {guideLink}.",
"questions-link-text": "guide"
"questions-link-text": "full guide"
}
}
}
42 changes: 42 additions & 0 deletions src/locales/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -1015,6 +1015,18 @@
},
"button-label": "Changer votre email"
}
},
"notifications": {
"delete": "Supprimer",
"last-seen": "Dernière visite le",
"unknown": "inconnu",
"unsupported": "Il semble que cet appareil ne soit pas compatible avec la technologie que nous utilisons pour les notifications WTMG. Sur Android, essayez un autre navigateur. Sur iOS (iPhone), mettez à jour votre iOS (16.4 ou plus) {link}.",
"ios16-link": "https://support.apple.com/fr-be/HT213411",
"ios16-check": "si votre appareil le permet",
"current": "Cet appareil",
"turn-on": "Activez les notifications",
"title": "Notifications mobiles",
"manage": "Vous pouvez gérer vos notifications mobiles ici."
}
},
"auth": {
Expand Down Expand Up @@ -1461,5 +1473,35 @@
},
"donate": "Faire un don"
}
},
"push-notifications": {
"registration-success": "Les notifications ont été activées avec succès",
"how-to": {
"questions": "Des questions ? Consultez notre {guideLink}.",
"questions-link-text": "guide",
"ios-browser-steps": {
"1": "Ajoutez WTMG sur votre Écran d'accueil.",
"2": "Ouvrez l’application WTMG.",
"3": "Connectez-vous à votre compte et activez les notifications.",
"1-chrome": "Cliquez sur “<em>Partager</em>” {shareIcon} (en haut à droite) → “<em>Ajouter sur Écran d'accueil</em>” {plusSquareIcon}.",
"1-firefox": "Cliquez sur le <em>menu</em> {burgerIcon} (⚠️ la petite icône de Firefox, <em>pas</em> le menu de WTMG) → “<em>Partager</em>” {shareIcon} → “<em>Ajouter sur Écran d'accueil</em>” {plusSquareIcon}.",
"1-safari": "Cliquez “Partager” {shareIcon} dans le menu ci-dessous, puis “<em>Ajouter sur Écran d'accueil</em>” {plusSquareIcon}."
},
"ios-upgrade": {
"account-settings": "compte WTMG",
"copy": "<p>Pour activer les notifications, vous devez d’abord <strong>mettre à jour votre {os} à 16.4 ou plus </strong>.</p>\n<p><a class=\"link\" href=\"{link}\" target=\"_blank\"> Apprenez comment mettre à jour votre version {os}.</a></p>\n<p>Après avoir fait la mise à jour, allez dans votre {accountSettings} pour activer les notifications mobiles.</p>",
"btn-show": "Montrez-moi comment faire la mise à jour",
"btn-skip": "Passer pour le moment",
"help-link": "https://support.apple.com/fr-be/HT204204"
}
},
"prompt": {
"follow-up-desktop": "Voulez-vous recevoir des <strong>notifications mobiles</strong> lorsque vous recevez un nouveau message ?",
"btn-show-me": "Montrez-moi comment",
"btn-turn-on": "Activez les notifications",
"ios-installed": "<p>Il semble que vous ayez ajouté WTMG sur votre écran d’accueil, génial !</p><p>Vous pouvez maintenant activer les notifications mobiles.</p>",
"ios-installed-title": "Vous y êtes presque !",
"title": "Recevez une notification mobile lorsque vous recevez un message"
}
}
}
42 changes: 42 additions & 0 deletions src/locales/nl.json
Original file line number Diff line number Diff line change
Expand Up @@ -632,6 +632,18 @@
},
"button-label": "Verander je emailadres"
}
},
"notifications": {
"delete": "Verwijder",
"last-seen": "Laatst gezien op",
"unknown": "onbekend",
"unsupported": "Het lijkt erop dat dit apparaat geen Web Push ondersteunt, wat vereist is voor mobiele meldingen van WTMG. Op Android kan je een andere of nieuwere browser proberen. Op iOS kan je kijken {link} naar iOS/iPadOS 16.4 of hoger. ",
"ios16-link": "https://support.apple.com/nl-be/HT213411",
"ios16-check": "of je kan updaten",
"current": "Dit apparaat",
"title": "Mobiele meldingen",
"manage": "Je kan hier je mobiele meldingen beheren.",
"turn-on": "Zet meldingen aan"
}
},
"auth": {
Expand Down Expand Up @@ -1465,5 +1477,35 @@
},
"donate": "Doneer"
}
},
"push-notifications": {
"registration-success": "Meldingen zijn succesvol aangezet",
"how-to": {
"questions": "Vragen? Bekijk onze {guideLink}.",
"questions-link-text": "volledige gids",
"ios-browser-steps": {
"1": "Zet WTMG op je beginscherm.",
"2": "Open de WTMG app.",
"3": "Meld je aan en zet meldingen aan.",
"1-chrome": "Druk op “<em>Deel</em>” {shareIcon} (rechtsboven) → “<em>Zet op je Beginscherm</em>” {plusSquareIcon}.",
"1-firefox": "Druk op het <em>menu</em> {burgerIcon} (⚠️ het kleine icoontje van Firefox, <em>niet</em> het grotere menu van de WTMG site) → “<em>Deel</em>” {shareIcon} → “<em>Zet op je Beginscherm</em>” {plusSquareIcon}.",
"1-safari": "Druk op “Deel” {shareIcon} in de menubalk hieronder, en dan op “<em>Zet op je Beginscherm</em>” {plusSquareIcon}."
},
"ios-upgrade": {
"account-settings": "WTMG accountinstellingen",
"copy": "<p>Om meldingen aan te zetten moet je eerst <strong>updaten naar {os} 16.4 or hoger</strong>.</p>\n<p><a class=\"link\" href=\"{link}\" target=\"_blank\">Leer hoe je je {os} versie bijwerkt.</a></p>\n<p>Ga na de update naar je {accountSettings} om meldingen aan te zetten.</p>",
"btn-show": "Toon hoe bij te werken",
"btn-skip": "Sla voorlopig over",
"help-link": "https://support.apple.com/nl-be/HT204204"
}
},
"prompt": {
"btn-show-me": "Toon me hoe",
"btn-turn-on": "Zet meldingen aan",
"follow-up-desktop": "Wil je <strong>mobiele meldingen</strong> ontvangen voor nieuwe chatberichten?",
"ios-installed": "<p>Het lijkt erop dat je WTMG aan je startscherm hebt toegevoegd, leuk!</p><p>Nu kan je meldingen aanzetten.</p>",
"ios-installed-title": "Je bent er bijna!",
"title": "Krijg een mobiele melding wanneer je een bericht ontvangt"
}
}
}
18 changes: 8 additions & 10 deletions src/routes/+layout.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,11 @@
import {
createPushRegistrationObserver,
getCurrentNativeSubscription,
hasNotificationSupportNow
isOnIDevicePWA
} from '$lib/api/push-registrations';
import { iDeviceInfo } from '$lib/util/uaInfo';
import { NOTIFICATION_PROMPT_DISMISSED_COOKIE } from '$lib/constants';
import { resetPushRegistrationStores } from '$lib/stores/pushRegistrations';
import { goto } from '$lib/util/navigate';
type MaybeUnsubscriberFunc = (() => void) | undefined;
Expand Down Expand Up @@ -118,23 +118,18 @@
// registrations
// TODO: check if this loads after loading pre-existing push registrations?
// TODO: make this influence dismissal somehow?
const { isIDevice, iDeviceVersion } = iDeviceInfo!;
const notificationsDismissed = getCookie(NOTIFICATION_PROMPT_DISMISSED_COOKIE);
const currentNativeSub = await getCurrentNativeSubscription();
if (
// Prevent the modal from being shown twice in the same boot session (we might get multiple user updates)
!hasShownIOSNotificationsModal &&
// We're logged in...
latestUser !== null &&
// ... Web Push is supported (redundant with getCurrentNativeSubscription, but just to protect against refactors...)
hasNotificationSupportNow() &&
// ... the browser has no native sub registered (but support exists)
currentNativeSub === null &&
(await getCurrentNativeSubscription()) === null &&
// ... the user hasn't dismissed notifications
notificationsDismissed !== 'true' &&
// ... we're on a supporting iOS version (preventing this from appearing on Android/... browsers)
isIDevice &&
iDeviceVersion! >= 16.4
// ... we're on the PWA of a supporting iOS version (preventing this from appearing on Android/... browsers)
isOnIDevicePWA()
) {
rootModal.set(IosNotificationPrompt);
hasShownIOSNotificationsModal = true;
Expand Down Expand Up @@ -168,6 +163,9 @@
if (!unsubscribeFromAuthObserver) {
unsubscribeFromAuthObserver = createAuthObserver();
}
if (isOnIDevicePWA()) {
goto(routes.SIGN_IN);
}
vh = `${window.innerHeight * 0.01}px`;
});
Expand Down
Loading

0 comments on commit 0fe53cc

Please sign in to comment.