aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorFuwn <[email protected]>2024-07-08 19:11:47 -0700
committerFuwn <[email protected]>2024-07-08 19:11:47 -0700
commite1af2369964e0e5eed8fed9d86a89b8547559251 (patch)
treebe70168527a44596b18a4d59142a48a6d4b52386 /src
parentfeat(manifest.json): add orientation (diff)
downloaddue.moe-e1af2369964e0e5eed8fed9d86a89b8547559251.tar.xz
due.moe-e1af2369964e0e5eed8fed9d86a89b8547559251.zip
feat(pwa): anilist notifications
Diffstat (limited to 'src')
-rw-r--r--src/lib/Locale/english.ts3
-rw-r--r--src/lib/Locale/japanese.ts3
-rw-r--r--src/lib/Locale/layout.ts1
-rw-r--r--src/lib/Settings/Categories/Display.svelte15
-rw-r--r--src/routes/+layout.svelte42
-rw-r--r--src/service-worker.ts17
-rw-r--r--src/stores/settings.ts2
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,