82 lines
1.9 KiB
TypeScript
82 lines
1.9 KiB
TypeScript
import Deferred from '../util/Deferred';
|
|
|
|
declare const self: ServiceWorkerGlobalScope;
|
|
|
|
type ShareData = {
|
|
title?: string;
|
|
text?: string;
|
|
url?: string;
|
|
files?: File[];
|
|
};
|
|
|
|
const READY_CLIENT_DEFERREDS = new Map<string, Deferred<void>>();
|
|
|
|
export async function respondForShare(e: FetchEvent) {
|
|
if (e.request.method === 'POST') {
|
|
try {
|
|
const formData = await e.request.formData();
|
|
const data = parseFormData(formData);
|
|
requestShare(data, e.resultingClientId);
|
|
} catch (err) {
|
|
// eslint-disable-next-line no-console
|
|
console.warn('[SHARE] Failed to parse input data', err);
|
|
}
|
|
}
|
|
|
|
return Response.redirect('.');
|
|
}
|
|
|
|
export function handleClientMessage(e: ExtendableMessageEvent) {
|
|
const { source, data } = e;
|
|
if (!source) return;
|
|
|
|
if (data.type === 'clientReady') {
|
|
const { id } = source as Client;
|
|
const deferred = READY_CLIENT_DEFERREDS.get(id);
|
|
if (deferred) {
|
|
deferred.resolve();
|
|
} else {
|
|
READY_CLIENT_DEFERREDS.set(id, Deferred.resolved());
|
|
}
|
|
}
|
|
}
|
|
|
|
async function requestShare(data: ShareData, clientId: string) {
|
|
const client = await self.clients.get(clientId);
|
|
if (!client) {
|
|
return;
|
|
}
|
|
|
|
await getClientReadyDeferred(clientId);
|
|
|
|
client.postMessage({
|
|
type: 'share',
|
|
payload: data,
|
|
});
|
|
}
|
|
|
|
function getClientReadyDeferred(clientId: string) {
|
|
const deferred = READY_CLIENT_DEFERREDS.get(clientId);
|
|
if (deferred) {
|
|
return deferred.promise;
|
|
}
|
|
|
|
const newDeferred = new Deferred<void>();
|
|
READY_CLIENT_DEFERREDS.set(clientId, newDeferred);
|
|
return newDeferred.promise;
|
|
}
|
|
|
|
function parseFormData(formData: FormData): ShareData {
|
|
const files = formData.getAll('files') as File[];
|
|
const title = formData.get('title') as string;
|
|
const text = formData.get('text') as string;
|
|
const url = formData.get('url') as string;
|
|
|
|
return {
|
|
title,
|
|
text,
|
|
url,
|
|
files,
|
|
};
|
|
}
|