Skip to content

Commit

Permalink
Merge branch 'feature/BDBD-525' into stage/sandbox
Browse files Browse the repository at this point in the history
# Conflicts:
#	presentation/src/main/res/navigation/nav_graph.xml
  • Loading branch information
minseonglove committed Feb 12, 2023
2 parents 89ec937 + b6872a1 commit 3f70b6a
Show file tree
Hide file tree
Showing 28 changed files with 652 additions and 267 deletions.
7 changes: 7 additions & 0 deletions data/src/main/java/com/fakedevelopers/data/di/MainModule.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.fakedevelopers.data.di

import android.content.Context
import com.fakedevelopers.data.repository.AlbumRepositoryImpl
import com.fakedevelopers.data.repository.ChatRepositoryImpl
import com.fakedevelopers.data.repository.ImageRepositoryImpl
import com.fakedevelopers.data.repository.LocalStorageRepositoryImpl
Expand All @@ -16,6 +17,7 @@ import com.fakedevelopers.data.service.ProductEditorService
import com.fakedevelopers.data.service.ProductListService
import com.fakedevelopers.data.service.ProductSearchService
import com.fakedevelopers.data.source.LocalStorageDataSource
import com.fakedevelopers.domain.repository.AlbumRepository
import com.fakedevelopers.domain.repository.ChatRepository
import com.fakedevelopers.domain.repository.ImageRepository
import com.fakedevelopers.domain.repository.LocalStorageRepository
Expand Down Expand Up @@ -112,4 +114,9 @@ object MainModule {
@Provides
fun provideProductSearchRepository(service: ProductSearchService): ProductSearchRepository =
ProductSearchRepositoryImpl(service)

@Singleton
@Provides
fun provideAlbumRepository(): AlbumRepository =
AlbumRepositoryImpl()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package com.fakedevelopers.data.repository

import com.fakedevelopers.domain.model.AlbumInfo
import com.fakedevelopers.domain.model.AlbumItem
import com.fakedevelopers.domain.repository.AlbumRepository

class AlbumRepositoryImpl : AlbumRepository {
override fun getAlbumInfo(
albumItems: List<AlbumItem>,
allImagesTitle: String
): List<AlbumInfo> {
val albumInfo = mutableListOf<AlbumInfo>()
albumInfo.add(
AlbumInfo(
path = "",
firstImage = albumItems[0].uri,
name = allImagesTitle,
count = albumItems.size
)
)
val countMap = mutableMapOf<String, Int>()
albumItems.forEach { albumItem ->
val relPath = albumItem.path.substringBeforeLast('/')
countMap[relPath] = (countMap[relPath] ?: 0) + 1
}
countMap.keys.forEach { relPath ->
albumInfo.add(
AlbumInfo(
path = relPath,
firstImage = albumItems.find { it.path.contains(relPath) }?.uri ?: "",
name = relPath.substringAfterLast('/'),
count = countMap[relPath] ?: 0
)
)
}
return albumInfo
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,27 @@ package com.fakedevelopers.data.repository

import android.content.ContentResolver
import android.content.ContentUris
import android.database.ContentObserver
import android.net.Uri
import android.os.Handler
import android.os.Looper
import android.provider.MediaStore
import androidx.exifinterface.media.ExifInterface
import com.fakedevelopers.domain.model.AlbumItem
import com.fakedevelopers.domain.model.MediaInfo
import com.fakedevelopers.domain.repository.ImageRepository
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.callbackFlow
import kotlinx.coroutines.withContext
import java.util.Locale
import javax.inject.Inject

class ImageRepositoryImpl @Inject constructor(
private val contentResolver: ContentResolver
) : ImageRepository {

override fun isValid(uri: String): Boolean {
contentResolver.runCatching {
openFileDescriptor(Uri.parse(uri), "r")?.use {
Expand All @@ -25,19 +32,22 @@ class ImageRepositoryImpl @Inject constructor(
return false
}

override suspend fun getAllImages(): Map<String, MutableList<AlbumItem>> {
override suspend fun getImages(path: String?): List<AlbumItem> {
val uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI
val albums = mutableMapOf<String, MutableList<AlbumItem>>().apply {
this[ALL_PICTURES] = mutableListOf()
val where = if (path.isNullOrEmpty().not()) {
MediaStore.Images.Media.DATA + " LIKE '%$path%'"
} else {
null
}
val images = mutableListOf<AlbumItem>()
contentResolver.query(
uri,
arrayOf(
MediaStore.Images.Media._ID,
MediaStore.Images.Media.DATA,
MediaStore.Images.ImageColumns.DATE_MODIFIED
),
null,
where,
null,
MediaStore.Images.ImageColumns.DATE_MODIFIED + " DESC"
)?.use { cursor ->
Expand All @@ -49,19 +59,30 @@ class ImageRepositoryImpl @Inject constructor(
).toString()
// 최근 수정 날짜
val date = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATE_MODIFIED))
val albumItem = AlbumItem(imageUri, date)
// 전체보기에 저장
albums[ALL_PICTURES]?.add(albumItem)
// 이미지 상대 경로에 저장
cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA)).let { path ->
val url = path.substringBeforeLast("/")
albums[url]?.add(albumItem) ?: run {
albums[url] = mutableListOf(albumItem)
}
val realPath = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA))
images.add(AlbumItem(imageUri, date, realPath))
}
}
return images
}

override fun getImageObserver(): Flow<String> = callbackFlow {
val contentObserver = object : ContentObserver(Handler(Looper.getMainLooper())) {
override fun onChange(selfChange: Boolean, uri: Uri?) {
super.onChange(selfChange, uri)
if (uri != null) {
trySend(uri.toString())
}
}
}
return albums
contentResolver.registerContentObserver(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
true,
contentObserver
)
awaitClose {
contentResolver.unregisterContentObserver(contentObserver)
}
}

override fun getValidUris(uris: List<String>): List<String> =
Expand Down Expand Up @@ -138,8 +159,4 @@ class ImageRepositoryImpl @Inject constructor(
}
updatedAlbumItem
}

companion object {
private const val ALL_PICTURES = "전체보기"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.fakedevelopers.domain.model

data class AlbumInfo(
val path: String,
val firstImage: String,
val name: String,
val count: Int
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.fakedevelopers.domain.repository

import com.fakedevelopers.domain.model.AlbumInfo
import com.fakedevelopers.domain.model.AlbumItem

interface AlbumRepository {
fun getAlbumInfo(albumItems: List<AlbumItem>, allImagesTitle: String): List<AlbumInfo>
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ import com.fakedevelopers.domain.model.AlbumItem
import com.fakedevelopers.domain.model.MediaInfo
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.Flow

interface ImageRepository {
fun isValid(uri: String): Boolean
suspend fun getAllImages(): Map<String, MutableList<AlbumItem>>
suspend fun getImages(path: String?): List<AlbumItem>
fun getImageObserver(): Flow<String>
fun getValidUris(uris: List<String>): List<String>
fun getDateModifiedByUri(uri: String): AlbumItem?
suspend fun getBytesByUri(uri: String, dispatcher: CoroutineDispatcher = Dispatchers.IO): ByteArray?
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.fakedevelopers.domain.usecase

import com.fakedevelopers.domain.repository.AlbumRepository
import javax.inject.Inject

class GetAlbumInfoUseCase @Inject constructor(
private val getImagesUseCase: GetImagesUseCase,
private val albumRepository: AlbumRepository
) {
suspend operator fun invoke(allImagesTitle: String) =
albumRepository.getAlbumInfo(
albumItems = getImagesUseCase(),
allImagesTitle = allImagesTitle
)
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
package com.fakedevelopers.domain.usecase

import com.fakedevelopers.domain.repository.ImageRepository
import kotlinx.coroutines.flow.Flow
import javax.inject.Inject

class GetAllImagesUseCase @Inject constructor(
class GetImageObserverUseCase @Inject constructor(
private val repository: ImageRepository
) {
suspend operator fun invoke() = repository.getAllImages()
operator fun invoke(): Flow<String> = repository.getImageObserver()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.fakedevelopers.domain.usecase

import com.fakedevelopers.domain.model.AlbumItem
import com.fakedevelopers.domain.repository.ImageRepository
import javax.inject.Inject

class GetImagesUseCase @Inject constructor(
private val repository: ImageRepository
) {
suspend operator fun invoke(path: String? = null): List<AlbumItem> =
repository.getImages(path)
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import android.view.View
import android.widget.AdapterView
import android.widget.ArrayAdapter
import android.widget.EditText
import androidx.activity.OnBackPressedCallback
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import androidx.annotation.StringRes
Expand Down Expand Up @@ -72,14 +71,6 @@ abstract class ProductEditorFragment(
)
}

private val backPressedCallback by lazy {
object : OnBackPressedCallback(true) {
override fun handleOnBackPressed() {
handleOnBackPressed()
}
}
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.vm = viewModel
Expand All @@ -94,7 +85,6 @@ abstract class ProductEditorFragment(

override fun onStart() {
super.onStart()
requireActivity().onBackPressedDispatcher.addCallback(backPressedCallback)
viewModel.refreshImages()
binding.textviewProductEditorContentLength.isVisible =
binding.edittextProductEditorContent.isFocused
Expand All @@ -121,8 +111,6 @@ abstract class ProductEditorFragment(

protected abstract fun initSelectedImages()

protected abstract fun handleOnBackPressed()

protected open fun initListener() {
// 가격 필터 등록
binding.edittextProductEditorHopePrice.setPriceFilter(MAX_PRICE_LENGTH)
Expand Down Expand Up @@ -168,7 +156,7 @@ abstract class ProductEditorFragment(
}
// 툴바 뒤로가기 버튼
binding.includeProductEditorToolbar.buttonToolbarBack.setOnClickListener {
backPressedCallback.handleOnBackPressed()
findNavController().popBackStack()
}
binding.spinnerProductEditorCategory.apply {
onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
Expand Down Expand Up @@ -254,7 +242,6 @@ abstract class ProductEditorFragment(

override fun onDestroyView() {
super.onDestroyView()
backPressedCallback.remove()
keyboardVisibilityUtils.deleteKeyboardListeners()
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -166,8 +166,8 @@ class ProductEditorViewModel @Inject constructor(
productModificationDto: ProductModificationDto? = null
) {
selectedImageInfo?.let {
selectedImageInfo.uris = it.uris
selectedImageInfo.changeBitmaps.putAll(it.changeBitmaps)
this.selectedImageInfo.uris = it.uris
this.selectedImageInfo.changeBitmaps.putAll(it.changeBitmaps)
adapter.submitList(it.uris.toMutableList())
}
productModificationDto?.let {
Expand Down
Loading

0 comments on commit 3f70b6a

Please sign in to comment.