diff --git a/android/app/src/main/java/com/goliath/emojihub/data_sources/EmojiPagingSource.kt b/android/app/src/main/java/com/goliath/emojihub/data_sources/EmojiPagingSource.kt index e83b8c84..8774e6bc 100644 --- a/android/app/src/main/java/com/goliath/emojihub/data_sources/EmojiPagingSource.kt +++ b/android/app/src/main/java/com/goliath/emojihub/data_sources/EmojiPagingSource.kt @@ -6,14 +6,29 @@ import com.goliath.emojihub.data_sources.api.EmojiApi import com.goliath.emojihub.models.EmojiDto import javax.inject.Inject +enum class EmojiFetchType { + GENERAL, MY_CREATED, MY_SAVED +} + class EmojiPagingSource @Inject constructor( - private val api: EmojiApi + private val api: EmojiApi, + private val type: EmojiFetchType ): PagingSource() { override suspend fun load(params: LoadParams): LoadResult { val cursor = params.key ?: 1 val count = params.loadSize return try { - val response = api.fetchEmojiList(1, cursor, count).body() + val response: List? = when (type) { + EmojiFetchType.GENERAL -> { + api.fetchEmojiList(1, cursor, count).body() + } + EmojiFetchType.MY_CREATED -> { + api.fetchMyCreatedEmojiList(1, cursor, count).body() + } + EmojiFetchType.MY_SAVED -> { + api.fetchMySavedEmojiList(1, cursor, count).body() + } + } val data = response ?: listOf() LoadResult.Page( data = data, diff --git a/android/app/src/main/java/com/goliath/emojihub/data_sources/PostPagingSource.kt b/android/app/src/main/java/com/goliath/emojihub/data_sources/PostPagingSource.kt index f45dfc63..8f4fcf2c 100644 --- a/android/app/src/main/java/com/goliath/emojihub/data_sources/PostPagingSource.kt +++ b/android/app/src/main/java/com/goliath/emojihub/data_sources/PostPagingSource.kt @@ -6,13 +6,25 @@ import com.goliath.emojihub.data_sources.api.PostApi import com.goliath.emojihub.models.PostDto import javax.inject.Inject +enum class PostFetchType { + GENERAL, MY +} + class PostPagingSource @Inject constructor( - private val api: PostApi + private val api: PostApi, + private val type: PostFetchType ): PagingSource() { override suspend fun load(params: LoadParams): LoadResult { val cursor = params.key ?: 1 return try { - val response = api.fetchPostList(cursor).body() + val response: List? = when (type) { + PostFetchType.GENERAL -> { + api.fetchPostList(cursor).body() + } + PostFetchType.MY -> { + api.fetchMyPostList(cursor).body() + } + } val data = response ?: listOf() LoadResult.Page( data = data, diff --git a/android/app/src/main/java/com/goliath/emojihub/data_sources/api/EmojiApi.kt b/android/app/src/main/java/com/goliath/emojihub/data_sources/api/EmojiApi.kt index a991404d..654d68ab 100644 --- a/android/app/src/main/java/com/goliath/emojihub/data_sources/api/EmojiApi.kt +++ b/android/app/src/main/java/com/goliath/emojihub/data_sources/api/EmojiApi.kt @@ -27,6 +27,20 @@ interface EmojiApi { @Path("id") id: String ): Response + @GET("emoji/me/created") + suspend fun fetchMyCreatedEmojiList( + @Query("sortByDate") sortByDate: Int, + @Query("index") index: Int, + @Query("count") count: Int + ): Response> + + @GET("emoji/me/saved") + suspend fun fetchMySavedEmojiList( + @Query("sortByDate") sortByDate: Int, + @Query("index") index: Int, + @Query("count") count: Int + ): Response> + @Multipart @POST("emoji") suspend fun uploadEmoji( diff --git a/android/app/src/main/java/com/goliath/emojihub/data_sources/api/PostApi.kt b/android/app/src/main/java/com/goliath/emojihub/data_sources/api/PostApi.kt index b32b8b06..7cd86e81 100644 --- a/android/app/src/main/java/com/goliath/emojihub/data_sources/api/PostApi.kt +++ b/android/app/src/main/java/com/goliath/emojihub/data_sources/api/PostApi.kt @@ -17,6 +17,11 @@ interface PostApi { @Query("index") index: Int ): Response> + @GET("post/me") + suspend fun fetchMyPostList( + @Query("index") index: Int + ): Response> + @GET("post") suspend fun getPostWithId( @Path("id") id: String 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 e5d0c71c..3ac410b6 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 @@ -7,6 +7,7 @@ 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.models.EmojiDto @@ -28,6 +29,8 @@ import javax.inject.Singleton interface EmojiRepository { suspend fun fetchEmojiList(): Flow> + suspend fun fetchMyCreatedEmojiList(): Flow> + suspend fun fetchMySavedEmojiList(): Flow> suspend fun getEmojiWithId(id: String): EmojiDto? suspend fun uploadEmoji(videoFile: File, emojiDto: UploadEmojiDto): Boolean suspend fun saveEmoji(id: String): Response @@ -43,7 +46,21 @@ class EmojiRepositoryImpl @Inject constructor( override suspend fun fetchEmojiList(): Flow> { return Pager( config = PagingConfig(pageSize = 10, initialLoadSize = 10, enablePlaceholders = false), - pagingSourceFactory = { EmojiPagingSource(emojiApi) } + pagingSourceFactory = { EmojiPagingSource(emojiApi, EmojiFetchType.GENERAL) } + ).flow + } + + override suspend fun fetchMyCreatedEmojiList(): Flow> { + return Pager( + config = PagingConfig(pageSize = 10, initialLoadSize = 10, enablePlaceholders = false), + pagingSourceFactory = { EmojiPagingSource(emojiApi, EmojiFetchType.MY_CREATED) } + ).flow + } + + override suspend fun fetchMySavedEmojiList(): Flow> { + return Pager( + config = PagingConfig(pageSize = 10, initialLoadSize = 10, enablePlaceholders = false), + pagingSourceFactory = { EmojiPagingSource(emojiApi, EmojiFetchType.MY_SAVED) } ).flow } diff --git a/android/app/src/main/java/com/goliath/emojihub/repositories/remote/PostRepository.kt b/android/app/src/main/java/com/goliath/emojihub/repositories/remote/PostRepository.kt index fe6b097d..20ffd20b 100644 --- a/android/app/src/main/java/com/goliath/emojihub/repositories/remote/PostRepository.kt +++ b/android/app/src/main/java/com/goliath/emojihub/repositories/remote/PostRepository.kt @@ -4,6 +4,7 @@ import android.util.Log import androidx.paging.Pager import androidx.paging.PagingConfig import androidx.paging.PagingData +import com.goliath.emojihub.data_sources.PostFetchType import com.goliath.emojihub.data_sources.PostPagingSource import com.goliath.emojihub.data_sources.api.PostApi import com.goliath.emojihub.models.PostDto @@ -15,6 +16,7 @@ import javax.inject.Singleton interface PostRepository { suspend fun fetchPostList(): Flow> + suspend fun fetchMyPostList(): Flow> suspend fun uploadPost(dto: UploadPostDto): Response suspend fun getPostWithId(id: String): PostDto? suspend fun editPost(id: String, content: String) @@ -28,7 +30,14 @@ class PostRepositoryImpl @Inject constructor( override suspend fun fetchPostList(): Flow> { return Pager( config = PagingConfig(pageSize = 10, enablePlaceholders = false), - pagingSourceFactory = { PostPagingSource(postApi) } + pagingSourceFactory = { PostPagingSource(postApi, PostFetchType.GENERAL) } + ).flow + } + + override suspend fun fetchMyPostList(): Flow> { + return Pager( + config = PagingConfig(pageSize = 10, enablePlaceholders = false), + pagingSourceFactory = { PostPagingSource(postApi, PostFetchType.MY) } ).flow } 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 066ee3e2..66caebf5 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 @@ -20,8 +20,14 @@ import javax.inject.Singleton interface EmojiUseCase { val emojiList: StateFlow> + val myCreatedEmojiList: StateFlow> + val mySavedEmojiList: StateFlow> suspend fun updateEmojiList(data: PagingData) + suspend fun updateMyCreatedEmojiList(data: PagingData) + suspend fun updateMySavedEmojiList(data: PagingData) suspend fun fetchEmojiList(): Flow> + suspend fun fetchMyCreatedEmojiList(): Flow> + suspend fun fetchMySavedEmojiList(): Flow> suspend fun createEmoji(videoUri: Uri, topK: Int): List suspend fun uploadEmoji(emojiUnicode: String, emojiLabel: String, videoFile: File): Boolean suspend fun saveEmoji(id: String): Boolean @@ -39,13 +45,38 @@ class EmojiUseCaseImpl @Inject constructor( override val emojiList: StateFlow> get() = _emojiList + private val _myCreatedEmojiList = MutableStateFlow>(PagingData.empty()) + override val myCreatedEmojiList: StateFlow> + get() = _myCreatedEmojiList + + private val _mySavedEmojiList = MutableStateFlow>(PagingData.empty()) + override val mySavedEmojiList: StateFlow> + get() = _mySavedEmojiList + override suspend fun updateEmojiList(data: PagingData) { _emojiList.emit(data) } + + override suspend fun updateMyCreatedEmojiList(data: PagingData) { + _myCreatedEmojiList.emit(data) + } + + override suspend fun updateMySavedEmojiList(data: PagingData) { + _mySavedEmojiList.emit(data) + } + override suspend fun fetchEmojiList(): Flow> { return emojiRepository.fetchEmojiList().map { it.map { dto -> Emoji(dto) } } } + override suspend fun fetchMyCreatedEmojiList(): Flow> { + return emojiRepository.fetchMyCreatedEmojiList().map { it.map { dto -> Emoji(dto) } } + } + + override suspend fun fetchMySavedEmojiList(): Flow> { + return emojiRepository.fetchMySavedEmojiList().map { it.map { dto -> Emoji(dto) } } + } + override suspend fun createEmoji(videoUri: Uri, topK: Int): List { return x3dRepository.createEmoji(videoUri, topK) } 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 2e65a634..83fe79b7 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 @@ -15,13 +15,17 @@ import javax.inject.Inject sealed interface PostUseCase { val postList: StateFlow> + val myPostList: StateFlow> suspend fun updatePostList(data: PagingData) + suspend fun updateMyPostList(data: PagingData) suspend fun fetchPostList(): Flow> + suspend fun fetchMyPostList(): Flow> suspend fun uploadPost(content: String): Boolean suspend fun getPostWithId(id: String): PostDto? suspend fun editPost(id: String, content: String) suspend fun deletePost(id: String) } + class PostUseCaseImpl @Inject constructor( private val repository: PostRepository, private val errorController: ApiErrorController @@ -31,14 +35,26 @@ class PostUseCaseImpl @Inject constructor( override val postList: StateFlow> get() = _postList + private val _myPostList = MutableStateFlow>(PagingData.empty()) + override val myPostList: StateFlow> + get() = _myPostList + override suspend fun updatePostList(data: PagingData) { _postList.emit(data) } + override suspend fun updateMyPostList(data: PagingData) { + _myPostList.emit(data) + } + override suspend fun fetchPostList(): Flow> { return repository.fetchPostList().map { it.map { dto -> Post(dto) } } } + override suspend fun fetchMyPostList(): Flow> { + return repository.fetchMyPostList().map { it.map { dto -> Post(dto) } } + } + override suspend fun uploadPost(content: String): Boolean { val dto = UploadPostDto(content) val response = repository.uploadPost(dto) diff --git a/android/app/src/main/java/com/goliath/emojihub/viewmodels/EmojiViewModel.kt b/android/app/src/main/java/com/goliath/emojihub/viewmodels/EmojiViewModel.kt index e82620aa..0319ae9a 100644 --- a/android/app/src/main/java/com/goliath/emojihub/viewmodels/EmojiViewModel.kt +++ b/android/app/src/main/java/com/goliath/emojihub/viewmodels/EmojiViewModel.kt @@ -27,11 +27,12 @@ class EmojiViewModel @Inject constructor( var isBottomSheetShown by mutableStateOf(false) val emojiList = emojiUseCase.emojiList + val myCreatedEmojiList = emojiUseCase.myCreatedEmojiList + val mySavedEmojiList = emojiUseCase.mySavedEmojiList private val _topK = 3 - fun fetchEmojiList() - { + fun fetchEmojiList() { viewModelScope.launch { emojiUseCase.fetchEmojiList() .cachedIn(viewModelScope) @@ -41,6 +42,26 @@ class EmojiViewModel @Inject constructor( } } + fun fetchMyCreatedEmojiList() { + viewModelScope.launch { + emojiUseCase.fetchMyCreatedEmojiList() + .cachedIn(viewModelScope) + .collect { + emojiUseCase.updateMyCreatedEmojiList(it) + } + } + } + + fun fetchMySavedEmojiList() { + viewModelScope.launch { + emojiUseCase.fetchMySavedEmojiList() + .cachedIn(viewModelScope) + .collect { + emojiUseCase.updateMySavedEmojiList(it) + } + } + } + suspend fun createEmoji(videoUri: Uri): List { return withContext(Dispatchers.IO) { val createdEmojiList = emojiUseCase.createEmoji(videoUri, _topK) diff --git a/android/app/src/main/java/com/goliath/emojihub/viewmodels/PostViewModel.kt b/android/app/src/main/java/com/goliath/emojihub/viewmodels/PostViewModel.kt index 2cd3c6bf..06945776 100644 --- a/android/app/src/main/java/com/goliath/emojihub/viewmodels/PostViewModel.kt +++ b/android/app/src/main/java/com/goliath/emojihub/viewmodels/PostViewModel.kt @@ -14,6 +14,7 @@ class PostViewModel @Inject constructor( ): ViewModel() { val postList = postUseCase.postList + val myPostList = postUseCase.myPostList suspend fun fetchPostList() { viewModelScope.launch { @@ -25,6 +26,16 @@ class PostViewModel @Inject constructor( } } + suspend fun fetchMyPostList() { + viewModelScope.launch { + postUseCase.fetchMyPostList() + .cachedIn(viewModelScope) + .collect { + postUseCase.updateMyPostList(it) + } + } + } + suspend fun uploadPost(content: String): Boolean { return postUseCase.uploadPost(content) } diff --git a/android/app/src/main/java/com/goliath/emojihub/views/ProfilePage.kt b/android/app/src/main/java/com/goliath/emojihub/views/ProfilePage.kt index ccea324f..82662fdf 100644 --- a/android/app/src/main/java/com/goliath/emojihub/views/ProfilePage.kt +++ b/android/app/src/main/java/com/goliath/emojihub/views/ProfilePage.kt @@ -10,12 +10,11 @@ import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.items import androidx.compose.foundation.rememberScrollState -import androidx.compose.foundation.verticalScroll import androidx.compose.material3.Divider import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf @@ -28,14 +27,13 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.hilt.navigation.compose.hiltViewModel +import androidx.paging.compose.collectAsLazyPagingItems import com.goliath.emojihub.LocalNavController import com.goliath.emojihub.NavigationDestination -import com.goliath.emojihub.models.createDummyEmoji -import com.goliath.emojihub.models.dummyEmoji -import com.goliath.emojihub.models.dummyPost import com.goliath.emojihub.ui.theme.Color import com.goliath.emojihub.ui.theme.Color.EmojiHubDetailLabel import com.goliath.emojihub.ui.theme.Color.White +import com.goliath.emojihub.viewmodels.EmojiViewModel import com.goliath.emojihub.viewmodels.PostViewModel import com.goliath.emojihub.viewmodels.UserViewModel import com.goliath.emojihub.views.components.CustomDialog @@ -55,21 +53,28 @@ fun ProfilePage( val userViewModel = hiltViewModel() val postViewModel = hiltViewModel() + val emojiViewModel = hiltViewModel() val currentUser = userViewModel.userState.collectAsState().value + val myPostList = postViewModel.myPostList.collectAsLazyPagingItems() + val myCreatedEmojiList = emojiViewModel.myCreatedEmojiList.collectAsLazyPagingItems() + val mySavedEmojiList = emojiViewModel.mySavedEmojiList.collectAsLazyPagingItems() + var showLogoutDialog by remember { mutableStateOf(false) } var showSignOutDialog by remember { mutableStateOf(false) } - LazyColumn( - Modifier.background(White) - ) { + LaunchedEffect(Unit) { + postViewModel.fetchMyPostList() + emojiViewModel.fetchMyCreatedEmojiList() + emojiViewModel.fetchMySavedEmojiList() + } + + LazyColumn(Modifier.background(White)) { item { TopNavigationBar("Profile", shouldNavigate = false) - Box( - modifier = Modifier.fillMaxSize() - ) { + Box(modifier = Modifier.fillMaxSize()) { if (currentUser?.accessToken.isNullOrEmpty()) { EmptyProfile() } else { @@ -103,12 +108,13 @@ fun ProfilePage( ProfileMenuCellWithPreview( label = "내가 작성한 포스트", - detailLabel = "count", + detailLabel = myPostList.itemCount.toString(), navigateToDestination = { navController.navigate(NavigationDestination.MyPostList) } ) { - // TODO: should show my posts - items(listOf(dummyPost, dummyPost, dummyPost)) { - PreviewPostCell(post = it) + items(myPostList.itemCount) { index -> + myPostList[index]?.let { + PreviewPostCell(post = it) + } } } @@ -119,11 +125,14 @@ fun ProfilePage( ProfileMenuCellWithPreview( label = "내가 만든 이모지", detailLabel = "더보기", - navigateToDestination = { navController.navigate(NavigationDestination.MyEmojiList) }, - content = { - // should show my emojis + navigateToDestination = { navController.navigate(NavigationDestination.MyEmojiList) } + ) { + items(myCreatedEmojiList.itemCount) { index -> + myCreatedEmojiList[index]?.let { + EmojiCell(emoji = it, onSelected = {}) + } } - ) + } Spacer(modifier = Modifier.height(32.dp)) @@ -132,12 +141,10 @@ fun ProfilePage( detailLabel = "더보기", navigateToDestination = { navController.navigate(NavigationDestination.MySavedEmojiList) } ) { - // TODO: should show saved emoji list - items(listOf( - dummyEmoji, dummyEmoji, - dummyEmoji, dummyEmoji) - ) { - EmojiCell(emoji = it, onSelected = {}) + items(mySavedEmojiList.itemCount) { index -> + mySavedEmojiList[index]?.let { + EmojiCell(emoji = it, onSelected = {}) + } } } diff --git a/android/app/src/main/java/com/goliath/emojihub/views/components/PreviewPostCell.kt b/android/app/src/main/java/com/goliath/emojihub/views/components/PreviewPostCell.kt index d49773ab..33bd47be 100644 --- a/android/app/src/main/java/com/goliath/emojihub/views/components/PreviewPostCell.kt +++ b/android/app/src/main/java/com/goliath/emojihub/views/components/PreviewPostCell.kt @@ -4,7 +4,6 @@ import androidx.compose.foundation.border import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.width