From 361ffae9a7002b8901ef5890ce6c531cec28da6a Mon Sep 17 00:00:00 2001 From: yonghanJu Date: Thu, 16 Nov 2023 04:02:03 +0900 Subject: [PATCH 1/3] =?UTF-8?q?:sparkles:=20=EB=82=B4=EA=B0=80=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1=ED=95=9C=20=EA=B8=80=20=ED=99=95=EC=9D=B8=ED=95=98?= =?UTF-8?q?=EA=B8=B0=20=EB=8D=94=EB=AF=B8=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/whyranoid/walkie/KoinModules.kt | 4 +- data/src/main/java/com/whyranoid/data/API.kt | 4 ++ .../datasource/follow/FollowDataSourceImpl.kt | 18 +++---- .../data/datasource/follow/FollowService.kt | 8 ++-- .../datasource/post/PostDataSourceImpl.kt | 47 +++++++++++++++++-- .../data/datasource/post/PostService.kt | 9 ++++ .../data/model/account/UserResponse.kt | 20 ++++++++ .../whyranoid/data/model/post/PostResponse.kt | 38 +++++++++++++++ .../data/repository/PostRepositoryImpl.kt | 13 +++++ .../domain/datasource/PostDataSource.kt | 9 ++++ .../domain/model/post/PostPreview.kt | 11 +++++ .../domain/repository/PostRepository.kt | 9 ++++ .../usecase/GetUserPostPreviewsUseCase.kt | 17 ++++++- .../com/whyranoid/domain/util/Extensions.kt | 6 +++ .../presentation/screens/AppScreen.kt | 11 +++-- .../screens/mypage/MyPageScreen.kt | 38 ++++++++++++--- .../screens/mypage/addpost/PostingScreen.kt | 4 +- .../screens/mypage/tabs/HistoryPage.kt | 7 +-- .../screens/mypage/tabs/PostPage.kt | 17 +++++-- .../presentation/viewmodel/UserViewModel.kt | 22 ++++++++- 20 files changed, 267 insertions(+), 45 deletions(-) create mode 100644 data/src/main/java/com/whyranoid/data/model/account/UserResponse.kt create mode 100644 data/src/main/java/com/whyranoid/data/model/post/PostResponse.kt diff --git a/app/src/main/java/com/whyranoid/walkie/KoinModules.kt b/app/src/main/java/com/whyranoid/walkie/KoinModules.kt index 2a88875a..45c60efa 100644 --- a/app/src/main/java/com/whyranoid/walkie/KoinModules.kt +++ b/app/src/main/java/com/whyranoid/walkie/KoinModules.kt @@ -91,7 +91,7 @@ val viewModelModule = module { single { ChallengeMainViewModel(get(), get(), get()) } single { ChallengeDetailViewModel(get()) } single { ChallengeExitViewModel(get()) } - single { UserPageViewModel(get(), get(), get(), get(), get()) } + single { UserPageViewModel(get(), get(), get(), get(), get(), get()) } factory { RunningViewModel(get(), get(), get(), get(), get(), get()) } factory { RunningEditViewModel() } factory { SplashViewModel(get()) } @@ -131,7 +131,7 @@ val useCaseModule = module { single { GetChallengeDetailUseCase(get()) } single { GetChallengePreviewsByTypeUseCase(get()) } single { GetPostUseCase(get()) } - single { GetUserPostPreviewsUseCase(get()) } + single { GetUserPostPreviewsUseCase(get(), get()) } single { GetUserBadgesUseCase(get()) } single { GetUserDetailUseCase(get()) } single { GetRunningFollowerUseCase(get(), get()) } diff --git a/data/src/main/java/com/whyranoid/data/API.kt b/data/src/main/java/com/whyranoid/data/API.kt index 6bb1d7de..3a4baf1d 100644 --- a/data/src/main/java/com/whyranoid/data/API.kt +++ b/data/src/main/java/com/whyranoid/data/API.kt @@ -19,6 +19,10 @@ object API { const val UPLOAD_POST = "api/community/upload-post" + const val LIST_UP_MY_POST = "api/walkies/listup-my-post" + + const val LIST_UP_POST = "api/community/listup-post" + object WalkingControl { const val RUNNING_START = "api/walk/start" diff --git a/data/src/main/java/com/whyranoid/data/datasource/follow/FollowDataSourceImpl.kt b/data/src/main/java/com/whyranoid/data/datasource/follow/FollowDataSourceImpl.kt index 99f1ac4e..f78bd7c7 100644 --- a/data/src/main/java/com/whyranoid/data/datasource/follow/FollowDataSourceImpl.kt +++ b/data/src/main/java/com/whyranoid/data/datasource/follow/FollowDataSourceImpl.kt @@ -24,30 +24,24 @@ class FollowDataSourceImpl(private val followService: FollowService) : FollowDat override suspend fun getWalkingFollowings(uid: Long): Result> { return kotlin.runCatching { val response = followService.getWalkingFollowings(uid) - val followingList = requireNotNull(response.body()).list - followingList.map { - User(it.walkieId, "name", it.nickname, it.profileImg) - } + val followingList = requireNotNull(response.body()) + followingList.map { it.toUser() } } } override suspend fun getFollowings(uid: Long): Result> { return kotlin.runCatching { val response = followService.getFollowings(uid) - val followingList = requireNotNull(response.body()).list - followingList.map { - User(it.walkieId, "name", it.nickname, it.profileImg) - } + val followingList = requireNotNull(response.body()) + followingList.map { it.toUser() } } } override suspend fun getFollowers(uid: Long): Result> { return kotlin.runCatching { val response = followService.getFollowers(uid) - val followerList = requireNotNull(response.body()).list - followerList.map { - User(it.walkieId, "name", it.nickname, it.profileImg) - } + val followerList = requireNotNull(response.body()) + followerList.map { it.toUser() } } } } diff --git a/data/src/main/java/com/whyranoid/data/datasource/follow/FollowService.kt b/data/src/main/java/com/whyranoid/data/datasource/follow/FollowService.kt index e7e9d2da..bbe686b5 100644 --- a/data/src/main/java/com/whyranoid/data/datasource/follow/FollowService.kt +++ b/data/src/main/java/com/whyranoid/data/datasource/follow/FollowService.kt @@ -1,9 +1,9 @@ package com.whyranoid.data.datasource.follow import com.whyranoid.data.API +import com.whyranoid.data.model.account.UserResponse import com.whyranoid.data.model.follow.FollowRequest import com.whyranoid.data.model.follow.FollowResponse -import com.whyranoid.data.model.follow.FollowersResponse import retrofit2.Response import retrofit2.http.Body import retrofit2.http.DELETE @@ -21,17 +21,17 @@ interface FollowService { @GET(API.WALKING_FOLLOWING) suspend fun getWalkingFollowings( @Path("uid") uid: Long, - ): Response + ): Response> @GET(API.FOLLOWINGS) suspend fun getFollowings( @Path("uid") uid: Long, - ): Response + ): Response> @GET(API.FOLLOWERS) suspend fun getFollowers( @Path("uid") uid: Long, - ): Response + ): Response> @DELETE(API.UNFOLLOW) suspend fun unfollow( diff --git a/data/src/main/java/com/whyranoid/data/datasource/post/PostDataSourceImpl.kt b/data/src/main/java/com/whyranoid/data/datasource/post/PostDataSourceImpl.kt index e51920d4..d0400007 100644 --- a/data/src/main/java/com/whyranoid/data/datasource/post/PostDataSourceImpl.kt +++ b/data/src/main/java/com/whyranoid/data/datasource/post/PostDataSourceImpl.kt @@ -1,5 +1,6 @@ package com.whyranoid.data.datasource.post +import android.util.Log import com.whyranoid.domain.datasource.PostDataSource import com.whyranoid.domain.model.post.Post import com.whyranoid.domain.model.post.PostPreview @@ -7,11 +8,15 @@ import okhttp3.MediaType import okhttp3.MultipartBody import okhttp3.RequestBody import java.io.File +import java.util.Date class PostDataSourceImpl(private val postService: PostService) : PostDataSource { // TODO: change to api call override suspend fun getPostPreviews(uid: Long): Result> { - return Result.success(PostPreview.DUMMY_LIST) + return kotlin.runCatching { + val posts = requireNotNull(postService.getPosts(uid).body()) + posts.map { it.toPostPreview() } + } } override suspend fun getPostPreviews( @@ -20,7 +25,34 @@ class PostDataSourceImpl(private val postService: PostService) : PostDataSource month: Int, day: Int, ): Result> { - return Result.success(PostPreview.DUMMY_LIST) + return getPostPreviews(uid).onSuccess { posts -> + posts.filter { postPreview -> + val date = Date(postPreview.date) + Log.d("TODOREMOVE", "${date.year}, ${date.month + 1}, ${date.date}") + date.month + 1 == month && year == date.year && day == date.date + } + } + } + + override suspend fun getMyPostPreviews(uid: Long): Result> { + val response = postService.myPosts(uid) + response.body()?.map { it.toPostPreview() } ?: throw Exception(response.message()) + return Result.success(response.body()?.map { it.toPostPreview() }!!) + } + + override suspend fun getMyPostPreviews( + uid: Long, + year: Int, + month: Int, + day: Int, + ): Result> { + return getMyPostPreviews(uid).onSuccess { posts -> + posts.filter { postPreview -> + val date = Date(postPreview.date) + Log.d("TODOREMOVE", "${date.year}, ${date.month + 1}, ${date.date}") + date.month + 1 == month && year == date.year && day == date.date + } + } } // TODO: change to api call @@ -37,7 +69,8 @@ class PostDataSourceImpl(private val postService: PostService) : PostDataSource ): Result { val uidBody = RequestBody.create(MediaType.parse("text/plain"), uid.toString()) val contentBody = RequestBody.create(MediaType.parse("text/plain"), content) - val colorModeBody = RequestBody.create(MediaType.parse("text/plain"), colorMode.toString()) + val colorModeBody = + RequestBody.create(MediaType.parse("text/plain"), colorMode.toString()) val historyBody = RequestBody.create(MediaType.parse("text/plain"), history) val file = File(imagePath) @@ -46,7 +79,13 @@ class PostDataSourceImpl(private val postService: PostService) : PostDataSource return kotlin.runCatching { val uploadPostResponse = - postService.uploadPost(uidBody, contentBody, colorModeBody, historyBody, imagePart) + postService.uploadPost( + uidBody, + contentBody, + colorModeBody, + historyBody, + imagePart, + ) .body() uploadPostResponse?.message.toString() } diff --git a/data/src/main/java/com/whyranoid/data/datasource/post/PostService.kt b/data/src/main/java/com/whyranoid/data/datasource/post/PostService.kt index 2f00c1e0..236b8bb0 100644 --- a/data/src/main/java/com/whyranoid/data/datasource/post/PostService.kt +++ b/data/src/main/java/com/whyranoid/data/datasource/post/PostService.kt @@ -1,13 +1,16 @@ package com.whyranoid.data.datasource.post import com.whyranoid.data.API +import com.whyranoid.data.model.post.PostResponse import com.whyranoid.data.model.post.UploadPostResponse import okhttp3.MultipartBody import okhttp3.RequestBody import retrofit2.Response +import retrofit2.http.GET import retrofit2.http.Multipart import retrofit2.http.POST import retrofit2.http.Part +import retrofit2.http.Query interface PostService { @Multipart @@ -19,4 +22,10 @@ interface PostService { @Part("historyContent") historyContent: RequestBody, @Part image: MultipartBody.Part, ): Response + + @GET(API.LIST_UP_MY_POST) + suspend fun myPosts(@Query("walkieId") uid: Long): Response> + + @GET(API.LIST_UP_POST) + suspend fun getPosts(@Query("walkieId") uid: Long): Response> } diff --git a/data/src/main/java/com/whyranoid/data/model/account/UserResponse.kt b/data/src/main/java/com/whyranoid/data/model/account/UserResponse.kt new file mode 100644 index 00000000..4510bc0c --- /dev/null +++ b/data/src/main/java/com/whyranoid/data/model/account/UserResponse.kt @@ -0,0 +1,20 @@ +package com.whyranoid.data.model.account + +import com.google.gson.annotations.SerializedName +import com.whyranoid.domain.model.user.User + +data class UserResponse( + @SerializedName("walkieId") val uid: Long, + @SerializedName("nickname") val nickname: String, + @SerializedName("profileImg") val profileImg: String, + @SerializedName("status") val status: String, +) { + fun toUser(): User { + return User( + uid, + status, + nickname, + profileImg, + ) + } +} diff --git a/data/src/main/java/com/whyranoid/data/model/post/PostResponse.kt b/data/src/main/java/com/whyranoid/data/model/post/PostResponse.kt new file mode 100644 index 00000000..9bc5d9c2 --- /dev/null +++ b/data/src/main/java/com/whyranoid/data/model/post/PostResponse.kt @@ -0,0 +1,38 @@ +package com.whyranoid.data.model.post + +import com.google.gson.annotations.SerializedName +import com.whyranoid.data.model.account.UserResponse +import com.whyranoid.domain.model.post.PostPreview +import com.whyranoid.domain.model.post.TextVisibleState +import com.whyranoid.domain.util.dateFormatter + +data class PostResponse( + @SerializedName("viewerId") val viewerId: Long, + @SerializedName("poster") val poster: UserResponse, + @SerializedName("postId") val postId: Long, + @SerializedName("liked") val liked: Boolean, + @SerializedName("likers") val likers: List, + @SerializedName("photo") val photo: String, + @SerializedName("content") val content: String, + @SerializedName("date") val date: String, + @SerializedName("colorMode") val colorMode: Long, + @SerializedName("historyContent") val historyContent: String, +) { + fun toPostPreview(): PostPreview { + val destructedHistoryContent = historyContent.split('_') + println(destructedHistoryContent) + return PostPreview( + poster = poster.toUser(), + id = this.poster.uid, + liked = this.liked, + likers = this.likers.map { it.toUser() }, + imageUrl = this.photo, + date = dateFormatter.parse(this.date.replace("T", " ")).time, + textVisibleState = TextVisibleState.values()[this.colorMode.toInt()], + distanceText = destructedHistoryContent[2], + timeText = destructedHistoryContent[3], + paceText = destructedHistoryContent[4], + address = destructedHistoryContent[1], + ) + } +} diff --git a/data/src/main/java/com/whyranoid/data/repository/PostRepositoryImpl.kt b/data/src/main/java/com/whyranoid/data/repository/PostRepositoryImpl.kt index d9e1064a..5b039f35 100644 --- a/data/src/main/java/com/whyranoid/data/repository/PostRepositoryImpl.kt +++ b/data/src/main/java/com/whyranoid/data/repository/PostRepositoryImpl.kt @@ -21,6 +21,19 @@ class PostRepositoryImpl( return postDataSource.getPostPreviews(uid, year, month, day) } + override suspend fun getMyPostPreviews(uid: Long): Result> { + return postDataSource.getMyPostPreviews(uid) + } + + override suspend fun getMyPostPreviews( + uid: Long, + year: Int, + month: Int, + day: Int, + ): Result> { + return postDataSource.getMyPostPreviews(uid, year, month, day) + } + override suspend fun getPost(postId: Long): Result { return postDataSource.getPost(postId) } diff --git a/domain/src/main/java/com/whyranoid/domain/datasource/PostDataSource.kt b/domain/src/main/java/com/whyranoid/domain/datasource/PostDataSource.kt index bb65cc39..c51da673 100644 --- a/domain/src/main/java/com/whyranoid/domain/datasource/PostDataSource.kt +++ b/domain/src/main/java/com/whyranoid/domain/datasource/PostDataSource.kt @@ -6,6 +6,8 @@ import com.whyranoid.domain.model.post.PostPreview interface PostDataSource { suspend fun getPostPreviews(uid: Long): Result> + suspend fun getMyPostPreviews(uid: Long): Result> + suspend fun getPostPreviews( uid: Long, year: Int, @@ -13,6 +15,13 @@ interface PostDataSource { day: Int, ): Result> + suspend fun getMyPostPreviews( + uid: Long, + year: Int, + month: Int, + day: Int, + ): Result> + suspend fun getPost(postId: Long): Result suspend fun uploadPost( diff --git a/domain/src/main/java/com/whyranoid/domain/model/post/PostPreview.kt b/domain/src/main/java/com/whyranoid/domain/model/post/PostPreview.kt index a590188a..826d4a24 100644 --- a/domain/src/main/java/com/whyranoid/domain/model/post/PostPreview.kt +++ b/domain/src/main/java/com/whyranoid/domain/model/post/PostPreview.kt @@ -1,33 +1,44 @@ package com.whyranoid.domain.model.post +import com.whyranoid.domain.model.user.User + data class PostPreview( + val poster: User, val id: Long, + val liked: Boolean = false, + val likers: List = listOf(), val imageUrl: String, val date: Long = 0L, val textVisibleState: TextVisibleState = TextVisibleState.HIDE, val distanceText: String = "", val timeText: String = "", val paceText: String = "", + val address: String = "", ) { companion object { val DUMMY_LIST = listOf( PostPreview( + poster = User.DUMMY, id = 0L, imageUrl = "https://picsum.photos/250/250", ), PostPreview( + poster = User.DUMMY, id = 1L, imageUrl = "https://picsum.photos/250/250", ), PostPreview( + poster = User.DUMMY, id = 2L, imageUrl = "https://picsum.photos/250/250", ), PostPreview( + poster = User.DUMMY, id = 3L, imageUrl = "https://picsum.photos/250/250", ), PostPreview( + poster = User.DUMMY, id = 4L, imageUrl = "https://picsum.photos/250/250", ), diff --git a/domain/src/main/java/com/whyranoid/domain/repository/PostRepository.kt b/domain/src/main/java/com/whyranoid/domain/repository/PostRepository.kt index 54205cc3..4a79bf1f 100644 --- a/domain/src/main/java/com/whyranoid/domain/repository/PostRepository.kt +++ b/domain/src/main/java/com/whyranoid/domain/repository/PostRepository.kt @@ -6,6 +6,8 @@ import com.whyranoid.domain.model.post.PostPreview interface PostRepository { suspend fun getUserPostPreviews(uid: Long): Result> + suspend fun getMyPostPreviews(uid: Long): Result> + suspend fun getUserPostPreviews( uid: Long, year: Int, @@ -13,6 +15,13 @@ interface PostRepository { day: Int, ): Result> + suspend fun getMyPostPreviews( + uid: Long, + year: Int, + month: Int, + day: Int, + ): Result> + suspend fun getPost(postId: Long): Result suspend fun uploadPost( diff --git a/domain/src/main/java/com/whyranoid/domain/usecase/GetUserPostPreviewsUseCase.kt b/domain/src/main/java/com/whyranoid/domain/usecase/GetUserPostPreviewsUseCase.kt index 0e7e850c..ba14e7f6 100644 --- a/domain/src/main/java/com/whyranoid/domain/usecase/GetUserPostPreviewsUseCase.kt +++ b/domain/src/main/java/com/whyranoid/domain/usecase/GetUserPostPreviewsUseCase.kt @@ -1,13 +1,21 @@ package com.whyranoid.domain.usecase import com.whyranoid.domain.model.post.PostPreview +import com.whyranoid.domain.repository.AccountRepository import com.whyranoid.domain.repository.PostRepository +import kotlinx.coroutines.flow.first class GetUserPostPreviewsUseCase( private val postRepository: PostRepository, + private val accountRepository: AccountRepository, ) { suspend operator fun invoke(uid: Long): Result> { - return postRepository.getUserPostPreviews(uid) + val myUid = accountRepository.uId.first() + return if (myUid == uid) { + postRepository.getMyPostPreviews(uid) + } else { + postRepository.getUserPostPreviews(uid) + } } suspend operator fun invoke( @@ -16,6 +24,11 @@ class GetUserPostPreviewsUseCase( month: Int, day: Int, ): Result> { - return postRepository.getUserPostPreviews(uid, year, month, day) + val myUid = accountRepository.uId.first() + return if (myUid == uid) { + postRepository.getMyPostPreviews(uid, year, month, day) + } else { + postRepository.getUserPostPreviews(uid, year, month, day) + } } } diff --git a/domain/src/main/java/com/whyranoid/domain/util/Extensions.kt b/domain/src/main/java/com/whyranoid/domain/util/Extensions.kt index b1adb2c5..b3d59ffd 100644 --- a/domain/src/main/java/com/whyranoid/domain/util/Extensions.kt +++ b/domain/src/main/java/com/whyranoid/domain/util/Extensions.kt @@ -1,5 +1,11 @@ package com.whyranoid.domain.util +import java.text.SimpleDateFormat + val String.Companion.EMPTY: String get() = "" val String.Companion.BLANK: String get() = " " + +val String.Companion.DATE_FORMAT: String get() = "yyyy-MM-dd HH:mm:ss" + +val dateFormatter = SimpleDateFormat(String.DATE_FORMAT) diff --git a/presentation/src/main/java/com/whyranoid/presentation/screens/AppScreen.kt b/presentation/src/main/java/com/whyranoid/presentation/screens/AppScreen.kt index f381e4e8..6c984187 100644 --- a/presentation/src/main/java/com/whyranoid/presentation/screens/AppScreen.kt +++ b/presentation/src/main/java/com/whyranoid/presentation/screens/AppScreen.kt @@ -25,7 +25,6 @@ import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable import androidx.navigation.compose.currentBackStackEntryAsState import androidx.navigation.compose.rememberNavController -import com.whyranoid.domain.model.user.User import com.whyranoid.presentation.screens.Screen.Companion.bottomNavigationItems import com.whyranoid.presentation.screens.challenge.ChallengeCompleteScreen import com.whyranoid.presentation.screens.challenge.ChallengeDetailScreen @@ -41,6 +40,7 @@ import com.whyranoid.presentation.screens.splash.SplashScreen import com.whyranoid.presentation.theme.WalkieColor import com.whyranoid.presentation.viewmodel.SplashState import com.whyranoid.presentation.viewmodel.SplashViewModel +import org.koin.androidx.compose.get import org.koin.androidx.compose.koinViewModel @Composable @@ -49,7 +49,7 @@ fun AppScreen(startWorker: () -> Unit) { val splashViewModel = koinViewModel() val splashState = splashViewModel.splashState.collectAsStateWithLifecycle() - AppScreenContent(startWorker, navController) + // AppScreenContent(startWorker, navController) // TODO Splash 적용 when (splashState.value) { SplashState.InitialState -> SplashScreen() @@ -63,7 +63,10 @@ fun AppScreen(startWorker: () -> Unit) { } @Composable -fun AppScreenContent(startWorker: () -> Unit, navController: NavHostController) { +fun AppScreenContent( + startWorker: () -> Unit, + navController: NavHostController, +) { Scaffold( bottomBar = { val navBackStackEntry by navController.currentBackStackEntryAsState() @@ -131,7 +134,7 @@ fun AppScreenContent(startWorker: () -> Unit, navController: NavHostController) // TODO: repo, viewModel로 하여금 uid를 받아오도록 변경 or MyPageScreen 내부적으로 uid 보관하도록 변경 composable(Screen.MyPage.route) { - MyPageScreen(navController, User.DUMMY.uid) + MyPageScreen(navController) } composable(Screen.AddPostScreen.route) { diff --git a/presentation/src/main/java/com/whyranoid/presentation/screens/mypage/MyPageScreen.kt b/presentation/src/main/java/com/whyranoid/presentation/screens/mypage/MyPageScreen.kt index eb36502d..410e656d 100644 --- a/presentation/src/main/java/com/whyranoid/presentation/screens/mypage/MyPageScreen.kt +++ b/presentation/src/main/java/com/whyranoid/presentation/screens/mypage/MyPageScreen.kt @@ -7,6 +7,7 @@ import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding @@ -54,27 +55,37 @@ import com.whyranoid.presentation.reusable.TextWithCountSpaceBetween import com.whyranoid.presentation.screens.Screen import com.whyranoid.presentation.screens.mypage.tabs.ChallengePage import com.whyranoid.presentation.screens.mypage.tabs.HistoryPage +import com.whyranoid.presentation.screens.mypage.tabs.PostImagePreview import com.whyranoid.presentation.screens.mypage.tabs.PostPage import com.whyranoid.presentation.theme.WalkieColor import com.whyranoid.presentation.theme.WalkieTypography import com.whyranoid.presentation.viewmodel.UserPageState import com.whyranoid.presentation.viewmodel.UserPageViewModel +import kotlinx.coroutines.flow.first import kotlinx.coroutines.launch import org.koin.androidx.compose.koinViewModel import org.orbitmvi.orbit.compose.collectAsState +import java.time.LocalDate import java.util.* @Composable fun MyPageScreen( navController: NavController, - uid: Long, + uid: Long? = null, ) { val viewModel = koinViewModel() LaunchedEffect(true) { - viewModel.getUserDetail(uid) - viewModel.getUserBadges(uid) - viewModel.getUserPostPreviews(uid) + uid?.let { + viewModel.getUserDetail(uid) + viewModel.getUserBadges(uid) + viewModel.getUserPostPreviews(uid) + } ?: run { + val myUid = requireNotNull(viewModel.accountRepository.uId.first()) + viewModel.getUserDetail(myUid) + viewModel.getUserBadges(myUid) + viewModel.getUserPostPreviews(myUid) + } } val state by viewModel.collectAsState() @@ -90,6 +101,7 @@ fun MyPageScreen( onLogoutClicked = { viewModel.signOut() }, + onDateClicked = viewModel::selectDate, ) } @@ -103,6 +115,7 @@ fun MyPageContent( onProfileEditClicked: () -> Unit = {}, // TODO onSettingsClicked: () -> Unit = {}, // TODO onLogoutClicked: () -> Unit = {}, // TODO + onDateClicked: (LocalDate) -> Unit = {}, ) { Scaffold( topBar = { @@ -198,7 +211,6 @@ fun MyPageContent( val coroutineScope = rememberCoroutineScope() - TabRow( selectedTabIndex = pagerState.currentPage, modifier = Modifier.height(40.dp), @@ -241,7 +253,21 @@ fun MyPageContent( onPostCreateClicked, ) } - 1 -> HistoryPage(onDayClicked = {}) // TODO: 해당 날짜 데이터 로드 + + 1 -> { + Column { + HistoryPage(onDayClicked = onDateClicked) + state.calendarPreviewsState.getDataOrNull()?.let { postPreviews -> + postPreviews.forEach { postPreview -> + PostImagePreview( + Modifier.fillMaxSize().padding(40.dp), + postPreview, + onPostPreviewClicked, + ) + } + } + } + } 2 -> ChallengePage() } } diff --git a/presentation/src/main/java/com/whyranoid/presentation/screens/mypage/addpost/PostingScreen.kt b/presentation/src/main/java/com/whyranoid/presentation/screens/mypage/addpost/PostingScreen.kt index d6790f99..cec94e4f 100644 --- a/presentation/src/main/java/com/whyranoid/presentation/screens/mypage/addpost/PostingScreen.kt +++ b/presentation/src/main/java/com/whyranoid/presentation/screens/mypage/addpost/PostingScreen.kt @@ -66,6 +66,7 @@ import com.naver.maps.map.compose.NaverMap import com.naver.maps.map.compose.rememberCameraPositionState import com.whyranoid.domain.model.post.TextVisibleState import com.whyranoid.domain.model.running.RunningHistory +import com.whyranoid.domain.util.DATE_FORMAT import com.whyranoid.presentation.R import com.whyranoid.presentation.model.running.toRunningHistoryUiModel import com.whyranoid.presentation.reusable.CircleProgressWithText @@ -264,7 +265,6 @@ fun Map( val viewModel = koinViewModel() - val context = LocalContext.current val updatedContent by rememberUpdatedState(content) val contentHistory = listOf( "%.2f".format(runningHistoryUiModel.distance.div(1000.toDouble())), @@ -344,7 +344,7 @@ fun Map( updatedContent, textVisibleState, "${ - SimpleDateFormat("yyyy.MM.dd HH:mm").format( + SimpleDateFormat(String.DATE_FORMAT).format( Date( runningHistory.finishedAt, ), diff --git a/presentation/src/main/java/com/whyranoid/presentation/screens/mypage/tabs/HistoryPage.kt b/presentation/src/main/java/com/whyranoid/presentation/screens/mypage/tabs/HistoryPage.kt index 6a46e39c..db281b1b 100644 --- a/presentation/src/main/java/com/whyranoid/presentation/screens/mypage/tabs/HistoryPage.kt +++ b/presentation/src/main/java/com/whyranoid/presentation/screens/mypage/tabs/HistoryPage.kt @@ -10,7 +10,6 @@ import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.aspectRatio import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width @@ -23,6 +22,7 @@ import androidx.compose.material.icons.filled.KeyboardArrowRight import androidx.compose.material3.Icon import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip @@ -46,6 +46,9 @@ fun HistoryPage(modifier: Modifier = Modifier, onDayClicked: (LocalDate) -> Unit initialSelection = listOf(LocalDate.now()), initialSelectionMode = SelectionMode.Single, ) + LaunchedEffect(Unit) { + onDayClicked(calendarState.selectionState.selection[0]) + } Column( modifier = modifier @@ -165,7 +168,5 @@ fun HistoryPage(modifier: Modifier = Modifier, onDayClicked: (LocalDate) -> Unit } }, ) - - Spacer(modifier = Modifier.height(100.dp)) } } diff --git a/presentation/src/main/java/com/whyranoid/presentation/screens/mypage/tabs/PostPage.kt b/presentation/src/main/java/com/whyranoid/presentation/screens/mypage/tabs/PostPage.kt index eef89f7d..6ae2ae8d 100644 --- a/presentation/src/main/java/com/whyranoid/presentation/screens/mypage/tabs/PostPage.kt +++ b/presentation/src/main/java/com/whyranoid/presentation/screens/mypage/tabs/PostPage.kt @@ -26,6 +26,7 @@ import androidx.compose.ui.unit.dp import coil.compose.AsyncImage import com.whyranoid.domain.model.post.PostPreview import com.whyranoid.domain.model.post.TextVisibleState +import com.whyranoid.domain.model.user.User import com.whyranoid.presentation.reusable.NonLazyGrid import com.whyranoid.presentation.theme.WalkieColor import com.whyranoid.presentation.theme.WalkieTypography @@ -44,7 +45,10 @@ fun PostPage( contentPadding = 4, ) { index -> if (index < postPreviews.size) { - PostImagePreview(postPreviews[index], onPostPreviewClicked) + PostImagePreview( + postPreview = postPreviews[index], + onPostPreviewClicked = onPostPreviewClicked, + ) } else { Box( modifier = Modifier @@ -74,10 +78,15 @@ fun PostPage( } @Composable -fun PostImagePreview(postPreview: PostPreview, onPostPreviewClicked: (id: Long) -> Unit = {}) { - Box { +fun PostImagePreview( + modifier: Modifier = Modifier, + postPreview: PostPreview, + onPostPreviewClicked: (id: Long) -> Unit = {}, +) { + // TODO modifier 크기 맞춰서 글자 크기 수정 + Box(modifier = modifier) { AsyncImage( - model = postPreview.imageUrl, + model = User.DUMMY.imageUrl, // TODO REMOVE postPreview.imageUrl, contentDescription = "postPreview Image", modifier = Modifier .fillMaxWidth() diff --git a/presentation/src/main/java/com/whyranoid/presentation/viewmodel/UserViewModel.kt b/presentation/src/main/java/com/whyranoid/presentation/viewmodel/UserViewModel.kt index e9b3e861..6ebd9d43 100644 --- a/presentation/src/main/java/com/whyranoid/presentation/viewmodel/UserViewModel.kt +++ b/presentation/src/main/java/com/whyranoid/presentation/viewmodel/UserViewModel.kt @@ -5,6 +5,7 @@ import androidx.lifecycle.viewModelScope import com.whyranoid.domain.model.challenge.Badge import com.whyranoid.domain.model.post.PostPreview import com.whyranoid.domain.model.user.UserDetail +import com.whyranoid.domain.repository.AccountRepository import com.whyranoid.domain.usecase.GetPostUseCase import com.whyranoid.domain.usecase.GetUserBadgesUseCase import com.whyranoid.domain.usecase.GetUserDetailUseCase @@ -16,6 +17,8 @@ import org.orbitmvi.orbit.ContainerHost import org.orbitmvi.orbit.syntax.simple.intent import org.orbitmvi.orbit.syntax.simple.reduce import org.orbitmvi.orbit.viewmodel.container +import java.time.LocalDate +import java.util.Date sealed class UserPageSideEffect @@ -23,9 +26,11 @@ data class UserPageState( val userDetailState: UiState = UiState.Idle, val userBadgesState: UiState> = UiState.Idle, val userPostPreviewsState: UiState> = UiState.Idle, + val calendarPreviewsState: UiState> = UiState.Idle, ) class UserPageViewModel( + val accountRepository: AccountRepository, private val getUserDetailUseCase: GetUserDetailUseCase, private val getUserBadgesUseCase: GetUserBadgesUseCase, private val getUserPostPreviewsUseCase: GetUserPostPreviewsUseCase, @@ -33,8 +38,7 @@ class UserPageViewModel( private val signOutUseCase: SignOutUseCase, ) : ViewModel(), ContainerHost { - override val container = - container(UserPageState()) + override val container = container(UserPageState()) fun getUserDetail(uid: Long) = intent { reduce { @@ -87,6 +91,20 @@ class UserPageViewModel( } } + fun selectDate(localDate: LocalDate) = intent { + reduce { + state.copy(calendarPreviewsState = UiState.Loading) + } + reduce { + val posts = state.userPostPreviewsState.getDataOrNull() ?: emptyList() + val filtered = posts.filter { + val date = Date(it.date) + date.year + 1900 == localDate.year && date.month + 1 == localDate.monthValue && date.date == localDate.dayOfMonth + } + state.copy(calendarPreviewsState = UiState.Success(filtered)) + } + } + fun signOut() { viewModelScope.launch { signOutUseCase() From 41f7aefdd2cd0855b585afdfef49fa684e7230dc Mon Sep 17 00:00:00 2001 From: yonghanJu Date: Wed, 22 Nov 2023 17:29:21 +0900 Subject: [PATCH 2/3] =?UTF-8?q?:recycle:=20=EC=BA=98=EB=A6=B0=EB=8D=94=20?= =?UTF-8?q?=ED=99=94=EB=A9=B4=20=EB=8F=8C=EC=95=84=EC=99=94=EC=9D=84=20?= =?UTF-8?q?=EB=95=8C=20=EB=8B=A4=EC=8B=9C=20=EC=84=A0=ED=83=9D=EB=90=98?= =?UTF-8?q?=EB=8F=84=EB=A1=9D=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../presentation/screens/mypage/tabs/HistoryPage.kt | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/presentation/src/main/java/com/whyranoid/presentation/screens/mypage/tabs/HistoryPage.kt b/presentation/src/main/java/com/whyranoid/presentation/screens/mypage/tabs/HistoryPage.kt index db281b1b..d2e09d40 100644 --- a/presentation/src/main/java/com/whyranoid/presentation/screens/mypage/tabs/HistoryPage.kt +++ b/presentation/src/main/java/com/whyranoid/presentation/screens/mypage/tabs/HistoryPage.kt @@ -22,7 +22,6 @@ import androidx.compose.material.icons.filled.KeyboardArrowRight import androidx.compose.material3.Icon import androidx.compose.material3.Text import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip @@ -46,9 +45,7 @@ fun HistoryPage(modifier: Modifier = Modifier, onDayClicked: (LocalDate) -> Unit initialSelection = listOf(LocalDate.now()), initialSelectionMode = SelectionMode.Single, ) - LaunchedEffect(Unit) { - onDayClicked(calendarState.selectionState.selection[0]) - } + onDayClicked(calendarState.selectionState.selection[0]) Column( modifier = modifier From fdc02658721cf24dfacfc692527408fce3c5d40b Mon Sep 17 00:00:00 2001 From: yonghanJu Date: Wed, 22 Nov 2023 22:24:02 +0900 Subject: [PATCH 3/3] =?UTF-8?q?:recycle:=20PostPreview.kt=20=EB=B3=80?= =?UTF-8?q?=EC=88=98=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 --- .../whyranoid/data/model/post/PostResponse.kt | 4 +- .../domain/model/post/PostPreview.kt | 14 +++--- .../screens/mypage/MyPageScreen.kt | 23 +++------- .../screens/mypage/tabs/PostPage.kt | 43 +++++++++++++------ 4 files changed, 46 insertions(+), 38 deletions(-) diff --git a/data/src/main/java/com/whyranoid/data/model/post/PostResponse.kt b/data/src/main/java/com/whyranoid/data/model/post/PostResponse.kt index 9bc5d9c2..a911cae3 100644 --- a/data/src/main/java/com/whyranoid/data/model/post/PostResponse.kt +++ b/data/src/main/java/com/whyranoid/data/model/post/PostResponse.kt @@ -22,9 +22,9 @@ data class PostResponse( val destructedHistoryContent = historyContent.split('_') println(destructedHistoryContent) return PostPreview( - poster = poster.toUser(), + author = poster.toUser(), id = this.poster.uid, - liked = this.liked, + isLiked = this.liked, likers = this.likers.map { it.toUser() }, imageUrl = this.photo, date = dateFormatter.parse(this.date.replace("T", " ")).time, diff --git a/domain/src/main/java/com/whyranoid/domain/model/post/PostPreview.kt b/domain/src/main/java/com/whyranoid/domain/model/post/PostPreview.kt index 826d4a24..6d07116a 100644 --- a/domain/src/main/java/com/whyranoid/domain/model/post/PostPreview.kt +++ b/domain/src/main/java/com/whyranoid/domain/model/post/PostPreview.kt @@ -3,9 +3,9 @@ package com.whyranoid.domain.model.post import com.whyranoid.domain.model.user.User data class PostPreview( - val poster: User, + val author: User, val id: Long, - val liked: Boolean = false, + val isLiked: Boolean = false, val likers: List = listOf(), val imageUrl: String, val date: Long = 0L, @@ -18,27 +18,27 @@ data class PostPreview( companion object { val DUMMY_LIST = listOf( PostPreview( - poster = User.DUMMY, + author = User.DUMMY, id = 0L, imageUrl = "https://picsum.photos/250/250", ), PostPreview( - poster = User.DUMMY, + author = User.DUMMY, id = 1L, imageUrl = "https://picsum.photos/250/250", ), PostPreview( - poster = User.DUMMY, + author = User.DUMMY, id = 2L, imageUrl = "https://picsum.photos/250/250", ), PostPreview( - poster = User.DUMMY, + author = User.DUMMY, id = 3L, imageUrl = "https://picsum.photos/250/250", ), PostPreview( - poster = User.DUMMY, + author = User.DUMMY, id = 4L, imageUrl = "https://picsum.photos/250/250", ), diff --git a/presentation/src/main/java/com/whyranoid/presentation/screens/mypage/MyPageScreen.kt b/presentation/src/main/java/com/whyranoid/presentation/screens/mypage/MyPageScreen.kt index 410e656d..4ff9d0d0 100644 --- a/presentation/src/main/java/com/whyranoid/presentation/screens/mypage/MyPageScreen.kt +++ b/presentation/src/main/java/com/whyranoid/presentation/screens/mypage/MyPageScreen.kt @@ -130,25 +130,19 @@ fun MyPageContent( val scrollState = rememberScrollState() Column( - modifier = Modifier - .padding(paddingValues) - .padding(top = 28.dp) + modifier = Modifier.padding(paddingValues).padding(top = 28.dp) .verticalScroll(scrollState), ) { state.userDetailState.getDataOrNull()?.let { userDetail -> Row( - modifier = Modifier - .fillMaxWidth() - .padding(horizontal = 20.dp), + modifier = Modifier.fillMaxWidth().padding(horizontal = 20.dp), horizontalArrangement = Arrangement.Start, verticalAlignment = Alignment.CenterVertically, ) { AsyncImage( model = userDetail.user.imageUrl, contentDescription = "유저 프로필 이미지", - modifier = Modifier - .clip(shape = CircleShape) - .size(70.dp), + modifier = Modifier.clip(shape = CircleShape).size(70.dp), ) Spacer(modifier = Modifier.width(20.dp)) @@ -183,18 +177,14 @@ fun MyPageContent( state.userBadgesState.getDataOrNull()?.let { userBadges -> LazyRow( - modifier = Modifier - .fillMaxWidth() - .padding(start = 20.dp), + modifier = Modifier.fillMaxWidth().padding(start = 20.dp), ) { items(userBadges.size) { index -> AsyncImage( model = userBadges[index].imageUrl, contentDescription = "badge image", - modifier = Modifier - .padding(vertical = 8.dp) - .clip(RoundedCornerShape(8.dp)) - .size(56.dp), + modifier = Modifier.padding(vertical = 8.dp) + .clip(RoundedCornerShape(8.dp)).size(56.dp), ) Spacer(modifier = Modifier.width(16.dp)) } @@ -268,6 +258,7 @@ fun MyPageContent( } } } + 2 -> ChallengePage() } } diff --git a/presentation/src/main/java/com/whyranoid/presentation/screens/mypage/tabs/PostPage.kt b/presentation/src/main/java/com/whyranoid/presentation/screens/mypage/tabs/PostPage.kt index 6ae2ae8d..010dcce0 100644 --- a/presentation/src/main/java/com/whyranoid/presentation/screens/mypage/tabs/PostPage.kt +++ b/presentation/src/main/java/com/whyranoid/presentation/screens/mypage/tabs/PostPage.kt @@ -15,21 +15,27 @@ import androidx.compose.material.icons.filled.Add import androidx.compose.material3.Icon import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.RectangleShape import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.layout.onGloballyPositioned +import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp import coil.compose.AsyncImage import com.whyranoid.domain.model.post.PostPreview import com.whyranoid.domain.model.post.TextVisibleState import com.whyranoid.domain.model.user.User import com.whyranoid.presentation.reusable.NonLazyGrid import com.whyranoid.presentation.theme.WalkieColor -import com.whyranoid.presentation.theme.WalkieTypography import java.text.SimpleDateFormat import java.util.* @@ -83,8 +89,17 @@ fun PostImagePreview( postPreview: PostPreview, onPostPreviewClicked: (id: Long) -> Unit = {}, ) { - // TODO modifier 크기 맞춰서 글자 크기 수정 - Box(modifier = modifier) { + var dynamicFontSize by remember { mutableStateOf(0.sp) } + var dynamicPaddingSize by remember { mutableStateOf(0.dp) } + + Box( + modifier = modifier.onGloballyPositioned { + val parentSize = it.size + dynamicFontSize = (parentSize.width / 60f).sp + dynamicPaddingSize = (parentSize.width / 50f).dp + it.providedAlignmentLines + }, + ) { AsyncImage( model = User.DUMMY.imageUrl, // TODO REMOVE postPreview.imageUrl, contentDescription = "postPreview Image", @@ -99,35 +114,37 @@ fun PostImagePreview( ) if (postPreview.textVisibleState != TextVisibleState.HIDE) { - val textColor = + val selectedTextColor = if (postPreview.textVisibleState == TextVisibleState.WHITE) Color.White else Color.Black Text( text = SimpleDateFormat("yyyy.MM.dd HH:mm").format(Date(postPreview.date)), modifier = Modifier - .padding(top = 12.dp) + .padding(top = dynamicPaddingSize) .align(Alignment.TopCenter), - style = WalkieTypography.Body2.copy(color = textColor), + color = selectedTextColor, + fontSize = dynamicFontSize, ) Row( modifier = Modifier - .padding(horizontal = 20.dp) .fillMaxWidth() .align(Alignment.BottomCenter) - .padding(bottom = 12.dp) - .padding(horizontal = 20.dp), - horizontalArrangement = Arrangement.SpaceBetween, + .padding(bottom = dynamicPaddingSize), + horizontalArrangement = Arrangement.SpaceAround, ) { listOf( "DISTANCE\n${postPreview.distanceText}", "TIME\n${postPreview.timeText}", - "PACE\n${postPreview.paceText}", + "PACE\n ${postPreview.paceText}", ).forEach { Text( - it, - style = WalkieTypography.Title.copy(color = textColor), + text = it, + color = selectedTextColor, + fontSize = dynamicFontSize, + lineHeight = dynamicFontSize, textAlign = TextAlign.Center, + fontWeight = FontWeight.Bold, ) } }