fix(web): respect user-disconnected federation instances on reload
Add third group for instances the user explicitly disconnected via the registry. These get a disconnected placeholder with preserved token for instant reconnect, but no auto-connect on page load.
This commit is contained in:
@@ -780,25 +780,50 @@ export const useInstanceStore = create<InstanceState>((set, get) => ({
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Split server-known instances into two groups:
|
// Split server-known instances into three groups:
|
||||||
// - withToken: have a cached token → attempt reconnection
|
// - withToken: have a cached token and should auto-connect
|
||||||
// - withoutToken: no cached token → add as error placeholder
|
// - withoutToken: no cached token → add as error placeholder
|
||||||
|
// - userDisconnected: user explicitly disconnected → add as disconnected placeholder (no auto-connect)
|
||||||
const withToken: Array<{ origin: string; ri: (typeof currentUser.replicatedInstances)[0]; entry: CachedInstanceToken }> = [];
|
const withToken: Array<{ origin: string; ri: (typeof currentUser.replicatedInstances)[0]; entry: CachedInstanceToken }> = [];
|
||||||
const withoutToken: Array<{ origin: string; ri: (typeof currentUser.replicatedInstances)[0] }> = [];
|
const withoutToken: Array<{ origin: string; ri: (typeof currentUser.replicatedInstances)[0] }> = [];
|
||||||
|
const userDisconnected: Array<{ origin: string; ri: (typeof currentUser.replicatedInstances)[0]; entry: CachedInstanceToken }> = [];
|
||||||
|
|
||||||
for (const ri of currentUser.replicatedInstances) {
|
for (const ri of currentUser.replicatedInstances) {
|
||||||
const origin = ri.origin || `https://${ri.domain}`;
|
const origin = ri.origin || `https://${ri.domain}`;
|
||||||
// Never connect to ourselves — home WS is managed separately
|
// Never connect to ourselves — home WS is managed separately
|
||||||
if (origin === window.location.origin) continue;
|
if (origin === window.location.origin) continue;
|
||||||
if (get().instances.some(i => i.origin === origin)) continue; // already loaded
|
if (get().instances.some(i => i.origin === origin)) continue; // already loaded
|
||||||
const entry = cached[origin];
|
const cachedEntry = cached[origin];
|
||||||
if (entry) {
|
const regEntry = registry.get(origin);
|
||||||
withToken.push({ origin, ri, entry });
|
if (cachedEntry) {
|
||||||
|
// Respect user's explicit disconnect — don't auto-reconnect
|
||||||
|
if (regEntry?.status === 'disconnected') {
|
||||||
|
userDisconnected.push({ origin, ri, entry: cachedEntry });
|
||||||
|
} else {
|
||||||
|
withToken.push({ origin, ri, entry: cachedEntry });
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
withoutToken.push({ origin, ri });
|
withoutToken.push({ origin, ri });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add user-disconnected instances as disconnected placeholders (token preserved
|
||||||
|
// so reconnect is instant, but no WebSocket or API calls until user clicks reconnect)
|
||||||
|
if (userDisconnected.length > 0) {
|
||||||
|
set((state) => {
|
||||||
|
const placeholders: ConnectedInstance[] = userDisconnected.map(({ origin, entry: cachedEntry }) => ({
|
||||||
|
origin,
|
||||||
|
label: cachedEntry.label || new URL(origin).host,
|
||||||
|
token: cachedEntry.token,
|
||||||
|
user: currentUser,
|
||||||
|
username: cachedEntry.username || '',
|
||||||
|
status: 'disconnected' as const,
|
||||||
|
api: createApiClient(origin, () => cachedEntry.token),
|
||||||
|
}));
|
||||||
|
return { instances: [...state.instances, ...placeholders] };
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Immediately add tokenless placeholders so they're visible in Zustand
|
// Immediately add tokenless placeholders so they're visible in Zustand
|
||||||
// (and therefore won't be erased by syncInstanceList)
|
// (and therefore won't be erased by syncInstanceList)
|
||||||
if (withoutToken.length > 0) {
|
if (withoutToken.length > 0) {
|
||||||
@@ -952,7 +977,7 @@ export const useInstanceStore = create<InstanceState>((set, get) => ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Save final state to localStorage — persist ALL instances regardless of status
|
// Save final state to localStorage — persist ALL instances regardless of status
|
||||||
// so disconnected instances survive page reload and can auto-reconnect later
|
// so tokens are preserved for instant reconnect (registry controls auto-connect behavior)
|
||||||
saveCachedTokens(get().instances, currentUser.id);
|
saveCachedTokens(get().instances, currentUser.id);
|
||||||
|
|
||||||
// Hydrate pendingSyncOrigins from localStorage cache and mark auto-connect done
|
// Hydrate pendingSyncOrigins from localStorage cache and mark auto-connect done
|
||||||
|
|||||||
Reference in New Issue
Block a user