Skip to content

feat(mentions): let DMs mention people outside the DM, like channels - #510

Merged
wesbillman merged 6 commits into
mainfrom
feat/dm-nonmember-mentions
Oct 5, 2026
Merged

wesbillman merged 6 commits into
mainfrom
feat/dm-nonmember-mentions

Conversation

@loganj

@loganj loganj commented Oct 1, 2026 •

Copy link
Copy Markdown
Contributor

🤖

Summary

  • In a DM, you can now @mention someone who is not in the DM. Before, the mention list showed only the people in the DM, so you could not finish the mention.
  • This works the same way as in channels. The list searches the community directory, and the row says the person is not in the DM.
  • When you send, the app does not ask first. Nobody can be added to a DM, so there is no choice to make. The person shows as a mention in the message, but they are not notified. The row already says so before you pick them.

Screenshots

The row for a person outside the DM:

DM mention row

Details

  • Every channel except a session can now name outside people: streams, forums, DMs and channels with no type tag. Sessions are unchanged: their mentions add agents to the session, so they use their own agent list and do not search the directory. This rule follows the channel type, not composer settings, because some session composers (media comments, edits) do not run in session mode.
  • Channels with no type tag show in the sidebar as ordinary channels, but they did not let you mention outside people. Now they do, and they ask on send like streams. Two tests that used an untyped channel to reach the old "no longer a channel member" error now expect the prompt. Two browser tests that remove a member while the list is open now wait for the directory page first; the removed person then shows as a disabled "Channel membership changed" row, which is how streams already behave.
  • In streams and forums, the send prompt and row text are unchanged. A DM never shows the prompt.
  • The mention rules spec (src/bundled/mentions/README.md) now includes DMs in the choice set and says a DM sends outside people as references without asking, so other clients can follow the same rule. The mobile port will follow it in a separate change.

@loganj
loganj force-pushed the feat/dm-nonmember-mentions branch 2 times, most recently from d34c802 to 9656bf3 Compare October 2, 2026 02:37
@loganj
loganj marked this pull request as ready for review October 2, 2026 15:20
@loganj
loganj requested review from a team, comp615 and wesbillman as code owners October 2, 2026 15:20
Larry added 5 commits October 2, 2026 11:24
The chooser now searches the community directory in DMs, as it does in
streams and forums. Sending asks first. A DM cannot add members, so the
prompt offers only Send anyway, and the outside people become references
that do not notify anyone. Row and prompt copy name the DM.

Signed-off-by: Larry <627498bd4bd1f281a16431e3c6cce3b5c25b6692798c78672298aefbf2f8f8b5@buzz.block.builderlab.xyz>
Rename outsideMentions to allowsOutsideMentions, fix import order, use a
plain test for sessions, and test the DM label in the toolbar picker.

Signed-off-by: Larry <627498bd4bd1f281a16431e3c6cce3b5c25b6692798c78672298aefbf2f8f8b5@buzz.block.builderlab.xyz>
Nobody can be added to a DM, so the send prompt offered no real choice.
A DM now sends outside people straight away as references, which do not
notify them. The chooser row already says so. Streams and forums still ask.

Signed-off-by: Larry <627498bd4bd1f281a16431e3c6cce3b5c25b6692798c78672298aefbf2f8f8b5@buzz.block.builderlab.xyz>
Every known channel can now name people outside it. Sessions already use
their own agent list, because their mentions admit agents. The type check
only left untyped channels out, although the sidebar shows them as
channels. Those channels now ask on send, like streams.

Signed-off-by: Larry <627498bd4bd1f281a16431e3c6cce3b5c25b6692798c78672298aefbf2f8f8b5@buzz.block.builderlab.xyz>
Untyped fixture channels now search the directory, like streams. Wait
for that page before the step under test, so a late page cannot race it.
A removed member that the directory still finds stays as a disabled
"membership changed" row, and the agent namesake shows its agent label.

Signed-off-by: Larry <627498bd4bd1f281a16431e3c6cce3b5c25b6692798c78672298aefbf2f8f8b5@buzz.block.builderlab.xyz>
@loganj
loganj force-pushed the feat/dm-nonmember-mentions branch from 7260e2f to c904935 Compare October 2, 2026 15:25

@wesbillman wesbillman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One change needed: keep community-directory mentions out of session media comments (inline finding).

Star Lord automated source review via Wes’s account. Reviewed head c904935fa3147a9f6b43703d959e8e1daa352caf against base f264c623887717b7fd48c4af39b0c719e0104256; source and PR screenshot inspected, with no tests, app execution, or CI assessment.

…oser

Media comments and edits in a session mount the composer without session
mode. Removing the channel-type gate let those composers search the
community directory and ask about outside people on send. Sessions now
stay excluded by channel type in the candidates, the directory search and
the send path. The session picker test now waits past the directory delay,
so it can catch this.

Signed-off-by: Larry <627498bd4bd1f281a16431e3c6cce3b5c25b6692798c78672298aefbf2f8f8b5@buzz.block.builderlab.xyz>

@wesbillman wesbillman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No further actionable changes requested. The channel-type guard now consistently excludes sessions from directory searches, candidate admission, and ordinary nonmember prompts, including media-comment composers without session mode; the regression test also advances past the directory debounce.

Star Lord’s automated source review via Wes’s account: head 80a309bb952c5d9308c113f55ac9151e68d0a189, base f264c623887717b7fd48c4af39b0c719e0104256. Source and PR screenshot inspected; no tests, app execution, or CI assessment, so running-app behavior remains unverified.

@wesbillman
wesbillman merged commit bcd2a37 into main Oct 5, 2026
22 checks passed
@wesbillman
wesbillman deleted the feat/dm-nonmember-mentions branch October 5, 2026 14:09
loganj added a commit to block/buzz that referenced this pull request Oct 5, 2026
🤖
## Summary
The mobile app's @mention chooser now follows the same rules as the
desktop app (buzz-app). The same typed text finds the same people in the
same order on both apps, and sending works the same way.

- **Same matching and order.** Mobile uses the shared mention rules and
runs their shared test cases. A multi-word search such as `@Mary J`
still searches the community directory, so it can find "Mary Jane" even
when she is not in the channel.
- **DMs can mention people outside the DM.** The chooser marks them "not
in DM". Nobody can be added to a DM, so the message sends without a
prompt. Outside people go out as references, so they are not notified.
This matches buzz-app #510.
- **Channels still ask.** In a stream or forum, mentioning someone
outside the channel asks "Invite" or "Do nothing" before the message
sends. A channel with no type tag counts as a stream.
- **Sessions do not search the directory.** Only session members appear.
- **A failed directory search stays visible.** The chooser shows the
error and a Retry button. Before, it closed.
- **Search results stay in their community.** If you switch communities
while a search runs, its people and its error do not show in the new
community. The search starts again there.
- **A failed send check keeps the draft.** Before a message with a
mention sends, the app checks who is in the channel. If that check
fails, the message stays in the compose bar and a notice offers Retry.
Before, nothing was sent and nothing was shown.
- **Invite stays in its community.** If you switch communities while the
"Invite" question is open, Invite adds nobody.

### Screenshots
The real compose bar widget, rendered by Flutter's test renderer with
the app's fonts and theme. The data is sample data. These are not device
captures.

| DM: outside person is "not in DM" | Stream: outside person is "not in
channel" |
|---|---|
| <img width="320" alt="DM chooser"
src="https://github.com/user-attachments/assets/0e884518-2386-4cd1-9f19-16661aaa194e"
/> | <img width="320" alt="Stream chooser"
src="https://github.com/user-attachments/assets/5395e4e1-032e-459b-98c6-0126c060c4d9"
/> |

| Stream: send asks first | Session: members only | Search failed: Retry
|
|---|---|---|
| <img width="260" alt="Stream ask on send"
src="https://github.com/user-attachments/assets/2b988257-3c6a-445d-acfa-fca47b9752fe"
/> | <img width="260" alt="Session chooser"
src="https://github.com/user-attachments/assets/e193551f-f5bf-41d9-aa29-bc8665c643f9"
/> | <img width="260" alt="Search failed with Retry"
src="https://github.com/user-attachments/assets/e8c4b9bb-067e-4fe9-9fdd-4e5691bc66be"
/> |

### Details
- `mobile/lib/shared/mentions/mention_rules.dart` holds the rules: query
syntax, match tiers, sort order, Space selection of an exact unique
name, stable rows while results arrive, and `p` and `mention` tags. A
`p` tag notifies the person. A `mention` tag is a reference and does not
notify.
- `mobile/test/shared/mentions/mention-rules.fixtures.json` is an exact
copy of the buzz-app fixture file. `mention_rules_test.dart` runs every
case.
- Known difference: desktop gives the directory to a channel with an
unknown explicit type (not stream, forum, DM or session). Mobile does
not. No such type exists today.

### Related issue
None found. Desktop counterpart: block/buzz-app#510. #7513 also edits
`send_message_provider.dart` and may conflict.

### Testing
`just mobile-install mobile-check mobile-test` passes: analyze clean,
2998 tests pass on `49c44653` (before rebase). The pre-push hook ran
`just mobile-check && just mobile-test` again on the rebased head
`de1ca080` and passed.

Each review fix was mutation-checked: removing the fix makes its new
test fail.

---------

Signed-off-by: Larry <627498bd4bd1f281a16431e3c6cce3b5c25b6692798c78672298aefbf2f8f8b5@buzz.block.builderlab.xyz>
Co-authored-by: Larry <627498bd4bd1f281a16431e3c6cce3b5c25b6692798c78672298aefbf2f8f8b5@buzz.block.builderlab.xyz>
abipalli pushed a commit to abipalli/buzz that referenced this pull request Oct 7, 2026
…#8102)

🤖
## Summary
The mobile app's @mention chooser now follows the same rules as the
desktop app (buzz-app). The same typed text finds the same people in the
same order on both apps, and sending works the same way.

- **Same matching and order.** Mobile uses the shared mention rules and
runs their shared test cases. A multi-word search such as `@Mary J`
still searches the community directory, so it can find "Mary Jane" even
when she is not in the channel.
- **DMs can mention people outside the DM.** The chooser marks them "not
in DM". Nobody can be added to a DM, so the message sends without a
prompt. Outside people go out as references, so they are not notified.
This matches buzz-app block#510.
- **Channels still ask.** In a stream or forum, mentioning someone
outside the channel asks "Invite" or "Do nothing" before the message
sends. A channel with no type tag counts as a stream.
- **Sessions do not search the directory.** Only session members appear.
- **A failed directory search stays visible.** The chooser shows the
error and a Retry button. Before, it closed.
- **Search results stay in their community.** If you switch communities
while a search runs, its people and its error do not show in the new
community. The search starts again there.
- **A failed send check keeps the draft.** Before a message with a
mention sends, the app checks who is in the channel. If that check
fails, the message stays in the compose bar and a notice offers Retry.
Before, nothing was sent and nothing was shown.
- **Invite stays in its community.** If you switch communities while the
"Invite" question is open, Invite adds nobody.

### Screenshots
The real compose bar widget, rendered by Flutter's test renderer with
the app's fonts and theme. The data is sample data. These are not device
captures.

| DM: outside person is "not in DM" | Stream: outside person is "not in
channel" |
|---|---|
| <img width="320" alt="DM chooser"
src="https://github.com/user-attachments/assets/0e884518-2386-4cd1-9f19-16661aaa194e"
/> | <img width="320" alt="Stream chooser"
src="https://github.com/user-attachments/assets/5395e4e1-032e-459b-98c6-0126c060c4d9"
/> |

| Stream: send asks first | Session: members only | Search failed: Retry
|
|---|---|---|
| <img width="260" alt="Stream ask on send"
src="https://github.com/user-attachments/assets/2b988257-3c6a-445d-acfa-fca47b9752fe"
/> | <img width="260" alt="Session chooser"
src="https://github.com/user-attachments/assets/e193551f-f5bf-41d9-aa29-bc8665c643f9"
/> | <img width="260" alt="Search failed with Retry"
src="https://github.com/user-attachments/assets/e8c4b9bb-067e-4fe9-9fdd-4e5691bc66be"
/> |

### Details
- `mobile/lib/shared/mentions/mention_rules.dart` holds the rules: query
syntax, match tiers, sort order, Space selection of an exact unique
name, stable rows while results arrive, and `p` and `mention` tags. A
`p` tag notifies the person. A `mention` tag is a reference and does not
notify.
- `mobile/test/shared/mentions/mention-rules.fixtures.json` is an exact
copy of the buzz-app fixture file. `mention_rules_test.dart` runs every
case.
- Known difference: desktop gives the directory to a channel with an
unknown explicit type (not stream, forum, DM or session). Mobile does
not. No such type exists today.

### Related issue
None found. Desktop counterpart: block/buzz-app#510. block#7513 also edits
`send_message_provider.dart` and may conflict.

### Testing
`just mobile-install mobile-check mobile-test` passes: analyze clean,
2998 tests pass on `49c44653` (before rebase). The pre-push hook ran
`just mobile-check && just mobile-test` again on the rebased head
`de1ca080` and passed.

Each review fix was mutation-checked: removing the fix makes its new
test fail.

---------

Signed-off-by: Larry <627498bd4bd1f281a16431e3c6cce3b5c25b6692798c78672298aefbf2f8f8b5@buzz.block.builderlab.xyz>
Co-authored-by: Larry <627498bd4bd1f281a16431e3c6cce3b5c25b6692798c78672298aefbf2f8f8b5@buzz.block.builderlab.xyz>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants