mirror of
https://github.com/basecamp/once-campfire.git
synced 2026-10-08 07:40:08 +09:00
a740581f20
The job picks the room's members once and then publishes to them one at a time, as the request did before it. A member who opens the room during that loop gets the read event in their other tabs and then the older notice, which marked the room unread again. Both events now carry the server time, and the sidebar ignores a notice dated before the room's latest read. The notice still moves a direct room to the top. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0142qgjggdJ2KDdGk7RF9Xm9
30 lines
1.2 KiB
Ruby
30 lines
1.2 KiB
Ruby
module Message::Broadcasts
|
|
def broadcast_create
|
|
broadcast_append_to room, :messages, target: [ room, :messages ]
|
|
broadcast_unread_room_later
|
|
end
|
|
|
|
def broadcast_remove
|
|
broadcast_remove_to room, :messages
|
|
end
|
|
|
|
# Fanned out to the room's members rather than published on one global stream, so
|
|
# that the timing of activity in a room only reaches people who are in it. Of those,
|
|
# only the ones who still have it unread or are in it now: by the time this runs,
|
|
# someone may have opened the room and moved on, and would see it marked unread again.
|
|
def broadcast_unread_room
|
|
payload = ActiveSupport::JSON.encode(roomId: room.id, at: created_at.to_fs(:epoch))
|
|
|
|
room.memberships.unread.or(room.memberships.connected).pluck(:user_id).each do |user_id|
|
|
ActionCable.server.broadcast UnreadRoomsChannel.stream_name_for(user_id), payload, coder: nil
|
|
end
|
|
end
|
|
|
|
private
|
|
# The fanout is one publish per member, which in a big room takes far longer than the
|
|
# rest of posting a message, so it runs in a job rather than while the poster waits.
|
|
def broadcast_unread_room_later
|
|
Message::BroadcastUnreadRoomJob.perform_later(self)
|
|
end
|
|
end
|