Skip to content

Commit b03be61

Browse files
loganjLarry
andauthored
fix(messages): restore main typecheck for pasted mentions (#684)
Signed-off-by: Larry <627498bd4bd1f281a16431e3c6cce3b5c25b6692798c78672298aefbf2f8f8b5@buzz.block.builderlab.xyz> Co-authored-by: Larry <627498bd4bd1f281a16431e3c6cce3b5c25b6692798c78672298aefbf2f8f8b5@buzz.block.builderlab.xyz>
1 parent 515554e commit b03be61

3 files changed

Lines changed: 73 additions & 20 deletions

File tree

‎src/features/messages/MessageComposer.tsx‎

Lines changed: 15 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import {
1010
allowsOutsideMentions,
1111
archivedMention,
1212
mentionAdmission,
13+
pastedMentionRecipient,
1314
} from "./mention-admission";
1415
import { rememberMention } from "./mention-history";
1516
import {
@@ -1398,25 +1399,20 @@ function Composer({
13981399
}}
13991400
onFormatsChange={setActiveFormats}
14001401
onEditLink={setLinkEdit}
1401-
// Pasted identity links notify the people the picker would offer,
1402-
// under their current names; edits never add recipients. In a
1403-
// stream or forum, a cached profile outside the channel counts as
1404-
// a picked directory row, so Send asks before adding them. The
1405-
// pasted label is never the name: it could disguise the invitee.
1406-
acceptRecipient={(pubkey) => {
1407-
if (editing.target) return null;
1408-
const name = session.profiles.snapshot().get(pubkey)?.name;
1409-
return (
1410-
mentionCandidates(
1411-
session,
1412-
channelId,
1413-
agentChoices,
1414-
mentionRoster,
1415-
name ? [{ pubkey, name }] : [],
1416-
).find((c) => c.recipient.pubkey === pubkey)?.recipient ??
1417-
null
1418-
);
1419-
}}
1402+
// Pasted identity links notify admitted recipients under their
1403+
// current names; edits never add recipients. Send still asks
1404+
// before adding someone outside the channel.
1405+
acceptRecipient={(pubkey) =>
1406+
editing.target
1407+
? null
1408+
: pastedMentionRecipient(
1409+
session,
1410+
channelId,
1411+
pubkey,
1412+
agentChoices,
1413+
mentionRoster,
1414+
)
1415+
}
14201416
data-single-emoji={largeEmojiDraft || undefined}
14211417
maxLength={16000}
14221418
aria-label={label}

‎src/features/messages/mention-admission.test.ts‎

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { expect, it } from "vitest";
22
import type { RelaySession } from "../relay/session";
3-
import { mentionAdmission } from "./mention-admission";
3+
import { mentionAdmission, pastedMentionRecipient } from "./mention-admission";
44

55
const member = "a".repeat(64);
66
const outside = "b".repeat(64);
@@ -84,3 +84,28 @@ it("refuses invalid keys, archived identities and closed destinations", () => {
8484
)(member),
8585
).toBe(false);
8686
});
87+
88+
it("names a pasted recipient from current state, and leaves an unknown outsider display-only", () => {
89+
const base = session({ channelType: "stream" });
90+
const profiles = new Map([[outside, { name: "Jane" }]]);
91+
const withProfiles = {
92+
...base,
93+
profiles: { snapshot: () => profiles },
94+
} as unknown as RelaySession;
95+
expect(pastedMentionRecipient(withProfiles, "channel", outside)).toEqual({
96+
pubkey: outside,
97+
name: "Jane",
98+
});
99+
expect(pastedMentionRecipient(withProfiles, "channel", member)).toEqual({
100+
pubkey: member,
101+
name: member.slice(0, 12),
102+
});
103+
expect(pastedMentionRecipient(withProfiles, "channel", library)).toEqual({
104+
pubkey: library,
105+
name: "Honey",
106+
});
107+
expect(pastedMentionRecipient(withProfiles, "channel", "f".repeat(64))).toBe(
108+
null,
109+
);
110+
expect(pastedMentionRecipient(withProfiles, "channel", archived)).toBe(null);
111+
});

‎src/features/messages/mention-admission.ts‎

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,3 +48,35 @@ export function mentionAdmission(
4848
!archivedMention(session, pubkey) &&
4949
(outside || allowed.has(pubkey));
5050
}
51+
52+
/**
53+
* The recipient a pasted identity link adds, under its current name, or null.
54+
* The pasted label is never the name: it could disguise the invitee. A key
55+
* with no known name is accepted only if it is a member; otherwise the link
56+
* stays display-only, as the chooser would not offer it.
57+
*/
58+
export function pastedMentionRecipient(
59+
session: RelaySession,
60+
channelId: string,
61+
pubkey: string,
62+
inviteAgents = false,
63+
roster?: readonly MentionRecipient[],
64+
): MentionRecipient | null {
65+
if (!mentionAdmission(session, channelId, inviteAgents, roster)(pubkey))
66+
return null;
67+
const listed = roster?.find((person) => person.pubkey === pubkey);
68+
const name =
69+
session.profiles.snapshot().get(pubkey)?.name ||
70+
listed?.name ||
71+
session.agentChoices
72+
.snapshot()
73+
.identities.find((agent) => agent.pubkey === pubkey)?.name;
74+
if (name) return { pubkey, name };
75+
const member = roster
76+
? !!listed
77+
: !!session.channels
78+
.list()
79+
.channels.find((c) => c.id === channelId)
80+
?.members?.includes(pubkey);
81+
return member ? { pubkey, name: pubkey.slice(0, 12) } : null;
82+
}

0 commit comments

Comments
 (0)