cc6ed741f0
Phase 7.1 — Per-channel notification settings
- New notification_settings table (user_id, channel_id, level)
- GET/PUT/DELETE handlers under /channels/{channelID}/notifications
- Push dispatch and @mention loops filtered by notification level
- Frontend: bell icon per channel cycling all/mentions/none
Phase 7.4 — Read receipts
- New read_states table (user_id, channel_id, last_read_message_id)
- PUT /channels/{channelID}/read and GET /users/me/read-states
- Auto-mark-read when messages load in ChatArea
- Unread dot for channels never opened
Also: favicon/icon refresh in index.html
35 lines
1.0 KiB
TypeScript
35 lines
1.0 KiB
TypeScript
import { create } from 'zustand';
|
|
import { api } from '../lib/api';
|
|
|
|
type NotificationLevel = 'all' | 'mentions' | 'none';
|
|
|
|
interface NotificationSettingsState {
|
|
settings: Record<string, NotificationLevel>;
|
|
initialized: boolean;
|
|
loaded: boolean;
|
|
fetchSettings: () => Promise<void>;
|
|
setLevel: (channelId: string, level: NotificationLevel) => Promise<void>;
|
|
}
|
|
|
|
export const useNotificationSettingsStore = create<NotificationSettingsState>()((set) => ({
|
|
settings: {},
|
|
initialized: false,
|
|
loaded: false,
|
|
|
|
fetchSettings: async () => {
|
|
try {
|
|
const settings = await api.get<Record<string, NotificationLevel>>('/channels/me/notifications');
|
|
set({ settings, loaded: true, initialized: true });
|
|
} catch {
|
|
set({ loaded: true, initialized: true });
|
|
}
|
|
},
|
|
|
|
setLevel: async (channelId: string, level: NotificationLevel) => {
|
|
await api.put(`/channels/${channelId}/notifications`, { level });
|
|
set((state) => ({
|
|
settings: { ...state.settings, [channelId]: level },
|
|
}));
|
|
},
|
|
}));
|