mirror of
https://github.com/PR0M3TH3AN/bitvid.git
synced 2026-10-27 07:52:24 +00:00
dm: make a selected recipient the active conversation in the right pane
Clicking "Message" added the user to the sidebar list but the right-hand message pane stayed on the previously-active conversation. setDirectMessageRecipient called setFocusedDmConversation (which only tracks read-state) and never set activeDmConversationId — the value buildDmConversationData reads to choose which thread the right pane renders — so it kept resolving the stale id. Set activeDmConversationId directly (mirroring handleDmConversationSelect), and switch the mobile pane to the thread for explicit selections (not the auto thread-default). Regression: tests/ui/dm-set-recipient-active.test.mjs. Co-Authored-By: Claude Opus 4.8 <[email protected]>
This commit is contained in:
1 parent
ebea4434de
commit
ab68ba51d0
2 files changed
+107
-4
No files matched your search
@@ -242,15 +242,24 @@ export class ProfileDirectMessageController {
|
||||
this.updateMessageThreadSelection(nextRecipient);
|
||||
|
||||
if (nextRecipient) {
|
||||
// Focus this recipient's conversation so a freshly-selected recipient
|
||||
// (e.g. the "Message" button for someone with no existing thread) isn't
|
||||
// overridden by a stale activeDmConversationId pointing at the top of the
|
||||
// inbox.
|
||||
// Make this recipient's conversation the active one so a freshly-selected
|
||||
// recipient (e.g. the "Message" button for someone with no existing
|
||||
// thread) isn't overridden by a stale activeDmConversationId pointing at
|
||||
// the top of the inbox. setFocusedDmConversation only tracks read-state —
|
||||
// activeDmConversationId is what buildDmConversationData reads to decide
|
||||
// which thread the right-hand pane renders, so set it directly (mirroring
|
||||
// handleDmConversationSelect).
|
||||
const actor = this.helper.resolveActiveDmActor();
|
||||
const conversationId = actor
|
||||
? this.helper.buildDmConversationId(actor, nextRecipient)
|
||||
: "";
|
||||
if (conversationId) {
|
||||
this.activeDmConversationId = conversationId;
|
||||
// Selecting a recipient explicitly (not the auto thread-default) means
|
||||
// the user wants to see that thread — switch the mobile pane to it too.
|
||||
if (reason !== "thread-default") {
|
||||
this.dmMobileView = "thread";
|
||||
}
|
||||
this.setFocusedDmConversation(conversationId);
|
||||
}
|
||||
void this.helper.ensureDmRecipientData(nextRecipient);
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
// Regression: clicking the "Message" button added the user to the sidebar but
|
||||
// the right-hand message pane stayed on the previously-active conversation.
|
||||
// setDirectMessageRecipient relied on setFocusedDmConversation (which only
|
||||
// tracks read-state) and never updated activeDmConversationId — the value
|
||||
// buildDmConversationData reads to decide which thread the right pane renders.
|
||||
//
|
||||
// Scenario (SCN-dm-select-makes-active):
|
||||
// Given a controller whose activeDmConversationId points at an old thread,
|
||||
// When a new recipient is selected via setDirectMessageRecipient,
|
||||
// Then activeDmConversationId becomes the new recipient's conversation id
|
||||
// (so the right pane switches), and the mobile pane shows the thread.
|
||||
|
||||
import test from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
|
||||
import { ProfileDirectMessageController } from "../../js/ui/profileModal/ProfileDirectMessageController.js";
|
||||
|
||||
// The method does `instanceof HTMLElement` guards; the stubbed DOM refs are null,
|
||||
// so the constructor just needs the global to exist.
|
||||
if (typeof globalThis.HTMLElement === "undefined") {
|
||||
globalThis.HTMLElement = class HTMLElement {};
|
||||
}
|
||||
|
||||
const ACTOR = "a".repeat(64);
|
||||
const OLD = "b".repeat(64);
|
||||
const NEW = "c".repeat(64);
|
||||
|
||||
function makeFakeController() {
|
||||
const focusCalls = [];
|
||||
return {
|
||||
activeDmConversationId: `dm:${[ACTOR, OLD].sort().join(":")}`,
|
||||
dmMobileView: "list",
|
||||
dmPrivacyToggleTouched: true,
|
||||
directMessagesCache: [],
|
||||
focusCalls,
|
||||
mainController: {
|
||||
normalizeHexPubkey: (v) => (typeof v === "string" && v.trim() ? v.trim() : ""),
|
||||
state: { setDmRecipient: () => {} },
|
||||
},
|
||||
helper: {
|
||||
resolveActiveDmActor: () => ACTOR,
|
||||
buildDmConversationId: (actor, remote) =>
|
||||
`dm:${[actor, remote].sort().join(":")}`,
|
||||
ensureDmRecipientData: () => {},
|
||||
},
|
||||
renderer: {
|
||||
profileMessagesList: null,
|
||||
dmAppShellContainer: null,
|
||||
setMessagesAnnouncement: () => {},
|
||||
renderDirectMessageConversation: () => {},
|
||||
renderDmAppShell: () => {},
|
||||
},
|
||||
updateMessageThreadSelection() {},
|
||||
setFocusedDmConversation(id) {
|
||||
focusCalls.push(id);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
test("selecting a recipient makes its conversation active in the right pane", () => {
|
||||
const ctx = makeFakeController();
|
||||
const expectedId = `dm:${[ACTOR, NEW].sort().join(":")}`;
|
||||
|
||||
const result = ProfileDirectMessageController.prototype.setDirectMessageRecipient.call(
|
||||
ctx,
|
||||
NEW,
|
||||
{ reason: "external" },
|
||||
);
|
||||
|
||||
assert.equal(result, NEW, "returns the normalized recipient");
|
||||
assert.equal(
|
||||
ctx.activeDmConversationId,
|
||||
expectedId,
|
||||
"activeDmConversationId must move to the selected recipient (not stay on the old thread)",
|
||||
);
|
||||
assert.equal(ctx.dmMobileView, "thread", "mobile pane switches to the thread");
|
||||
assert.deepEqual(
|
||||
ctx.focusCalls,
|
||||
[expectedId],
|
||||
"still tracks read-state for the focused conversation",
|
||||
);
|
||||
});
|
||||
|
||||
test("the auto thread-default does not force the mobile thread view", () => {
|
||||
const ctx = makeFakeController();
|
||||
ProfileDirectMessageController.prototype.setDirectMessageRecipient.call(ctx, NEW, {
|
||||
reason: "thread-default",
|
||||
});
|
||||
assert.equal(
|
||||
ctx.dmMobileView,
|
||||
"list",
|
||||
"thread-default keeps the inbox list visible on mobile",
|
||||
);
|
||||
});
|
||||
Reference in new issue
Block a user