mirror of
https://github.com/basecamp/once-campfire.git
synced 2026-10-09 00:00:12 +09:00
Keep an unread notice older than the latest read from marking the room
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
This commit is contained in:
@@ -16,7 +16,7 @@ export default class extends Controller {
|
||||
})
|
||||
}
|
||||
|
||||
#read = ({ room_id }) => {
|
||||
this.dispatch("read", { detail: { roomId: room_id } })
|
||||
#read = ({ room_id, at }) => {
|
||||
this.dispatch("read", { detail: { roomId: room_id, at } })
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ export default class extends Controller {
|
||||
static classes = [ "unread" ]
|
||||
|
||||
#disconnected = true
|
||||
#readAt = new Map()
|
||||
|
||||
async connect() {
|
||||
this.channel ??= await cable.subscribeTo({ channel: "UnreadRoomsChannel" }, {
|
||||
@@ -27,9 +28,13 @@ export default class extends Controller {
|
||||
this.read({ detail: { roomId: Current.room.id } })
|
||||
}
|
||||
|
||||
read({ detail: { roomId } }) {
|
||||
read({ detail: { roomId, at } }) {
|
||||
const room = this.#findRoomTarget(roomId)
|
||||
|
||||
if (at) {
|
||||
this.#readAt.set(Number(roomId), Math.max(Number(at), this.#readAt.get(Number(roomId)) ?? 0))
|
||||
}
|
||||
|
||||
if (room) {
|
||||
room.classList.remove(this.unreadClass)
|
||||
this.dispatch("read", { detail: { targetId: roomId } })
|
||||
@@ -47,11 +52,11 @@ export default class extends Controller {
|
||||
this.#disconnected = true
|
||||
}
|
||||
|
||||
#unread({ roomId }) {
|
||||
#unread({ roomId, at }) {
|
||||
const unreadRoom = this.#findRoomTarget(roomId)
|
||||
|
||||
if (unreadRoom) {
|
||||
if (Current.room.id != roomId) {
|
||||
if (Current.room.id != roomId && !this.#readSince(roomId, at)) {
|
||||
unreadRoom.classList.add(this.unreadClass)
|
||||
}
|
||||
|
||||
@@ -59,6 +64,12 @@ export default class extends Controller {
|
||||
}
|
||||
}
|
||||
|
||||
// Notices fan out one member at a time, so one can arrive after the member has already
|
||||
// read the room in another tab. It still reorders the room, but doesn't mark it unread.
|
||||
#readSince(roomId, at) {
|
||||
return Number(at) <= this.#readAt.get(Number(roomId))
|
||||
}
|
||||
|
||||
#findRoomTarget(roomId) {
|
||||
return this.roomTargets.find(roomTarget => roomTarget.dataset.roomId == roomId)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user