fix: prevent logout 401 and login double-attempt caused by LWW layout push race

resetUserStores() was abusing populateFromReady('', [], [], []) to clear the
space store. Its LWW timestamp logic fired an async pushLayoutToOrigin when
_layoutUpdatedAt > 0, which read a null token from localStorage (already
removed on logout, not yet set on login). The 401 response triggered
handleUnauthorized(), deleting the freshly-stored login token and forcing a
full page reload — requiring users to log in twice.

Replace with a proper reset() method that synchronously sets all state to
initial values with no LWW comparison or API side effects.
This commit is contained in:
Jannis Braun
2026-03-16 22:52:32 +01:00
parent 1c806be94f
commit bf64c4678b
2 changed files with 24 additions and 1 deletions
+23
View File
@@ -82,6 +82,7 @@ interface SpaceState {
removeInstanceSpaces: (origin: string) => void;
transferOwnership: (spaceId: string, newOwnerId: string) => Promise<void>;
findExistingDmForUser: (targetUser: { id: string; homeUserId?: string | null }) => { dm: DmChannel; origin: string } | null;
reset: () => void;
}
/**
@@ -129,6 +130,28 @@ export const useSpaceStore = create<SpaceState>((set, get) => ({
categoryOriginMap: new Map(),
_layoutUpdatedAt: 0,
reset: () => {
_myUserIdByOrigin.clear();
set({
spaces: [],
currentSpaceId: null,
channels: [],
categories: [],
members: [],
roles: [],
folders: [],
spaceLayout: null,
dmChannels: [],
channelToSpaceMap: new Map(),
channelLastMessageIds: new Map(),
spacePermissions: new Map(),
channelPermissions: new Map(),
channelOriginMap: new Map(),
categoryOriginMap: new Map(),
_layoutUpdatedAt: 0,
});
},
setSpaces: (spaces) => set({ spaces }),
setCurrentSpace: (spaceId) => set({ currentSpaceId: spaceId }),
setChannels: (channels) => set({ channels }),