feat(phase7): per-channel notification settings and read receipts
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
This commit is contained in:
@@ -6,6 +6,7 @@ import { useMemberStore } from "../stores/member.ts";
|
||||
import { useThreadStore } from "../stores/thread.ts";
|
||||
import { GiphyPicker, type Gif } from "./GiphyPicker";
|
||||
import { MentionDropdown } from "./MentionDropdown";
|
||||
import { useReadStatesStore } from "../stores/readStates.ts";
|
||||
import { MessageSearch } from "./MessageSearch";
|
||||
import { ThreadListPanel } from "./ThreadListPanel.tsx";
|
||||
import { ThreadPanel } from "./ThreadPanel.tsx";
|
||||
@@ -140,6 +141,7 @@ export function ChatArea() {
|
||||
const activeChannel = channels.find((c) => c.id === activeChannelId);
|
||||
const members = activeServerId ? membersByServer[activeServerId] || [] : [];
|
||||
const memberUsernames = useMemo(() => new Set(members.map((m) => m.username)), [members]);
|
||||
const markRead = useReadStatesStore((s) => s.markRead);
|
||||
|
||||
useEffect(() => {
|
||||
if (activeChannelId) {
|
||||
@@ -148,6 +150,14 @@ export function ChatArea() {
|
||||
}
|
||||
}, [activeChannelId, fetchMessages]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!activeChannelId || messages.length === 0 || isLoading) return;
|
||||
const lastMsg = messages[messages.length - 1];
|
||||
if (lastMsg?.id) {
|
||||
markRead(activeChannelId, lastMsg.id);
|
||||
}
|
||||
}, [activeChannelId, messages.length, isLoading]);
|
||||
|
||||
useEffect(() => {
|
||||
bottomRef.current?.scrollIntoView({ behavior: "auto" });
|
||||
}, [messages]);
|
||||
|
||||
Reference in New Issue
Block a user