diff --git a/web/index.html b/web/index.html index c714263c..5c26ff1c 100644 --- a/web/index.html +++ b/web/index.html @@ -1,4 +1,4 @@ - + diff --git a/web/public/static/css/fonts.css b/web/public/static/css/fonts.css index 2cf00a3c..1fd7c607 100644 --- a/web/public/static/css/fonts.css +++ b/web/public/static/css/fonts.css @@ -5,7 +5,9 @@ font-family: "Roboto"; font-style: normal; font-weight: 300; - src: local(""), url("../fonts/roboto-v29-latin-300.woff2") format("woff2"); + src: + local(""), + url("../fonts/roboto-v29-latin-300.woff2") format("woff2"); } /* roboto-regular - latin */ @@ -13,7 +15,9 @@ font-family: "Roboto"; font-style: normal; font-weight: 400; - src: local(""), url("../fonts/roboto-v29-latin-regular.woff2") format("woff2"); + src: + local(""), + url("../fonts/roboto-v29-latin-regular.woff2") format("woff2"); } /* roboto-500 - latin */ @@ -21,7 +25,9 @@ font-family: "Roboto"; font-style: normal; font-weight: 500; - src: local(""), url("../fonts/roboto-v29-latin-500.woff2") format("woff2"); + src: + local(""), + url("../fonts/roboto-v29-latin-500.woff2") format("woff2"); } /* roboto-700 - latin */ @@ -29,5 +35,7 @@ font-family: "Roboto"; font-style: normal; font-weight: 700; - src: local(""), url("../fonts/roboto-v29-latin-700.woff2") format("woff2"); + src: + local(""), + url("../fonts/roboto-v29-latin-700.woff2") format("woff2"); } diff --git a/web/public/sw.js b/web/public/sw.js index 0ace286e..1c0235d3 100644 --- a/web/public/sw.js +++ b/web/public/sw.js @@ -61,7 +61,7 @@ const handlePushMessage = async (data) => { topicRoute: new URL(message.topic, self.location.origin).toString(), baseUrl: subscription.baseUrl, topic: subscription.topic, - }) + }), ); // Delete existing notification with same sequence ID (if any) @@ -417,7 +417,7 @@ self.addEventListener("notificationclick", (event) => { // [{"revision":"aaabbbcccdddeeefff12345","url":"/index.html"},...] precacheAndRoute( // eslint-disable-next-line no-underscore-dangle - self.__WB_MANIFEST + self.__WB_MANIFEST, ); // Claim all open windows @@ -441,7 +441,7 @@ if (!import.meta.env.DEV) { // the app root itself, could be /, or not new RegExp(`^${config.app_root}$`), ], - }) + }), ); // the manifest excludes config.js (see vite.config.js) since the dist-file differs from the diff --git a/web/src/app/AccountApi.test.js b/web/src/app/AccountApi.test.js index 9fb16c54..79348c2c 100644 --- a/web/src/app/AccountApi.test.js +++ b/web/src/app/AccountApi.test.js @@ -65,7 +65,7 @@ describe("AccountApi.create", () => { await accountApi.create("phil", "pw"); expect(fetchMock).toHaveBeenCalledWith( "https://ntfy.sh/v1/account", - expect.objectContaining({ method: "POST", body: JSON.stringify({ username: "phil", password: "pw", email: "" }) }) + expect.objectContaining({ method: "POST", body: JSON.stringify({ username: "phil", password: "pw", email: "" }) }), ); }); }); @@ -195,7 +195,7 @@ describe("AccountApi.sync", () => { notification: { sound: "ding", delete_after: 3600, min_priority: 3 }, subscriptions: [{ topic: "t" }], reservations: [{ topic: "t" }], - }) + }), ); await accountApi.sync(); diff --git a/web/src/app/Api.test.js b/web/src/app/Api.test.js index 29e55994..42c8639d 100644 --- a/web/src/app/Api.test.js +++ b/web/src/app/Api.test.js @@ -57,7 +57,7 @@ describe("Api.publish", () => { expect.objectContaining({ method: "PUT", body: JSON.stringify({ topic: "mytopic", message: "Hello", priority: 5, tags: ["warning"] }), - }) + }), ); }); @@ -109,7 +109,7 @@ describe("Api web push", () => { expect.objectContaining({ method: "POST", body: JSON.stringify({ endpoint: "https://push.example/abc", auth: "AUTH", p256dh: "P256", topics: ["topicA", "topicB"] }), - }) + }), ); }); @@ -121,7 +121,7 @@ describe("Api web push", () => { expect.objectContaining({ method: "DELETE", body: JSON.stringify({ endpoint: "https://push.example/abc" }), - }) + }), ); }); }); diff --git a/web/src/app/Connection.js b/web/src/app/Connection.js index 8e02d6f7..27e8c7d9 100644 --- a/web/src/app/Connection.js +++ b/web/src/app/Connection.js @@ -67,7 +67,7 @@ class Connection { this.ws.onclose = (event) => { if (event.wasClean) { console.log( - `[Connection, ${this.shortUrl}, ${this.connectionId}] Connection closed cleanly, code=${event.code} reason=${event.reason}` + `[Connection, ${this.shortUrl}, ${this.connectionId}] Connection closed cleanly, code=${event.code} reason=${event.reason}`, ); this.ws = null; } else { diff --git a/web/src/app/ConnectionManager.js b/web/src/app/ConnectionManager.js index 32ffe807..2b3c638e 100644 --- a/web/src/app/ConnectionManager.js +++ b/web/src/app/ConnectionManager.js @@ -70,13 +70,13 @@ class ConnectionManager { user, since, (subId, notification) => this.notificationReceived(subId, notification), - (subId, state) => this.stateChanged(subId, state) + (subId, state) => this.stateChanged(subId, state), ); this.connections.set(connectionId, connection); console.log( `[ConnectionManager] Starting new connection ${connectionId} (subscription ${subscriptionId} with user ${ user ? user.username : "anonymous" - })` + })`, ); connection.start(); } diff --git a/web/src/app/Notifier.js b/web/src/app/Notifier.js index e43393a8..5e3b9a60 100644 --- a/web/src/app/Notifier.js +++ b/web/src/app/Notifier.js @@ -30,7 +30,7 @@ class Notifier { topicRoute: new URL(routes.forSubscription(subscription), window.location.origin).toString(), baseUrl: subscription.baseUrl, topic: subscription.topic, - }) + }), ); } diff --git a/web/src/app/Poller.js b/web/src/app/Poller.js index b455a308..534ccead 100644 --- a/web/src/app/Poller.js +++ b/web/src/app/Poller.js @@ -35,7 +35,7 @@ class Poller { } catch (e) { console.log(`[Poller] Error polling ${s.id}`, e); } - }) + }), ); } @@ -61,7 +61,7 @@ class Poller { if (deletedSequenceIds.length > 0) { console.log(`[Poller] Deleting notifications with deleted sequence IDs for ${subscription.id}`, deletedSequenceIds); await Promise.all( - deletedSequenceIds.map((sequenceId) => subscriptionManager.deleteNotificationBySequenceId(subscription.id, sequenceId)) + deletedSequenceIds.map((sequenceId) => subscriptionManager.deleteNotificationBySequenceId(subscription.id, sequenceId)), ); } diff --git a/web/src/app/SubscriptionManager.js b/web/src/app/SubscriptionManager.js index b6e28dbc..9303f1d9 100644 --- a/web/src/app/SubscriptionManager.js +++ b/web/src/app/SubscriptionManager.js @@ -18,7 +18,7 @@ export class SubscriptionManager { subscriptions.map(async (s) => ({ ...s, new: await this.db.notifications.where({ subscriptionId: s.id, new: 1 }).count(), - })) + })), ); } @@ -122,7 +122,7 @@ export class SubscriptionManager { }); return local.id; - }) + }), ); // Remove local subscriptions that do not exist remotely @@ -134,7 +134,7 @@ export class SubscriptionManager { if (!local.internal && !remoteExists) { await this.remove(local); } - }) + }), ); } @@ -144,7 +144,7 @@ export class SubscriptionManager { if (!browserSubscription) { console.log( - "[SubscriptionManager] No browser subscription currently exists, so web push was never enabled or the notification permission was removed. Skipping." + "[SubscriptionManager] No browser subscription currently exists, so web push was never enabled or the notification permission was removed. Skipping.", ); return; } diff --git a/web/src/app/errors.test.js b/web/src/app/errors.test.js index 62a9bd9f..6e2a827f 100644 --- a/web/src/app/errors.test.js +++ b/web/src/app/errors.test.js @@ -56,7 +56,7 @@ describe("throwAppError", () => { await expect(throwAppError(fakeResponse(409, { code: UserExistsError.CODE }))).rejects.toBeInstanceOf(UserExistsError); await expect(throwAppError(fakeResponse(409, { code: TopicReservedError.CODE }))).rejects.toBeInstanceOf(TopicReservedError); await expect(throwAppError(fakeResponse(429, { code: AccountActionLimitReachedError.CODE }))).rejects.toBeInstanceOf( - AccountActionLimitReachedError + AccountActionLimitReachedError, ); }); @@ -78,7 +78,7 @@ describe("fetchOrThrow", () => { const response = { status: 200 }; vi.stubGlobal( "fetch", - vi.fn(async () => response) + vi.fn(async () => response), ); await expect(fetchOrThrow("https://ntfy.sh/mytopic/json")).resolves.toBe(response); }); @@ -86,7 +86,7 @@ describe("fetchOrThrow", () => { it("throws on a non-200 response", async () => { vi.stubGlobal( "fetch", - vi.fn(async () => fakeResponse(401)) + vi.fn(async () => fakeResponse(401)), ); await expect(fetchOrThrow("https://ntfy.sh/mytopic/json")).rejects.toBeInstanceOf(UnauthorizedError); }); diff --git a/web/src/components/App.jsx b/web/src/components/App.jsx index a68d56f7..ea5fbc47 100644 --- a/web/src/components/App.jsx +++ b/web/src/components/App.jsx @@ -130,7 +130,7 @@ const Layout = () => { const [selected] = (subscriptionsWithoutInternal || []).filter( (s) => (params.baseUrl && expandUrl(params.baseUrl).includes(s.baseUrl) && params.topic === s.topic) || - (config.base_url === s.baseUrl && params.topic === s.topic) + (config.base_url === s.baseUrl && params.topic === s.topic), ); useConnectionListeners(account, subscriptions, users, webPushTopics); diff --git a/web/src/components/Notifications.jsx b/web/src/components/Notifications.jsx index 39927e4d..316ebfa6 100644 --- a/web/src/components/Notifications.jsx +++ b/web/src/components/Notifications.jsx @@ -80,7 +80,7 @@ const SingleSubscriptionList = (props) => { // getAllNotifications() filtered by id), so topic switches are instant. const notifications = useMemo( () => allNotifications.filter((notification) => notification.subscriptionId === subscription.id), - [allNotifications, subscription.id] + [allNotifications, subscription.id], ); if (notifications.length === 0) { return ; @@ -104,7 +104,7 @@ const NotificationList = (props) => { main.scrollTo(0, 0); } }, - [props.id] + [props.id], ); return ( @@ -319,7 +319,7 @@ const Attachment = (props) => { infos.push( t("notifications_attachment_link_expires", { date: formatDateTime(attachment.expires, dateFormat, timeFormat), - }) + }), ); } if (expired) { diff --git a/web/src/components/PublishDialog.jsx b/web/src/components/PublishDialog.jsx index 18844b65..8bae0261 100644 --- a/web/src/components/PublishDialog.jsx +++ b/web/src/components/PublishDialog.jsx @@ -168,7 +168,7 @@ const PublishDialog = (props) => { loaded: formatBytes(ev.loaded), total: formatBytes(ev.total), percent: Math.round((ev.loaded * 100.0) / ev.total), - }) + }), ); } else { setStatus(t("publish_dialog_progress_uploading")); @@ -201,19 +201,19 @@ const PublishDialog = (props) => { t("publish_dialog_attachment_limits_file_and_quota_reached", { fileSizeLimit: formatBytes(fileSizeLimit), remainingBytes: formatBytes(remainingBytes), - }) + }), ); } else if (fileSizeLimitReached) { setAttachFileError( t("publish_dialog_attachment_limits_file_reached", { fileSizeLimit: formatBytes(fileSizeLimit), - }) + }), ); } else if (quotaReached) { setAttachFileError( t("publish_dialog_attachment_limits_quota_reached", { remainingBytes: formatBytes(remainingBytes), - }) + }), ); } else { setAttachFileError(""); diff --git a/web/src/components/SubscribeDialog.jsx b/web/src/components/SubscribeDialog.jsx index bc8bbe2d..13dbdd9f 100644 --- a/web/src/components/SubscribeDialog.jsx +++ b/web/src/components/SubscribeDialog.jsx @@ -93,7 +93,7 @@ const SubscribePage = (props) => { const { topic } = props; const existingTopicUrls = props.subscriptions.map((s) => topicUrl(s.baseUrl, s.topic)); const existingBaseUrls = Array.from(new Set([publicBaseUrl, ...props.subscriptions.map((s) => s.baseUrl)])).filter( - (s) => s !== config.base_url + (s) => s !== config.base_url, ); const showReserveTopicCheckbox = config.enable_reservations && !anotherServerVisible && (config.enable_payments || account); const reserveTopicEnabled = @@ -113,7 +113,7 @@ const SubscribePage = (props) => { setError( t("subscribe_dialog_error_user_not_authorized", { username, - }) + }), ); return; } diff --git a/web/src/components/SubscriptionPopup.jsx b/web/src/components/SubscriptionPopup.jsx index 4390095f..1bb4f493 100644 --- a/web/src/components/SubscriptionPopup.jsx +++ b/web/src/components/SubscriptionPopup.jsx @@ -120,14 +120,14 @@ export const SubscriptionPopup = (props) => { `Hello friend, this is a test notification from ntfy web. It's ${formatDateTime( nowSeconds, dateFormat, - timeFormat + timeFormat, )} right now. Is that early or late?`, `So I heard you like ntfy? If that's true, go to GitHub and star it, or to the Play store and rate it. Thanks! Oh yeah, this is a test notification.`, `It's almost like you want to hear what I have to say. I'm not even a machine. I'm just a sentence that Phil typed on a random Thursday.`, `Alright then, it's ${formatDateTime( nowSeconds, dateFormat, - timeFormat + timeFormat, )} already. Boy oh boy, where did the time go? I hope you're alright, friend.`, `There are nine million bicycles in Beijing That's a fact; It's a thing we can't deny. I wonder if that's true ...`, `I'm really excited that you're trying out ntfy. Did you know that there are a few public topics, such as ntfy.sh/stats and ntfy.sh/announcements.`, diff --git a/web/src/components/hooks.js b/web/src/components/hooks.js index b2502b48..ba62f54f 100644 --- a/web/src/components/hooks.js +++ b/web/src/components/hooks.js @@ -30,7 +30,7 @@ export const useConnectionListeners = (account, subscriptions, users, webPushTop // wsSubscriptions should stay stable unless the list of subscription IDs changes. Without the memo, the connection // listener calls a refresh for no reason. This isn't a problem due to the makeConnectionId, but it triggers an // unnecessary recomputation for every received message. - [JSON.stringify({ subscriptions: subscriptions?.map(({ id }) => id), webPushTopics })] + [JSON.stringify({ subscriptions: subscriptions?.map(({ id }) => id), webPushTopics })], ); // Register listeners for incoming messages, and connection state changes @@ -103,7 +103,7 @@ export const useConnectionListeners = (account, subscriptions, users, webPushTop }, // We have to disable dep checking for "navigate". This is fine, it never changes. - [] + [], ); // Sync topic listener: For accounts with sync_topic, subscribe to an internal topic @@ -233,7 +233,7 @@ export const useWebPushTopics = () => { const topics = useLiveQuery( async () => subscriptionManager.webPushTopics(pushPossible), // invalidate (reload) query when these values change - [pushPossible] + [pushPossible], ); useWebPushListener(topics); diff --git a/web/vite.config.js b/web/vite.config.js index a4fd5a31..5f1e0741 100644 --- a/web/vite.config.js +++ b/web/vite.config.js @@ -39,7 +39,7 @@ export default defineConfig(({ mode }) => ({ ...entry, url: "app.html", } - : entry + : entry, ), }), ],