diff --git a/js/ui/videoModalCommentController.js b/js/ui/videoModalCommentController.js index 7c2451f0..508a44a2 100644 --- a/js/ui/videoModalCommentController.js +++ b/js/ui/videoModalCommentController.js @@ -202,21 +202,29 @@ export default class VideoModalCommentController { this.videoModal.resetCommentComposer?.(); this.videoModal.setCommentStatus?.("Loading comments…"); - const loadPromise = this.commentThreadService.loadThread({ + const loadResult = this.commentThreadService.loadThread({ video, parentCommentId: null, limit: this.modalCommentLimit, }); - if (!loadPromise || typeof loadPromise.then !== "function") { + if (!loadResult) { this.applyCommentComposerAuthState(); return; } - this.modalCommentLoadPromise = loadPromise; - loadPromise + if (typeof loadResult.then !== "function") { + const didRenderSnapshot = this.handleCommentThreadReady(loadResult); + if (didRenderSnapshot === false) { + this.applyCommentComposerAuthState(); + } + return; + } + + this.modalCommentLoadPromise = loadResult; + loadResult .then((snapshot) => { - if (this.modalCommentLoadPromise === loadPromise) { + if (this.modalCommentLoadPromise === loadResult) { this.modalCommentLoadPromise = null; } @@ -226,7 +234,7 @@ export default class VideoModalCommentController { } }) .catch((error) => { - if (this.modalCommentLoadPromise === loadPromise) { + if (this.modalCommentLoadPromise === loadResult) { this.modalCommentLoadPromise = null; } this.handleCommentThreadError(error); diff --git a/tests/video-modal-comments.test.mjs b/tests/video-modal-comments.test.mjs index 983e8f6f..6c4b59b4 100644 --- a/tests/video-modal-comments.test.mjs +++ b/tests/video-modal-comments.test.mjs @@ -240,6 +240,60 @@ test( }, ); +test( + "Controller renders synchronous loadThread snapshots immediately", + async (t) => { + const { modal, cleanup } = await setupModal(); + t.after(cleanup); + + const snapshot = { + videoEventId: "video-sync-snapshot", + parentCommentId: null, + commentsById: new Map([ + [ + "sync-comment", + createCommentEvent({ + id: "sync-comment", + pubkey: "pk-sync", + content: "Snapshot delivered instantly", + createdAt: 1700000200, + }), + ], + ]), + childrenByParent: new Map([[null, ["sync-comment"]]]), + profiles: new Map([["pk-sync", { name: "Synchronous" }]]), + }; + + const controller = new VideoModalCommentController({ + commentThreadService: { + defaultLimit: 1, + setCallbacks: () => {}, + teardown: () => {}, + loadThread: () => snapshot, + }, + videoModal: modal, + auth: { + isLoggedIn: () => false, + }, + }); + + controller.load({ id: "video-sync-snapshot", enableComments: true }); + await Promise.resolve(); + + const renderedComments = Array.from( + modal.commentsList.querySelectorAll("[data-comment-id]") || [], + ); + assert.equal(renderedComments.length, 1); + assert.equal(renderedComments[0].dataset.commentId, "sync-comment"); + + const statusText = + modal.commentsStatusMessage?.textContent.trim().replace(/\s+/g, " ") || + ""; + assert.equal(statusText, ""); + assert.equal(modal.commentComposerState.reason, "login-required"); + }, +); + test( "VideoModalCommentController attaches profiles using normalized pubkeys", async () => {