Boost from Hey!, Assignments, and Pulse with cross-account routing#155
Boost from Hey!, Assignments, and Pulse with cross-account routing#155
Conversation
Introduce FocusedItemScope (AccountID, ProjectID, RecordingID) to replace the previous recording-ID-only interface. The workspace's `o` handler now merges all non-zero fields from the focused item into the scope before building the Basecamp URL, so pressing `o` from Hey!, Assignments, Pulse, or any other global view opens the correct item — not the project root. All 9 list views implement FocusedItem(): assignments, hey, pulse, activity, timeline, search, messages, todos, campfire (returns zero — no single-item URL for chat).
Add b/B key to Hey!, Assignments, and Pulse views — all three emit OpenBoostPickerMsg with full scope (AccountID, ProjectID, RecordingID). BoostTarget gains an AccountID field. Hub.CreateBoost now accepts accountID and routes through multi.ClientFor() when non-empty, falling back to the current account client otherwise. This fixes cross-account boosting where items from a different account would silently hit the wrong API endpoint.
There was a problem hiding this comment.
Pull request overview
This PR adds boost functionality to three cross-account views (Hey!, Assignments, and Pulse) with proper account routing support. The implementation extends the existing boost pattern to handle items from multiple accounts by adding an AccountID field to BoostTarget and updating Hub.CreateBoost to route requests to the appropriate account client.
Changes:
- Add
b/Bkey binding andboostSelected()methods to Hey!, Assignments, and Pulse views - Extend
BoostTargetwithAccountIDfield for cross-account routing - Update
Hub.CreateBoostto acceptaccountIDparameter and useClientFor()for cross-account operations
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| internal/tui/workspace/msg.go | Add AccountID field to BoostTarget struct for cross-account routing |
| internal/tui/workspace/workspace.go | Add createBoostFunc injection point for testing; update createBoost to pass AccountID to Hub |
| internal/tui/workspace/data/hub.go | Update CreateBoost signature to accept accountID parameter; implement cross-account client routing with nil check |
| internal/tui/workspace/views/hey.go | Add boost key binding and boostSelected() method that includes meta.AccountID |
| internal/tui/workspace/views/pulse.go | Add boost key binding and boostSelected() method that includes meta.AccountID |
| internal/tui/workspace/views/assignments.go | Add boost key binding and boostSelected() method that includes meta.AccountID |
| internal/tui/workspace/workspace_test.go | Add comprehensive tests for cross-account boost targeting, picker state, and dismissal; initialize boostPicker in test helpers |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f623b4eb08
ℹ️ 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".
| ctx := w.session.Hub().ProjectContext() | ||
| _, err := w.session.Hub().CreateBoost(ctx, target.ProjectID, target.RecordingID, emoji) | ||
| _, err := w.session.Hub().CreateBoost(ctx, target.AccountID, target.ProjectID, target.RecordingID, emoji) |
There was a problem hiding this comment.
Use target-scoped context for cross-account boosts
This boost mutation always uses ProjectContext(), which resolves to the currently active account/project realm, not the target item's account. After this commit, Hey!/Assignments/Pulse can boost recordings from other accounts, so switching accounts while the request is in flight can cancel the context and fail the boost even though the target account is different. For cross-account targets (target.AccountID != ""), use a context that is not tied to the current account realm (for example global or target-account scoped) to avoid spurious cancellations.
Useful? React with 👍 / 👎.
) * Open-in-browser from list views with full cross-account scope Introduce FocusedItemScope (AccountID, ProjectID, RecordingID) to replace the previous recording-ID-only interface. The workspace's `o` handler now merges all non-zero fields from the focused item into the scope before building the Basecamp URL, so pressing `o` from Hey!, Assignments, Pulse, or any other global view opens the correct item — not the project root. All 9 list views implement FocusedItem(): assignments, hey, pulse, activity, timeline, search, messages, todos, campfire (returns zero — no single-item URL for chat). * Boost from Hey!, Assignments, and Pulse with cross-account routing Add b/B key to Hey!, Assignments, and Pulse views — all three emit OpenBoostPickerMsg with full scope (AccountID, ProjectID, RecordingID). BoostTarget gains an AccountID field. Hub.CreateBoost now accepts accountID and routes through multi.ClientFor() when non-empty, falling back to the current account client otherwise. This fixes cross-account boosting where items from a different account would silently hit the wrong API endpoint.
Summary
b/Bboost key to Hey!, Assignments, and Pulse views (matching existing Todos/Messages/Cards pattern)AccountIDtoBoostTargetfor cross-account boost routingHub.CreateBoostusesClientFor(accountID)when target is from a different accountTest plan
TestWorkspace_BoostTarget_PreservesAccountID— OpenBoostPickerMsg stores cross-account targetTestWorkspace_BoostEmoji_PassesCrossAccountTarget— createBoostFunc spy verifies account-aware routingTestWorkspace_BoostPickerDismiss_ClearsState— Esc dismisses picker