diff options
| author | Fuwn <[email protected]> | 2024-07-08 19:11:47 -0700 |
|---|---|---|
| committer | Fuwn <[email protected]> | 2024-07-08 19:11:47 -0700 |
| commit | e1af2369964e0e5eed8fed9d86a89b8547559251 (patch) | |
| tree | be70168527a44596b18a4d59142a48a6d4b52386 /src | |
| parent | feat(manifest.json): add orientation (diff) | |
| download | due.moe-e1af2369964e0e5eed8fed9d86a89b8547559251.tar.xz due.moe-e1af2369964e0e5eed8fed9d86a89b8547559251.zip | |
feat(pwa): anilist notifications
Diffstat (limited to 'src')
| -rw-r--r-- | src/lib/Locale/english.ts | 3 | ||||
| -rw-r--r-- | src/lib/Locale/japanese.ts | 3 | ||||
| -rw-r--r-- | src/lib/Locale/layout.ts | 1 | ||||
| -rw-r--r-- | src/lib/Settings/Categories/Display.svelte | 15 | ||||
| -rw-r--r-- | src/routes/+layout.svelte | 42 | ||||
| -rw-r--r-- | src/service-worker.ts | 17 | ||||
| -rw-r--r-- | src/stores/settings.ts | 2 |
7 files changed, 79 insertions, 4 deletions
diff --git a/src/lib/Locale/english.ts b/src/lib/Locale/english.ts index 509ebca0..2b9d1c3e 100644 --- a/src/lib/Locale/english.ts +++ b/src/lib/Locale/english.ts @@ -75,7 +75,8 @@ const English: Locale = { title: 'Motion & Accessibility', fields: { disablePageTransitionAnimations: 'Disable page transition animations', - disableNotifications: 'Disable notifications', + disableNotifications: 'Disable verbose site notifications', + disableAniListNotifications: 'Disable AniList notifications', limitPanelAreaToScreenHeight: 'Limit panel area to screen height', interfaceLanguage: 'Interface language' } diff --git a/src/lib/Locale/japanese.ts b/src/lib/Locale/japanese.ts index 089946ef..cc094e07 100644 --- a/src/lib/Locale/japanese.ts +++ b/src/lib/Locale/japanese.ts @@ -76,7 +76,8 @@ const Japanese: Locale = { title: 'モーションとアクセシビリティ', fields: { disablePageTransitionAnimations: 'ページ遷移アニメーションを無効にする', - disableNotifications: '通知を無効にする', + disableNotifications: '詳細なサイト通知を無効にする', + disableAniListNotifications: 'AniListの通知を無効にする', limitPanelAreaToScreenHeight: 'メディアパネルの面積をスクリーンの高さに制限する', interfaceLanguage: 'インターフェース言語' } diff --git a/src/lib/Locale/layout.ts b/src/lib/Locale/layout.ts index 4fea935a..081926fd 100644 --- a/src/lib/Locale/layout.ts +++ b/src/lib/Locale/layout.ts @@ -78,6 +78,7 @@ export interface Locale { fields: { disablePageTransitionAnimations: LocaleValue; disableNotifications: LocaleValue; + disableAniListNotifications: LocaleValue; limitPanelAreaToScreenHeight: LocaleValue; interfaceLanguage: LocaleValue; }; diff --git a/src/lib/Settings/Categories/Display.svelte b/src/lib/Settings/Categories/Display.svelte index 0b23904b..76337b58 100644 --- a/src/lib/Settings/Categories/Display.svelte +++ b/src/lib/Settings/Categories/Display.svelte @@ -185,6 +185,21 @@ <p /> +<SettingCheckboxToggle + setting="displayAniListNotifications" + text={$locale().settings.display.categories.motionAndAccessibility.fields + .disableAniListNotifications} +> + <SettingHint lineBreak> + Periodically check and display recent AniList notifications as a native platform notification + <br /> + This may be useful for users who have installed due.moe as a PWA or on mobile devices, since AniList + has no official mobile app. + </SettingHint> +</SettingCheckboxToggle> + +<p /> + <b>{$locale().settings.display.categories.dateAndTime.title}</b><br /> <SettingCheckboxToggle setting="displayCountdownRightAligned" diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte index 1c849fca..a34b24b1 100644 --- a/src/routes/+layout.svelte +++ b/src/routes/+layout.svelte @@ -11,7 +11,7 @@ import { readable, type Readable } from 'svelte/store'; import { navigating } from '$app/stores'; import Notifications from 'svelte-notifications'; - import Notification from '$lib/Notification/Notification.svelte'; + import * as EventNotification from '$lib/Notification/Notification.svelte'; import Root from '$lib/Home/Root.svelte'; import root from '$lib/Utility/root'; import { addMessages, init, locale as i18nLocale, locales } from 'svelte-i18n'; @@ -28,6 +28,7 @@ import settingsSyncTimes from '$stores/settingsSyncTimes'; import Announcement from '$lib/Announcement.svelte'; import Message from '$lib/Loading/Message.svelte'; + import { notifications } from '$lib/Data/AniList/notifications'; injectSpeedInsights(); @@ -35,6 +36,8 @@ let isHeaderVisible = true; let previousScrollPosition = 0; + let notificationInterval: NodeJS.Timeout | undefined = undefined; + let lastNotificationId = 0; addMessages('en', english as unknown as LocaleDictionary); addMessages('ja', japanese as unknown as LocaleDictionary); @@ -106,10 +109,45 @@ } }); }); + + if ($settings.displayAniListNotifications && data.user !== undefined) { + if ('Notification' in window && navigator.serviceWorker) Notification.requestPermission(); + + if (window.matchMedia('(display-mode: standalone)').matches) { + notificationInterval = setInterval(async () => { + try { + const recentNotifications = await notifications(data.user.accessToken); + + if ( + recentNotifications && + recentNotifications.length > 0 && + recentNotifications[0].id > lastNotificationId && + new Date(recentNotifications[0].createdAt * 1000).getTime() + 30000 > + new Date().getTime() + ) { + lastNotificationId = recentNotifications[0].id; + + if ('serviceWorker' in navigator && navigator.serviceWorker.controller) { + navigator.serviceWorker.ready.then((registration) => { + registration.showNotification('due.moe', { + body: `${recentNotifications[0].user.name}${recentNotifications[0].context}`, + icon: recentNotifications[0].user.avatar.large || '/favicon-196x196.png' + }); + }); + } + } + } catch (error) { + console.error(error); + } + }, 15000); + } + } }); onDestroy(() => { if (browser) window.removeEventListener('scroll', handleScroll); + + if (notificationInterval) clearInterval(notificationInterval); }); $: { @@ -229,7 +267,7 @@ <p /> - <Notifications item={Notification} zIndex={5000}> + <Notifications item={EventNotification} zIndex={5000}> <Root {data} {way}> {#if $userIdentity.id !== -1} <slot /> diff --git a/src/service-worker.ts b/src/service-worker.ts index b1dcc3b3..7d2310f6 100644 --- a/src/service-worker.ts +++ b/src/service-worker.ts @@ -89,3 +89,20 @@ self.addEventListener('fetch', (event) => { event.respondWith(respond()); }); + +self.addEventListener('push', (e: Event) => { + if (!(self.Notification && self.Notification.permission === 'granted')) { + return; + } + + const event = e as PushEvent; + + if (event.data) { + event.waitUntil( + (self as unknown as ServiceWorkerGlobalScope).registration.showNotification('due.moe', { + body: event.data.json().url, + icon: '/favicon-196x196.png' + }) + ); + } +}); diff --git a/src/stores/settings.ts b/src/stores/settings.ts index 7dfd6e4a..37558cba 100644 --- a/src/stores/settings.ts +++ b/src/stores/settings.ts @@ -60,6 +60,7 @@ export interface Settings { displayBlurAdultContent: boolean; displayCopyMediaTitleNotLink: boolean; displayTotalDueEpisodes: boolean; + displayAniListNotifications: boolean; } const defaultSettings: Settings = { @@ -98,6 +99,7 @@ const defaultSettings: Settings = { displayBlurAdultContent: true, displayCopyMediaTitleNotLink: false, displayTotalDueEpisodes: false, + displayAniListNotifications: false, // Calculation calculateChaptersRoundedDown: true, |