fix: read receipts (single/double check), push notifications for all users

- Track when others read messages via messages_read WS event
- Show Check (single) for sent, CheckCheck (double) only when read
- Send push to all recipients, SW suppresses if app is focused

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Ai
2026-05-22 13:47:38 +03:00
parent 86073c0549
commit 20daa2ca2f
6 changed files with 31 additions and 16 deletions

View File

@@ -9,6 +9,7 @@ interface AppStore {
onlineUsers: Set<string>;
typingUsers: Record<string, string[]>;
connected: boolean;
chatReadAt: Record<string, string>; // chatId → ISO timestamp others last read
setUser: (user: User | null) => void;
setChats: (chats: Chat[]) => void;
@@ -23,6 +24,7 @@ interface AppStore {
setTyping: (chatId: string, userId: string, typing: boolean) => void;
setConnected: (v: boolean) => void;
markRead: (chatId: string) => void;
markReadByOther: (chatId: string) => void;
logout: () => void;
}
@@ -41,6 +43,7 @@ export const useStore = create<AppStore>((set, get) => ({
onlineUsers: new Set(),
typingUsers: {},
connected: false,
chatReadAt: {},
setUser: (user) => set({ user }),
@@ -120,9 +123,13 @@ export const useStore = create<AppStore>((set, get) => ({
chats: state.chats.map(c => c.id === chatId ? { ...c, unreadCount: 0 } : c)
})),
markReadByOther: (chatId) => set(state => ({
chatReadAt: { ...state.chatReadAt, [chatId]: new Date().toISOString() }
})),
logout: () => {
localStorage.removeItem('jc_token');
localStorage.removeItem('jc_user');
set({ user: null, chats: [], activeChat: null, messages: {}, connected: false });
set({ user: null, chats: [], activeChat: null, messages: {}, connected: false, chatReadAt: {} });
},
}));