wetalk/src/lib/offline.ts
ordinarthur 5ea5a390ce
All checks were successful
Build & Deploy / build-and-deploy (push) Successful in 38s
add offline part
2026-04-13 13:45:04 +02:00

94 lines
2.4 KiB
TypeScript

const CACHE_NAME = 'wetalk-audio-cache'
export async function cacheAudio(
url: string,
onProgress?: (percent: number) => void,
): Promise<boolean> {
try {
const cache = await caches.open(CACHE_NAME)
// Check if already cached
const existing = await cache.match(url)
if (existing) return true
const response = await fetch(url)
if (!response.ok) return false
if (onProgress && response.body) {
const contentLength = Number(response.headers.get('content-length') || 0)
const reader = response.body.getReader()
const chunks: Uint8Array[] = []
let received = 0
while (true) {
const { done, value } = await reader.read()
if (done) break
chunks.push(value)
received += value.length
if (contentLength > 0) onProgress(Math.round((received / contentLength) * 100))
}
const blob = new Blob(chunks, { type: response.headers.get('content-type') || 'audio/mpeg' })
const cachedResponse = new Response(blob, {
status: 200,
headers: { 'Content-Type': blob.type, 'Content-Length': String(blob.size) },
})
await cache.put(url, cachedResponse)
} else {
await cache.put(url, response)
}
return true
} catch (e) {
console.error('[offline] cache failed:', e)
return false
}
}
export async function getCachedAudioUrl(url: string): Promise<string | null> {
try {
const cache = await caches.open(CACHE_NAME)
const response = await cache.match(url)
if (!response) return null
const blob = await response.blob()
return URL.createObjectURL(blob)
} catch {
return null
}
}
export async function isAudioCached(url: string): Promise<boolean> {
try {
const cache = await caches.open(CACHE_NAME)
const response = await cache.match(url)
return !!response
} catch {
return false
}
}
export async function removeCachedAudio(url: string): Promise<void> {
try {
const cache = await caches.open(CACHE_NAME)
await cache.delete(url)
} catch { /* ignore */ }
}
export async function getCacheSize(): Promise<number> {
try {
const cache = await caches.open(CACHE_NAME)
const keys = await cache.keys()
let total = 0
for (const req of keys) {
const res = await cache.match(req)
if (res) {
const blob = await res.blob()
total += blob.size
}
}
return total
} catch {
return 0
}
}