fix(notifications): sync mute state in chat store immediately
Some checks failed
CI / test (push) Has been cancelled

This commit is contained in:
2026-03-08 20:40:44 +03:00
parent 418c9e6044
commit 20f31cd15e
3 changed files with 8 additions and 1 deletions

View File

@@ -34,7 +34,7 @@ Legend:
25. Admin Rights - `PARTIAL` (delete/pin/edit info + explicit ban API for groups/channels; integration tests cover channel member read-only, channel admin full-delete, channel message delete-for-all permissions, group profile edit permissions, and owner-only role management rules; remaining UX moderation tools limited) 25. Admin Rights - `PARTIAL` (delete/pin/edit info + explicit ban API for groups/channels; integration tests cover channel member read-only, channel admin full-delete, channel message delete-for-all permissions, group profile edit permissions, and owner-only role management rules; remaining UX moderation tools limited)
26. Channels - `PARTIAL` (create/post/edit/delete/subscribe/unsubscribe; UX edge-cases still polishing) 26. Channels - `PARTIAL` (create/post/edit/delete/subscribe/unsubscribe; UX edge-cases still polishing)
27. Channel Types - `DONE` (public/private) 27. Channel Types - `DONE` (public/private)
28. Notifications - `PARTIAL` (browser notifications + mute/settings; chat mute is now propagated in chat list payload and honored by web realtime notifications with mention override; no mobile push infra) 28. Notifications - `PARTIAL` (browser notifications + mute/settings; chat mute is propagated in chat list payload, honored by web realtime notifications with mention override, and mute toggle now syncs instantly in chat store; no mobile push infra)
29. Archive - `DONE` 29. Archive - `DONE`
30. Blacklist - `DONE` 30. Blacklist - `DONE`
31. Privacy - `PARTIAL` (avatar/last-seen/group-invites + PM policy `everyone|contacts|nobody`; group-invite `nobody` is available in API and web settings; integration tests cover PM policy matrix (`everyone/contacts/nobody`), group-invite policy matrix (`everyone/contacts/nobody`), and private chat counterpart visibility for `nobody/contacts`, remaining UX/matrix hardening) 31. Privacy - `PARTIAL` (avatar/last-seen/group-invites + PM policy `everyone|contacts|nobody`; group-invite `nobody` is available in API and web settings; integration tests cover PM policy matrix (`everyone/contacts/nobody`), group-invite policy matrix (`everyone/contacts/nobody`), and private chat counterpart visibility for `nobody/contacts`, remaining UX/matrix hardening)

View File

@@ -34,6 +34,7 @@ interface Props {
export function ChatInfoPanel({ chatId, open, onClose }: Props) { export function ChatInfoPanel({ chatId, open, onClose }: Props) {
const me = useAuthStore((s) => s.me); const me = useAuthStore((s) => s.me);
const loadChats = useChatStore((s) => s.loadChats); const loadChats = useChatStore((s) => s.loadChats);
const updateChatMuted = useChatStore((s) => s.updateChatMuted);
const setActiveChatId = useChatStore((s) => s.setActiveChatId); const setActiveChatId = useChatStore((s) => s.setActiveChatId);
const setFocusedMessage = useChatStore((s) => s.setFocusedMessage); const setFocusedMessage = useChatStore((s) => s.setFocusedMessage);
const showToast = useUiStore((s) => s.showToast); const showToast = useUiStore((s) => s.showToast);
@@ -306,6 +307,7 @@ export function ChatInfoPanel({ chatId, open, onClose }: Props) {
try { try {
const updated = await updateChatNotificationSettings(chatId, !muted); const updated = await updateChatNotificationSettings(chatId, !muted);
setMuted(updated.muted); setMuted(updated.muted);
updateChatMuted(chatId, updated.muted);
} catch { } catch {
setError("Failed to update notifications"); setError("Failed to update notifications");
} finally { } finally {

View File

@@ -99,6 +99,7 @@ interface ChatState {
setReplyToMessage: (chatId: number, message: Message | null) => void; setReplyToMessage: (chatId: number, message: Message | null) => void;
setEditingMessage: (chatId: number, message: Message | null) => void; setEditingMessage: (chatId: number, message: Message | null) => void;
updateChatPinnedMessage: (chatId: number, pinnedMessageId: number | null) => void; updateChatPinnedMessage: (chatId: number, pinnedMessageId: number | null) => void;
updateChatMuted: (chatId: number, muted: boolean) => void;
applyPresenceEvent: (chatId: number, userId: number, isOnline: boolean, lastSeenAt?: string) => void; applyPresenceEvent: (chatId: number, userId: number, isOnline: boolean, lastSeenAt?: string) => void;
removeChat: (chatId: number) => void; removeChat: (chatId: number) => void;
setDraft: (chatId: number, text: string) => void; setDraft: (chatId: number, text: string) => void;
@@ -416,6 +417,10 @@ export const useChatStore = create<ChatState>((set, get) => ({
set((state) => ({ set((state) => ({
chats: state.chats.map((chat) => (chat.id === chatId ? { ...chat, pinned_message_id: pinnedMessageId } : chat)) chats: state.chats.map((chat) => (chat.id === chatId ? { ...chat, pinned_message_id: pinnedMessageId } : chat))
})), })),
updateChatMuted: (chatId, muted) =>
set((state) => ({
chats: state.chats.map((chat) => (chat.id === chatId ? { ...chat, muted } : chat))
})),
applyPresenceEvent: (chatId, userId, isOnline, lastSeenAt) => applyPresenceEvent: (chatId, userId, isOnline, lastSeenAt) =>
set((state) => ({ set((state) => ({
chats: state.chats.map((chat) => { chats: state.chats.map((chat) => {