Skip to content

Commit

Permalink
fix: disable sw in dev
Browse files Browse the repository at this point in the history
Signed-off-by: Innei <tukon479@gmail.com>
  • Loading branch information
Innei committed Dec 5, 2024
1 parent 83ca873 commit 150cdea
Show file tree
Hide file tree
Showing 5 changed files with 133 additions and 152 deletions.
3 changes: 0 additions & 3 deletions apps/renderer/src/components/common/ReloadPrompt.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,6 @@ export function ReloadPrompt() {
// }, [offlineReady, close])

useEffect(() => {
const isPwa = window.matchMedia("(display-mode: standalone)").matches
if (!isPwa) return

if (needRefresh) {
toast.info("New version available", {
action: {
Expand Down
7 changes: 2 additions & 5 deletions apps/renderer/src/push-notification.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,10 @@ export async function registerWebPushNotifications() {
}
try {
const existingRegistration = await navigator.serviceWorker.getRegistration()
let registration = existingRegistration
const registration = existingRegistration

const isPWA = window.matchMedia("(display-mode: standalone)").matches
if (!registration) {
registration = await navigator.serviceWorker.register(`/sw.js${isPWA ? "?pwa=true" : ""}`, {
scope: "/",
})
return
}

await navigator.serviceWorker.ready
Expand Down
145 changes: 1 addition & 144 deletions apps/renderer/src/sw.ts
Original file line number Diff line number Diff line change
@@ -1,144 +1 @@
/// <reference lib="webworker" />
import { cleanupOutdatedCaches, precacheAndRoute } from "workbox-precaching"
import type { NavigationRouteMatchOptions } from "workbox-routing"
import { NavigationRoute, registerRoute } from "workbox-routing"
import { CacheFirst, NetworkFirst } from "workbox-strategies"

declare let self: ServiceWorkerGlobalScope

const isPWA = new URL(self.location.href).searchParams.get("pwa") === "true"

self.addEventListener("message", (event) => {
if (event.data && event.data.type === "SKIP_WAITING") self.skipWaiting()
})

interface NewEntryMessage {
description: string
entryId: string
feedId: string
title: string
type: "new-entry"
view: string
}

type Message = NewEntryMessage

// Firebase Cloud Messaging handler
self.addEventListener("push", (event) => {
if (event.data) {
const { data } = event.data.json()
const payload = data as Message

switch (payload.type) {
case "new-entry": {
const notificationPromise = self.registration.showNotification(payload.title, {
body: payload.description,
icon: "https://app.follow.is/favicon.ico",
data: {
type: payload.type,
feedId: payload.feedId,
entryId: payload.entryId,
view: Number.parseInt(payload.view),
},
})
event.waitUntil(notificationPromise)
break
}
}
}
})

self.addEventListener("notificationclick", (event) => {
event.notification.close()

const notificationData = event.notification.data
if (!notificationData) return

let urlToOpen: URL

switch (notificationData.type) {
case "new-entry": {
urlToOpen = new URL(
`/feeds/${notificationData.feedId}/${notificationData.entryId}`,
self.location.origin,
)
break
}
default: {
urlToOpen = new URL("/", self.location.origin)
break
}
}

const promiseChain = self.clients
.matchAll({
type: "window",
includeUncontrolled: true,
})
.then((windowClients) => {
if (windowClients.length > 0) {
const client = windowClients[0]
return client.focus()
}
return self.clients.openWindow(urlToOpen.href)
})
.then((client) => {
if (client && "postMessage" in client) {
switch (notificationData.type) {
case "new-entry": {
client.postMessage({
type: "NOTIFICATION_CLICK",
action: "NAVIGATE_ENTRY",
data: {
feedId: notificationData.feedId,
entryId: notificationData.entryId,
view: notificationData.view,
url: urlToOpen.pathname,
},
})
break
}
default: {
console.warn("Unknown notification type:", notificationData.type)
break
}
}
}
})

event.waitUntil(promiseChain)
})

const preCacheExclude = new Set(["og-image.png", "opengraph-image.png"])

const precacheManifest = self.__WB_MANIFEST.filter((entry) => {
return typeof entry === "string" || !preCacheExclude.has(entry.url)
})
precacheAndRoute(precacheManifest)

cleanupOutdatedCaches()

const strategy = isPWA
? new CacheFirst({ cacheName: "assets-cache-first" })
: new NetworkFirst({
cacheName: "assets-network-first",
networkTimeoutSeconds: 1,
})

const fileExtensionRegexp = /\/[^/?][^./?]*\.[^/]+$/
registerRoute(({ url }) => {
if (
precacheManifest.some((entry) => {
const urlToMatch = typeof entry === "string" ? entry : entry.url
return url.pathname === urlToMatch
})
) {
return true
}
return fileExtensionRegexp.test(url.pathname)
}, strategy)

let allowlist: NavigationRouteMatchOptions["allowlist"]
if (import.meta.env.DEV) allowlist = [/^\/$/]

registerRoute(new NavigationRoute(strategy, { allowlist }))
import "./workers/sw/index"
27 changes: 27 additions & 0 deletions apps/renderer/src/workers/sw/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/// <reference lib="webworker" />
import { cleanupOutdatedCaches, precacheAndRoute } from "workbox-precaching"
import { registerRoute } from "workbox-routing"
import { CacheFirst } from "workbox-strategies"

import { registerPusher } from "./pusher"

declare let self: ServiceWorkerGlobalScope

registerPusher(self)

const preCacheExclude = new Set(["og-image.png", "opengraph-image.png"])

const precacheManifest = self.__WB_MANIFEST.filter((entry) => {
return typeof entry === "string" || !preCacheExclude.has(entry.url)
})

registerRoute(
({ request }) => request.destination === "image",
new CacheFirst({
cacheName: "image-assets",
}),
)

precacheAndRoute(precacheManifest)

cleanupOutdatedCaches()
103 changes: 103 additions & 0 deletions apps/renderer/src/workers/sw/pusher.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
/// <reference lib="webworker" />
interface NewEntryMessage {
description: string
entryId: string
feedId: string
title: string
type: "new-entry"
view: string
}

type Message = NewEntryMessage

export const registerPusher = (self: ServiceWorkerGlobalScope) => {
self.addEventListener("message", (event) => {
if (event.data && event.data.type === "SKIP_WAITING") self.skipWaiting()
})

// Firebase Cloud Messaging handler
self.addEventListener("push", (event) => {
if (event.data) {
const { data } = event.data.json()
const payload = data as Message

switch (payload.type) {
case "new-entry": {
const notificationPromise = self.registration.showNotification(payload.title, {
body: payload.description,
icon: "https://app.follow.is/favicon.ico",
data: {
type: payload.type,
feedId: payload.feedId,
entryId: payload.entryId,
view: Number.parseInt(payload.view),
},
})
event.waitUntil(notificationPromise)
break
}
}
}
})

self.addEventListener("notificationclick", (event) => {
event.notification.close()

const notificationData = event.notification.data
if (!notificationData) return

let urlToOpen: URL

switch (notificationData.type) {
case "new-entry": {
urlToOpen = new URL(
`/feeds/${notificationData.feedId}/${notificationData.entryId}`,
self.location.origin,
)
break
}
default: {
urlToOpen = new URL("/", self.location.origin)
break
}
}

const promiseChain = self.clients
.matchAll({
type: "window",
includeUncontrolled: true,
})
.then((windowClients) => {
if (windowClients.length > 0) {
const client = windowClients[0]
return client.focus()
}
return self.clients.openWindow(urlToOpen.href)
})
.then((client) => {
if (client && "postMessage" in client) {
switch (notificationData.type) {
case "new-entry": {
client.postMessage({
type: "NOTIFICATION_CLICK",
action: "NAVIGATE_ENTRY",
data: {
feedId: notificationData.feedId,
entryId: notificationData.entryId,
view: notificationData.view,
url: urlToOpen.pathname,
},
})
break
}
default: {
console.warn("Unknown notification type:", notificationData.type)
break
}
}
}
})

event.waitUntil(promiseChain)
})
}

0 comments on commit 150cdea

Please sign in to comment.