b2d03ef8b2
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>
50 lines
1.7 KiB
Kotlin
50 lines
1.7 KiB
Kotlin
package com.tt.honeyDue.models
|
|
|
|
import kotlinx.serialization.SerialName
|
|
import kotlinx.serialization.Serializable
|
|
|
|
/**
|
|
* Task completion create request matching Go API CreateTaskCompletionRequest
|
|
*/
|
|
@Serializable
|
|
data class TaskCompletionCreateRequest(
|
|
@SerialName("task_id") val taskId: Int,
|
|
@SerialName("completed_at") val completedAt: String? = null, // Defaults to now on server
|
|
val notes: String? = null,
|
|
@SerialName("actual_cost") val actualCost: Double? = null,
|
|
val rating: Int? = null, // 1-5 star rating
|
|
@SerialName("upload_ids") val uploadIds: List<Int>? = null // pending_uploads.id values from /api/uploads/presign + direct B2 POST
|
|
)
|
|
|
|
/**
|
|
* Presigned upload session — request body for POST /api/uploads/presign.
|
|
*
|
|
* Category: "completion" | "document_image" | "document_file"
|
|
* ContentType: the MIME type the client will upload (must match the policy
|
|
* exactly when POSTing to B2).
|
|
* ContentLength: byte count of the upload (server permits ±256 bytes slack).
|
|
*/
|
|
@Serializable
|
|
data class PresignUploadRequest(
|
|
val category: String,
|
|
@SerialName("content_type") val contentType: String,
|
|
@SerialName("content_length") val contentLength: Long
|
|
)
|
|
|
|
/**
|
|
* Presigned upload session — response from POST /api/uploads/presign.
|
|
*
|
|
* The client uses [uploadUrl] + [fields] to perform a multipart/form-data
|
|
* POST directly to B2, then passes [id] back in the upload_ids[] field of
|
|
* the next /api/task-completions/ or /api/documents/ create call.
|
|
*/
|
|
@Serializable
|
|
data class PresignUploadResponse(
|
|
val id: Int,
|
|
@SerialName("upload_url") val uploadUrl: String,
|
|
val fields: Map<String, String>,
|
|
val key: String,
|
|
@SerialName("expires_at") val expiresAt: String
|
|
)
|
|
|