feat: Add chat seperator and restore last viewed chat on restart
This commit is contained in:
@@ -6,12 +6,15 @@ Offline-first storage layer that keeps messages, users, rooms, reactions, bans,
|
||||
|
||||
```
|
||||
persistence/
|
||||
├── index.ts Barrel (exports DatabaseService)
|
||||
├── app-resume.storage.ts localStorage helpers for launch settings and last viewed chat
|
||||
├── index.ts Barrel (exports DatabaseService and storage helpers)
|
||||
├── database.service.ts Platform-agnostic facade
|
||||
├── browser-database.service.ts IndexedDB backend (web)
|
||||
└── electron-database.service.ts IPC/SQLite backend (desktop)
|
||||
```
|
||||
|
||||
`app-resume.storage.ts` is the one exception to the `DatabaseService` facade. It stores lightweight UI-level launch preferences and the last viewed room/channel snapshot in `localStorage`, which would be unnecessary overhead to route through IndexedDB or SQLite.
|
||||
|
||||
## Platform routing
|
||||
|
||||
```mermaid
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
import {
|
||||
STORAGE_KEY_GENERAL_SETTINGS,
|
||||
STORAGE_KEY_LAST_VIEWED_CHAT
|
||||
} from '../../core/constants';
|
||||
|
||||
export interface GeneralSettings {
|
||||
reopenLastViewedChat: boolean;
|
||||
}
|
||||
|
||||
export const DEFAULT_GENERAL_SETTINGS: GeneralSettings = {
|
||||
reopenLastViewedChat: true
|
||||
};
|
||||
|
||||
export interface LastViewedChatSnapshot {
|
||||
userId: string;
|
||||
roomId: string;
|
||||
channelId: string | null;
|
||||
}
|
||||
|
||||
export function loadGeneralSettingsFromStorage(): GeneralSettings {
|
||||
try {
|
||||
const raw = localStorage.getItem(STORAGE_KEY_GENERAL_SETTINGS);
|
||||
|
||||
if (!raw) {
|
||||
return { ...DEFAULT_GENERAL_SETTINGS };
|
||||
}
|
||||
|
||||
return normaliseGeneralSettings(JSON.parse(raw) as Partial<GeneralSettings>);
|
||||
} catch {
|
||||
return { ...DEFAULT_GENERAL_SETTINGS };
|
||||
}
|
||||
}
|
||||
|
||||
export function saveGeneralSettingsToStorage(patch: Partial<GeneralSettings>): GeneralSettings {
|
||||
const nextSettings = normaliseGeneralSettings({
|
||||
...loadGeneralSettingsFromStorage(),
|
||||
...patch
|
||||
});
|
||||
|
||||
try {
|
||||
localStorage.setItem(STORAGE_KEY_GENERAL_SETTINGS, JSON.stringify(nextSettings));
|
||||
} catch {}
|
||||
|
||||
return nextSettings;
|
||||
}
|
||||
|
||||
export function loadLastViewedChatFromStorage(userId?: string | null): LastViewedChatSnapshot | null {
|
||||
try {
|
||||
const raw = localStorage.getItem(STORAGE_KEY_LAST_VIEWED_CHAT);
|
||||
|
||||
if (!raw) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const snapshot = normaliseLastViewedChatSnapshot(JSON.parse(raw) as Partial<LastViewedChatSnapshot>);
|
||||
|
||||
if (!snapshot) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (userId && snapshot.userId !== userId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return snapshot;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
export function saveLastViewedChatToStorage(snapshot: LastViewedChatSnapshot): void {
|
||||
const normalised = normaliseLastViewedChatSnapshot(snapshot);
|
||||
|
||||
if (!normalised) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
localStorage.setItem(STORAGE_KEY_LAST_VIEWED_CHAT, JSON.stringify(normalised));
|
||||
} catch {}
|
||||
}
|
||||
|
||||
export function clearLastViewedChatFromStorage(): void {
|
||||
try {
|
||||
localStorage.removeItem(STORAGE_KEY_LAST_VIEWED_CHAT);
|
||||
} catch {}
|
||||
}
|
||||
|
||||
function normaliseGeneralSettings(raw: Partial<GeneralSettings>): GeneralSettings {
|
||||
return {
|
||||
reopenLastViewedChat:
|
||||
typeof raw.reopenLastViewedChat === 'boolean'
|
||||
? raw.reopenLastViewedChat
|
||||
: DEFAULT_GENERAL_SETTINGS.reopenLastViewedChat
|
||||
};
|
||||
}
|
||||
|
||||
function normaliseLastViewedChatSnapshot(raw: Partial<LastViewedChatSnapshot>): LastViewedChatSnapshot | null {
|
||||
const userId = typeof raw.userId === 'string' ? raw.userId.trim() : '';
|
||||
const roomId = typeof raw.roomId === 'string' ? raw.roomId.trim() : '';
|
||||
const channelId = typeof raw.channelId === 'string'
|
||||
? raw.channelId.trim() || null
|
||||
: null;
|
||||
|
||||
if (!userId || !roomId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
userId,
|
||||
roomId,
|
||||
channelId
|
||||
};
|
||||
}
|
||||
@@ -1 +1,2 @@
|
||||
export * from './app-resume.storage';
|
||||
export * from './database.service';
|
||||
|
||||
Reference in New Issue
Block a user