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:
@@ -76,10 +76,13 @@ func (m *MentionHandler) ParseAndNotify(ctx context.Context, channelID, authorID
|
||||
}
|
||||
|
||||
if isEveryone {
|
||||
// Send to all server members
|
||||
// Send to all server members except those who muted this channel
|
||||
rows, err := m.db.QueryContext(ctx,
|
||||
`SELECT user_id FROM members WHERE server_id = $1 AND user_id != $2`,
|
||||
serverID, authorID,
|
||||
`SELECT m.user_id FROM members m
|
||||
LEFT JOIN notification_settings ns ON ns.user_id = m.user_id AND ns.channel_id = $3
|
||||
WHERE m.server_id = $1 AND m.user_id != $2
|
||||
AND (ns.level IS NULL OR ns.level != 'none')`,
|
||||
serverID, authorID, channelID,
|
||||
)
|
||||
if err != nil {
|
||||
m.logger.Error("failed to query server members for @everyone", "error", err)
|
||||
@@ -141,6 +144,16 @@ func (m *MentionHandler) ParseAndNotify(ctx context.Context, channelID, authorID
|
||||
continue
|
||||
}
|
||||
|
||||
// Check if user muted this channel
|
||||
var level string
|
||||
err = m.db.QueryRowContext(ctx,
|
||||
`SELECT level FROM notification_settings WHERE user_id = $1 AND channel_id = $2`,
|
||||
userID, channelID,
|
||||
).Scan(&level)
|
||||
if err == nil && level == "none" {
|
||||
continue
|
||||
}
|
||||
|
||||
go m.push.SendPush(ctx, userID, payload)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user