refactor(team): extract messages panel mode persistence
This commit is contained in:
parent
f0ca6a57c2
commit
ab76e5424d
3 changed files with 104 additions and 27 deletions
|
|
@ -89,6 +89,10 @@ import {
|
||||||
pruneOptimisticMessages,
|
pruneOptimisticMessages,
|
||||||
upsertOptimisticTeamMessage,
|
upsertOptimisticTeamMessage,
|
||||||
} from '../team/teamMessagesCache';
|
} from '../team/teamMessagesCache';
|
||||||
|
import {
|
||||||
|
loadPersistedMessagesPanelMode,
|
||||||
|
savePersistedMessagesPanelMode,
|
||||||
|
} from '../team/teamMessagesPanelModePersistence';
|
||||||
import {
|
import {
|
||||||
clearAllPendingReplyRefreshWaits,
|
clearAllPendingReplyRefreshWaits,
|
||||||
clearPendingReplyRefreshWaits,
|
clearPendingReplyRefreshWaits,
|
||||||
|
|
@ -175,6 +179,10 @@ export type {
|
||||||
TeamMessagesCacheEntry,
|
TeamMessagesCacheEntry,
|
||||||
} from '../team/teamMessagesCache';
|
} from '../team/teamMessagesCache';
|
||||||
export { selectMemberMessagesForTeamMember, selectTeamMessages } from '../team/teamMessagesCache';
|
export { selectMemberMessagesForTeamMember, selectTeamMessages } from '../team/teamMessagesCache';
|
||||||
|
export {
|
||||||
|
loadPersistedMessagesPanelMode,
|
||||||
|
savePersistedMessagesPanelMode,
|
||||||
|
} from '../team/teamMessagesPanelModePersistence';
|
||||||
export {
|
export {
|
||||||
getActiveTeamPendingReplyWaits,
|
getActiveTeamPendingReplyWaits,
|
||||||
hasActiveTeamPendingReplyWait,
|
hasActiveTeamPendingReplyWait,
|
||||||
|
|
@ -2200,33 +2208,6 @@ export interface TeamSlice {
|
||||||
|
|
||||||
// --- Per-team launch params persistence ---
|
// --- Per-team launch params persistence ---
|
||||||
const LAUNCH_PARAMS_PREFIX = 'team:launchParams:';
|
const LAUNCH_PARAMS_PREFIX = 'team:launchParams:';
|
||||||
const MESSAGES_PANEL_MODE_STORAGE_KEY = 'team:messagesPanelMode';
|
|
||||||
const DEFAULT_MESSAGES_PANEL_MODE: TeamMessagesPanelMode = 'sidebar';
|
|
||||||
const VALID_MESSAGES_PANEL_MODES: ReadonlySet<TeamMessagesPanelMode> = new Set([
|
|
||||||
'sidebar',
|
|
||||||
'inline',
|
|
||||||
'bottom-sheet',
|
|
||||||
'floating-composer',
|
|
||||||
]);
|
|
||||||
|
|
||||||
export function loadPersistedMessagesPanelMode(): TeamMessagesPanelMode {
|
|
||||||
try {
|
|
||||||
const persisted = localStorage.getItem(MESSAGES_PANEL_MODE_STORAGE_KEY);
|
|
||||||
return VALID_MESSAGES_PANEL_MODES.has(persisted as TeamMessagesPanelMode)
|
|
||||||
? (persisted as TeamMessagesPanelMode)
|
|
||||||
: DEFAULT_MESSAGES_PANEL_MODE;
|
|
||||||
} catch {
|
|
||||||
return DEFAULT_MESSAGES_PANEL_MODE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function savePersistedMessagesPanelMode(mode: TeamMessagesPanelMode): void {
|
|
||||||
try {
|
|
||||||
localStorage.setItem(MESSAGES_PANEL_MODE_STORAGE_KEY, mode);
|
|
||||||
} catch {
|
|
||||||
// ignore - best-effort UI preference persistence
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getCurrentProvisioningProgressForTeam(
|
export function getCurrentProvisioningProgressForTeam(
|
||||||
state: Pick<TeamSlice, 'currentProvisioningRunIdByTeam' | 'provisioningRuns'>,
|
state: Pick<TeamSlice, 'currentProvisioningRunIdByTeam' | 'provisioningRuns'>,
|
||||||
|
|
|
||||||
29
src/renderer/store/team/teamMessagesPanelModePersistence.ts
Normal file
29
src/renderer/store/team/teamMessagesPanelModePersistence.ts
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
import type { TeamMessagesPanelMode } from '@renderer/types/teamMessagesPanelMode';
|
||||||
|
|
||||||
|
const MESSAGES_PANEL_MODE_STORAGE_KEY = 'team:messagesPanelMode';
|
||||||
|
const DEFAULT_MESSAGES_PANEL_MODE: TeamMessagesPanelMode = 'sidebar';
|
||||||
|
const VALID_MESSAGES_PANEL_MODES: ReadonlySet<TeamMessagesPanelMode> = new Set([
|
||||||
|
'sidebar',
|
||||||
|
'inline',
|
||||||
|
'bottom-sheet',
|
||||||
|
'floating-composer',
|
||||||
|
]);
|
||||||
|
|
||||||
|
export function loadPersistedMessagesPanelMode(): TeamMessagesPanelMode {
|
||||||
|
try {
|
||||||
|
const persisted = localStorage.getItem(MESSAGES_PANEL_MODE_STORAGE_KEY);
|
||||||
|
return VALID_MESSAGES_PANEL_MODES.has(persisted as TeamMessagesPanelMode)
|
||||||
|
? (persisted as TeamMessagesPanelMode)
|
||||||
|
: DEFAULT_MESSAGES_PANEL_MODE;
|
||||||
|
} catch {
|
||||||
|
return DEFAULT_MESSAGES_PANEL_MODE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function savePersistedMessagesPanelMode(mode: TeamMessagesPanelMode): void {
|
||||||
|
try {
|
||||||
|
localStorage.setItem(MESSAGES_PANEL_MODE_STORAGE_KEY, mode);
|
||||||
|
} catch {
|
||||||
|
// ignore - best-effort UI preference persistence
|
||||||
|
}
|
||||||
|
}
|
||||||
67
test/renderer/store/teamMessagesPanelModePersistence.test.ts
Normal file
67
test/renderer/store/teamMessagesPanelModePersistence.test.ts
Normal file
|
|
@ -0,0 +1,67 @@
|
||||||
|
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
||||||
|
|
||||||
|
import {
|
||||||
|
loadPersistedMessagesPanelMode,
|
||||||
|
savePersistedMessagesPanelMode,
|
||||||
|
} from '../../../src/renderer/store/team/teamMessagesPanelModePersistence';
|
||||||
|
|
||||||
|
import type { TeamMessagesPanelMode } from '../../../src/renderer/types/teamMessagesPanelMode';
|
||||||
|
|
||||||
|
const STORAGE_KEY = 'team:messagesPanelMode';
|
||||||
|
|
||||||
|
describe('teamMessagesPanelModePersistence', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
window.localStorage.clear();
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
vi.restoreAllMocks();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('defaults to sidebar when no value was persisted', () => {
|
||||||
|
expect(loadPersistedMessagesPanelMode()).toBe('sidebar');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('loads each supported persisted mode', () => {
|
||||||
|
const modes: TeamMessagesPanelMode[] = [
|
||||||
|
'sidebar',
|
||||||
|
'inline',
|
||||||
|
'bottom-sheet',
|
||||||
|
'floating-composer',
|
||||||
|
];
|
||||||
|
|
||||||
|
for (const mode of modes) {
|
||||||
|
window.localStorage.setItem(STORAGE_KEY, mode);
|
||||||
|
|
||||||
|
expect(loadPersistedMessagesPanelMode()).toBe(mode);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('falls back to sidebar for invalid persisted values', () => {
|
||||||
|
window.localStorage.setItem(STORAGE_KEY, 'bad-mode');
|
||||||
|
|
||||||
|
expect(loadPersistedMessagesPanelMode()).toBe('sidebar');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('persists the selected mode', () => {
|
||||||
|
savePersistedMessagesPanelMode('inline');
|
||||||
|
|
||||||
|
expect(window.localStorage.getItem(STORAGE_KEY)).toBe('inline');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('falls back to sidebar when localStorage read fails', () => {
|
||||||
|
vi.spyOn(Storage.prototype, 'getItem').mockImplementation(() => {
|
||||||
|
throw new Error('blocked');
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(loadPersistedMessagesPanelMode()).toBe('sidebar');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('ignores localStorage write failures', () => {
|
||||||
|
vi.spyOn(Storage.prototype, 'setItem').mockImplementation(() => {
|
||||||
|
throw new Error('blocked');
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(() => savePersistedMessagesPanelMode('bottom-sheet')).not.toThrow();
|
||||||
|
});
|
||||||
|
});
|
||||||
Loading…
Reference in a new issue