Repository navigation
Remove this Bot: fast optimistic hide, per-row pending state, compact control - #93
Conversation
hideRemote waited for room leave and a fresh roster fetch, so the click felt stuck. Persist the hide and return the locally filtered list; leave rooms in parallel and refresh in the background. Friends' Bots tracked one hiding handle, so a second Remove re-enabled the first. Track a set per handle. Replace the large button with a hover/focus × that stays on the keyboard tab order and the context menu. Co-authored-by: Danyang Chen <birfychen@gmail.com>
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 93a778211f
ℹ️ 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".
| fetchedAt = 0 | ||
| const roster = await remoteBots({ fresh: true }) | ||
| return { handle: key, hidden: true, leftRooms, homes: roster.homes } | ||
| remote = { homes: filterHiddenHomes(remote.homes, settings) } |
There was a problem hiding this comment.
Keep refresh reconciliation on raw roster data
If a hide lands while an earlier fresh remoteBots call has assigned its server result and is awaiting syncOutgoingGrants() (and that call resumes before this hide's new fetch), this assignment replaces the shared raw roster with an already-filtered one. The earlier call then runs forgetHiddenIfGone against remote.homes, treats the just-hidden handle as revoked, deletes it from settings.hiddenRemotes, and a later refresh republishes the Bot without any re-grant. Keep each refresh's raw homes local until reconciliation, or serialize these mutations.
Useful? React with 👍 / 👎.
| })))) | ||
| const leftRooms = roomsHolding(key) | ||
| void afterHideRemote(key).catch(error => warn('hide-remote follow-up failed', error)) | ||
| return { handle: key, hidden: true, leftRooms, homes: remote.homes } |
There was a problem hiding this comment.
Make concurrent hide responses monotonic
When two rows are removed before either request settles, each call now returns a replace-all roster snapshot, but HTTP responses need not arrive in request order. If B's empty snapshot is applied first and A's earlier {B} snapshot arrives later, FriendsBots.removeBot replaces its state with that older result and B remains drawn even though B is persisted as hidden; this component only polls approvals, not the remote roster. Return/apply a monotonic update (for example, filter the completed handle from current state) or reject stale snapshots.
Useful? React with 👍 / 👎.
| handle: bot.handle, name: bot.name, home: entry.home, homeName: entry.name, owner: entry.owner, | ||
| })))) | ||
| const leftRooms = roomsHolding(key) | ||
| void afterHideRemote(key).catch(error => warn('hide-remote follow-up failed', error)) |
There was a problem hiding this comment.
Reconcile room cleanup after an interrupted hide
If the DSH/Desktop process exits after this endpoint has replied but before afterHideRemote finishes—especially while a networked face-room leave is pending—the cleanup is lost. The hide is already persisted and removes the only row the user could act on, while startup only filters hiddenRemotes and never retries departures, so the hidden Bot can remain a live room participant indefinitely. Persist/retry the cleanup intent or reconcile hidden handles against rooms on startup while still returning the UI response immediately.
Useful? React with 👍 / 👎.
…' Bots panel (#92) (#100) Follow-up to #96 / #93 / #91. - **Face-to-face group** is now an entry in the global sidebar **+** (new-chat picker), right after New group chat, via a new `flybot.new-chat.action` slot (patch layer). It also stays in Friends' Bots + Add and works while the roster is loading. - **Removed Bots stay gone:** a hide is forgotten only after two consecutive successful non-legacy roster fetches without that handle (or an explicit revoke); hidden handles are kept out of `flybot.remote.publish`, so persisted remote chats do not return in the sidebar, the send-to picker or mentions. Home-level rows are filtered the same way. - **Performance:** parallel mount, stale-while-revalidate roster (Refreshing\u2026 instead of blocking Loading\u2026), keep-alive HTTP, non-blocking grant listing, slower/paused polling. - Tests, bundle check, patches check, CHANGELOG updated. --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Follow-up to #91 / #90.
social/hide-remotepersists the hide and returns the locally filtered roster at once; room leaving (parallel) and the fresh roster fetch run in the background and never un-hide on failure.