diff --git a/app/javascript/controllers/rooms_list_controller.js b/app/javascript/controllers/rooms_list_controller.js index fdab037..11f5e3a 100644 --- a/app/javascript/controllers/rooms_list_controller.js +++ b/app/javascript/controllers/rooms_list_controller.js @@ -8,6 +8,7 @@ export default class extends Controller { #disconnected = true #connection = 0 + #readAt = new Map() async connect() { this.channel ??= await cable.subscribeTo({ channel: "UnreadRoomsChannel" }, { @@ -29,9 +30,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 } }) @@ -54,11 +59,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) } @@ -66,6 +71,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) }