From a22b57d6cde599b186a02ff026dfa2262e6f57d7 Mon Sep 17 00:00:00 2001 From: dodo Date: Thu, 5 Feb 2026 16:21:41 +0900 Subject: [PATCH 01/10] =?UTF-8?q?[Refactor/#145]=20Qaulifier=20=EC=9D=B4?= =?UTF-8?q?=EB=A6=84=20=EB=B3=80=EA=B2=BD=20-=20S3=20to=20File=20:=20S3=20?= =?UTF-8?q?=EB=B2=84=ED=82=B7=EC=9D=80=20=EC=84=9C=EB=B2=84=20=EB=8B=A8?= =?UTF-8?q?=EC=97=90=EC=84=9C=20=ED=99=9C=EC=9A=A9=ED=95=98=EB=8A=94=20?= =?UTF-8?q?=EB=8F=84=EA=B5=AC=EC=9D=B4=EB=AF=80=EB=A1=9C,=20=EB=B3=B8=20?= =?UTF-8?q?=ED=94=84=EB=A1=9C=EC=A0=9D=ED=8A=B8=EC=97=90=EC=84=9C=20?= =?UTF-8?q?=ED=95=B4=EB=8B=B9=20=EC=9D=B4=EB=A6=84=EC=9D=84=20=EC=82=AC?= =?UTF-8?q?=EC=9A=A9=ED=95=98=EC=A7=80=20=EC=95=8A=EC=8A=B5=EB=8B=88?= =?UTF-8?q?=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../data/di/{S3UploadClient.kt => FileUploadClient.kt} | 2 +- app/src/main/java/com/poti/android/data/di/NetworkModule.kt | 2 +- .../java/com/poti/android/data/repository/S3RepositoryImpl.kt | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) rename app/src/main/java/com/poti/android/data/di/{S3UploadClient.kt => FileUploadClient.kt} (77%) diff --git a/app/src/main/java/com/poti/android/data/di/S3UploadClient.kt b/app/src/main/java/com/poti/android/data/di/FileUploadClient.kt similarity index 77% rename from app/src/main/java/com/poti/android/data/di/S3UploadClient.kt rename to app/src/main/java/com/poti/android/data/di/FileUploadClient.kt index 37052715..5f0afcb7 100644 --- a/app/src/main/java/com/poti/android/data/di/S3UploadClient.kt +++ b/app/src/main/java/com/poti/android/data/di/FileUploadClient.kt @@ -4,4 +4,4 @@ import javax.inject.Qualifier @Qualifier @Retention(AnnotationRetention.BINARY) -annotation class S3UploadClient +annotation class FileUploadClient diff --git a/app/src/main/java/com/poti/android/data/di/NetworkModule.kt b/app/src/main/java/com/poti/android/data/di/NetworkModule.kt index d517fa50..74a4c0ea 100644 --- a/app/src/main/java/com/poti/android/data/di/NetworkModule.kt +++ b/app/src/main/java/com/poti/android/data/di/NetworkModule.kt @@ -70,7 +70,7 @@ object NetworkModule { .addConverterFactory(json.asConverterFactory("application/json".toMediaType())) .build() - @S3UploadClient + @FileUploadClient @Provides @Singleton fun provideOkHttpClientForS3(): OkHttpClient = OkHttpClient.Builder().build() diff --git a/app/src/main/java/com/poti/android/data/repository/S3RepositoryImpl.kt b/app/src/main/java/com/poti/android/data/repository/S3RepositoryImpl.kt index 7c2e7fd7..bc7b967d 100644 --- a/app/src/main/java/com/poti/android/data/repository/S3RepositoryImpl.kt +++ b/app/src/main/java/com/poti/android/data/repository/S3RepositoryImpl.kt @@ -1,7 +1,7 @@ package com.poti.android.data.repository import com.poti.android.core.network.util.HttpResponseHandler -import com.poti.android.data.di.S3UploadClient +import com.poti.android.data.di.FileUploadClient import com.poti.android.domain.model.image.PresignedUploadInfo import com.poti.android.domain.repository.S3Repository import okhttp3.MediaType.Companion.toMediaType @@ -13,7 +13,7 @@ import javax.inject.Inject class S3RepositoryImpl @Inject constructor( private val httpResponseHandler: HttpResponseHandler, - @param:S3UploadClient private val okHttpClient: OkHttpClient, + @param:FileUploadClient private val okHttpClient: OkHttpClient, ) : S3Repository { override suspend fun uploadImages( uploadInfos: List, From 21d81d2b9d7dc30cbccd6197739ab64dec7388f0 Mon Sep 17 00:00:00 2001 From: dodo Date: Thu, 5 Feb 2026 16:59:35 +0900 Subject: [PATCH 02/10] =?UTF-8?q?[Feat/#145]=20=EC=9D=B4=EB=AF=B8=EC=A7=80?= =?UTF-8?q?=20=EC=B5=9C=EC=A0=81=ED=99=94=20=EC=9C=84=ED=95=9C=20FileLocal?= =?UTF-8?q?DataSource=20=EA=B5=AC=ED=98=84=20-=20=EC=9B=90=EB=B3=B8=20?= =?UTF-8?q?=EC=82=AC=EC=9D=B4=EC=A6=88=20=EC=9D=BD=EC=96=B4=20=EB=B9=84?= =?UTF-8?q?=EC=9C=A8=20=EC=9C=A0=EC=A7=80=ED=95=B4=20=EB=A6=AC=EC=82=AC?= =?UTF-8?q?=EC=9D=B4=EC=A7=95=20-=20=EC=83=9D=EC=84=B1=EB=90=9C=20?= =?UTF-8?q?=ED=8C=8C=EC=9D=BC=20=EA=B0=9D=EC=B2=B4=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../local/datasource/FileLocalDataSource.kt | 91 +++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 app/src/main/java/com/poti/android/data/local/datasource/FileLocalDataSource.kt diff --git a/app/src/main/java/com/poti/android/data/local/datasource/FileLocalDataSource.kt b/app/src/main/java/com/poti/android/data/local/datasource/FileLocalDataSource.kt new file mode 100644 index 00000000..b3871964 --- /dev/null +++ b/app/src/main/java/com/poti/android/data/local/datasource/FileLocalDataSource.kt @@ -0,0 +1,91 @@ +package com.poti.android.data.local.datasource + +import android.content.Context +import android.graphics.Bitmap +import android.graphics.ImageDecoder +import android.net.Uri +import android.util.Size +import androidx.core.net.toUri +import com.poti.android.core.common.constant.ImageConstants.IMAGE_EXTENSION +import dagger.hilt.android.qualifiers.ApplicationContext +import java.io.ByteArrayOutputStream +import java.io.File +import java.util.UUID +import javax.inject.Inject +import kotlin.math.max + +class FileLocalDataSource @Inject constructor( + @param:ApplicationContext private val context: Context, +) { + fun createImageFile(uriString: String): File { + val uri = uriString.toUri() + + val directory = getDirectory() + val compressedImage = compressImage(uri, directory) + + return compressedImage + } + + fun clearDirectory() { + val directory = getDirectory() + directory.listFiles()?.forEach { it.delete() } + } + + private fun getDirectory(): File = File(context.cacheDir, DIRECTORY).apply { + mkdirs() + } + + private fun compressImage( + uri: Uri, + dir: File, + ): File { + val source = ImageDecoder.createSource(context.contentResolver, uri) + val bitmap = ImageDecoder.decodeBitmap(source) { decoder, info, _ -> + // 디코더 설정 + decoder.allocator = ImageDecoder.ALLOCATOR_SOFTWARE + decoder.isMutableRequired = true + + // 리사이징 크기 설정 + val targetSize = calculateTargetSize(info.size.width, info.size.height) + decoder.setTargetSize(targetSize.width, targetSize.height) + } + + // bitmap을 리사이징(압축)한 jpeg byteArray 생성 + val compressedImage = ByteArrayOutputStream().use { stream -> + bitmap.compress(Bitmap.CompressFormat.JPEG, QUALITY, stream) + bitmap.recycle() + stream.toByteArray() + } + + // 임시 파일 객체 생성 + val tempFile = File( + dir, + "${UUID.randomUUID()}.$IMAGE_EXTENSION", + ) + + // 파일 객채에 리사이징 byteArray 덮어씌워 최종 이미지 파일 생성 + tempFile.outputStream().use { stream -> + stream.write(compressedImage) + } + + return tempFile + } + + private fun calculateTargetSize( + width: Int, + height: Int, + ): Size { + if (width <= MAX_WIDTH && height <= MAX_HEIGHT) return Size(width, height) + + val ratio = max(width.toFloat() / MAX_WIDTH, height.toFloat() / MAX_HEIGHT) + + return Size((width / ratio).toInt(), (height / ratio).toInt()) + } + + companion object { + private const val MAX_WIDTH = 1024 + private const val MAX_HEIGHT = 1024 + private const val QUALITY = 80 + private const val DIRECTORY = "compressed" + } +} From 232e10c5e6666fd73eea95a00e8764c0b744970a Mon Sep 17 00:00:00 2001 From: dodo Date: Thu, 5 Feb 2026 17:01:01 +0900 Subject: [PATCH 03/10] =?UTF-8?q?[Feat/#145]=20=EC=9D=B4=EB=AF=B8=EC=A7=80?= =?UTF-8?q?=20=ED=8C=8C=EC=9D=BC=20=EC=97=85=EB=A1=9C=EB=93=9C=20=EC=9C=84?= =?UTF-8?q?=ED=95=9C=20FileUploadRepository=20=EA=B5=AC=ED=98=84=20-=20fil?= =?UTF-8?q?e=20=EA=B8=B0=EB=B0=98=20=EC=9D=B4=EB=AF=B8=EC=A7=80=20?= =?UTF-8?q?=EC=97=85=EB=A1=9C=EB=93=9C=20-=20uri=20=EA=B8=B0=EB=B0=98=20?= =?UTF-8?q?=EC=9D=B4=EB=AF=B8=EC=A7=80=20=EC=83=9D=EC=84=B1=20-=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=EB=90=9C=20=EC=9D=B4=EB=AF=B8=EC=A7=80=20?= =?UTF-8?q?=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/common/constant/ImageConstants.kt | 6 +++ .../poti/android/data/di/RepositoryModule.kt | 6 +++ .../remote/datasource/FileUploadDataSource.kt | 37 ++++++++++++++++++ .../repository/FileUploadRepositoryImpl.kt | 39 +++++++++++++++++++ .../domain/repository/FileUplaodRepository.kt | 14 +++++++ 5 files changed, 102 insertions(+) create mode 100644 app/src/main/java/com/poti/android/core/common/constant/ImageConstants.kt create mode 100644 app/src/main/java/com/poti/android/data/remote/datasource/FileUploadDataSource.kt create mode 100644 app/src/main/java/com/poti/android/data/repository/FileUploadRepositoryImpl.kt create mode 100644 app/src/main/java/com/poti/android/domain/repository/FileUplaodRepository.kt diff --git a/app/src/main/java/com/poti/android/core/common/constant/ImageConstants.kt b/app/src/main/java/com/poti/android/core/common/constant/ImageConstants.kt new file mode 100644 index 00000000..4453fe1c --- /dev/null +++ b/app/src/main/java/com/poti/android/core/common/constant/ImageConstants.kt @@ -0,0 +1,6 @@ +package com.poti.android.core.common.constant + +object ImageConstants { + const val IMAGE_EXTENSION = "jpg" + const val IMAGE_CONTENT_TYPE = "image/jpeg" +} diff --git a/app/src/main/java/com/poti/android/data/di/RepositoryModule.kt b/app/src/main/java/com/poti/android/data/di/RepositoryModule.kt index 8b60de05..24385f6f 100644 --- a/app/src/main/java/com/poti/android/data/di/RepositoryModule.kt +++ b/app/src/main/java/com/poti/android/data/di/RepositoryModule.kt @@ -3,6 +3,7 @@ package com.poti.android.data.di import com.poti.android.data.repository.ArtistRepositoryImpl import com.poti.android.data.repository.AuthRepositoryImpl import com.poti.android.data.repository.DeliveryRepositoryImpl +import com.poti.android.data.repository.FileUploadRepositoryImpl import com.poti.android.data.repository.HomeRepositoryImpl import com.poti.android.data.repository.ImageRepositoryImpl import com.poti.android.data.repository.ParticipationRepositoryImpl @@ -14,6 +15,7 @@ import com.poti.android.data.repository.UserRepositoryImpl import com.poti.android.domain.repository.ArtistRepository import com.poti.android.domain.repository.AuthRepository import com.poti.android.domain.repository.DeliveryRepository +import com.poti.android.domain.repository.FileUploadRepository import com.poti.android.domain.repository.HomeRepository import com.poti.android.domain.repository.ImageRepository import com.poti.android.domain.repository.ParticipationRepository @@ -74,4 +76,8 @@ abstract class RepositoryModule { @Binds @Singleton abstract fun bindReviewRepository(reviewRepositoryImpl: ReviewRepositoryImpl): ReviewRepository + + @Binds + @Singleton + abstract fun bindFileUploadRepository(fileUploadRepositoryImpl: FileUploadRepositoryImpl): FileUploadRepository } diff --git a/app/src/main/java/com/poti/android/data/remote/datasource/FileUploadDataSource.kt b/app/src/main/java/com/poti/android/data/remote/datasource/FileUploadDataSource.kt new file mode 100644 index 00000000..0a807c4e --- /dev/null +++ b/app/src/main/java/com/poti/android/data/remote/datasource/FileUploadDataSource.kt @@ -0,0 +1,37 @@ +package com.poti.android.data.remote.datasource + +import com.poti.android.core.common.constant.ImageConstants.IMAGE_CONTENT_TYPE +import com.poti.android.data.di.FileUploadClient +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext +import okhttp3.MediaType.Companion.toMediaType +import okhttp3.OkHttpClient +import okhttp3.Request +import okhttp3.RequestBody.Companion.asRequestBody +import java.io.File +import javax.inject.Inject + +class FileUploadDataSource @Inject constructor( + @param:FileUploadClient private val okHttpClient: OkHttpClient, +) { + suspend fun uploadImage( + uploadUrl: String, + file: File, + ) = withContext(Dispatchers.IO) { + val requestBody = file.asRequestBody(IMAGE_CONTENT_TYPE.toMediaType()) + + val request = Request.Builder() + .url(uploadUrl) + .put(requestBody) + .header("Content-Type", IMAGE_CONTENT_TYPE) + .build() + + okHttpClient.newCall(request).execute().use { response -> + if (!response.isSuccessful) { + throw IllegalStateException( + "File upload failed: ${response.code}", + ) + } + } + } +} diff --git a/app/src/main/java/com/poti/android/data/repository/FileUploadRepositoryImpl.kt b/app/src/main/java/com/poti/android/data/repository/FileUploadRepositoryImpl.kt new file mode 100644 index 00000000..688b7cad --- /dev/null +++ b/app/src/main/java/com/poti/android/data/repository/FileUploadRepositoryImpl.kt @@ -0,0 +1,39 @@ +package com.poti.android.data.repository + +import com.poti.android.core.network.util.HttpResponseHandler +import com.poti.android.data.local.datasource.FileLocalDataSource +import com.poti.android.data.remote.datasource.FileUploadDataSource +import com.poti.android.domain.repository.FileUploadRepository +import java.io.File +import javax.inject.Inject + +class FileUploadRepositoryImpl @Inject constructor( + private val httpResponseHandler: HttpResponseHandler, + private val fileUplaodRemoteDataSource: FileUploadDataSource, + private val fileLocalDataSource: FileLocalDataSource, +) : FileUploadRepository { + override suspend fun uploadImage( + uploadUrl: String, + file: File, + ): Result = httpResponseHandler.safeApiCall { + fileUplaodRemoteDataSource.uploadImage(uploadUrl, file) + } + + override fun createImage(uriString: String): Result { + try { + val file = fileLocalDataSource.createImageFile(uriString) + return Result.success(file) + } catch (exception: Throwable) { + return Result.failure(exception) + } + } + + override fun clearDirectory(): Result { + try { + fileLocalDataSource.clearDirectory() + return Result.success(Unit) + } catch (exception: Throwable) { + return Result.failure(exception) + } + } +} diff --git a/app/src/main/java/com/poti/android/domain/repository/FileUplaodRepository.kt b/app/src/main/java/com/poti/android/domain/repository/FileUplaodRepository.kt new file mode 100644 index 00000000..c2da0bed --- /dev/null +++ b/app/src/main/java/com/poti/android/domain/repository/FileUplaodRepository.kt @@ -0,0 +1,14 @@ +package com.poti.android.domain.repository + +import java.io.File + +interface FileUploadRepository { + suspend fun uploadImage( + uploadUrl: String, + file: File, + ): Result + + fun createImage(uriString: String): Result + + fun clearDirectory(): Result +} From fa9cf53d08068f305547ecdae679297e93875bbd Mon Sep 17 00:00:00 2001 From: dodo Date: Thu, 5 Feb 2026 17:02:14 +0900 Subject: [PATCH 04/10] =?UTF-8?q?[Feat/#145]=20=EC=9D=B4=EB=AF=B8=EC=A7=80?= =?UTF-8?q?=20=EC=97=85=EB=A1=9C=EB=93=9C=20=EC=9C=A0=EC=8A=A4=EC=BC=80?= =?UTF-8?q?=EC=9D=B4=EC=8A=A4=20=EC=83=9D=EC=84=B1=20(V2)=20-=20=EB=8B=A4?= =?UTF-8?q?=EC=9D=8C=20=EA=B3=BC=EC=A0=95=20=EC=88=9C=EC=B0=A8=20=EC=88=98?= =?UTF-8?q?=ED=96=89=20:=20presigned-url=20=EB=B0=9C=EA=B8=89=20>=20?= =?UTF-8?q?=EB=A6=AC=EC=82=AC=EC=9D=B4=EC=A7=95=EB=90=9C=20=ED=8C=8C?= =?UTF-8?q?=EC=9D=BC=20=EA=B0=9D=EC=B2=B4=20=EC=83=9D=EC=84=B1=20>=20s3=20?= =?UTF-8?q?=EC=97=85=EB=A1=9C=EB=93=9C=20>=20=ED=8C=8C=EC=9D=BC=20?= =?UTF-8?q?=EA=B0=9D=EC=B2=B4=20=EB=A9=94=EB=AA=A8=EB=A6=AC=EC=97=90?= =?UTF-8?q?=EC=84=9C=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../usecase/image/UploadImagesUseCaseV2.kt | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 app/src/main/java/com/poti/android/domain/usecase/image/UploadImagesUseCaseV2.kt diff --git a/app/src/main/java/com/poti/android/domain/usecase/image/UploadImagesUseCaseV2.kt b/app/src/main/java/com/poti/android/domain/usecase/image/UploadImagesUseCaseV2.kt new file mode 100644 index 00000000..b65e63e6 --- /dev/null +++ b/app/src/main/java/com/poti/android/domain/usecase/image/UploadImagesUseCaseV2.kt @@ -0,0 +1,55 @@ +package com.poti.android.domain.usecase.image + +import com.poti.android.core.common.constant.ImageConstants.IMAGE_EXTENSION +import com.poti.android.domain.model.image.PresignedUploadInfo +import com.poti.android.domain.repository.FileUploadRepository +import com.poti.android.domain.repository.ImageRepository +import java.io.File +import javax.inject.Inject + +class UploadImagesUseCaseV2 @Inject constructor( + private val imageRepository: ImageRepository, + private val fileUploadRepository: FileUploadRepository, +) { + suspend operator fun invoke( + uploadType: String, + uriStrings: List, + ): Result> { + try { + val uploadInfos = getUploadUrls(uploadType, uriStrings.size) + val (urls, fileNames) = uploadInfos.map { it.url to it.fileName }.unzip() + val files = createImages(uriStrings) + + uploadImages(urls, files) + clearDirectory() + + return Result.success(fileNames) + } catch (t: Throwable) { + return Result.failure(t) + } + } + + private suspend fun getUploadUrls( + uploadType: String, + size: Int, + ): List = imageRepository.getPresignedUrls( + type = uploadType, + extensions = List(size) { IMAGE_EXTENSION }, + ).getOrThrow() + + private fun createImages( + uriStrings: List, + ): List = uriStrings.map { uri -> + fileUploadRepository.createImage(uri).getOrThrow() + } + + private suspend fun uploadImages( + urls: List, + files: List, + ) = urls.zip(files) { url, file -> + fileUploadRepository.uploadImage(url, file).getOrThrow() + } + + private fun clearDirectory() = fileUploadRepository + .clearDirectory().getOrThrow() +} From 88b81cf6f15ad441f4b8b61ce4865e3414c15d36 Mon Sep 17 00:00:00 2001 From: dodo Date: Thu, 5 Feb 2026 17:39:45 +0900 Subject: [PATCH 05/10] =?UTF-8?q?[Refactor/#145]=20FileUploadRemoteDataSou?= =?UTF-8?q?rce=EB=A1=9C=20=EC=9D=B4=EB=A6=84=20=EB=B3=80=EA=B2=BD=20-=20Fi?= =?UTF-8?q?leUploadDataSource=20to=20FileUploadRemoteDataSource?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...{FileUploadDataSource.kt => FileUploadRemoteDataSource.kt} | 2 +- .../poti/android/data/repository/FileUploadRepositoryImpl.kt | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) rename app/src/main/java/com/poti/android/data/remote/datasource/{FileUploadDataSource.kt => FileUploadRemoteDataSource.kt} (95%) diff --git a/app/src/main/java/com/poti/android/data/remote/datasource/FileUploadDataSource.kt b/app/src/main/java/com/poti/android/data/remote/datasource/FileUploadRemoteDataSource.kt similarity index 95% rename from app/src/main/java/com/poti/android/data/remote/datasource/FileUploadDataSource.kt rename to app/src/main/java/com/poti/android/data/remote/datasource/FileUploadRemoteDataSource.kt index 0a807c4e..770967b0 100644 --- a/app/src/main/java/com/poti/android/data/remote/datasource/FileUploadDataSource.kt +++ b/app/src/main/java/com/poti/android/data/remote/datasource/FileUploadRemoteDataSource.kt @@ -11,7 +11,7 @@ import okhttp3.RequestBody.Companion.asRequestBody import java.io.File import javax.inject.Inject -class FileUploadDataSource @Inject constructor( +class FileUploadRemoteDataSource @Inject constructor( @param:FileUploadClient private val okHttpClient: OkHttpClient, ) { suspend fun uploadImage( diff --git a/app/src/main/java/com/poti/android/data/repository/FileUploadRepositoryImpl.kt b/app/src/main/java/com/poti/android/data/repository/FileUploadRepositoryImpl.kt index 688b7cad..6efd3a4b 100644 --- a/app/src/main/java/com/poti/android/data/repository/FileUploadRepositoryImpl.kt +++ b/app/src/main/java/com/poti/android/data/repository/FileUploadRepositoryImpl.kt @@ -2,14 +2,14 @@ package com.poti.android.data.repository import com.poti.android.core.network.util.HttpResponseHandler import com.poti.android.data.local.datasource.FileLocalDataSource -import com.poti.android.data.remote.datasource.FileUploadDataSource +import com.poti.android.data.remote.datasource.FileUploadRemoteDataSource import com.poti.android.domain.repository.FileUploadRepository import java.io.File import javax.inject.Inject class FileUploadRepositoryImpl @Inject constructor( private val httpResponseHandler: HttpResponseHandler, - private val fileUplaodRemoteDataSource: FileUploadDataSource, + private val fileUplaodRemoteDataSource: FileUploadRemoteDataSource, private val fileLocalDataSource: FileLocalDataSource, ) : FileUploadRepository { override suspend fun uploadImage( From 6d69b0987622f5095879569b588aa6f1b1380fd2 Mon Sep 17 00:00:00 2001 From: dodo Date: Thu, 5 Feb 2026 18:24:09 +0900 Subject: [PATCH 06/10] =?UTF-8?q?[Fix/#143]=20=EC=98=A4=ED=83=88=EC=9E=90?= =?UTF-8?q?=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/poti/android/data/di/RepositoryModule.kt | 6 +++--- ...adRepositoryImpl.kt => FileUplaodRepositoryImpl.kt} | 10 +++++----- .../android/domain/repository/FileUplaodRepository.kt | 2 +- .../domain/usecase/image/UploadImagesUseCaseV2.kt | 10 +++++----- 4 files changed, 14 insertions(+), 14 deletions(-) rename app/src/main/java/com/poti/android/data/repository/{FileUploadRepositoryImpl.kt => FileUplaodRepositoryImpl.kt} (80%) diff --git a/app/src/main/java/com/poti/android/data/di/RepositoryModule.kt b/app/src/main/java/com/poti/android/data/di/RepositoryModule.kt index 24385f6f..08c4fd23 100644 --- a/app/src/main/java/com/poti/android/data/di/RepositoryModule.kt +++ b/app/src/main/java/com/poti/android/data/di/RepositoryModule.kt @@ -3,7 +3,7 @@ package com.poti.android.data.di import com.poti.android.data.repository.ArtistRepositoryImpl import com.poti.android.data.repository.AuthRepositoryImpl import com.poti.android.data.repository.DeliveryRepositoryImpl -import com.poti.android.data.repository.FileUploadRepositoryImpl +import com.poti.android.data.repository.FileUplaodRepositoryImpl import com.poti.android.data.repository.HomeRepositoryImpl import com.poti.android.data.repository.ImageRepositoryImpl import com.poti.android.data.repository.ParticipationRepositoryImpl @@ -15,7 +15,7 @@ import com.poti.android.data.repository.UserRepositoryImpl import com.poti.android.domain.repository.ArtistRepository import com.poti.android.domain.repository.AuthRepository import com.poti.android.domain.repository.DeliveryRepository -import com.poti.android.domain.repository.FileUploadRepository +import com.poti.android.domain.repository.FileUplaodRepository import com.poti.android.domain.repository.HomeRepository import com.poti.android.domain.repository.ImageRepository import com.poti.android.domain.repository.ParticipationRepository @@ -79,5 +79,5 @@ abstract class RepositoryModule { @Binds @Singleton - abstract fun bindFileUploadRepository(fileUploadRepositoryImpl: FileUploadRepositoryImpl): FileUploadRepository + abstract fun bindFileUploadRepository(fileUploadRepositoryImpl: FileUplaodRepositoryImpl): FileUplaodRepository } diff --git a/app/src/main/java/com/poti/android/data/repository/FileUploadRepositoryImpl.kt b/app/src/main/java/com/poti/android/data/repository/FileUplaodRepositoryImpl.kt similarity index 80% rename from app/src/main/java/com/poti/android/data/repository/FileUploadRepositoryImpl.kt rename to app/src/main/java/com/poti/android/data/repository/FileUplaodRepositoryImpl.kt index 6efd3a4b..94126091 100644 --- a/app/src/main/java/com/poti/android/data/repository/FileUploadRepositoryImpl.kt +++ b/app/src/main/java/com/poti/android/data/repository/FileUplaodRepositoryImpl.kt @@ -3,20 +3,20 @@ package com.poti.android.data.repository import com.poti.android.core.network.util.HttpResponseHandler import com.poti.android.data.local.datasource.FileLocalDataSource import com.poti.android.data.remote.datasource.FileUploadRemoteDataSource -import com.poti.android.domain.repository.FileUploadRepository +import com.poti.android.domain.repository.FileUplaodRepository import java.io.File import javax.inject.Inject -class FileUploadRepositoryImpl @Inject constructor( +class FileUplaodRepositoryImpl @Inject constructor( private val httpResponseHandler: HttpResponseHandler, - private val fileUplaodRemoteDataSource: FileUploadRemoteDataSource, + private val fileUploadRemoteDataSource: FileUploadRemoteDataSource, private val fileLocalDataSource: FileLocalDataSource, -) : FileUploadRepository { +) : FileUplaodRepository { override suspend fun uploadImage( uploadUrl: String, file: File, ): Result = httpResponseHandler.safeApiCall { - fileUplaodRemoteDataSource.uploadImage(uploadUrl, file) + fileUploadRemoteDataSource.uploadImage(uploadUrl, file) } override fun createImage(uriString: String): Result { diff --git a/app/src/main/java/com/poti/android/domain/repository/FileUplaodRepository.kt b/app/src/main/java/com/poti/android/domain/repository/FileUplaodRepository.kt index c2da0bed..2160b5fa 100644 --- a/app/src/main/java/com/poti/android/domain/repository/FileUplaodRepository.kt +++ b/app/src/main/java/com/poti/android/domain/repository/FileUplaodRepository.kt @@ -2,7 +2,7 @@ package com.poti.android.domain.repository import java.io.File -interface FileUploadRepository { +interface FileUplaodRepository { suspend fun uploadImage( uploadUrl: String, file: File, diff --git a/app/src/main/java/com/poti/android/domain/usecase/image/UploadImagesUseCaseV2.kt b/app/src/main/java/com/poti/android/domain/usecase/image/UploadImagesUseCaseV2.kt index b65e63e6..48db399c 100644 --- a/app/src/main/java/com/poti/android/domain/usecase/image/UploadImagesUseCaseV2.kt +++ b/app/src/main/java/com/poti/android/domain/usecase/image/UploadImagesUseCaseV2.kt @@ -2,14 +2,14 @@ package com.poti.android.domain.usecase.image import com.poti.android.core.common.constant.ImageConstants.IMAGE_EXTENSION import com.poti.android.domain.model.image.PresignedUploadInfo -import com.poti.android.domain.repository.FileUploadRepository +import com.poti.android.domain.repository.FileUplaodRepository import com.poti.android.domain.repository.ImageRepository import java.io.File import javax.inject.Inject class UploadImagesUseCaseV2 @Inject constructor( private val imageRepository: ImageRepository, - private val fileUploadRepository: FileUploadRepository, + private val fileUplaodRepository: FileUplaodRepository, ) { suspend operator fun invoke( uploadType: String, @@ -40,16 +40,16 @@ class UploadImagesUseCaseV2 @Inject constructor( private fun createImages( uriStrings: List, ): List = uriStrings.map { uri -> - fileUploadRepository.createImage(uri).getOrThrow() + fileUplaodRepository.createImage(uri).getOrThrow() } private suspend fun uploadImages( urls: List, files: List, ) = urls.zip(files) { url, file -> - fileUploadRepository.uploadImage(url, file).getOrThrow() + fileUplaodRepository.uploadImage(url, file).getOrThrow() } - private fun clearDirectory() = fileUploadRepository + private fun clearDirectory() = fileUplaodRepository .clearDirectory().getOrThrow() } From 1b19a904763c336ec310a5cd8028574f8231cfec Mon Sep 17 00:00:00 2001 From: dodo Date: Thu, 5 Feb 2026 18:29:22 +0900 Subject: [PATCH 07/10] =?UTF-8?q?[Fix/#145]=20=EC=98=A4=ED=83=88=EC=9E=90?= =?UTF-8?q?=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/com/poti/android/data/di/RepositoryModule.kt | 6 +++--- ...eUplaodRepositoryImpl.kt => FileUploadRepositoryImpl.kt} | 6 +++--- .../{FileUplaodRepository.kt => FileUploadRepository.kt} | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) rename app/src/main/java/com/poti/android/data/repository/{FileUplaodRepositoryImpl.kt => FileUploadRepositoryImpl.kt} (89%) rename app/src/main/java/com/poti/android/domain/repository/{FileUplaodRepository.kt => FileUploadRepository.kt} (88%) diff --git a/app/src/main/java/com/poti/android/data/di/RepositoryModule.kt b/app/src/main/java/com/poti/android/data/di/RepositoryModule.kt index 08c4fd23..24385f6f 100644 --- a/app/src/main/java/com/poti/android/data/di/RepositoryModule.kt +++ b/app/src/main/java/com/poti/android/data/di/RepositoryModule.kt @@ -3,7 +3,7 @@ package com.poti.android.data.di import com.poti.android.data.repository.ArtistRepositoryImpl import com.poti.android.data.repository.AuthRepositoryImpl import com.poti.android.data.repository.DeliveryRepositoryImpl -import com.poti.android.data.repository.FileUplaodRepositoryImpl +import com.poti.android.data.repository.FileUploadRepositoryImpl import com.poti.android.data.repository.HomeRepositoryImpl import com.poti.android.data.repository.ImageRepositoryImpl import com.poti.android.data.repository.ParticipationRepositoryImpl @@ -15,7 +15,7 @@ import com.poti.android.data.repository.UserRepositoryImpl import com.poti.android.domain.repository.ArtistRepository import com.poti.android.domain.repository.AuthRepository import com.poti.android.domain.repository.DeliveryRepository -import com.poti.android.domain.repository.FileUplaodRepository +import com.poti.android.domain.repository.FileUploadRepository import com.poti.android.domain.repository.HomeRepository import com.poti.android.domain.repository.ImageRepository import com.poti.android.domain.repository.ParticipationRepository @@ -79,5 +79,5 @@ abstract class RepositoryModule { @Binds @Singleton - abstract fun bindFileUploadRepository(fileUploadRepositoryImpl: FileUplaodRepositoryImpl): FileUplaodRepository + abstract fun bindFileUploadRepository(fileUploadRepositoryImpl: FileUploadRepositoryImpl): FileUploadRepository } diff --git a/app/src/main/java/com/poti/android/data/repository/FileUplaodRepositoryImpl.kt b/app/src/main/java/com/poti/android/data/repository/FileUploadRepositoryImpl.kt similarity index 89% rename from app/src/main/java/com/poti/android/data/repository/FileUplaodRepositoryImpl.kt rename to app/src/main/java/com/poti/android/data/repository/FileUploadRepositoryImpl.kt index 94126091..ad774af9 100644 --- a/app/src/main/java/com/poti/android/data/repository/FileUplaodRepositoryImpl.kt +++ b/app/src/main/java/com/poti/android/data/repository/FileUploadRepositoryImpl.kt @@ -3,15 +3,15 @@ package com.poti.android.data.repository import com.poti.android.core.network.util.HttpResponseHandler import com.poti.android.data.local.datasource.FileLocalDataSource import com.poti.android.data.remote.datasource.FileUploadRemoteDataSource -import com.poti.android.domain.repository.FileUplaodRepository +import com.poti.android.domain.repository.FileUploadRepository import java.io.File import javax.inject.Inject -class FileUplaodRepositoryImpl @Inject constructor( +class FileUploadRepositoryImpl @Inject constructor( private val httpResponseHandler: HttpResponseHandler, private val fileUploadRemoteDataSource: FileUploadRemoteDataSource, private val fileLocalDataSource: FileLocalDataSource, -) : FileUplaodRepository { +) : FileUploadRepository { override suspend fun uploadImage( uploadUrl: String, file: File, diff --git a/app/src/main/java/com/poti/android/domain/repository/FileUplaodRepository.kt b/app/src/main/java/com/poti/android/domain/repository/FileUploadRepository.kt similarity index 88% rename from app/src/main/java/com/poti/android/domain/repository/FileUplaodRepository.kt rename to app/src/main/java/com/poti/android/domain/repository/FileUploadRepository.kt index 2160b5fa..c2da0bed 100644 --- a/app/src/main/java/com/poti/android/domain/repository/FileUplaodRepository.kt +++ b/app/src/main/java/com/poti/android/domain/repository/FileUploadRepository.kt @@ -2,7 +2,7 @@ package com.poti.android.domain.repository import java.io.File -interface FileUplaodRepository { +interface FileUploadRepository { suspend fun uploadImage( uploadUrl: String, file: File, From ae9c4de5b06bb78ce677d07f1d1fa462617ece74 Mon Sep 17 00:00:00 2001 From: dodo Date: Thu, 5 Feb 2026 18:30:39 +0900 Subject: [PATCH 08/10] =?UTF-8?q?[Fix/#145]=20=EC=9D=B4=EB=AF=B8=EC=A7=80?= =?UTF-8?q?=20=EC=97=85=EB=A1=9C=EB=93=9C=20=EC=9C=A0=EC=8A=A4=EC=BC=80?= =?UTF-8?q?=EC=9D=B4=EC=8A=A4=20=EC=88=98=EC=A0=95=20-=20=EC=BA=94?= =?UTF-8?q?=EC=8A=AC=20throw=20=EB=A1=9C=EC=A7=81=20=EC=B6=94=EA=B0=80=20-?= =?UTF-8?q?=20zip=20=EB=82=B4=EC=97=90=EC=84=9C=20suspend=20=ED=98=B8?= =?UTF-8?q?=EC=B6=9C=ED=95=98=EC=A7=80=20=EC=95=8A=EB=8F=84=EB=A1=9D=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD=20-=20uri/files=20=ED=81=AC=EA=B8=B0=20?= =?UTF-8?q?=EB=8B=A4=EB=A5=BC=20=EB=95=8C=20=EC=98=88=EC=99=B8=EC=B2=98?= =?UTF-8?q?=EB=A6=AC=20-=20=EC=B5=9C=EC=A2=85=20=EC=8B=A4=ED=8C=A8=20?= =?UTF-8?q?=EC=8B=9C=EC=97=90=EB=8F=84=20=EC=9D=B4=EB=AF=B8=EC=A7=80=20?= =?UTF-8?q?=EB=94=94=EB=A0=89=ED=86=A0=EB=A6=AC=20=EB=B9=84=EC=9A=B0?= =?UTF-8?q?=EB=8F=84=EB=A1=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../usecase/image/UploadImagesUseCaseV2.kt | 23 +++++++++++++------ 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/app/src/main/java/com/poti/android/domain/usecase/image/UploadImagesUseCaseV2.kt b/app/src/main/java/com/poti/android/domain/usecase/image/UploadImagesUseCaseV2.kt index 48db399c..ac9e4c42 100644 --- a/app/src/main/java/com/poti/android/domain/usecase/image/UploadImagesUseCaseV2.kt +++ b/app/src/main/java/com/poti/android/domain/usecase/image/UploadImagesUseCaseV2.kt @@ -2,14 +2,15 @@ package com.poti.android.domain.usecase.image import com.poti.android.core.common.constant.ImageConstants.IMAGE_EXTENSION import com.poti.android.domain.model.image.PresignedUploadInfo -import com.poti.android.domain.repository.FileUplaodRepository +import com.poti.android.domain.repository.FileUploadRepository import com.poti.android.domain.repository.ImageRepository import java.io.File import javax.inject.Inject +import kotlin.coroutines.cancellation.CancellationException class UploadImagesUseCaseV2 @Inject constructor( private val imageRepository: ImageRepository, - private val fileUplaodRepository: FileUplaodRepository, + private val fileUploadRepository: FileUploadRepository, ) { suspend operator fun invoke( uploadType: String, @@ -21,11 +22,13 @@ class UploadImagesUseCaseV2 @Inject constructor( val files = createImages(uriStrings) uploadImages(urls, files) - clearDirectory() return Result.success(fileNames) } catch (t: Throwable) { + if (t is CancellationException) throw t return Result.failure(t) + } finally { + clearDirectory() } } @@ -40,16 +43,22 @@ class UploadImagesUseCaseV2 @Inject constructor( private fun createImages( uriStrings: List, ): List = uriStrings.map { uri -> - fileUplaodRepository.createImage(uri).getOrThrow() + fileUploadRepository.createImage(uri).getOrThrow() } private suspend fun uploadImages( urls: List, files: List, - ) = urls.zip(files) { url, file -> - fileUplaodRepository.uploadImage(url, file).getOrThrow() + ) { + if (urls.size != files.size) { + throw IllegalStateException("Upload URL count and file count must match") + } + + for (i in urls.indices) { + fileUploadRepository.uploadImage(urls[i], files[i]).getOrThrow() + } } - private fun clearDirectory() = fileUplaodRepository + private fun clearDirectory() = fileUploadRepository .clearDirectory().getOrThrow() } From 181453fcf91ea1ff733fe0da3f14744c7914ba8a Mon Sep 17 00:00:00 2001 From: dodo Date: Tue, 10 Feb 2026 13:33:03 +0900 Subject: [PATCH 09/10] =?UTF-8?q?[Fix/#145]=20clearDirectory=20=EC=97=90?= =?UTF-8?q?=EB=9F=AC=EC=B2=98=EB=A6=AC=20=EC=88=98=EC=A0=95=20-=20as-is=20?= =?UTF-8?q?:=20finally=20=EB=B8=94=EB=A1=9D=EC=97=90=EC=84=9C=20=EC=97=90?= =?UTF-8?q?=EB=9F=AC=EB=A5=BC=20throw=EB=A1=9C=20=EC=A0=84=ED=8C=8C?= =?UTF-8?q?=ED=95=B4=20=EC=9C=84=ED=97=98=20-=20to-be=20:=20throw=20?= =?UTF-8?q?=EC=A0=9C=EA=B1=B0,=20runCatching=EC=9C=BC=EB=A1=9C=20=EC=97=90?= =?UTF-8?q?=EB=9F=AC=20=EC=8B=9C=20=EB=A1=9C=EA=B7=B8=EB=A7=8C=20=EC=B0=8D?= =?UTF-8?q?=EC=9D=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/usecase/image/UploadImagesUseCaseV2.kt | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/poti/android/domain/usecase/image/UploadImagesUseCaseV2.kt b/app/src/main/java/com/poti/android/domain/usecase/image/UploadImagesUseCaseV2.kt index ac9e4c42..149f034f 100644 --- a/app/src/main/java/com/poti/android/domain/usecase/image/UploadImagesUseCaseV2.kt +++ b/app/src/main/java/com/poti/android/domain/usecase/image/UploadImagesUseCaseV2.kt @@ -4,6 +4,7 @@ import com.poti.android.core.common.constant.ImageConstants.IMAGE_EXTENSION import com.poti.android.domain.model.image.PresignedUploadInfo import com.poti.android.domain.repository.FileUploadRepository import com.poti.android.domain.repository.ImageRepository +import timber.log.Timber import java.io.File import javax.inject.Inject import kotlin.coroutines.cancellation.CancellationException @@ -59,6 +60,10 @@ class UploadImagesUseCaseV2 @Inject constructor( } } - private fun clearDirectory() = fileUploadRepository - .clearDirectory().getOrThrow() + private fun clearDirectory() = runCatching { + fileUploadRepository.clearDirectory() + .onFailure { + Timber.e(it, "fail on clearDirectory") + } + } } From d2252e4fff0866eb2e17ec0871cdb505d0a84c4a Mon Sep 17 00:00:00 2001 From: dodo Date: Tue, 10 Feb 2026 13:49:38 +0900 Subject: [PATCH 10/10] =?UTF-8?q?[Fix/#145]=20=EC=9C=A0=EC=8A=A4=EC=BC=80?= =?UTF-8?q?=EC=9D=B4=EC=8A=A4=20=EC=97=90=EB=9F=AC=20=EC=B2=98=EB=A6=AC=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20-=20Timber=20=EC=9D=98=EC=A1=B4=EC=84=B1?= =?UTF-8?q?=20=EC=A0=9C=EA=B1=B0=20-=20Repository=EC=97=90=20=EA=B8=B0?= =?UTF-8?q?=EB=B3=B8=20=EC=97=90=EB=9F=AC=EC=B2=98=EB=A6=AC=EA=B0=80=20?= =?UTF-8?q?=EB=90=98=EC=96=B4=EC=9E=88=EC=96=B4=20=EC=A4=91=EB=B3=B5?= =?UTF-8?q?=EC=B2=98=EB=A6=AC=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/usecase/image/UploadImagesUseCaseV2.kt | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/app/src/main/java/com/poti/android/domain/usecase/image/UploadImagesUseCaseV2.kt b/app/src/main/java/com/poti/android/domain/usecase/image/UploadImagesUseCaseV2.kt index 149f034f..a876d892 100644 --- a/app/src/main/java/com/poti/android/domain/usecase/image/UploadImagesUseCaseV2.kt +++ b/app/src/main/java/com/poti/android/domain/usecase/image/UploadImagesUseCaseV2.kt @@ -4,7 +4,6 @@ import com.poti.android.core.common.constant.ImageConstants.IMAGE_EXTENSION import com.poti.android.domain.model.image.PresignedUploadInfo import com.poti.android.domain.repository.FileUploadRepository import com.poti.android.domain.repository.ImageRepository -import timber.log.Timber import java.io.File import javax.inject.Inject import kotlin.coroutines.cancellation.CancellationException @@ -29,7 +28,7 @@ class UploadImagesUseCaseV2 @Inject constructor( if (t is CancellationException) throw t return Result.failure(t) } finally { - clearDirectory() + fileUploadRepository.clearDirectory() } } @@ -59,11 +58,4 @@ class UploadImagesUseCaseV2 @Inject constructor( fileUploadRepository.uploadImage(urls[i], files[i]).getOrThrow() } } - - private fun clearDirectory() = runCatching { - fileUploadRepository.clearDirectory() - .onFailure { - Timber.e(it, "fail on clearDirectory") - } - } }