/// declare const self: ServiceWorkerGlobalScope const clientResolves: { [key: string]: Function } = {} self.addEventListener('message', (event) => { if (event.data.action !== 'ready-to-receive') return const id: string | undefined = (event.source as any)?.id ?? undefined if (id && clientResolves[id] !== undefined) clientResolves[id]() }) export function onShareTarget(event: FetchEvent) { if (!event.request.url.endsWith('/web-share-target') || event.request.method !== 'POST') return event.waitUntil(handleSharedTarget(event)) } async function handleSharedTarget(event: FetchEvent) { event.respondWith(Response.redirect('/home?share-target=true', 303)) await waitForClientToGetReady(event.resultingClientId) const [client, formData] = await getClientAndFormData(event) if (client === undefined) return await sendShareTargetMessage(client, formData) } async function sendShareTargetMessage(client: Client, data: FormData) { const sharedData: { textParts: string[]; files: File[] } = { textParts: [], files: [], } // We collect the text data shared with us const title = data.get('title') if (title !== null) sharedData.textParts.push(title.toString()) const text = data.get('text') if (text !== null) sharedData.textParts.push(text.toString()) const link = data.get('link') if (link !== null) sharedData.textParts.push(link.toString()) // We collect the files shared with us for (const [name, file] of data.entries()) { if (name === 'files' && file instanceof File) sharedData.files.push(file) } client.postMessage({ data: sharedData, action: 'compose-with-shared-data' }) } function waitForClientToGetReady(clientId: string) { return new Promise((resolve) => { clientResolves[clientId] = resolve }) } function getClientAndFormData(event: FetchEvent): Promise<[client: Client | undefined, formData: FormData]> { return Promise.all([ self.clients.get(event.resultingClientId), event.request.formData(), ]) }