From ca0a3a556e855aab7ea5bf8da74855972da5f53f Mon Sep 17 00:00:00 2001 From: agvber Date: Thu, 15 May 2025 16:57:41 +0900 Subject: [PATCH 1/4] =?UTF-8?q?feat:=20=EA=B7=B8=EB=A3=B9=EC=97=90=20?= =?UTF-8?q?=EA=B0=80=EC=9E=85=EB=90=9C=20=EC=9C=A0=EC=A0=80=20=EC=A0=95?= =?UTF-8?q?=EB=B3=B4=20=EC=A1=B0=ED=9A=8C=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../LocalGroupManagementRepositoryImpl.kt | 30 ++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/core/data/src/main/java/com/teampatch/core/data/repository/local/LocalGroupManagementRepositoryImpl.kt b/core/data/src/main/java/com/teampatch/core/data/repository/local/LocalGroupManagementRepositoryImpl.kt index 5cad5531..578d3694 100644 --- a/core/data/src/main/java/com/teampatch/core/data/repository/local/LocalGroupManagementRepositoryImpl.kt +++ b/core/data/src/main/java/com/teampatch/core/data/repository/local/LocalGroupManagementRepositoryImpl.kt @@ -3,12 +3,15 @@ package com.teampatch.core.data.repository.local import com.harmony.core.database.dao.GroupDao import com.harmony.core.database.dao.UserDao import com.harmony.core.database.model.GroupEntity +import com.teampatch.core.data.mapper.roleStringMapper +import com.teampatch.core.domain.model.FamilyInfo import com.teampatch.core.domain.model.InvitedGroup import com.teampatch.core.domain.model.UserGroup import com.teampatch.core.domain.repository.GroupManagementRepository import javax.inject.Inject import kotlin.random.Random import kotlinx.coroutines.flow.first +import kotlinx.coroutines.flow.map internal class LocalGroupManagementRepositoryImpl @Inject constructor( private val groupDao: GroupDao, @@ -51,7 +54,32 @@ internal class LocalGroupManagementRepositoryImpl @Inject constructor( } override suspend fun getUserGroupList(uid: String): List { - TODO("Not yet implemented") + val userEntity = userDao.getUserById(uid.toLong()).first() + val userGroupIds = userEntity.groupId + ?.let { listOf(it) } + ?: emptyList() + + return userGroupIds.map { groupId -> + groupDao.queryGroupById(groupId).map { groupEntity -> + UserGroup( + groupId = groupId.toString(), + name = "", + members = userDao.getUserByGroupId(groupId).map { userEntities -> + userEntities.map { + FamilyInfo( + title = it.relation, + name = it.name, + isManager = groupEntity.managerUid == it.uid, + role = roleStringMapper(it.role), + profileImageUrl = it.profileImageUri + ) + } + } + .first() + ) + } + .first() + } } override suspend fun queryGroupInvitationCode(): String { From 3c469b8fd3b4aeea992cdec2810381bbe55478f3 Mon Sep 17 00:00:00 2001 From: agvber Date: Fri, 16 May 2025 10:23:22 +0900 Subject: [PATCH 2/4] =?UTF-8?q?refactor:=20CoroutineDispatcher=20->=20Harm?= =?UTF-8?q?onyDispatcher=20=EC=9D=B4=EB=A6=84=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../teampatch/core/data/di/CoroutineModule.kt | 19 +++++++------------ ...tineDispatcher.kt => HarmonyDispatcher.kt} | 5 ++--- 2 files changed, 9 insertions(+), 15 deletions(-) rename core/data/src/main/java/com/teampatch/core/data/di/annotation/{CoroutineDispatcher.kt => HarmonyDispatcher.kt} (55%) diff --git a/core/data/src/main/java/com/teampatch/core/data/di/CoroutineModule.kt b/core/data/src/main/java/com/teampatch/core/data/di/CoroutineModule.kt index b467c8e7..ba8d2edb 100644 --- a/core/data/src/main/java/com/teampatch/core/data/di/CoroutineModule.kt +++ b/core/data/src/main/java/com/teampatch/core/data/di/CoroutineModule.kt @@ -1,28 +1,23 @@ package com.teampatch.core.data.di -import com.teampatch.core.data.di.annotation.CoroutineDispatcher -import com.teampatch.core.data.di.annotation.DispatcherContext +import com.teampatch.core.data.di.annotation.DispatchersContext +import com.teampatch.core.data.di.annotation.HarmonyDispatcher import dagger.Module import dagger.Provides import dagger.hilt.InstallIn import dagger.hilt.components.SingletonComponent -import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.SupervisorJob @Module @InstallIn(SingletonComponent::class) internal object CoroutineModule { - @CoroutineDispatcher(DispatcherContext.Default) + @HarmonyDispatcher(DispatchersContext.Default) @Provides - fun providesDefaultCoroutine(): CoroutineScope = CoroutineScope(context = SupervisorJob() + Dispatchers.Default) + fun providesDefaultCoroutine(): CoroutineDispatcher = Dispatchers.Default - @CoroutineDispatcher(DispatcherContext.IO) + @HarmonyDispatcher(DispatchersContext.IO) @Provides - fun providesIoCoroutine(): CoroutineScope = CoroutineScope(context = SupervisorJob() + Dispatchers.IO) - - @CoroutineDispatcher(DispatcherContext.Main) - @Provides - fun providesMainCoroutine(): CoroutineScope = CoroutineScope(context = SupervisorJob() + Dispatchers.Main) + fun providesIoCoroutine(): CoroutineDispatcher = Dispatchers.IO } \ No newline at end of file diff --git a/core/data/src/main/java/com/teampatch/core/data/di/annotation/CoroutineDispatcher.kt b/core/data/src/main/java/com/teampatch/core/data/di/annotation/HarmonyDispatcher.kt similarity index 55% rename from core/data/src/main/java/com/teampatch/core/data/di/annotation/CoroutineDispatcher.kt rename to core/data/src/main/java/com/teampatch/core/data/di/annotation/HarmonyDispatcher.kt index 1a532989..a4cd53f6 100644 --- a/core/data/src/main/java/com/teampatch/core/data/di/annotation/CoroutineDispatcher.kt +++ b/core/data/src/main/java/com/teampatch/core/data/di/annotation/HarmonyDispatcher.kt @@ -4,10 +4,9 @@ import javax.inject.Qualifier @Qualifier @Retention(AnnotationRetention.RUNTIME) -annotation class CoroutineDispatcher(val dispatcherContext: DispatcherContext) +annotation class HarmonyDispatcher(val dispatchersContext: DispatchersContext) -enum class DispatcherContext { +enum class DispatchersContext { Default, IO, - Main, } \ No newline at end of file From f6108830e362846e2295ba04df83f6b17a77c916 Mon Sep 17 00:00:00 2001 From: agvber Date: Fri, 16 May 2025 10:26:43 +0900 Subject: [PATCH 3/4] =?UTF-8?q?feat:=20contentResolver=20utils=20=ED=95=A8?= =?UTF-8?q?=EC=88=98=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/data/model/MediaStoreInfo.kt | 7 ++++ .../core/data/utils/ContentResolverUtils.kt | 33 +++++++++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 core/data/src/main/java/com/teampatch/core/data/model/MediaStoreInfo.kt create mode 100644 core/data/src/main/java/com/teampatch/core/data/utils/ContentResolverUtils.kt diff --git a/core/data/src/main/java/com/teampatch/core/data/model/MediaStoreInfo.kt b/core/data/src/main/java/com/teampatch/core/data/model/MediaStoreInfo.kt new file mode 100644 index 00000000..09dd7b9e --- /dev/null +++ b/core/data/src/main/java/com/teampatch/core/data/model/MediaStoreInfo.kt @@ -0,0 +1,7 @@ +package com.teampatch.core.data.model + +data class MediaStoreInfo( + val displayName: String, + val mimType: String, + val size: Long, +) \ No newline at end of file diff --git a/core/data/src/main/java/com/teampatch/core/data/utils/ContentResolverUtils.kt b/core/data/src/main/java/com/teampatch/core/data/utils/ContentResolverUtils.kt new file mode 100644 index 00000000..3e9b2dcf --- /dev/null +++ b/core/data/src/main/java/com/teampatch/core/data/utils/ContentResolverUtils.kt @@ -0,0 +1,33 @@ +package com.teampatch.core.data.utils + +import android.content.ContentResolver +import android.net.Uri +import android.provider.MediaStore +import com.teampatch.core.data.model.MediaStoreInfo + +internal fun ContentResolver.getMediaStoreInfo(uri: Uri): MediaStoreInfo? { + query( + uri, + arrayOf( + MediaStore.MediaColumns.DISPLAY_NAME, + MediaStore.MediaColumns.MIME_TYPE, + MediaStore.MediaColumns.SIZE + ), + null, + null, + null + )?.use { cursor -> + cursor.moveToFirst() + val fileName = cursor.getString(0) + val fileMediaType = cursor.getString(1) + val fileSize = cursor.getLong(2) + + return MediaStoreInfo( + displayName = fileName, + mimType = fileMediaType, + size = fileSize + ) + } + + return null +} \ No newline at end of file From aae9a9ca4742364723485dc6189f6a84d4f7721a Mon Sep 17 00:00:00 2001 From: agvber Date: Fri, 16 May 2025 11:36:59 +0900 Subject: [PATCH 4/4] =?UTF-8?q?feat:=20=EB=A1=9C=EC=BB=AC=EC=97=90?= =?UTF-8?q?=EC=84=9C=20=ED=94=84=EB=A1=9C=ED=95=84=20=EC=9D=B4=EB=AF=B8?= =?UTF-8?q?=EC=A7=80=20=EC=A0=80=EC=9E=A5=20=EA=B8=B0=EB=8A=A5=EC=9D=84=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=ED=95=A9=EB=8B=88=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../local/LocalUserRepositoryImpl.kt | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/core/data/src/main/java/com/teampatch/core/data/repository/local/LocalUserRepositoryImpl.kt b/core/data/src/main/java/com/teampatch/core/data/repository/local/LocalUserRepositoryImpl.kt index 8c92aa47..acc9839a 100644 --- a/core/data/src/main/java/com/teampatch/core/data/repository/local/LocalUserRepositoryImpl.kt +++ b/core/data/src/main/java/com/teampatch/core/data/repository/local/LocalUserRepositoryImpl.kt @@ -1,28 +1,71 @@ package com.teampatch.core.data.repository.local +import android.content.Context +import android.net.Uri +import android.webkit.MimeTypeMap +import androidx.core.net.toUri import com.harmony.core.database.dao.UserDao import com.harmony.core.database.model.UserEntity +import com.teampatch.core.data.di.annotation.DispatchersContext +import com.teampatch.core.data.di.annotation.HarmonyDispatcher import com.teampatch.core.data.mapper.MEMBER import com.teampatch.core.data.mapper.VIP import com.teampatch.core.data.mapper.toDomain +import com.teampatch.core.data.utils.getMediaStoreInfo import com.teampatch.core.domain.entity.SocialLoginHelper import com.teampatch.core.domain.model.Role import com.teampatch.core.domain.model.User import com.teampatch.core.domain.repository.UserRepository +import dagger.hilt.android.qualifiers.ApplicationContext +import java.io.File +import java.io.FileOutputStream import javax.inject.Inject +import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.map +import kotlinx.coroutines.withContext internal class LocalUserRepositoryImpl @Inject constructor( private val userDao: UserDao, private val socialLoginHelper: SocialLoginHelper, + @ApplicationContext private val appContext: Context, + @HarmonyDispatcher(DispatchersContext.IO) private val ioDispatcher: CoroutineDispatcher, ) : UserRepository { + private val profileImageFolder: File by lazy(LazyThreadSafetyMode.SYNCHRONIZED) { + File("${appContext.dataDir.absolutePath}/profile_image") + .also { it.mkdirs() } + } + override fun getUserInfo(): Flow = userDao.getMyUserData().map { it.toDomain() } override suspend fun editProfile(name: String?, profileImageUri: String?) { + val processedProfileImageUri: Uri? = profileImageUri?.toUri()?.let { + withContext(ioDispatcher) { + val contentResolver = appContext.contentResolver + val mediaStoreInfo = contentResolver.getMediaStoreInfo(it) + val mimeTypeMap = MimeTypeMap.getSingleton() + val fileExtension = mimeTypeMap.getExtensionFromMimeType(mediaStoreInfo?.mimType) + + contentResolver.openInputStream(it)?.use { profileImageInputStream -> + val file = File.createTempFile("profile_image", ".$fileExtension", profileImageFolder) + FileOutputStream(file).use { + it.write(profileImageInputStream.readBytes()) + } + file.toUri() + } + } + } + + val userEntity = userDao.getMyUserData().first() + val updateUserEntity = userEntity.copy( + name = name ?: userEntity.name, + profileImageUri = processedProfileImageUri?.toString() ?: userEntity.profileImageUri + ) + userDao.updateUser(updateUserEntity) } override suspend fun addUserProfile(