Files
amethyst/commons
nrobi144 9aad12804a feat(desktop): fail-loud confirm dialog on compression failure
Phase 7 of the desktop image compression plan.

Never silently downgrade — when ImageReencoder throws
CompressionException for one or more attachments (UnsupportedFormat,
InputTooLarge, EncodeFailed), the compose dialog now surfaces a
modal listing each failure and lets the user choose between Send
Original (uploads raw bytes, EXIF-stripped for JPEGs) or Cancel
post.

  - UploadOrchestrator gains bypassReencode: Boolean = false. When
    true, the orchestrator skips ImageReencoder and treats the
    source as a PassThrough(BypassByUser), preserving the EXIF
    strip + temp-cleanup semantics from the normal pass-through
    path.
  - ImageReencoder.PassReason gains BypassByUser.

  - CompressionFailureDialog is built as Dialog { Surface } (not
    AlertDialog) because:
      * the body is a LazyColumn that grows with N failures —
        AlertDialog's `text` slot has fixed-width constraints,
      * LaunchedEffect / produceState don't fire inside
        AlertDialog.text (see custom-feeds-alertdialog.md memory),
        leaving room for future per-row actions (e.g. per-file
        retry).
    Each row shows: filename, "Could not compress: <reason>" in
    error color, original byte count, and a privacy hint that
    differs by source format ("EXIF will be stripped" for JPEG
    bypass, "metadata may still be present" for PNG/HEIC bypass).

  - ComposeNoteDialog send loop now wraps each upload in try/catch
    (CompressionException), collects failures, and after the loop
    awaits the user's choice via CompletableDeferred<FailureUserChoice>.
    On SendOriginal: re-uploads each failure with
    bypassReencode=true. On Cancel: aborts the post.
2026-06-09 11:42:00 +03:00
..