refactor(uploads): drop legacy multipart helpers; route Android UI through presigned flow
Android UI Tests / ui-tests (pull_request) Has been cancelled

The KMP shared layer's task-completion-with-images path now exclusively
uses the presigned-URL flow: each image is compressed, uploaded directly
to B2 via APILayer.uploadImage, and the resulting upload_ids are passed
to /api/task-completions/ as JSON. Bytes never traverse our API server.

Changes:
  - TaskCompletionViewModel.createTaskCompletionWithImages now does the
    presign→POST→collect-ids dance internally. The signature stays the
    same so the three Android UI call sites (TasksScreen, AllTasksScreen,
    ResidenceDetailScreen, CompleteTaskDialog, CompleteTaskScreen) need
    no changes.
  - APILayer.createTaskCompletionWithImages removed (dead).
  - TaskCompletionApi.createCompletionWithImages removed (the multipart
    HTTP helper that posted to the legacy POST /api/task-completions/
    multipart endpoint).
  - TaskCompletionCreateRequest.imageUrls field removed.
  - Three Swift call sites (CompleteTaskView, WidgetActionProcessor,
    PushNotificationManager) updated to drop the imageUrls argument.
  - Two Kotlin call sites (CompleteTaskDialog, CompleteTaskScreen) updated.

Image uploads now match WhatsApp/Slack-class architecture: client-side
compression + direct-to-storage upload + lightweight JSON entity create.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Trey t
2026-05-01 15:19:46 -07:00
parent fa0ce30257
commit b2d03ef8b2
11 changed files with 47 additions and 96 deletions
@@ -13,8 +13,7 @@ data class TaskCompletionCreateRequest(
val notes: String? = null,
@SerialName("actual_cost") val actualCost: Double? = null,
val rating: Int? = null, // 1-5 star rating
@SerialName("image_urls") val imageUrls: List<String>? = null, // Legacy: URLs returned by /api/uploads/* multipart endpoints
@SerialName("upload_ids") val uploadIds: List<Int>? = null // New: pending_uploads.id values from /api/uploads/presign + direct B2 POST
@SerialName("upload_ids") val uploadIds: List<Int>? = null // pending_uploads.id values from /api/uploads/presign + direct B2 POST
)
/**