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 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/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( 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