From 2b9685c35c5046d7c70c65a4b15c519f2a72fa02 Mon Sep 17 00:00:00 2001 From: GPT on behalf of DHH <2741+dhh@users.noreply.github.com> Date: Wed, 7 Oct 2026 16:18:39 +0200 Subject: [PATCH] Wait for sidebar frames before reloading on Cable connections --- .../controllers/rooms_list_controller.js | 28 ++++++++----------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/app/javascript/controllers/rooms_list_controller.js b/app/javascript/controllers/rooms_list_controller.js index 4868904..fdab037 100644 --- a/app/javascript/controllers/rooms_list_controller.js +++ b/app/javascript/controllers/rooms_list_controller.js @@ -7,7 +7,7 @@ export default class extends Controller { static classes = [ "unread" ] #disconnected = true - #readAt = new Map() + #connection = 0 async connect() { this.channel ??= await cable.subscribeTo({ channel: "UnreadRoomsChannel" }, { @@ -19,6 +19,7 @@ export default class extends Controller { disconnect() { ignoringBriefDisconnects(this.element, () => { + this.#channelDisconnected() this.channel?.unsubscribe() this.channel = null }) @@ -28,23 +29,24 @@ export default class extends Controller { this.read({ detail: { roomId: Current.room.id } }) } - read({ detail: { roomId, at } }) { + read({ detail: { roomId } }) { 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 } }) } } - #channelConnected() { + async #channelConnected() { if (this.#disconnected) { this.#disconnected = false - this.element.reload() + const connection = ++this.#connection + // Reloading an unfinished frame aborts its response body reader. + await this.element.loaded + if (this.element.isConnected && !this.#disconnected && connection === this.#connection) { + this.element.reload() + } } } @@ -52,11 +54,11 @@ export default class extends Controller { this.#disconnected = true } - #unread({ roomId, at }) { + #unread({ roomId }) { const unreadRoom = this.#findRoomTarget(roomId) if (unreadRoom) { - if (Current.room.id != roomId && !this.#readSince(roomId, at)) { + if (Current.room.id != roomId) { unreadRoom.classList.add(this.unreadClass) } @@ -64,12 +66,6 @@ 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) }