fix: keep the login and mailbox owner in notification links on safari 16 #1499

This commit is contained in:
Linus Rath
2026-11-02 20:15:34 +01:00
parent 0c421f5557
commit 244e8b7b5a
3 changed files with 14 additions and 3 deletions
+6 -2
View File
@@ -5,7 +5,7 @@ import vm from 'node:vm';
export async function pushClick(
accountId: string,
preview: (url: string) => Promise<unknown>,
options: { warm?: boolean; basePath?: string; legacy?: boolean; emailId?: string } = {},
options: { warm?: boolean; basePath?: string; legacy?: boolean; emailId?: string; noParamsSize?: boolean } = {},
): Promise<string> {
const source = readFileSync(resolve('public/sw.js'), 'utf8');
let notification: { data: unknown } | undefined;
@@ -18,8 +18,12 @@ export async function pushClick(
async focus() { return this; },
async navigate(url: string) { target = url; return this; },
};
// Safari before 17 has no URLSearchParams.size.
const SearchParams = options.noParamsSize
? class extends URLSearchParams { get size(): number { return undefined as unknown as number; } }
: URLSearchParams;
const context = vm.createContext({
URL, URLSearchParams, Response, AbortController, setTimeout, clearTimeout, console,
URL, URLSearchParams: SearchParams, Response, AbortController, setTimeout, clearTimeout, console,
self: {
location: { href: `https://mail.example.test${options.basePath ?? ''}/sw.js`, origin: 'https://mail.example.test' },
addEventListener: (type: string, fn: (event: unknown) => void) => listeners.set(type, fn),
+5
View File
@@ -47,6 +47,11 @@ describe('push click keeps the owning mailbox (#1491)', () => {
expect(parseTarget(target)).toMatchObject({ kind: 'folder', ownerAccountId: 'team', slot: 2 });
});
it('keeps the slot and owner where URLSearchParams has no size', async () => {
const target = await pushClick('team', async () => ({ slot: 1, unreadTotal: 1, email: { id: 'same-id' } }), { noParamsSize: true });
expect(parseTarget(target)).toMatchObject({ kind: 'message', ownerAccountId: 'team', slot: 1 });
});
it('does not fall back to a personal folder for an unavailable owner', () => {
expect(resolveFolderRef('inbox', folders, 'unavailable')).toBeNull();
});
+3 -1
View File
@@ -925,7 +925,9 @@ function buildClickUrl(data) {
const params = new URLSearchParams();
if (Number.isInteger(data.slot)) params.set("slot", String(data.slot));
if (typeof data.accountId === "string" && data.accountId) params.set("owner", data.accountId);
const targetQuery = params.size ? `?${params}` : "";
// Not params.size: Safari before 17 (iOS 16.4+ web push) lacks it.
const qs = params.toString();
const targetQuery = qs ? `?${qs}` : "";
if (data.kind === "email" && data.emailId) {
// Permalink (#733). Under NEXT_PUBLIC_LOCALE_PREFIX=always the proxy
// redirects this to the localised path; the worker has no locale to add.