fix: keep a late notification link from pulling you out of what you opened #1131

A notification link now waits up to 20 s for its login to reconnect.
If the user opened another folder or message, switched account or left
Mail in the meantime, the late link used to switch account anyway and
take them away from it. It now stays put.

When the account switch was overtaken by another one or failed, a
folder link was resolved against whichever folders were on screen, so
an Inbox link could open the wrong account's Inbox. It now stops there.
This commit is contained in:
Linus Rath
2026-09-30 20:33:08 +02:00
parent efe44e09cc
commit ca7d5e22df
+12
View File
@@ -1390,6 +1390,8 @@ export function MailApp({ linkSegments: routeSegments }: MailAppProps = {}) {
// session and the mailbox list are up. Runs at most once per mount: after
// this, the URL is an output of the view (see buildMailUrl), not an input.
const deepLinkHandledRef = useRef(false);
const mailAppMountedRef = useRef(false);
useEffect(() => { mailAppMountedRef.current = true; return () => { mailAppMountedRef.current = false; }; }, []);
const applyMailDeepLink = async (link: MailDeepLink, opts?: { onLoad?: boolean }) => {
// The folder list before an account switch, if one happened: until the
// new mailbox's folders arrive the store still holds these (or nothing).
@@ -1403,6 +1405,9 @@ export function MailApp({ linkSegments: routeSegments }: MailAppProps = {}) {
: undefined);
const switchesAccount = !!linkAccountId && linkAccountId !== useAuthStore.getState().activeAccountId;
if (switchesAccount) {
const startedOn = useAuthStore.getState().activeAccountId;
const startedIn = useEmailStore.getState().selectedMailbox;
const startedWith = useEmailStore.getState().selectedEmail?.id ?? null;
// The login may still be reconnecting - a tapped notification reopens
// the app and the logins come back one at a time - so wait for it
// rather than calling a late mailbox unavailable.
@@ -1410,8 +1415,15 @@ export function MailApp({ linkSegments: routeSegments }: MailAppProps = {}) {
toast.error(t('deep_link.account_unavailable'));
return;
}
// The user moved on while the login reconnected: don't pull them away.
if (!mailAppMountedRef.current
|| useAuthStore.getState().activeAccountId !== startedOn
|| useEmailStore.getState().selectedMailbox !== startedIn
|| (useEmailStore.getState().selectedEmail?.id ?? null) !== startedWith) return;
switchedFrom = useEmailStore.getState().mailboxes;
await switchAccount(linkAccountId);
// Overtaken or failed: the folders on screen are not the link's account's.
if (useAuthStore.getState().activeAccountId !== linkAccountId) return;
}
const activeClient = useAuthStore.getState().client;