mirror of
https://github.com/bulwarkmail/webmail.git
synced 2026-11-05 16:16:49 +00:00
The installed app only handled mailto: and webcal: launches. The launch consumer dropped files, and nothing could hand a File to the composer or the import dialogs, because the pending mailto is JSON in sessionStorage. - manifest: `shortcuts` named in the browser's language, `file_handlers` for .eml, .ics and .vcf, and `share_target`, all with the base path and per-domain branding. Lite's manifest is unchanged. - `lib/launch-handoff.ts`: the one place files and links wait, in memory and in the Cache API, so they survive a sign-in that leaves the page. The desktop bridge can call the same functions, since launchQueue never fires in Electron. Sign-out clears it. - launch consumer: routes files by type, and takes a shortcut to an open window, which focus-existing would otherwise only focus. - .eml opens in a new host for the preview, also before sign-in, with the strictest device policy deciding about saving. .ics and .vcf open their import dialogs through a new `initialFile` prop. A .ics needs the server, so offline the dialog says so and carries on once back online. - composer: `initialFiles` goes through `addFiles`, so plugin vetoes and size limits still apply, also from a Pro compose tab. - `sw.js` takes the share POST before the offline check and keeps the files for the page. Without a worker, `/protocol/share` passes text and links on and the page says the files are lost. `protocol` joins the app sections and the handler pages join the shell, so a mailto: launch offline no longer gets a network error. Browsers without launchQueue or a service worker behave as before.
27 lines
1.0 KiB
TypeScript
27 lines
1.0 KiB
TypeScript
import { afterEach, describe, expect, it, vi } from 'vitest';
|
|
|
|
// A mailto: or webcal: launch without a connection needs its handler page in
|
|
// the app shell. Its address is what opens the draft; the start page alone
|
|
// doesn't read it outside an installed app.
|
|
|
|
vi.mock('@/lib/browser-navigation', () => ({
|
|
apiFetch: async () => new Response(JSON.stringify({ buildId: 'build-1', files: ['/_next/static/a.js'] })),
|
|
withBasePath: (path: string) => path,
|
|
}));
|
|
vi.mock('@/lib/app-update', () => ({ currentBuildId: () => 'build-1', SW_SCOPE: '/' }));
|
|
|
|
const { tellServiceWorker } = await import('../shell');
|
|
|
|
afterEach(() => vi.unstubAllGlobals());
|
|
|
|
describe('app shell pages', () => {
|
|
it('includes the protocol handler pages', async () => {
|
|
const postMessage = vi.fn();
|
|
vi.stubGlobal('navigator', { serviceWorker: { getRegistration: async () => ({ active: { postMessage } }) } });
|
|
|
|
await tellServiceWorker(true);
|
|
|
|
expect(postMessage.mock.calls[0][0].urls).toEqual(expect.arrayContaining(['/', '/protocol/mailto', '/protocol/webcal']));
|
|
});
|
|
});
|