Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,9 @@ import com.afternote.feature.afternote.domain.model.author.ProcessingMethod
import com.afternote.feature.afternote.domain.repository.author.AfternoteRepository
import com.afternote.feature.afternote.domain.repository.author.AuthorReceiverRepository
import com.afternote.feature.afternote.domain.repository.author.MediaInput
import com.afternote.feature.afternote.domain.repository.author.MemorialPhotoUploadRepository
import com.afternote.feature.afternote.domain.repository.author.MediaKind
import com.afternote.feature.afternote.domain.repository.author.MemorialMediaUploadRepository
import com.afternote.feature.afternote.domain.repository.author.MemorialThumbnailUploadRepository
import com.afternote.feature.afternote.domain.repository.author.MemorialVideoUploadRepository
import com.afternote.feature.afternote.domain.repository.author.PhotoUploadOutcome
import com.afternote.feature.afternote.domain.repository.author.VideoUploadOutcome
import com.afternote.feature.afternote.domain.usecase.editor.ResolveMemorialMediaForSaveUseCase
import com.afternote.feature.afternote.presentation.author.editor.AfternoteEditorViewModel
import com.afternote.feature.afternote.presentation.author.editor.SaveAfternoteMemorialMedia
Expand Down Expand Up @@ -178,23 +176,24 @@ class AfternoteAuthorAndroidTest {
memorialThumbnailUploadRepository = MemorialThumbnailUploadRepository { Result.success("https://cdn.test/thumb.jpg") },
resolveMemorialMediaForSave =
ResolveMemorialMediaForSaveUseCase(
memorialVideoUploadRepository =
MemorialVideoUploadRepository { input ->
memorialMediaUploadRepository =
MemorialMediaUploadRepository { input, kind ->
Result.success(
when (input) {
MediaInput.None -> VideoUploadOutcome.Empty
is MediaInput.Local -> VideoUploadOutcome.FreshlyUploaded("https://cdn.test/video.mp4")
is MediaInput.Remote -> VideoUploadOutcome.Existing(input.url)
},
)
},
memorialPhotoUploadRepository =
MemorialPhotoUploadRepository { input ->
Result.success(
when (input) {
MediaInput.None -> PhotoUploadOutcome.Empty
is MediaInput.Local -> PhotoUploadOutcome.FreshlyUploaded("https://cdn.test/photo.jpg")
is MediaInput.Remote -> PhotoUploadOutcome.Existing(input.url)
MediaInput.None -> {
null
}

is MediaInput.Local -> {
when (kind) {
MediaKind.VIDEO -> "https://cdn.test/video.mp4"
MediaKind.PHOTO -> "https://cdn.test/photo.jpg"
}
}

is MediaInput.Remote -> {
input.url
}
},
)
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,9 @@ import com.afternote.feature.afternote.domain.model.author.ReceiverRefPayload
import com.afternote.feature.afternote.domain.repository.author.AfternoteRepository
import com.afternote.feature.afternote.domain.repository.author.AuthorReceiverRepository
import com.afternote.feature.afternote.domain.repository.author.MediaInput
import com.afternote.feature.afternote.domain.repository.author.MemorialPhotoUploadRepository
import com.afternote.feature.afternote.domain.repository.author.MediaKind
import com.afternote.feature.afternote.domain.repository.author.MemorialMediaUploadRepository
import com.afternote.feature.afternote.domain.repository.author.MemorialThumbnailUploadRepository
import com.afternote.feature.afternote.domain.repository.author.MemorialVideoUploadRepository
import com.afternote.feature.afternote.domain.repository.author.PhotoUploadOutcome
import com.afternote.feature.afternote.domain.repository.author.VideoUploadOutcome
import com.afternote.feature.afternote.domain.usecase.editor.ResolveMemorialMediaForSaveUseCase
import com.afternote.feature.afternote.presentation.R
import com.afternote.feature.afternote.presentation.author.detail.AfternoteDetailDeleteResult
Expand Down Expand Up @@ -559,38 +557,23 @@ private fun editorViewModel(
},
resolveMemorialMediaForSave =
ResolveMemorialMediaForSaveUseCase(
memorialVideoUploadRepository =
MemorialVideoUploadRepository { input ->
memorialMediaUploadRepository =
MemorialMediaUploadRepository { input, kind ->
Result.success(
when (input) {
MediaInput.None -> {
VideoUploadOutcome.Empty
null
}

is MediaInput.Local -> {
VideoUploadOutcome.FreshlyUploaded("https://cdn.test/video.mp4")
when (kind) {
MediaKind.VIDEO -> "https://cdn.test/video.mp4"
MediaKind.PHOTO -> "https://cdn.test/photo.jpg"
}
}

is MediaInput.Remote -> {
VideoUploadOutcome.Existing(input.url)
}
},
)
},
memorialPhotoUploadRepository =
MemorialPhotoUploadRepository { input ->
Result.success(
when (input) {
MediaInput.None -> {
PhotoUploadOutcome.Empty
}

is MediaInput.Local -> {
PhotoUploadOutcome.FreshlyUploaded("https://cdn.test/photo.jpg")
}

is MediaInput.Remote -> {
PhotoUploadOutcome.Existing(input.url)
input.url
}
},
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,9 @@ import com.afternote.feature.afternote.domain.model.author.ProcessingMethod
import com.afternote.feature.afternote.domain.repository.author.AfternoteRepository
import com.afternote.feature.afternote.domain.repository.author.AuthorReceiverRepository
import com.afternote.feature.afternote.domain.repository.author.MediaInput
import com.afternote.feature.afternote.domain.repository.author.MemorialPhotoUploadRepository
import com.afternote.feature.afternote.domain.repository.author.MediaKind
import com.afternote.feature.afternote.domain.repository.author.MemorialMediaUploadRepository
import com.afternote.feature.afternote.domain.repository.author.MemorialThumbnailUploadRepository
import com.afternote.feature.afternote.domain.repository.author.MemorialVideoUploadRepository
import com.afternote.feature.afternote.domain.repository.author.PhotoUploadOutcome
import com.afternote.feature.afternote.domain.repository.author.VideoUploadOutcome
import com.afternote.feature.afternote.domain.usecase.editor.ResolveMemorialMediaForSaveUseCase
import com.afternote.feature.afternote.presentation.author.editor.AfternoteEditorViewModel
import com.afternote.feature.afternote.presentation.author.editor.SaveAfternoteMemorialMedia
Expand Down Expand Up @@ -344,40 +342,27 @@ private fun implementedCoverageViewModel(
},
resolveMemorialMediaForSave =
ResolveMemorialMediaForSaveUseCase(
memorialVideoUploadRepository =
MemorialVideoUploadRepository { input ->
videoInputs += input
memorialMediaUploadRepository =
MemorialMediaUploadRepository { input, kind ->
when (kind) {
MediaKind.VIDEO -> videoInputs += input
MediaKind.PHOTO -> photoInputs += input
}
Result.success(
when (input) {
MediaInput.None -> {
VideoUploadOutcome.Empty
null
}

is MediaInput.Local -> {
VideoUploadOutcome.FreshlyUploaded("https://cdn.test/uploaded-video.mp4")
when (kind) {
MediaKind.VIDEO -> "https://cdn.test/uploaded-video.mp4"
MediaKind.PHOTO -> "https://cdn.test/uploaded-photo.jpg"
}
}

is MediaInput.Remote -> {
VideoUploadOutcome.Existing(input.url)
}
},
)
},
memorialPhotoUploadRepository =
MemorialPhotoUploadRepository { input ->
photoInputs += input
Result.success(
when (input) {
MediaInput.None -> {
PhotoUploadOutcome.Empty
}

is MediaInput.Local -> {
PhotoUploadOutcome.FreshlyUploaded("https://cdn.test/uploaded-photo.jpg")
}

is MediaInput.Remote -> {
PhotoUploadOutcome.Existing(input.url)
input.url
}
},
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,13 @@ package com.afternote.feature.afternote.data.di

import com.afternote.feature.afternote.data.repositoryimpl.author.AfternoteRepositoryImpl
import com.afternote.feature.afternote.data.repositoryimpl.author.AuthorReceiverRepositoryImpl
import com.afternote.feature.afternote.data.repositoryimpl.author.MemorialPhotoUploadRepositoryImpl
import com.afternote.feature.afternote.data.repositoryimpl.author.MemorialMediaUploadRepositoryImpl
import com.afternote.feature.afternote.data.repositoryimpl.author.MemorialThumbnailUploadRepositoryImpl
import com.afternote.feature.afternote.data.repositoryimpl.author.MemorialVideoUploadRepositoryImpl
import com.afternote.feature.afternote.data.repositoryimpl.author.MusicSearchRepositoryImpl
import com.afternote.feature.afternote.domain.repository.author.AfternoteRepository
import com.afternote.feature.afternote.domain.repository.author.AuthorReceiverRepository
import com.afternote.feature.afternote.domain.repository.author.MemorialPhotoUploadRepository
import com.afternote.feature.afternote.domain.repository.author.MemorialMediaUploadRepository
import com.afternote.feature.afternote.domain.repository.author.MemorialThumbnailUploadRepository
import com.afternote.feature.afternote.domain.repository.author.MemorialVideoUploadRepository
import com.afternote.feature.afternote.domain.repository.author.MusicSearchRepository
import dagger.Binds
import dagger.Module
Expand Down Expand Up @@ -44,10 +42,5 @@ interface AfternoteAuthorRepositoryModule {
@Suppress("unused")
@Binds
@Singleton
fun bindMemorialVideoUploadRepository(impl: MemorialVideoUploadRepositoryImpl): MemorialVideoUploadRepository

@Suppress("unused")
@Binds
@Singleton
fun bindMemorialPhotoUploadRepository(impl: MemorialPhotoUploadRepositoryImpl): MemorialPhotoUploadRepository
fun bindMemorialMediaUploadRepository(impl: MemorialMediaUploadRepositoryImpl): MemorialMediaUploadRepository
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package com.afternote.feature.afternote.data.repositoryimpl.author

import com.afternote.core.domain.repository.PhotoUploadRepository
import com.afternote.core.domain.repository.VideoUploadRepository
import com.afternote.feature.afternote.domain.repository.author.MediaInput
import com.afternote.feature.afternote.domain.repository.author.MediaKind
import com.afternote.feature.afternote.domain.repository.author.MemorialMediaUploadRepository
import javax.inject.Inject

/**
* 서버 S3 의 애프터노트 미디어 폴더명. presigned URL 경로에 박혀 `bucket/afternotes/<file>` 형태가 됨. 서버와 약속된 문자열.
*
* 같은 패키지의 [MemorialThumbnailUploadRepositoryImpl] 가 이 값을 공유하므로 `internal`.
*/
internal const val DIRECTORY_AFTERNOTES = "afternotes"

/**
* 추모 미디어 *상태 해석* + 필요 시 업로드. 업로드 자체(presigned 발급·S3 PUT·MIME 추론)는
* [PhotoUploadRepository] · [VideoUploadRepository] 가 담당하고, 본 클래스는 분기 라우팅만 한다.
*/
class MemorialMediaUploadRepositoryImpl
@Inject
constructor(
private val photoUploadRepository: PhotoUploadRepository,
private val videoUploadRepository: VideoUploadRepository,
) : MemorialMediaUploadRepository {
override suspend fun resolve(
input: MediaInput,
kind: MediaKind,
): Result<String?> =
when (input) {
MediaInput.None -> {
Result.success(null)
}

is MediaInput.Remote -> {
Result.success(input.url)
}

is MediaInput.Local -> {
when (kind) {
MediaKind.PHOTO -> photoUploadRepository.upload(input.uri, DIRECTORY_AFTERNOTES)
MediaKind.VIDEO -> videoUploadRepository.upload(input.uri, DIRECTORY_AFTERNOTES)
}
}
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import okhttp3.RequestBody.Companion.toRequestBody
import javax.inject.Inject
import javax.inject.Named

// DIRECTORY_AFTERNOTES 는 같은 패키지 [MemorialPhotoUploadRepositoryImpl] 의 internal const 공유.
// DIRECTORY_AFTERNOTES 는 같은 패키지 [MemorialMediaUploadRepositoryImpl] 의 internal const 공유.
private const val EXTENSION_JPG = "jpg"
private const val CONTENT_TYPE_JPEG = "image/jpeg"

Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ package com.afternote.feature.afternote.domain.repository.author
*
* 진입 시점(presentation)에 로컬/원격을 *한 번* 확정해 resolve 경계로 넘긴다. 그러면 data 레이어가
* `content://` 같은 prefix 를 런타임에 문자열 비교하지 않고 [when] 분기(exhaustive)로 처리할 수 있다.
* 새 상태가 늘면 분기 누락이 컴파일 에러로 드러난다. (출력단 sealed `*UploadOutcome` #247 의 입력단 대칭.)
* 새 상태가 늘면 분기 누락이 컴파일 에러로 드러난다.
*/
sealed interface MediaInput {
/** 사용자가 이번 세션에 새로 고른 로컬 파일(`content://` URI). 업로드 대상. */
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.afternote.feature.afternote.domain.repository.author

/** 추모 미디어의 종류. 업로드 위임 대상을 가른다. */
enum class MediaKind {
PHOTO,
VIDEO,
}
Loading
Loading