diff --git a/android/.idea/deploymentTargetDropDown.xml b/android/.idea/deploymentTargetDropDown.xml
deleted file mode 100644
index 2ed6eec2..00000000
--- a/android/.idea/deploymentTargetDropDown.xml
+++ /dev/null
@@ -1,17 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/android/app/src/main/java/com/goliath/emojihub/data_sources/ApiErrorController.kt b/android/app/src/main/java/com/goliath/emojihub/data_sources/ApiErrorController.kt
index 9715a26b..69f5a820 100644
--- a/android/app/src/main/java/com/goliath/emojihub/data_sources/ApiErrorController.kt
+++ b/android/app/src/main/java/com/goliath/emojihub/data_sources/ApiErrorController.kt
@@ -51,7 +51,7 @@ enum class CustomError(
override fun body(): String = "이미 있는 계정입니다."
},
INTERNAL_SERVER_ERROR(500) {
- override fun body(): String = "접속 오류가 발생했습니다."
+ override fun body(): String = "네트워크 접속 오류가 발생했습니다."
},;
companion object {
diff --git a/android/app/src/main/java/com/goliath/emojihub/data_sources/DataSourceModule.kt b/android/app/src/main/java/com/goliath/emojihub/data_sources/DataSourceModule.kt
index 72ca0e40..01f122d7 100644
--- a/android/app/src/main/java/com/goliath/emojihub/data_sources/DataSourceModule.kt
+++ b/android/app/src/main/java/com/goliath/emojihub/data_sources/DataSourceModule.kt
@@ -2,6 +2,8 @@ package com.goliath.emojihub.data_sources
import com.goliath.emojihub.data_sources.local.X3dDataSource
import com.goliath.emojihub.data_sources.local.X3dDataSourceImpl
+import com.goliath.emojihub.data_sources.remote.EmojiDataSource
+import com.goliath.emojihub.data_sources.remote.EmojiDataSourceImpl
import dagger.Binds
import dagger.Module
import dagger.hilt.InstallIn
@@ -13,6 +15,9 @@ abstract class DataSourceModule {
@Binds
abstract fun bindsX3dDataSource(impl: X3dDataSourceImpl): X3dDataSource
+ @Binds
+ abstract fun bindsEmojiDataSource(impl: EmojiDataSourceImpl): EmojiDataSource
+
@Binds
abstract fun bindsApiErrorController(impl: ApiErrorControllerImpl): ApiErrorController
}
\ No newline at end of file
diff --git a/android/app/src/main/java/com/goliath/emojihub/data_sources/remote/EmojiDataSource.kt b/android/app/src/main/java/com/goliath/emojihub/data_sources/remote/EmojiDataSource.kt
new file mode 100644
index 00000000..a7bf5e21
--- /dev/null
+++ b/android/app/src/main/java/com/goliath/emojihub/data_sources/remote/EmojiDataSource.kt
@@ -0,0 +1,40 @@
+package com.goliath.emojihub.data_sources.remote
+
+import android.content.Context
+import android.graphics.Bitmap
+import android.media.MediaMetadataRetriever
+import android.util.Log
+import dagger.hilt.android.qualifiers.ApplicationContext
+import java.io.File
+import java.io.FileOutputStream
+import javax.inject.Inject
+
+interface EmojiDataSource {
+ fun createVideoThumbNail(videoFile: File): File?
+}
+class EmojiDataSourceImpl @Inject constructor(
+ @ApplicationContext private val context: Context
+): EmojiDataSource {
+
+ override fun createVideoThumbNail(videoFile: File): File? {
+ val retriever = MediaMetadataRetriever()
+ try {
+ retriever.setDataSource(videoFile.absolutePath)
+ val bitmap = retriever.frameAtTime
+
+ bitmap?.let {
+ val thumbnailFile = File(context.cacheDir, "thumbnail_${videoFile.name}.jpg")
+ FileOutputStream(thumbnailFile).use { out ->
+ bitmap.compress(Bitmap.CompressFormat.JPEG, 75, out)
+ }
+ Log.d("EmojiDataSource", "Thumbnail created: ${thumbnailFile.absolutePath}")
+ return thumbnailFile
+ }
+ } catch (e: Exception) {
+ Log.e("EmojiDataSource", "ERROR creating thumbnail: ${e.message?:"Unknown error"}")
+ } finally {
+ retriever.release()
+ }
+ return null
+ }
+}
\ No newline at end of file
diff --git a/android/app/src/main/java/com/goliath/emojihub/repositories/local/X3dRepository.kt b/android/app/src/main/java/com/goliath/emojihub/repositories/local/X3dRepository.kt
index 469949c4..2d41f462 100644
--- a/android/app/src/main/java/com/goliath/emojihub/repositories/local/X3dRepository.kt
+++ b/android/app/src/main/java/com/goliath/emojihub/repositories/local/X3dRepository.kt
@@ -10,6 +10,7 @@ import javax.inject.Inject
import javax.inject.Singleton
interface X3dRepository {
+ val DEFAULT_EMOJI_LIST: List
suspend fun createEmoji(videoUri: Uri, topK: Int): List
}
@@ -17,19 +18,20 @@ interface X3dRepository {
class X3dRepositoryImpl @Inject constructor(
private val x3dDataSource: X3dDataSource
): X3dRepository {
+
+ // FIXME: Default emojis should be topK different emojis -> use just 3 emojis for now
+ override val DEFAULT_EMOJI_LIST = listOf(
+ CreatedEmoji("love it", "U+2764 U+FE0F"),
+ CreatedEmoji("like", "U+1F44D"),
+ CreatedEmoji("ok", "U+1F646")
+ )
companion object{
const val moduleName = "Hagrid/efficient_x3d_s_hagrid_float.pt"
const val idToClassFileName = "Hagrid/hagrid_id_to_classname.json"
const val classToUnicodeFileName = "Hagrid/hagrid_classname_to_unicode.json"
const val SCORE_THRESHOLD = 0.4F
- // FIXME: Default emojis should be topK different emojis
- const val DEFAULT_EMOJI_NAME_1 = "love it"
- const val DEFAULT_EMOJI_UNICODE_1 = "U+2764 U+FE0F"
- const val DEFAULT_EMOJI_NAME_2 = "like"
- const val DEFAULT_EMOJI_UNICODE_2 = "U+1F44D"
- const val DEFAULT_EMOJI_NAME_3 = "ok"
- const val DEFAULT_EMOJI_UNICODE_3 = "U+1F646"
}
+
override suspend fun createEmoji(videoUri: Uri, topK: Int): List {
val x3dModule = x3dDataSource.loadModule(moduleName)
?: return emptyList()
@@ -57,9 +59,7 @@ class X3dRepositoryImpl @Inject constructor(
val inferenceResults = x3dDataSource.runInference(x3dModule, videoTensor, topK)
if (inferenceResults.isEmpty() || inferenceResults[0].score < SCORE_THRESHOLD) {
Log.w("X3d Repository", "Score is lower than threshold, return default emoji")
- return listOf(CreatedEmoji(DEFAULT_EMOJI_NAME_1, DEFAULT_EMOJI_UNICODE_1),
- CreatedEmoji(DEFAULT_EMOJI_NAME_2, DEFAULT_EMOJI_UNICODE_2),
- CreatedEmoji(DEFAULT_EMOJI_NAME_3, DEFAULT_EMOJI_UNICODE_3))
+ return DEFAULT_EMOJI_LIST
}
return x3dDataSource.indexToCreatedEmojiList(
inferenceResults, idToClassFileName, classToUnicodeFileName
diff --git a/android/app/src/main/java/com/goliath/emojihub/repositories/remote/EmojiRepository.kt b/android/app/src/main/java/com/goliath/emojihub/repositories/remote/EmojiRepository.kt
index 5fa9c9b1..0b01cec6 100644
--- a/android/app/src/main/java/com/goliath/emojihub/repositories/remote/EmojiRepository.kt
+++ b/android/app/src/main/java/com/goliath/emojihub/repositories/remote/EmojiRepository.kt
@@ -1,29 +1,22 @@
package com.goliath.emojihub.repositories.remote
-import android.content.Context
-import android.graphics.Bitmap
-import android.media.MediaMetadataRetriever
-import android.util.Log
import androidx.paging.Pager
import androidx.paging.PagingConfig
import androidx.paging.PagingData
import com.goliath.emojihub.data_sources.EmojiFetchType
import com.goliath.emojihub.data_sources.EmojiPagingSource
import com.goliath.emojihub.data_sources.api.EmojiApi
+import com.goliath.emojihub.data_sources.remote.EmojiDataSource
import com.goliath.emojihub.models.EmojiDto
import com.goliath.emojihub.models.UploadEmojiDto
import com.google.gson.Gson
-import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.flow.Flow
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.MultipartBody
import okhttp3.RequestBody.Companion.asRequestBody
import okhttp3.RequestBody.Companion.toRequestBody
-import retrofit2.HttpException
import retrofit2.Response
import java.io.File
-import java.io.FileOutputStream
-import java.io.IOException
import javax.inject.Inject
import javax.inject.Singleton
@@ -32,7 +25,7 @@ interface EmojiRepository {
suspend fun fetchMyCreatedEmojiList(): Flow>
suspend fun fetchMySavedEmojiList(): Flow>
suspend fun getEmojiWithId(id: String): EmojiDto?
- suspend fun uploadEmoji(videoFile: File, emojiDto: UploadEmojiDto): Boolean
+ suspend fun uploadEmoji(videoFile: File, emojiDto: UploadEmojiDto): Response
suspend fun saveEmoji(id: String): Response
suspend fun unSaveEmoji(id: String): Response
suspend fun deleteEmoji(id: String): Response
@@ -41,7 +34,7 @@ interface EmojiRepository {
@Singleton
class EmojiRepositoryImpl @Inject constructor(
private val emojiApi: EmojiApi,
- @ApplicationContext private val context: Context
+ private val emojiDataSource: EmojiDataSource
): EmojiRepository {
override suspend fun fetchEmojiList(sortByDate: Int): Flow> {
return Pager(
@@ -68,35 +61,20 @@ class EmojiRepositoryImpl @Inject constructor(
TODO("Not yet implemented")
}
- override suspend fun uploadEmoji(videoFile: File, emojiDto: UploadEmojiDto): Boolean {
+ override suspend fun uploadEmoji(videoFile: File, emojiDto: UploadEmojiDto): Response {
val emojiDtoJson = Gson().toJson(emojiDto)
val emojiDtoRequestBody = emojiDtoJson.toRequestBody("application/json".toMediaTypeOrNull())
val videoFileRequestBody = videoFile.asRequestBody("video/mp4".toMediaTypeOrNull())
val videoFileMultipartBody = MultipartBody.Part.createFormData("file", videoFile.name, videoFileRequestBody)
- val thumbnailFile = createVideoThumbnail(context, videoFile)
+ val thumbnailFile = emojiDataSource.createVideoThumbNail(videoFile)
val thumbnailRequestBody = thumbnailFile!!
.asRequestBody("image/jpg".toMediaTypeOrNull())
val thumbnailMultipartBody = MultipartBody.Part.createFormData("thumbnail",
thumbnailFile.name, thumbnailRequestBody)
- return try {
- emojiApi.uploadEmoji(videoFileMultipartBody, thumbnailMultipartBody, emojiDtoRequestBody)
- true
- }
- catch (e: IOException) {
- Log.e("EmojiRepository", "IOException")
- false
- }
- catch (e: HttpException) {
- Log.e("EmojiRepository", "HttpException")
- false
- }
- catch (e: Exception) {
- Log.e("EmojiRepository", "Unknown Exception: ${e.message}")
- false
- }
+ return emojiApi.uploadEmoji(videoFileMultipartBody, thumbnailMultipartBody, emojiDtoRequestBody)
}
override suspend fun saveEmoji(id: String): Response {
@@ -110,26 +88,4 @@ class EmojiRepositoryImpl @Inject constructor(
override suspend fun deleteEmoji(id: String): Response {
TODO("Not yet implemented")
}
-
- fun createVideoThumbnail(context: Context, videoFile: File): File? {
- val retriever = MediaMetadataRetriever()
- try {
- retriever.setDataSource(videoFile.absolutePath)
- val bitmap = retriever.frameAtTime
-
- bitmap?.let {
- val thumbnailFile = File(context.cacheDir, "thumbnail_${videoFile.name}.jpg")
- FileOutputStream(thumbnailFile).use { out ->
- bitmap.compress(Bitmap.CompressFormat.JPEG, 75, out)
- }
- Log.d("create_TN", "Thumbnail created: ${thumbnailFile.absolutePath}")
- return thumbnailFile
- }
- } catch (e: Exception) {
- Log.e("EmojiRepository_create_TN", "ERROR creating thumbnail: ${e.message?:"Unknown error"}")
- } finally {
- retriever.release()
- }
- return null
- }
}
\ No newline at end of file
diff --git a/android/app/src/main/java/com/goliath/emojihub/usecases/EmojiUseCase.kt b/android/app/src/main/java/com/goliath/emojihub/usecases/EmojiUseCase.kt
index 50971e04..4a3b1446 100644
--- a/android/app/src/main/java/com/goliath/emojihub/usecases/EmojiUseCase.kt
+++ b/android/app/src/main/java/com/goliath/emojihub/usecases/EmojiUseCase.kt
@@ -5,6 +5,7 @@ import android.util.Log
import androidx.paging.PagingData
import androidx.paging.map
import com.goliath.emojihub.data_sources.ApiErrorController
+import com.goliath.emojihub.data_sources.CustomError
import com.goliath.emojihub.models.CreatedEmoji
import com.goliath.emojihub.models.Emoji
import com.goliath.emojihub.models.UploadEmojiDto
@@ -13,8 +14,11 @@ import com.goliath.emojihub.repositories.remote.EmojiRepository
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.map
import java.io.File
+import java.io.IOException
+import java.net.ConnectException
import javax.inject.Inject
import javax.inject.Singleton
@@ -66,57 +70,92 @@ class EmojiUseCaseImpl @Inject constructor(
}
override suspend fun fetchEmojiList(sortByDate: Int): Flow> {
- return emojiRepository.fetchEmojiList(sortByDate).map { it.map { dto -> Emoji(dto) } }
+ return try {
+ emojiRepository.fetchEmojiList(sortByDate).map { it.map { dto -> Emoji(dto) } }
+ } catch (e: ConnectException) {
+ errorController.setErrorState(CustomError.INTERNAL_SERVER_ERROR.statusCode)
+ flowOf(PagingData.empty())
+ } catch (e: Exception) {
+ Log.e("EmojiUseCase", "Unknown Exception on fetchMyEmojiList: ${e.message}")
+ flowOf(PagingData.empty())
+ }
}
override suspend fun fetchMyCreatedEmojiList(): Flow> {
- return emojiRepository.fetchMyCreatedEmojiList().map { it.map { dto -> Emoji(dto) } }
+ return try {
+ emojiRepository.fetchMyCreatedEmojiList().map { it.map { dto -> Emoji(dto) } }
+ } catch (e: ConnectException) {
+ errorController.setErrorState(CustomError.INTERNAL_SERVER_ERROR.statusCode)
+ flowOf(PagingData.empty())
+ } catch (e: Exception) {
+ Log.e("EmojiUseCase", "Unknown Exception on fetchMyCreatedEmojiList: ${e.message}")
+ flowOf(PagingData.empty())
+ }
}
override suspend fun fetchMySavedEmojiList(): Flow> {
- return emojiRepository.fetchMySavedEmojiList().map { it.map { dto -> Emoji(dto) } }
+ return try {
+ emojiRepository.fetchMySavedEmojiList().map { it.map { dto -> Emoji(dto) } }
+ } catch (e: ConnectException) {
+ errorController.setErrorState(CustomError.INTERNAL_SERVER_ERROR.statusCode)
+ flowOf(PagingData.empty())
+ } catch (e: Exception) {
+ Log.e("EmojiUseCase", "Unknown Exception on fetchMySavedEmojiList: ${e.message}")
+ flowOf(PagingData.empty())
+ }
}
override suspend fun createEmoji(videoUri: Uri, topK: Int): List {
- return x3dRepository.createEmoji(videoUri, topK)
+ return try {
+ x3dRepository.createEmoji(videoUri, topK)
+ } catch (e: Exception) {
+ Log.e("EmojiUseCase", "Unknown Exception on createEmoji: ${e.message}")
+ x3dRepository.DEFAULT_EMOJI_LIST
+ }
}
override suspend fun uploadEmoji(emojiUnicode: String, emojiLabel: String, videoFile: File): Boolean {
val dto = UploadEmojiDto(emojiUnicode, emojiLabel)
- return emojiRepository.uploadEmoji(videoFile, dto)
- }
-
- override suspend fun saveEmoji(id: String): Boolean {
return try {
- val response = emojiRepository.saveEmoji(id)
- Log.d("EmojiUseCase", "SaveEmoji Api response : ${response.code()}")
-
+ val response = emojiRepository.uploadEmoji(videoFile, dto)
if (response.isSuccessful) {
- Log.d("EmojiUseCase", "Successfully saved Emoji (Id: $id)")
true
} else {
- Log.e("EmojiUseCase", "Failed to save Emoji (Id: $id), ${response.code()}")
+ errorController.setErrorState(response.code())
false
}
+ } catch (e: IOException) {
+ Log.e("EmojiUseCase", "IOException")
+ false
+ } catch (e: ConnectException) {
+ errorController.setErrorState(CustomError.INTERNAL_SERVER_ERROR.statusCode)
+ false
+ } catch (e: Exception) {
+ Log.e("EmojiUseCase", "Unknown Exception on uploadEmoji: ${e.message}")
+ false
+ }
+ }
+
+ override suspend fun saveEmoji(id: String): Boolean {
+ return try {
+ emojiRepository.saveEmoji(id).isSuccessful
+ } catch (e: ConnectException) {
+ errorController.setErrorState(CustomError.INTERNAL_SERVER_ERROR.statusCode)
+ false
} catch (e: Exception) {
- Log.e("EmojiUseCase", "Unknown Exception at Save emoji: ${e.message}")
+ Log.e("EmojiUseCase", "Unknown Exception on saveEmoji: ${e.message}")
false
}
}
override suspend fun unSaveEmoji(id: String): Boolean {
return try {
- val response = emojiRepository.unSaveEmoji(id)
- Log.d("EmojiUseCase", "UnSaveEmoji Api response : ${response.code()}")
- if (response.isSuccessful) {
- Log.d("EmojiUseCase", "Successfully unsaved Emoji (Id: $id)")
- true
- } else {
- Log.e("EmojiUseCase", "Failed to unsave Emoji (Id: $id), ${response.code()}")
- false
- }
+ emojiRepository.unSaveEmoji(id).isSuccessful
+ } catch (e: ConnectException) {
+ errorController.setErrorState(CustomError.INTERNAL_SERVER_ERROR.statusCode)
+ false
} catch (e: Exception) {
- Log.e("EmojiUseCase", "Unknown Exception at UnSave emoji: ${e.message}")
+ Log.e("EmojiUseCase", "Unknown Exception on unSaveEmoji: ${e.message}")
false
}
}
diff --git a/android/app/src/main/java/com/goliath/emojihub/usecases/PostUseCase.kt b/android/app/src/main/java/com/goliath/emojihub/usecases/PostUseCase.kt
index 2ca9f337..cf007c78 100644
--- a/android/app/src/main/java/com/goliath/emojihub/usecases/PostUseCase.kt
+++ b/android/app/src/main/java/com/goliath/emojihub/usecases/PostUseCase.kt
@@ -1,8 +1,10 @@
package com.goliath.emojihub.usecases
+import android.util.Log
import androidx.paging.PagingData
import androidx.paging.map
import com.goliath.emojihub.data_sources.ApiErrorController
+import com.goliath.emojihub.data_sources.CustomError
import com.goliath.emojihub.models.Post
import com.goliath.emojihub.models.PostDto
import com.goliath.emojihub.models.UploadPostDto
@@ -10,7 +12,9 @@ import com.goliath.emojihub.repositories.remote.PostRepository
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.map
+import java.net.ConnectException
import javax.inject.Inject
import javax.inject.Singleton
@@ -50,20 +54,44 @@ class PostUseCaseImpl @Inject constructor(
}
override suspend fun fetchPostList(): Flow> {
- return repository.fetchPostList().map { it.map { dto -> Post(dto) } }
+ return try {
+ repository.fetchPostList().map { it.map { dto -> Post(dto) } }
+ } catch (e: ConnectException) {
+ errorController.setErrorState(CustomError.INTERNAL_SERVER_ERROR.statusCode)
+ flowOf(PagingData.empty())
+ } catch (e: Exception) {
+ Log.e("PostUseCase", "Unknown Exception on fetchPostList: ${e.message}")
+ flowOf(PagingData.empty())
+ }
}
override suspend fun fetchMyPostList(): Flow> {
- return repository.fetchMyPostList().map { it.map { dto -> Post(dto) } }
+ return try {
+ repository.fetchMyPostList().map { it.map { dto -> Post(dto) } }
+ } catch (e: ConnectException) {
+ errorController.setErrorState(CustomError.INTERNAL_SERVER_ERROR.statusCode)
+ flowOf(PagingData.empty())
+ } catch (e: Exception) {
+ Log.e("PostUseCase", "Unknown Exception on fetchMyPostList: ${e.message}")
+ flowOf(PagingData.empty())
+ }
}
override suspend fun uploadPost(content: String): Boolean {
val dto = UploadPostDto(content)
- val response = repository.uploadPost(dto)
- return if (response.isSuccessful) {
- true
- } else {
- errorController.setErrorState(response.code())
+ return try {
+ val response = repository.uploadPost(dto)
+ if (response.isSuccessful) {
+ true
+ } else {
+ errorController.setErrorState(response.code())
+ false
+ }
+ } catch (e: ConnectException) {
+ errorController.setErrorState(CustomError.INTERNAL_SERVER_ERROR.statusCode)
+ false
+ } catch (e: Exception) {
+ Log.e("PostUseCase", "Unknown Exception on uploadPost: ${e.message}")
false
}
}
diff --git a/android/app/src/main/java/com/goliath/emojihub/usecases/UserUseCase.kt b/android/app/src/main/java/com/goliath/emojihub/usecases/UserUseCase.kt
index 4a73498b..acc75f3e 100644
--- a/android/app/src/main/java/com/goliath/emojihub/usecases/UserUseCase.kt
+++ b/android/app/src/main/java/com/goliath/emojihub/usecases/UserUseCase.kt
@@ -1,7 +1,9 @@
package com.goliath.emojihub.usecases
+import android.util.Log
import com.goliath.emojihub.EmojiHubApplication
import com.goliath.emojihub.data_sources.ApiErrorController
+import com.goliath.emojihub.data_sources.CustomError
import com.goliath.emojihub.models.LoginUserDto
import com.goliath.emojihub.models.RegisterUserDto
import com.goliath.emojihub.models.User
@@ -11,6 +13,7 @@ import com.goliath.emojihub.repositories.remote.UserRepository
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.update
+import java.net.ConnectException
import javax.inject.Inject
import javax.inject.Singleton
@@ -52,69 +55,99 @@ class UserUseCaseImpl @Inject constructor(
override suspend fun fetchMyInfo() {
val accessToken = EmojiHubApplication.preferences.accessToken ?: return
if (accessToken.isEmpty()) return
-
- val response = repository.fetchMyInfo(accessToken)
- response.let {
- if(it.isSuccessful) {
- val userDetailsDto = it.body() ?: return // FIXME: may be considered as an error
- _userDetailsState.update { UserDetails(userDetailsDto) }
+ try {
+ val response = repository.fetchMyInfo(accessToken)
+ response.let {
+ if(it.isSuccessful) {
+ val userDetailsDto = it.body() ?: return // FIXME: may be considered as an error
+ _userDetailsState.update { UserDetails(userDetailsDto) }
+ }
+ else errorController.setErrorState(it.code())
}
- else errorController.setErrorState(it.code())
+ } catch (e: ConnectException) {
+ errorController.setErrorState(CustomError.INTERNAL_SERVER_ERROR.statusCode)
+ } catch (e: Exception) {
+ Log.e("UserUseCase", "Unknown Exception on fetchMyEmoji: ${e.message}")
}
}
override suspend fun registerUser(email: String, name: String, password: String): Boolean {
val dto = RegisterUserDto(email, name, password)
- val response = repository.registerUser(dto)
- response.let {
- if(it.isSuccessful) return true
- else errorController.setErrorState(it.code())
+ try {
+ val response = repository.registerUser(dto)
+ response.let {
+ if(it.isSuccessful) return true
+ else errorController.setErrorState(it.code())
+ }
+ return response.isSuccessful
+ } catch (e: ConnectException) {
+ errorController.setErrorState(CustomError.INTERNAL_SERVER_ERROR.statusCode)
+ } catch (e: Exception) {
+ Log.e("UserUseCase", "Unknown Exception on registerUser: ${e.message}")
}
- return response.isSuccessful
+ return false
}
override suspend fun login(name: String, password: String) {
val dto = LoginUserDto(name, password)
- val response = repository.login(dto)
- response.let {
- if (it.isSuccessful) {
- val accessToken = it.body()?.accessToken
- _accessTokenState.update { accessToken }
- _userState.update { User(UserDto(name)) }
- EmojiHubApplication.preferences.accessToken = accessToken
- EmojiHubApplication.preferences.currentUser = name
- } else {
- errorController.setErrorState(it.code())
+ try {
+ val response = repository.login(dto)
+ response.let {
+ if (it.isSuccessful) {
+ val accessToken = it.body()?.accessToken
+ _accessTokenState.update { accessToken }
+ _userState.update { User(UserDto(name)) }
+ EmojiHubApplication.preferences.accessToken = accessToken
+ EmojiHubApplication.preferences.currentUser = name
+ } else {
+ errorController.setErrorState(it.code())
+ }
}
+ } catch (e: ConnectException) {
+ errorController.setErrorState(CustomError.INTERNAL_SERVER_ERROR.statusCode)
+ } catch (e: Exception) {
+ Log.e("UserUseCase", "Unknown Exception on login: ${e.message}")
}
}
override suspend fun logout() {
- val response = repository.logout()
- response.let {
- if (it.isSuccessful) {
- EmojiHubApplication.preferences.accessToken = null
- EmojiHubApplication.preferences.currentUser = null
- _accessTokenState.update { null }
- _userState.update { null }
- } else {
- errorController.setErrorState(it.code())
+ try {
+ val response = repository.logout()
+ response.let {
+ if (it.isSuccessful) {
+ EmojiHubApplication.preferences.accessToken = null
+ EmojiHubApplication.preferences.currentUser = null
+ _accessTokenState.update { null }
+ _userState.update { null }
+ } else {
+ errorController.setErrorState(it.code())
+ }
}
+ } catch (e: ConnectException) {
+ errorController.setErrorState(CustomError.INTERNAL_SERVER_ERROR.statusCode)
+ } catch (e: Exception) {
+ Log.e("UserUseCase", "Unknown Exception on logout: ${e.message}")
}
}
override suspend fun signOut() {
val accessToken = EmojiHubApplication.preferences.accessToken ?: return
- val response = repository.signOut(accessToken)
- response.let {
- if (it.isSuccessful) {
- EmojiHubApplication.preferences.accessToken = null
- EmojiHubApplication.preferences.currentUser = null
- _accessTokenState.update { null }
- _userState.update { null }
- } else {
- errorController.setErrorState(it.code())
+ try {
+ val response = repository.signOut(accessToken)
+ response.let {
+ if (it.isSuccessful) {
+ EmojiHubApplication.preferences.accessToken = null
+ EmojiHubApplication.preferences.currentUser = null
+ _accessTokenState.update { null }
+ _userState.update { null }
+ } else {
+ errorController.setErrorState(it.code())
+ }
}
+ } catch (e: ConnectException) {
+ errorController.setErrorState(CustomError.INTERNAL_SERVER_ERROR.statusCode)
+ } catch (e: Exception) {
+ Log.e("UserUseCase", "Unknown Exception on signOut: ${e.message}")
}
}
}
\ No newline at end of file
diff --git a/android/app/src/main/java/com/goliath/emojihub/views/EmojiPage.kt b/android/app/src/main/java/com/goliath/emojihub/views/EmojiPage.kt
index 811efc52..6128af2c 100644
--- a/android/app/src/main/java/com/goliath/emojihub/views/EmojiPage.kt
+++ b/android/app/src/main/java/com/goliath/emojihub/views/EmojiPage.kt
@@ -38,7 +38,6 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.font.FontWeight
-import androidx.compose.ui.unit.DpOffset
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.core.content.ContextCompat
@@ -49,7 +48,6 @@ import com.goliath.emojihub.NavigationDestination
import com.goliath.emojihub.extensions.toEmoji
import com.goliath.emojihub.navigateAsOrigin
import com.goliath.emojihub.ui.theme.Color.Black
-import com.goliath.emojihub.ui.theme.Color.LightGray
import com.goliath.emojihub.ui.theme.Color.White
import com.goliath.emojihub.viewmodels.EmojiViewModel
import com.goliath.emojihub.viewmodels.UserViewModel
diff --git a/android/app/src/test/java/com/goliath/emojihub/repositories/remote/EmojiRepositoryImplTest.kt b/android/app/src/test/java/com/goliath/emojihub/repositories/remote/EmojiRepositoryImplTest.kt
index 413bbe98..731a233a 100644
--- a/android/app/src/test/java/com/goliath/emojihub/repositories/remote/EmojiRepositoryImplTest.kt
+++ b/android/app/src/test/java/com/goliath/emojihub/repositories/remote/EmojiRepositoryImplTest.kt
@@ -3,6 +3,7 @@ package com.goliath.emojihub.repositories.remote
import androidx.paging.testing.asSnapshot
import com.goliath.emojihub.data_sources.CustomError
import com.goliath.emojihub.data_sources.api.EmojiApi
+import com.goliath.emojihub.data_sources.remote.EmojiDataSource
import com.goliath.emojihub.mockLogClass
import com.goliath.emojihub.models.EmojiDto
import com.goliath.emojihub.models.UploadEmojiDto
@@ -28,8 +29,8 @@ import java.lang.Exception
@RunWith(JUnit4::class)
class EmojiRepositoryImplTest {
private val emojiApi = mockk()
- private val context = mockk()
- private val emojiRepositoryImpl = EmojiRepositoryImpl(emojiApi, context)
+ private val emojiDataSource = mockk()
+ private val emojiRepositoryImpl = EmojiRepositoryImpl(emojiApi, emojiDataSource)
private val sampleEmojiDto = EmojiDto(
createdBy = "channn",
createdAt = "2023-11-24 14:25:05",
@@ -123,22 +124,22 @@ class EmojiRepositoryImplTest {
emojiApi.uploadEmoji(any(), any(), any())
} returns Response.success(Unit)
- val emojiRepositoryImpl = spyk(EmojiRepositoryImpl(emojiApi, context))
+ val emojiRepositoryImpl = spyk(EmojiRepositoryImpl(emojiApi, emojiDataSource))
every {
- emojiRepositoryImpl.createVideoThumbnail(any(), any())
+ emojiDataSource.createVideoThumbNail(any())
} returns File("sampleThumbnailFile")
// when
- val isUploaded = runBlocking {
+ val response = runBlocking {
emojiRepositoryImpl.uploadEmoji(sampleVideoFile, sampleUploadEmojiDto)
}
// then
coVerify(exactly = 1) { emojiApi.uploadEmoji(any(), any(), any()) }
- assertTrue(isUploaded)
+ assertTrue(response.isSuccessful)
}
@Test
- fun uploadEmoji_failureWithIOException_returnsFalse() {
+ fun uploadEmoji_failureWithException_throwsException() {
// given
mockkStatic(File::class)
val sampleVideoFile = File("sampleVideoFile")
@@ -147,18 +148,21 @@ class EmojiRepositoryImplTest {
emojiApi.uploadEmoji(any(), any(), any())
} throws mockk()
- val emojiRepositoryImpl = spyk(EmojiRepositoryImpl(emojiApi, context))
+ val emojiRepositoryImpl = spyk(EmojiRepositoryImpl(emojiApi, emojiDataSource))
every {
- emojiRepositoryImpl.createVideoThumbnail(any(), any())
+ emojiDataSource.createVideoThumbNail(any())
} returns File("sampleThumbnailFile")
// when
- val isUploaded = runBlocking {
- emojiRepositoryImpl.uploadEmoji(sampleVideoFile, sampleUploadEmojiDto)
+ try {
+ runBlocking {
+ emojiRepositoryImpl.uploadEmoji(sampleVideoFile, sampleUploadEmojiDto)
+ }
+ } catch (e: Exception) {
+ // then
+ coVerify(exactly = 1) { emojiApi.uploadEmoji(any(), any(), any()) }
+ assertTrue(e is IOException)
}
- // then
- coVerify(exactly = 1) { emojiApi.uploadEmoji(any(), any(), any()) }
- assertFalse(isUploaded)
}
@Test
@@ -171,42 +175,21 @@ class EmojiRepositoryImplTest {
emojiApi.uploadEmoji(any(), any(), any())
} throws mockk()
- val emojiRepositoryImpl = spyk(EmojiRepositoryImpl(emojiApi, context))
+ val emojiRepositoryImpl = spyk(EmojiRepositoryImpl(emojiApi, emojiDataSource))
every {
- emojiRepositoryImpl.createVideoThumbnail(any(), any())
+ emojiDataSource.createVideoThumbNail(any())
} returns File("sampleThumbnailFile")
// when
- val isUploaded = runBlocking {
- emojiRepositoryImpl.uploadEmoji(sampleVideoFile, sampleUploadEmojiDto)
+ try {
+ runBlocking {
+ emojiRepositoryImpl.uploadEmoji(sampleVideoFile, sampleUploadEmojiDto)
+ }
+ } catch (e: Exception) {
+ // then
+ coVerify(exactly = 1) { emojiApi.uploadEmoji(any(), any(), any()) }
+ assertTrue(e is HttpException)
}
- // then
- coVerify(exactly = 1) { emojiApi.uploadEmoji(any(), any(), any()) }
- assertFalse(isUploaded)
- }
-
- @Test
- fun uploadEmoji_failureWithOtherException_returnsFalse() {
- // given
- mockkStatic(File::class)
- val sampleVideoFile = File("sampleVideoFile")
- val sampleUploadEmojiDto = mockk()
- coEvery {
- emojiApi.uploadEmoji(any(), any(), any())
- } throws spyk()
-
- val emojiRepositoryImpl = spyk(EmojiRepositoryImpl(emojiApi, context))
- every {
- emojiRepositoryImpl.createVideoThumbnail(any(), any())
- } returns File("sampleThumbnailFile")
-
- // when
- val isUploaded = runBlocking {
- emojiRepositoryImpl.uploadEmoji(sampleVideoFile, sampleUploadEmojiDto)
- }
- // then
- coVerify(exactly = 1) { emojiApi.uploadEmoji(any(), any(), any()) }
- assertFalse(isUploaded)
}
@Test
diff --git a/android/app/src/test/java/com/goliath/emojihub/usecases/EmojiUseCaseImplTest.kt b/android/app/src/test/java/com/goliath/emojihub/usecases/EmojiUseCaseImplTest.kt
index 9c517d2e..c5aa66b3 100644
--- a/android/app/src/test/java/com/goliath/emojihub/usecases/EmojiUseCaseImplTest.kt
+++ b/android/app/src/test/java/com/goliath/emojihub/usecases/EmojiUseCaseImplTest.kt
@@ -184,7 +184,7 @@ class EmojiUseCaseImplTest {
val videoFile = File("sample.mp4")
coEvery {
emojiRepository.uploadEmoji(videoFile, any())
- } returns true
+ } returns Response.success(Unit)
// when
val isUploaded = runBlocking {
emojiUseCaseImpl.uploadEmoji(emojiUnicode, emojiLabel, videoFile)