Skip to content

Commit a3faa3d

Browse files
committed
File ops: Redesign type-mismatch conflict dialog
Rebuild the conflict dialog on top of the original file→file shape (filename, "Existing:" / "New:" rows, the 4×2 button grid, the bottom Rollback row) so every clash type reads the same way. The variants only differ where the spec actually wants them to: - File→file and folder→folder stay baseline. - Folder→file: row labels switch to `Existing (file):` and `New (folder):`; no warning, `Overwrite` label unchanged. - File→folder: row labels switch to `Existing (folder):` and `New (file):`; a red `role="alert"` block sits below the title and above the filename, calling out that the entire target folder would be deleted; `Overwrite` becomes `Overwrite folder with file`, `Overwrite all` becomes `Overwrite folders with files`. When `destinationSize === null`, the Existing-size slot renders `(unknown)` in muted color and `Overwrite all smaller` disables (with a tooltip) since there's no folder size to compare against. `Overwrite all older` always stays enabled — mtime is always available. Wire-shape: `WriteConflictEvent.destinationSize` and `sizeDifference` shift to `number | null` to match the BE event the index-backed dir-size lookup now emits. The hand-maintained shim in `apps/desktop/src/lib/file-explorer/types.ts` is the only place this needs to land; `bindings.ts` doesn't carry this type. Drop the agent's earlier "Currently / Incoming" cards + danger-styled "Replace folder" / "Replace file" buttons and their CSS (`.mismatch-cards`, `.mismatch-card*`, `.conflict-lede`) — they forked the layout where the spec wants one consistent shape. Test coverage: `TransferProgressDialog.conflict.test.ts` walks a `describe.each`-driven matrix over the four clash types plus a known-size / null-size axis for the file→folder case, mounts the dialog component directly, captures the `onWriteConflict` callback from the mock, and asserts row labels, button copy, warning markup, disabled state, and one axe-core run per variant. 32 tests, ≈25 ms each in jsdom.
1 parent d2b8f15 commit a3faa3d

3 files changed

Lines changed: 357 additions & 349 deletions

File tree

apps/desktop/src/lib/file-explorer/types.ts

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -554,18 +554,21 @@ export interface WriteConflictEvent {
554554
operationId: string
555555
sourcePath: string
556556
destinationPath: string
557-
/** Source file size in bytes */
557+
/** Source file size in bytes. Always known from the pre-flight scan. */
558558
sourceSize: number
559-
/** Destination file size in bytes */
560-
destinationSize: number
559+
/** Destination size in bytes. `null` when the destination is a folder whose
560+
* size the drive index hasn't crawled yet (network mount, MTP, fresh paths) —
561+
* rendered as `(unknown)` in the UI. */
562+
destinationSize: number | null
561563
/** Source modification time (Unix timestamp in seconds), if available */
562564
sourceModified: number | null
563565
/** Destination modification time (Unix timestamp in seconds), if available */
564566
destinationModified: number | null
565567
/** Whether destination is newer than source */
566568
destinationIsNewer: boolean
567-
/** Size difference (positive = destination is larger) */
568-
sizeDifference: number
569+
/** `destinationSize - sourceSize` when both are known. Collapses to `null`
570+
* when `destinationSize` is `null` (no folder size to subtract against). */
571+
sizeDifference: number | null
569572
/** Whether the source side is a directory. Renders the type-mismatch warning when this differs from `destinationIsDirectory`. */
570573
sourceIsDirectory: boolean
571574
/** Whether the destination side is a directory. See `sourceIsDirectory`. */

0 commit comments

Comments
 (0)