镜像站点 · 本页由第三方 GitHub 只读镜像提供,非 GitHub 官方站点,不接受任何登录或凭据输入。前往 github.com
Skip to content

fix(mobile): start no threads in Solo chats - #9123

Merged
brow merged 2 commits into
mainfrom
solo-no-new-threads
Nov 9, 2026
Merged

brow merged 2 commits into
mainfrom
solo-no-new-threads

Conversation

@brow

@brow brow commented Nov 5, 2026 •

Copy link
Copy Markdown
Collaborator

Agents in a Solo chat always answer at the chat's top level. On mobile you can still start a thread in Solo (Reply action, swipe-to-reply, media reply) or reply inside an existing one, so the agent's answer lands outside the thread you wrote in. Desktop already avoids this: Solo shows existing threads but starts none and has no thread composer.

This matches desktop on mobile:

  • No Reply quick action, swipe-to-reply or media reply in Solo chats.
  • Existing Solo threads still open from their reply summary, read-only (no composer).
  • Every other channel is unchanged.

Demo

Synthetic Solo chat "QA demo", iPhone 17 Pro simulator. Each clip: right swipe on an agent message, then long-press for the actions.

Before (main): the swipe shows the reply circle and opens a thread with a composer; Reply is in the actions.

before.mp4

After (this branch): the swipe does nothing; the actions have no Reply.

after.mp4

Validation

Added tests: a Solo chat's message neither swipes to reply nor offers Reply in its actions, and a Solo thread opens without a composer. Existing swipe-reply and Solo channel tests pass, along with the full mobile suite and analyzer.

Simulator run on an iPhone 17 Pro, signed in to a real community: in an existing Solo chat, a right swipe on an agent message no longer moves or opens a thread, and the long-press actions show no Reply (Copy link, Remind me and the rest are unchanged). Team-channel Reply is covered by the existing swipe-reply tests, not this run.

A second simulator run on an iPhone 17 Pro, in a synthetic Solo chat, compared main and this branch: on main the swipe opens a thread with a composer and the actions list Reply; on this branch neither does (see Demo). The Demo's "Follow thread" action still appears in a Solo chat's actions on both builds; this PR does not change it.

🤖 Generated with Claude Code

Solo agents answer at the chat's top level, so a thread reply in a Solo
chat gets its answer outside the thread. Desktop already shows existing
Solo threads but starts none and takes no replies in them. Match that on
mobile: hide the Reply quick action, swipe-to-reply and media reply in
Solo chats, and open an existing Solo thread without a composer.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tom Brow <tomb@squareup.com>
@brow

brow commented Nov 5, 2026

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Nov 5, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-11-05T22:49:17.715015Z 164b30c Draft marked ready
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 164b30c7c5

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +1163 to +1166
(ref, channelId) => !(ref.watch(
channelByIdProvider(
channelId,
).select((channel) => channel?.isSolo ?? false),

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Preserve Solo identity while the channel list reloads

When a new Solo chat is created, createChannel(... waitForChannelList: false) invalidates channelsProvider and returns the confirmed Channel without adding it to _openedAheadProvider; the page can therefore render while this lookup is null. Defaulting null to non-Solo re-enables swipe, action, media replies, and the thread composer until the full list reload finishes, allowing the exact misplaced thread reply this change intends to prevent. Use the route's known channel metadata or remember the fast-opened channel rather than treating an unresolved lookup as thread-capable. The added tests miss this because _buildTestable always seeds the fake channel list with the Solo channel instead of exercising this production seam.

AGENTS.md reference: AGENTS.md:L242-L246

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

[P2] Preserve confirmed Solo metadata during fast creation

I verified this path: Solo creation uses waitForChannelList: false, invalidates the list without rememberOpened, then opens from the returned channel. While that lookup is missing, reply actions and submission remain available. Could we retain the confirmed channel before navigation or derive the restriction from the metadata the page already has?

Posted by Codex (gpt-6.1-sol) on behalf of kylez.


final tiles = <Widget>[
if (messages != null)
if (messages != null && startsThreads)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🤖 P2 · Existing Solo threads lose their normal entry points

Owned Solo chats build the main timeline with flat: personalChat, so buildMainTimelineEntries creates no reply summaries. The message bubble consequently has neither a summary link nor a tappable hasReplies target once optimistic local replies and typing indicators have cleared. Removing Reply here, alongside swipe and media reply, removes the remaining normal routes into those existing threads.

User/system effect: The promised read-only access to an existing Solo thread is unavailable from the conversation. A view-only entry point needs to remain for messages with replies.

Test: Open a Solo chat with persisted replies after a cold start, then open its existing thread through the conversation without composing.

],
),
if (isMember && !isArchived)
if (canReply)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🤖 P2 · Read-only threads lose their bottom system inset

The composer dock supplies MediaQuery.viewPadding.bottom; hiding it leaves composerDockHeight at zero. With the keyboard closed, timelineBottomInset is then zero and _ThreadMessageList reserves only Grid.xs (16 logical pixels). Neither FrostedScaffold nor this thread body adds a bottom SafeArea.

User/system effect: On edge-to-edge Android devices with a navigation inset larger than 16 pixels, the last reply or footer cannot scroll fully clear of the system navigation controls. The read-only layout still needs that inset in its list and tail geometry.

Test: Open a populated Solo thread with a 48-pixel bottom system inset and scroll to its last reply; all text and footer controls should remain above the navigation area.

@brow
brow marked this pull request as ready for review November 5, 2026 22:47
@brow
brow requested a review from a team as a code owner November 5, 2026 22:47
@github-actions github-actions Bot added the codex-security-review-current The posted Codex security review matches its recorded range. label Nov 5, 2026
@github-actions

github-actions Bot commented Nov 5, 2026 •

Copy link
Copy Markdown

🔐 Codex Security Review

Note: This is an automated, security-focused review generated by Codex.
Use it as a supplement to human review; false positives are possible.

Scope

  • Exact PR diff: 8cce12f591988f29cc2beab5ff0c89d51862f31b...3c03ad74be3f14400d69e50dd5762309ae2bd1cd
  • Model: gpt-6.1-sol

💡 Click "edited" above to see earlier reviews for this PR.


Review Summary

Overall Risk: MEDIUM

Newly created Solo chats can still create thread replies while the background channel list is loading.

Findings

[MEDIUM] Preserve Solo metadata before enabling thread actions

  • Category: Reliability
  • Location: mobile/lib/features/channels/channels_provider.dart:1166 (source)
  • Description: The null fallback enables threads when channelByIdProvider cannot find the channel. Solo creation uses createChannel with waitForChannelList false and opens ChannelDetailPage directly from the returned metadata, without calling rememberOpened. Consequently, while the background list is loading or has failed, this provider returns true even though the opened page already knows the channel is Solo. Swipe, message actions, and the thread composer remain enabled, and the composer calls SendMessage with reply tags without another Solo check.
  • Impact: Users can create and submit the Solo thread replies this change intends to prevent. On slow or failed channel-list refreshes, this remains possible until the list successfully includes the channel.
  • Recommendation: Remember the confirmed Solo channel before opening it, or derive the thread restriction from the metadata already available to the page. Cover creation with a stalled channel list in a regression test.

Notes

  • Review used read-only source inspection; builds and tests were not executed.

Generated by Codex Security Review |
Requested by: @brow |
Workflow run

.first;
final initial = tester.getTopLeft(row);
final gesture = await tester.startGesture(tester.getCenter(bubble));
await gesture.moveBy(const Offset(25, 0));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

could you make this test drag left after #9127? rightward drags now leave replies closed in every channel, so these assertions also pass when the solo swipe guard is removed.

@github-actions github-actions Bot added codex-security-review-current The posted Codex security review matches its recorded range. and removed codex-security-review-current The posted Codex security review matches its recorded range. labels Nov 8, 2026

@tlongwell-block tlongwell-block 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.

🤖 Meli, Tyler’s AI agent, posting on his explicit behalf.

Approved as directed by Tyler.

Follow-up test-quality finding: the new swipe test drags right although reply recognizes a left drag. Mutation checks showed the rightward test passes with the gate removed; reversing the drag catches it. Add media-reply assertions as well. This approval follows Tyler’s explicit decision; it does not claim those test gaps are fixed.

Reviewed head: 3c03ad74be3f14400d69e50dd5762309ae2bd1cd.

@kazemek21 kazemek21 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Kyle reviewed the PR and the Nexus review-tracker notes and directed this approval. C1 is non-blocking.

Posted by Codex (gpt-6.1-sol) on behalf of kylez.

Comment on lines +1163 to +1166
(ref, channelId) => !(ref.watch(
channelByIdProvider(
channelId,
).select((channel) => channel?.isSolo ?? false),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

[P2] Preserve confirmed Solo metadata during fast creation

I verified this path: Solo creation uses waitForChannelList: false, invalidates the list without rememberOpened, then opens from the returned channel. While that lookup is missing, reply actions and submission remain available. Could we retain the confirmed channel before navigation or derive the restriction from the metadata the page already has?

Posted by Codex (gpt-6.1-sol) on behalf of kylez.

@brow
brow merged commit ad5699d into main Nov 9, 2026
53 checks passed
@brow
brow deleted the solo-no-new-threads branch November 9, 2026 14:58
bostonaholic added a commit that referenced this pull request Nov 9, 2026
…ction-p

* origin/main: (111 commits)
  feat(mobile): tag the reacted-to message author on reactions (#9141)
  fix(mobile): steady New DM picker rows and animate picks (#9249)
  perf(mobile): keep remote images on disk and show small ones as thumbnails (#9158)
  fix(relay): deliver slow cross-node events late instead of closing their recipients (#9235)
  fix(mobile): read only shown events from filtered Activity rows (#9215)
  fix(mobile): show the channel name as the notification subtitle (#9173)
  fix(mobile): keep Home's header clean under sheets (#9152)
  fix(mobile): show already-loaded custom emoji in the iOS reactions sheet (#9150)
  mobile: add follow and remind actions to inbox row menu (#9142)
  fix(mobile): start no threads in Solo chats (#9123)
  mobile: persist user profiles so names and avatars render on launch (#9116)
  fix(mobile): keep a sent thread reply above the composer (#9026)
  [buzz] Recover database pool capacity after stalled connections (#9267)
  feat: send a User-Agent on relay WebSocket upgrades (#9246)
  Record why relay connections close and quiet close warnings (#9245)
  fix(relay): say "channel owner or admin" in the call_webhook save refusal (#9169)
  feat(mobile): consolidate Solo chat settings in one sheet (#9255)
  fix(cli): preserve attachments across successive edits (#9226)
  fix(mobile): swipe left to reply so swipe-back keeps rightward drags (#9127)
  mobile: long-press a message link for open, copy and share (#9135)
  ...

Signed-off-by: Matthew Boston <mboston@squareup.com>
fsola-sq added a commit that referenced this pull request Nov 9, 2026
…-profile

* origin/main: (307 commits)
  fix: inline ARM64 atomics in Sprig image build (#9291)
  fix(mobile): show observed thread replies in Activity (#9286)
  Enable mobile huddles with Codex agents (#9269)
  fix(mobile): read mentions taller than the screen (#9243)
  test(relay): give every media e2e upload its own blob hash (#9272)
  Add invite preview video and fallback poster (#9282)
  NEXUS-4336: Wait for desktop-provider socket ownership proof (#9270)
  fix: unblock image audit with patched MCP SDK (#9287)
  feat(ci): allow admin dispatch of desktop candidate validation (#9288)
  feat(mobile): tag the reacted-to message author on reactions (#9141)
  fix(mobile): steady New DM picker rows and animate picks (#9249)
  perf(mobile): keep remote images on disk and show small ones as thumbnails (#9158)
  fix(relay): deliver slow cross-node events late instead of closing their recipients (#9235)
  fix(mobile): read only shown events from filtered Activity rows (#9215)
  fix(mobile): show the channel name as the notification subtitle (#9173)
  fix(mobile): keep Home's header clean under sheets (#9152)
  fix(mobile): show already-loaded custom emoji in the iOS reactions sheet (#9150)
  mobile: add follow and remind actions to inbox row menu (#9142)
  fix(mobile): start no threads in Solo chats (#9123)
  mobile: persist user profiles so names and avatars render on launch (#9116)
  ...

Signed-off-by: Franco Sola <fsola@squareup.com>

# Conflicts:
#	docs/nips/NIP-FA.md
#	docs/nips/NIP-FI.md
wpfleger96 added a commit that referenced this pull request Nov 9, 2026
…e-mode

* origin/main: (36 commits)
  feat(relay): let an operator mint invites for a community owner or admin (#9265)
  fix: inline ARM64 atomics in Sprig image build (#9291)
  fix(mobile): show observed thread replies in Activity (#9286)
  Enable mobile huddles with Codex agents (#9269)
  fix(mobile): read mentions taller than the screen (#9243)
  test(relay): give every media e2e upload its own blob hash (#9272)
  Add invite preview video and fallback poster (#9282)
  NEXUS-4336: Wait for desktop-provider socket ownership proof (#9270)
  fix: unblock image audit with patched MCP SDK (#9287)
  feat(ci): allow admin dispatch of desktop candidate validation (#9288)
  feat(mobile): tag the reacted-to message author on reactions (#9141)
  fix(mobile): steady New DM picker rows and animate picks (#9249)
  perf(mobile): keep remote images on disk and show small ones as thumbnails (#9158)
  fix(relay): deliver slow cross-node events late instead of closing their recipients (#9235)
  fix(mobile): read only shown events from filtered Activity rows (#9215)
  fix(mobile): show the channel name as the notification subtitle (#9173)
  fix(mobile): keep Home's header clean under sheets (#9152)
  fix(mobile): show already-loaded custom emoji in the iOS reactions sheet (#9150)
  mobile: add follow and remind actions to inbox row menu (#9142)
  fix(mobile): start no threads in Solo chats (#9123)
  ...

Signed-off-by: Will Pfleger <wpfleger@block.xyz>

This branch was previously deployed

1 inactive deployment
codex-review — 3c03ad74 Deployed Nov 8, 2026 by brow via Run Codex Security Review #13878
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

codex-security-review-current The posted Codex security review matches its recorded range.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants