diff --git a/app/src/main/java/com/swoosh/microblog/data/api/GhostApiService.kt b/app/src/main/java/com/swoosh/microblog/data/api/GhostApiService.kt index 952ed4d..1916136 100644 --- a/app/src/main/java/com/swoosh/microblog/data/api/GhostApiService.kt +++ b/app/src/main/java/com/swoosh/microblog/data/api/GhostApiService.kt @@ -1,6 +1,7 @@ package com.swoosh.microblog.data.api import com.swoosh.microblog.data.model.GhostSite +import com.swoosh.microblog.data.model.MediaUploadResponse import com.swoosh.microblog.data.model.MembersResponse import com.swoosh.microblog.data.model.PageWrapper import com.swoosh.microblog.data.model.PagesResponse @@ -114,6 +115,20 @@ interface GhostApiService { @Part file: MultipartBody.Part, @Part("purpose") purpose: RequestBody ): Response + + @Multipart + @POST("ghost/api/admin/media/upload/") + suspend fun uploadMedia( + @Part file: MultipartBody.Part, + @Part("ref") ref: RequestBody? = null + ): Response + + @Multipart + @POST("ghost/api/admin/media/thumbnail/upload/") + suspend fun uploadMediaThumbnail( + @Part file: MultipartBody.Part, + @Part("ref") ref: RequestBody? = null + ): Response } data class ImageUploadResponse( diff --git a/app/src/main/java/com/swoosh/microblog/data/model/MediaModels.kt b/app/src/main/java/com/swoosh/microblog/data/model/MediaModels.kt new file mode 100644 index 0000000..7765d18 --- /dev/null +++ b/app/src/main/java/com/swoosh/microblog/data/model/MediaModels.kt @@ -0,0 +1,11 @@ +package com.swoosh.microblog.data.model + +data class MediaUploadResponse( + val media: List +) + +data class UploadedMedia( + val url: String, + val ref: String?, + val fileName: String? +) diff --git a/app/src/main/java/com/swoosh/microblog/data/repository/PostRepository.kt b/app/src/main/java/com/swoosh/microblog/data/repository/PostRepository.kt index ec0a46e..927cb4b 100644 --- a/app/src/main/java/com/swoosh/microblog/data/repository/PostRepository.kt +++ b/app/src/main/java/com/swoosh/microblog/data/repository/PostRepository.kt @@ -113,8 +113,8 @@ class PostRepository(private val context: Context) { suspend fun uploadImage(uri: Uri): Result = withContext(Dispatchers.IO) { try { - val file = copyUriToTempFile(uri) val mimeType = context.contentResolver.getType(uri) ?: "image/jpeg" + val file = copyUriToTempFile(uri, ".jpg") val requestBody = file.asRequestBody(mimeType.toMediaType()) val part = MultipartBody.Part.createFormData("file", file.name, requestBody) val purpose = "image".toRequestBody("text/plain".toMediaType()) @@ -156,10 +156,41 @@ class PostRepository(private val context: Context) { } } - private fun copyUriToTempFile(uri: Uri): File { + /** + * Uploads a media file (video or audio) to the Ghost media upload endpoint. + * Determines MIME type from the content resolver. Returns the uploaded URL on success. + */ + suspend fun uploadMediaFile(uri: Uri): Result = + withContext(Dispatchers.IO) { + try { + val mimeType = context.contentResolver.getType(uri) ?: "application/octet-stream" + val extension = when { + mimeType.startsWith("video/") -> mimeType.substringAfter("video/").let { ".$it" } + mimeType.startsWith("audio/") -> mimeType.substringAfter("audio/").let { ".$it" } + else -> "" + } + val file = copyUriToTempFile(uri, extension) + val requestBody = file.asRequestBody(mimeType.toMediaType()) + val part = MultipartBody.Part.createFormData("file", file.name, requestBody) + + val response = getApi().uploadMedia(part) + file.delete() + + if (response.isSuccessful) { + val url = response.body()!!.media.first().url + Result.success(url) + } else { + Result.failure(Exception("Media upload failed ${response.code()}")) + } + } catch (e: Exception) { + Result.failure(e) + } + } + + private fun copyUriToTempFile(uri: Uri, extension: String = ".jpg"): File { val inputStream = context.contentResolver.openInputStream(uri) ?: throw IllegalStateException("Cannot open URI") - val tempFile = File.createTempFile("upload_", ".jpg", context.cacheDir) + val tempFile = File.createTempFile("upload_", extension, context.cacheDir) FileOutputStream(tempFile).use { output -> inputStream.copyTo(output) }