Compare commits
No commits in common. "c21d21015f7ab98ba8d4d6199360827afe62a60d" and "5669489dc9284af55d8fd7bdd1726b442d12fac1" have entirely different histories.
c21d21015f
...
5669489dc9
|
@ -1,13 +0,0 @@
|
||||||
.island__is_online {
|
|
||||||
position: sticky;
|
|
||||||
top: 0;
|
|
||||||
width: 100%;
|
|
||||||
text-align: center;
|
|
||||||
padding: var(--_gap-half);
|
|
||||||
/* invert accent color */
|
|
||||||
background: hsl(from #82c91e calc(h + 180) s l / 1);
|
|
||||||
font-family: var(--_font-family-accent);
|
|
||||||
color: white;
|
|
||||||
font-weight: bold;
|
|
||||||
z-index: 9999;
|
|
||||||
}
|
|
|
@ -1,52 +0,0 @@
|
||||||
import { type Signal, useSignal } from '@preact/signals'
|
|
||||||
import { useEffect } from 'preact/hooks'
|
|
||||||
import { JSX } from 'preact'
|
|
||||||
import { requestApi } from ':src/utils.ts'
|
|
||||||
|
|
||||||
type NetworkConnection = {
|
|
||||||
addEventListener: (
|
|
||||||
type: 'change',
|
|
||||||
listener: (event: Event) => void | Promise<void>,
|
|
||||||
) => void
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function IsOnline(
|
|
||||||
{ online, offline }: { online?: string; offline: string },
|
|
||||||
) {
|
|
||||||
const status = useSignal(offline)
|
|
||||||
const connection = 'connection' in navigator
|
|
||||||
? navigator.connection as NetworkConnection
|
|
||||||
: null
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
// Update connection status on network changes
|
|
||||||
connection?.addEventListener('change', () => {
|
|
||||||
updateNetworkStatus(status, online, offline)
|
|
||||||
})
|
|
||||||
// Update connection status on 1st load
|
|
||||||
updateNetworkStatus(status, online, offline)
|
|
||||||
// Update connection status on interval (10s)
|
|
||||||
setInterval(() => updateNetworkStatus(status, online, offline), 10_000)
|
|
||||||
})
|
|
||||||
|
|
||||||
return <>{status}</>
|
|
||||||
}
|
|
||||||
|
|
||||||
async function updateNetworkStatus(
|
|
||||||
status: Signal<JSX.Element>,
|
|
||||||
online: string | undefined,
|
|
||||||
offline: string,
|
|
||||||
) {
|
|
||||||
const isOnline = await requestApi<void, boolean>(
|
|
||||||
'/serviceworker/is-online',
|
|
||||||
'POST',
|
|
||||||
).catch(() => false)
|
|
||||||
|
|
||||||
if (isOnline) {
|
|
||||||
status.value = online === undefined
|
|
||||||
? <span style={{ display: 'none' }}></span>
|
|
||||||
: <span>{online}</span>
|
|
||||||
} else {
|
|
||||||
status.value = <span class={'island__is_online'}>{offline}</span>
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -3,7 +3,6 @@ import { type PageProps } from '$fresh/server.ts'
|
||||||
import { Footer } from ':components/Footer.tsx'
|
import { Footer } from ':components/Footer.tsx'
|
||||||
import { Header } from ':components/Header.tsx'
|
import { Header } from ':components/Header.tsx'
|
||||||
import { ProgressiveWebApp } from ':components/ProgressiveWebApp.tsx'
|
import { ProgressiveWebApp } from ':components/ProgressiveWebApp.tsx'
|
||||||
import IsOnline from ':islands/IsOnline.tsx'
|
|
||||||
|
|
||||||
export default function App({ Component }: PageProps) {
|
export default function App({ Component }: PageProps) {
|
||||||
return (
|
return (
|
||||||
|
@ -43,9 +42,6 @@ export default function App({ Component }: PageProps) {
|
||||||
</Head>
|
</Head>
|
||||||
<body>
|
<body>
|
||||||
<Header />
|
<Header />
|
||||||
<IsOnline
|
|
||||||
offline={'Vous êtes hors ligne / Serveur inaccessible'}
|
|
||||||
/>
|
|
||||||
<main f-client-nav>
|
<main f-client-nav>
|
||||||
<Partial name='main'>
|
<Partial name='main'>
|
||||||
<Component />
|
<Component />
|
||||||
|
|
|
@ -1,9 +0,0 @@
|
||||||
import { SessionHandlers } from ':src/session/mod.ts'
|
|
||||||
import { respondApi } from ':src/utils.ts'
|
|
||||||
|
|
||||||
export const handler: SessionHandlers = {
|
|
||||||
POST() {
|
|
||||||
// Check if server is online
|
|
||||||
return respondApi<'success', true>('success', true)
|
|
||||||
},
|
|
||||||
}
|
|
|
@ -1,16 +1,11 @@
|
||||||
import { expandGlob } from '$std/fs/mod.ts'
|
import { expandGlob } from '$std/fs/mod.ts'
|
||||||
import { SessionHandlers } from ':src/session/mod.ts'
|
import { SessionHandlers } from ':src/session/mod.ts'
|
||||||
import { respondApi } from ':src/utils.ts'
|
import { respondApi } from ':src/utils.ts'
|
||||||
import { BUILD_ID } from '$fresh/src/server/build_id.ts'
|
|
||||||
import { encodeBase64 } from '@std/encoding'
|
|
||||||
|
|
||||||
export type PrecacheResponse = { version: string; preCachedUrls: string[] }
|
export type PrecacheResponse = { version: string; preCachedUrls: string[] }
|
||||||
|
|
||||||
async function getVersion() {
|
// Updated only at server start
|
||||||
const versionBytes = new TextEncoder().encode(BUILD_ID)
|
const version = crypto.randomUUID()
|
||||||
const versionHash = await crypto.subtle.digest('SHA-256', versionBytes)
|
|
||||||
return encodeBase64(versionHash)
|
|
||||||
}
|
|
||||||
|
|
||||||
export const handler: SessionHandlers = {
|
export const handler: SessionHandlers = {
|
||||||
async GET() {
|
async GET() {
|
||||||
|
@ -18,7 +13,6 @@ export const handler: SessionHandlers = {
|
||||||
const preCachedUrls: string[] = ['/', '/imports/markdown_css']
|
const preCachedUrls: string[] = ['/', '/imports/markdown_css']
|
||||||
const paths = ['/static/**', '/_fresh/static/**']
|
const paths = ['/static/**', '/_fresh/static/**']
|
||||||
const routes = '/routes/*/index.tsx'
|
const routes = '/routes/*/index.tsx'
|
||||||
const version = await getVersion()
|
|
||||||
|
|
||||||
//Pre-cache routes
|
//Pre-cache routes
|
||||||
for await (const route of expandGlob(routes, { root: '.' })) {
|
for await (const route of expandGlob(routes, { root: '.' })) {
|
||||||
|
|
|
@ -69,7 +69,6 @@ if (IS_SW) {
|
||||||
})
|
})
|
||||||
|
|
||||||
self.addEventListener('push', (event) => {
|
self.addEventListener('push', (event) => {
|
||||||
console.log('push')
|
|
||||||
const { title, options } = (event.data?.json() ?? {}) as {
|
const { title, options } = (event.data?.json() ?? {}) as {
|
||||||
title?: string
|
title?: string
|
||||||
options?: Partial<NotificationOptions>
|
options?: Partial<NotificationOptions>
|
||||||
|
@ -87,15 +86,11 @@ async function fetchHandler(event: FetchEvent) {
|
||||||
const method = event.request.method
|
const method = event.request.method
|
||||||
const preCachedUrls = await getPreCachedUrls()
|
const preCachedUrls = await getPreCachedUrls()
|
||||||
const cache = await getCache()
|
const cache = await getCache()
|
||||||
// Cache will be updated on each request if version change
|
|
||||||
updateCache()
|
|
||||||
|
|
||||||
// Cache first for "pre-cached-urls"
|
// Cache first for "pre-cached-urls"
|
||||||
if (preCachedUrls.includes(url.pathname) && method === 'GET') {
|
if (preCachedUrls.includes(url.pathname) && method === 'GET') {
|
||||||
const cached = await cache.match(event.request) ??
|
const cached = await cache.match(event.request) ??
|
||||||
await fetch(event.request).then((response) =>
|
await fetch(event.request).catch(() => null) ??
|
||||||
response.ok ? response : null
|
|
||||||
).catch(() => null) ??
|
|
||||||
await cache.match(event.request, { ignoreSearch: true })
|
await cache.match(event.request, { ignoreSearch: true })
|
||||||
|
|
||||||
if (cached === undefined) {
|
if (cached === undefined) {
|
||||||
|
@ -110,12 +105,7 @@ async function fetchHandler(event: FetchEvent) {
|
||||||
|
|
||||||
const response = fetch(event.request)
|
const response = fetch(event.request)
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
if (!response.ok) {
|
// Update cache
|
||||||
throw new Error(
|
|
||||||
`failed to get request: [${response.status}] ${response.statusText}`,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
// Update cache if ok
|
|
||||||
cache.put(event.request, response.clone())
|
cache.put(event.request, response.clone())
|
||||||
return response
|
return response
|
||||||
})
|
})
|
||||||
|
@ -138,29 +128,6 @@ async function fetchHandler(event: FetchEvent) {
|
||||||
return fetch(event.request)
|
return fetch(event.request)
|
||||||
}
|
}
|
||||||
|
|
||||||
async function updateCache() {
|
|
||||||
const serverVersion = await getServerCacheVersion()
|
|
||||||
const clientVersion = await swStorage.getItem<string>('$sw.cache.version')
|
|
||||||
if (clientVersion === null) return
|
|
||||||
if (serverVersion === undefined) return
|
|
||||||
if (clientVersion === serverVersion) return
|
|
||||||
|
|
||||||
// Open new pre-cache
|
|
||||||
await openCache()
|
|
||||||
// Delete old pre-cache
|
|
||||||
caches.delete(clientVersion)
|
|
||||||
}
|
|
||||||
|
|
||||||
async function getServerCacheVersion() {
|
|
||||||
const response = await fetch('/api/serviceworker/precache').then(
|
|
||||||
(response) => response.json() as Promise<ApiPayload<PrecacheResponse>>,
|
|
||||||
)
|
|
||||||
|
|
||||||
if (response.kind === 'success') {
|
|
||||||
return response.data.version
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function openCache() {
|
async function openCache() {
|
||||||
const response = await fetch('/api/serviceworker/precache').then(
|
const response = await fetch('/api/serviceworker/precache').then(
|
||||||
(response) => response.json() as Promise<ApiPayload<PrecacheResponse>>,
|
(response) => response.json() as Promise<ApiPayload<PrecacheResponse>>,
|
||||||
|
|
|
@ -13,4 +13,3 @@
|
||||||
@import url('../../islands/MoreBox.css');
|
@import url('../../islands/MoreBox.css');
|
||||||
@import url('../../islands/AiChatBox.css');
|
@import url('../../islands/AiChatBox.css');
|
||||||
@import url('../../islands/LoginForm.css');
|
@import url('../../islands/LoginForm.css');
|
||||||
@import url('../../islands/IsOnline.css');
|
|
||||||
|
|
Loading…
Reference in a new issue