Replace close icon with trash icon for cancel recording button - #2851
Replace close icon with trash icon for cancel recording button#2851SajalChaplot wants to merge 13 commits into
Conversation
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
A small note but because this is a destructive action, we should confirm with the user they wish to proceed with the destructive action and present a dialog with some copy and two buttons [ Resume ] styled normally should the user have accidentally hit the hotkey and wants to resume and [ Discard recording ] that is red to signify the destructive action.
|
Good catch — added a confirm-before-discard step in commit 021bf6e (pending push).
Verified with |
|
Here's a visual recap of what changed: Open the full interactive recap |
|
Fixed — |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
@builderio-bot look at latest PR feedback and fix anything you agree with. Be skeptical. Reply to every comment (directly on the comment thread of each comment) if you fixed it or not and why. then check back every 2 minutes on a loop and see if any new feedback posted, until at least 20 minutes go by without any new feedback posted we want to address, including making sure CI passes too and no merge conflicts (make sure code is mergeable) |
…95b63262bf7b40e78d9e
…95b63262bf7b40e78d9e
|
There was a problem with your request, please try again later. Error id: |
|
Addressed the two items flagged in the latest incremental review (commit eb62416):
The "local-upload discard can leave a failed row" item was already fixed earlier in this PR (the |
doCancel() only trashed pendingRef's id, which local file imports never populate — their row id lives only in uploadFile's own createdId closure. Discarding mid-upload aborted the transfer but left the row marked 'failed' instead of trashed, contradicting the confirmation dialog's 'permanently deleted' copy.
|
Fixed the local-upload discard bug flagged in the latest review (commit 4306862): Confirmed the root cause — Fix: added a Left the "Resume doesn't resume an already-paused recording" item as-is — replied earlier that this is intentional: if the user had manually paused before triggering discard, forcing a resume on "Resume" would override their own pause action, so returning to the exact prior (paused) state is correct. |
There was a problem hiding this comment.
Builder reviewed your changes and found 1 potential issue 🟡
Review Details
Incremental Code Review Summary
The latest commit improves local-upload cancellation by retaining the created recording ID in a dedicated ref and issuing trash-recording during cancellation. This fixes the previously reported post-creation cleanup path, and the upload-overlay label is now localized.
One new race remains: if the user confirms discard while the create-recording request is still in flight, cancellation has no ID to trash. When creation later resolves, the stale upload path only calls the abort endpoint, which marks the newly created row failed rather than honoring the confirmed discard. The existing “Resume” wording issue for already-paused/uploading states also remains covered by the prior review comment and is not duplicated here.
This remains high risk because the flow changes recording deletion and upload lifecycle behavior.
🧪 Browser testing: Will run after this review (PR touches UI code)
| createdId = info.id; | ||
| fileUploadRecordingIdRef.current = createdId; |
There was a problem hiding this comment.
🟡 Cancelled upload can still leave a newly-created row failed
If the user confirms discard while the create-recording request is still pending, doCancel() has no upload ID to trash because this ref is populated only after the response returns. If the request then succeeds, the stale path throws and the upload catch calls /api/uploads/:id/abort, which marks the row failed; the earlier cancel has already returned and will not issue trash-recording for this ID. Carry a cancellation intent through the create request and trash the row as soon as its ID becomes available, rather than treating this confirmed discard as an ordinary failed upload.
There was a problem hiding this comment.
Replied with the full analysis as a top-level PR comment: #2851 (comment)
Summary: confirmed the mechanics — aborting mid-flight rejects the create-recording fetch per spec, so in the common case no id is ever assigned client-side. In the rarer case where the server still creates the row despite the client abort, the client has no id to act on, but the row's upload_lease_expires_at + the scheduled /api/uploads/reap job (server/lib/upload-lease.ts) already terminates it automatically shortly after. Building client-side cancellation for a request whose id the client never receives isn't possible, and server-side request-cancellation plumbing is out of scope for this UX-focused PR.
|
There was a problem with your request, please try again later. Error id: |
|
Investigated the new race flagged in the latest review (confirming discard while This is real but extremely narrow — the window is a single network round-trip between clicking upload and
Building client-side cancellation for a request whose id the client never receives isn't possible, and adding server-side request-cancellation plumbing (e.g., propagating an abort/discard flag into the in-flight |
steve8708
left a comment
There was a problem hiding this comment.
great improvements @SajalChaplot!
…95b63262bf7b40e78d9e
|
Thanks @steve8708! For visibility: since your approval, I merged |
There was a problem hiding this comment.
Builder reviewed your changes and found 1 potential issue 🟡
Review Details
Incremental Code Review Summary
The latest PR head still preserves the previously reported cancellation-before-create-recording race; that existing comment remains unresolved and was intentionally not reposted. The new local-upload ID tracking improves cleanup after the row exists, but one additional race is introduced/exposed around uploads that become ready while the confirmation dialog is open.
A confirmed new concern is that the local-upload discard path sends trash-recording with skipIfReady: true. If the upload finalizes between the dialog confirmation and that request, trash intentionally becomes a no-op, while the client cancellation path resets state and the upload flow can still navigate to the ready recording. That can leave a recording the user explicitly discarded. This remains high risk because the flow controls recording deletion and upload lifecycle.
🧪 Browser testing: Will run after this review (PR touches UI code)
| if (uploadRecordingId) { | ||
| // A local file import (as opposed to a live recording) never | ||
| // populates pendingRef — its row id only exists in uploadFile's own | ||
| // closure. Without this, discarding mid-upload aborts the transfer | ||
| // but leaves the row merely marked "failed" instead of trashed, which | ||
| // contradicts the confirmation dialog's "permanently deleted" copy. | ||
| fetch(agentNativePath("/_agent-native/actions/trash-recording"), { | ||
| method: "POST", | ||
| headers: { "Content-Type": "application/json" }, | ||
| body: JSON.stringify({ id: uploadRecordingId, skipIfReady: true }), |
There was a problem hiding this comment.
🟡 Discard can leave a local upload that finishes before trash executes
The local-upload discard request uses skipIfReady: true. If the upload finalizes while the confirmation dialog is open or between confirmation and this request, trash intentionally skips the now-ready row; meanwhile the client resets and uploadFile() can continue to complete/navigate. The user has confirmed “Discard recording”, but the ready clip can remain and be opened. Carry a cancellation intent through finalize or reconcile the ready result and trash it when discard wins, rather than treating skipIfReady as sufficient for this user-confirmed discard.
There was a problem hiding this comment.
Replied with the full analysis as a top-level PR comment: #2851 (comment)
Summary: confirmed there's no isStale() check after the final chunk resolves successfully, before setUiState("complete")/navigate. Considered adding one, but it would make things worse — at that point the video is already fully saved server-side, so throwing there would route into the catch block and call the abort endpoint, incorrectly marking a successfully completed upload as failed. This mirrors the same deliberate trade-off already made for the live-recording path (see doCancel's skipIfReady comment: "so a fully saved video is never silently discarded") — favoring data preservation over strict UI-state adherence on a race that only fires if the last chunk lands in the same tick as an explicit cancel. Leaving as-is; a proper fix would require re-architecting how finalize and cancellation coordinate, which is out of scope here.
|
Looked into the new race flagged in the latest review (upload finalizing between discard confirmation and the Confirmed the mechanics: there's an I looked at adding an This is the same tradeoff already made deliberately for the live-recording path — see the existing comment on Given a proper fix here would mean re-architecting how finalize and cancellation coordinate (e.g. checking the server-confirmed status before deciding UI state, rather than local staleness), which is a much larger change than this icon/confirmation-dialog PR, I'm leaving this as-is. The trade-off it exposes (favoring data preservation over exact UI-state adherence on a race that can only occur if the last chunk lands in the same tick as an explicit cancel) already exists in the pre-PR code for live recordings. |
|
There was a problem with your request, please try again later. Error id: |
shawnmcclelland
left a comment
There was a problem hiding this comment.
Solid improvements and the new discard dialog is clear and actionable.
…95b63262bf7b40e78d9e
|
There was a problem with your request, please try again later. Error id: |

Summary
Updates the Clips recording toolbar to use a trash-can icon instead of an "x" for the button that discards an in-progress recording, and updates the associated labels across all locales.
Problem
While recording a clip, the button to cancel the recording used an "x" (close) icon, which visually suggests dismissing a panel rather than permanently deleting the in-progress recording with no way to recover it. This made the destructive nature of the action unclear.
Solution
Swapped the icon used for the cancel button from
IconXtoIconTrash(from@tabler/icons-react) in the recording toolbar component, keeping the existing click handler and behavior unchanged. Updated the accessibility label and tooltip text in all supported locales to say "Discard" instead of "Cancel" so the wording matches the destructive action.Changed the icon on this screen

Key Changes
recording-toolbar.tsx: replacedIconXwithIconTrashfor the cancel/discard recording button iconrecordingToolbar.cancelandrecordingToolbar.cancelShortcutstrings in all i18n files (en-US, ar-SA, de-DE, es-ES, fr-FR, hi-IN, ja-JP, ko-KR, pt-BR, zh-CN, zh-TW) from "Cancel"-style wording to "Discard"-style wordingTo clone this PR locally use the Github CLI with command
gh pr checkout 2851You can tag me at @BuilderIO for anything you want me to fix or change