From 97ef88ec1018b849b4a5963bfc85419a4dfc4dec Mon Sep 17 00:00:00 2001 From: "Luna D." Date: Sun, 23 Jun 2024 19:21:24 +0200 Subject: [PATCH] convert notifications to typescript --- .../js/{notifications.js => notifications.ts} | 40 +++++++++---------- assets/js/utils/events.ts | 5 ++- assets/js/utils/store.ts | 4 +- 3 files changed, 25 insertions(+), 24 deletions(-) rename assets/js/{notifications.js => notifications.ts} (56%) diff --git a/assets/js/notifications.js b/assets/js/notifications.ts similarity index 56% rename from assets/js/notifications.js rename to assets/js/notifications.ts index 2447debb..d76cf533 100644 --- a/assets/js/notifications.js +++ b/assets/js/notifications.ts @@ -5,19 +5,17 @@ import { fetchJson, handleError } from './utils/requests'; import { $ } from './utils/dom'; import { delegate } from './utils/events'; +import { assertNotNull, assertNotUndefined } from './utils/assert'; import store from './utils/store'; const NOTIFICATION_INTERVAL = 600000, NOTIFICATION_EXPIRES = 300000; -function makeRequest(verb) { - return fetchJson(verb, '/notifications/unread').then(handleError); -} - function bindSubscriptionLinks() { delegate(document, 'fetchcomplete', { '.js-subscription-link': event => { - const target = event.target.closest('.js-subscription-target'); + const target = assertNotNull(event.target.closest('.js-subscription-target')); + event.detail.text().then(text => { target.outerHTML = text; }); @@ -30,42 +28,42 @@ function getNewNotifications() { return; } - makeRequest('GET').then(response => response.json()).then(({ notifications }) => { - updateNotificationTicker(notifications); - storeNotificationCount(notifications); + fetchJson('GET', '/notifications/unread') + .then(handleError) + .then(response => response.json()) + .then(({ notifications }) => { + updateNotificationTicker(notifications); + storeNotificationCount(notifications); - setTimeout(getNewNotifications, NOTIFICATION_INTERVAL); - }); + setTimeout(getNewNotifications, NOTIFICATION_INTERVAL); + }); } -function updateNotificationTicker(notificationCount) { - const ticker = $('.js-notification-ticker'); +function updateNotificationTicker(notificationCount: string | null) { + const ticker = assertNotNull($('.js-notification-ticker')); const parsedNotificationCount = Number(notificationCount); - ticker.dataset.notificationCount = parsedNotificationCount; - ticker.textContent = parsedNotificationCount; + ticker.dataset.notificationCount = parsedNotificationCount.toString(); + ticker.textContent = parsedNotificationCount.toString(); } - -function storeNotificationCount(notificationCount) { +function storeNotificationCount(notificationCount: string) { // The current number of notifications are stored along with the time when the data expires store.setWithExpireTime('notificationCount', notificationCount, NOTIFICATION_EXPIRES); } - -function setupNotifications() { +export function setupNotifications() { if (!window.booru.userIsSignedIn) return; // Fetch notifications from the server at a regular interval setTimeout(getNewNotifications, NOTIFICATION_INTERVAL); // Update the current number of notifications based on the latest page load - storeNotificationCount($('.js-notification-ticker').dataset.notificationCount); + const ticker = assertNotNull($('.js-notification-ticker')); + storeNotificationCount(assertNotUndefined(ticker.dataset.notificationCount)); // Update ticker when the stored value changes - this will occur in all open tabs store.watch('notificationCount', updateNotificationTicker); bindSubscriptionLinks(); } - -export { setupNotifications }; diff --git a/assets/js/utils/events.ts b/assets/js/utils/events.ts index 65c2c496..e92b0109 100644 --- a/assets/js/utils/events.ts +++ b/assets/js/utils/events.ts @@ -1,5 +1,7 @@ // DOM events +import '../../types/ujs'; + export interface PhilomenaAvailableEventsMap { dragstart: DragEvent, dragover: DragEvent, @@ -9,7 +11,8 @@ export interface PhilomenaAvailableEventsMap { drop: DragEvent, click: MouseEvent, submit: Event, - reset: Event + reset: Event, + fetchcomplete: FetchcompleteEvent } export interface PhilomenaEventElement { diff --git a/assets/js/utils/store.ts b/assets/js/utils/store.ts index c09a09ce..a71d4256 100644 --- a/assets/js/utils/store.ts +++ b/assets/js/utils/store.ts @@ -38,9 +38,9 @@ export default { }, // Watch changes to a specified key - returns value on change - watch(key: string, callback: (value: unknown) => void) { + watch(key: string, callback: (value: Value | null) => void) { const handler = (event: StorageEvent) => { - if (event.key === key) callback(this.get(key)); + if (event.key === key) callback(this.get(key)); }; window.addEventListener('storage', handler); return () => window.removeEventListener('storage', handler);