Private
Public Access
Add unread message indicators for rooms (#38)
Shows a dot on rooms with unread messages in the sidebar, updated live over WebSocket. Reuses the same offline-member audience computation already used for push notifications: a member gets the real-time signal whenever they aren't currently connected to that room's channel, which correctly covers both "room not open" and "room open but tab backgrounded" (the client leaves a room's channel while hidden). Persisted server-side via a new room_memberships.last_read_at column so state survives reload and stays consistent across devices, advanced by an explicit mark-read call the frontend makes on room-open and on each live message received while the room is genuinely visible -- gated on a live visibility check, not a cached ref, so a backgrounded-but-open room keeps accumulating unread instead of auto-marking-read the instant a message arrives somewhere it can't be seen. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -26,6 +26,13 @@ class RoomMembership(Base):
|
||||
joined_at: Mapped[datetime] = mapped_column(
|
||||
DateTime(timezone=True), server_default=func.now(), nullable=False
|
||||
)
|
||||
# A server_default (not an app-code default) so every membership-creation
|
||||
# call site (create_room, join_room, add_member) gets a sane starting
|
||||
# point automatically: joining counts as being caught up as of then, not
|
||||
# retroactively unread for the room's entire prior history.
|
||||
last_read_at: Mapped[datetime] = mapped_column(
|
||||
DateTime(timezone=True), server_default=func.now(), nullable=False
|
||||
)
|
||||
|
||||
room = relationship("Room", back_populates="memberships")
|
||||
user = relationship("User")
|
||||
|
||||
Reference in New Issue
Block a user