Skip to content

Commit

Permalink
Merge pull request #65 from Team-Walkie/feat/like_post
Browse files Browse the repository at this point in the history
좋아요 기능 구현, Reponse(retrofit)에서 결과를 가져오는 확장함수 구현
  • Loading branch information
soopeach authored Jan 7, 2024
2 parents a794448 + c3e8bb7 commit 4b81878
Show file tree
Hide file tree
Showing 19 changed files with 184 additions and 14 deletions.
13 changes: 12 additions & 1 deletion app/src/main/java/com/whyranoid/walkie/KoinModules.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ import com.whyranoid.data.datasource.OtherUserPagingSource
import com.whyranoid.data.datasource.UserDataSourceImpl
import com.whyranoid.data.datasource.account.AccountDataSourceImpl
import com.whyranoid.data.datasource.account.AccountService
import com.whyranoid.data.datasource.community.CommunityDataSource
import com.whyranoid.data.datasource.community.CommunityDataSourceImpl
import com.whyranoid.data.datasource.community.CommunityService
import com.whyranoid.data.datasource.follow.FollowDataSourceImpl
import com.whyranoid.data.datasource.follow.FollowService
import com.whyranoid.data.datasource.post.PostDataSourceImpl
Expand All @@ -19,6 +22,7 @@ import com.whyranoid.data.datasource.running.RunningControlDataSourceImpl
import com.whyranoid.data.datasource.running.RunningService
import com.whyranoid.data.repository.AccountRepositoryImpl
import com.whyranoid.data.repository.ChallengeRepositoryImpl
import com.whyranoid.data.repository.CommunityRepositoryImpl
import com.whyranoid.data.repository.FollowRepositoryImpl
import com.whyranoid.data.repository.GpsRepositoryImpl
import com.whyranoid.data.repository.NetworkRepositoryImpl
Expand All @@ -35,6 +39,7 @@ import com.whyranoid.domain.datasource.RunningControlDataSource
import com.whyranoid.domain.datasource.UserDataSource
import com.whyranoid.domain.repository.AccountRepository
import com.whyranoid.domain.repository.ChallengeRepository
import com.whyranoid.domain.repository.CommunityRepository
import com.whyranoid.domain.repository.FollowRepository
import com.whyranoid.domain.repository.GpsRepository
import com.whyranoid.domain.repository.NetworkRepository
Expand All @@ -53,6 +58,7 @@ import com.whyranoid.domain.usecase.GetPostUseCase
import com.whyranoid.domain.usecase.GetUserBadgesUseCase
import com.whyranoid.domain.usecase.GetUserDetailUseCase
import com.whyranoid.domain.usecase.GetUserPostPreviewsUseCase
import com.whyranoid.domain.usecase.LikePostUseCase
import com.whyranoid.domain.usecase.SignOutUseCase
import com.whyranoid.domain.usecase.UploadPostUseCase
import com.whyranoid.domain.usecase.broadcast.AddGpsListener
Expand Down Expand Up @@ -106,7 +112,7 @@ val viewModelModule = module {
factory { AddPostViewModel(get()) }
factory { SearchFriendViewModel(get(), get(), get()) }
factory { DialogViewModel(get(), get(), get(), get(), get(), get()) }
factory { CommunityScreenViewModel(get(), get()) }
factory { CommunityScreenViewModel(get(), get(), get()) }
}

val repositoryModule = module {
Expand All @@ -120,6 +126,7 @@ val repositoryModule = module {
single<NetworkRepository> { NetworkRepositoryImpl(get()) }
single<GpsRepository> { GpsRepositoryImpl(get()) }
single<OtherUserRepository> { OtherUserRepositoryImpl(OtherUserPagingSource()) }
single<CommunityRepository> { CommunityRepositoryImpl(get()) }
}

val dataSourceModule = module {
Expand All @@ -129,6 +136,7 @@ val dataSourceModule = module {
single<AccountDataSource> { AccountDataSourceImpl(get()) }
single<FollowDataSource> { FollowDataSourceImpl(get()) }
single<RunningControlDataSource> { RunningControlDataSourceImpl(get()) }
single<CommunityDataSource> { CommunityDataSourceImpl(get()) }
}

val useCaseModule = module {
Expand Down Expand Up @@ -157,6 +165,7 @@ val useCaseModule = module {
single { UnFollowUseCase(get(), get()) }
single { GetMyFollowingUseCase(get(), get()) }
single { GetFollowingsPostsUseCase(get(), get()) }
single { LikePostUseCase(get(), get()) }
}

val databaseModule = module {
Expand Down Expand Up @@ -222,4 +231,6 @@ val networkModule = module {
single { get<Retrofit>().create(PostService::class.java) }

single { get<Retrofit>().create(RunningService::class.java) }

single { get<Retrofit>().create(CommunityService::class.java) }
}
2 changes: 2 additions & 0 deletions data/src/main/java/com/whyranoid/data/API.kt
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ object API {

const val SEARCH = "api/community/search-nickname"

const val SEND_LIKE = "api/community/send-like"

object WalkingControl {
const val RUNNING_START = "api/walk/start"

Expand Down
12 changes: 12 additions & 0 deletions data/src/main/java/com/whyranoid/data/Utils.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.whyranoid.data

import retrofit2.Response

fun <T, R> Response<T>.getResult(transform: (T) -> R): R {
if (this.isSuccessful.not())
throw Exception(this.errorBody().toString())
else if (this.body() == null)
throw Exception(this.message())

return requireNotNull(this.body()?.let(transform) ?: throw Exception("empty response"))
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.whyranoid.data.datasource.community

interface CommunityDataSource {

suspend fun likePost(postId: Long, likerId: Long): Result<Long>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.whyranoid.data.datasource.community

import com.whyranoid.data.getResult
import com.whyranoid.data.model.community.request.PostLikeRequest

class CommunityDataSourceImpl(
private val service: CommunityService
) : CommunityDataSource {
override suspend fun likePost(postId: Long, likerId: Long): Result<Long> {

return kotlin.runCatching {
val request = PostLikeRequest(likerId, postId)
val response = service.likePost(request)

response.getResult {
it.likerCount
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.whyranoid.data.datasource.community

import com.whyranoid.data.API
import com.whyranoid.data.model.community.request.PostLikeRequest
import com.whyranoid.data.model.community.response.PostLikeResponse
import retrofit2.Response
import retrofit2.http.Body
import retrofit2.http.POST

interface CommunityService {

@POST(API.SEND_LIKE)
suspend fun likePost(@Body postLikeRequest: PostLikeRequest): Response<PostLikeResponse>

}
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ class PostDataSourceImpl(private val postService: PostService) : PostDataSource
override suspend fun getMyFollowingsPost(uid: Long): Result<List<Post>> {
return kotlin.runCatching {
val posts = requireNotNull(postService.getPosts(uid).body())
posts.map { it.toPost() }
posts.map { it.toPost(uid) }
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.whyranoid.data.model.community.request

import com.google.gson.annotations.SerializedName

data class PostLikeRequest(
@SerializedName("likerId") val likerId: Long,
@SerializedName("postId") val postId: Long,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.whyranoid.data.model.community.response

import com.google.gson.annotations.SerializedName

data class LikerProfile(
@SerializedName("nickname") val nickname: String,
@SerializedName("profileImg") val profileImg: String,
@SerializedName("status") val status: String,
@SerializedName("walkieId") val walkieId: Long
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.whyranoid.data.model.community.response

import com.google.gson.annotations.SerializedName

data class PostLikeResponse(
@SerializedName("likerCount") val likerCount: Long,
@SerializedName("likerId") val likerId: Long,
@SerializedName("likerProfiles") val likerProfiles: List<LikerProfile>,
@SerializedName("postId") val postId: Long
)
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,14 @@ data class PostResponse(
)
}

fun toPost(): Post {
fun toPost(myUid: Long): Post {
return Post(
id = this.postId,
imageUrl = this.photo,
likeCount = this.likers.size,
contents = this.content,
author = this.poster.toUser(),
isLiked = this.likers.firstOrNull { it.uid == myUid } != null,
date = dateFormatter.parse(this.date.replace("T", " ")).time,
)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.whyranoid.data.repository

import com.whyranoid.data.datasource.community.CommunityDataSource
import com.whyranoid.domain.repository.CommunityRepository

class CommunityRepositoryImpl(
private val communityDataSource: CommunityDataSource
): CommunityRepository {
override suspend fun likePost(postId: Long, likerId: Long): Result<Long> {
return communityDataSource.likePost(postId, likerId)
}
}
2 changes: 2 additions & 0 deletions domain/src/main/java/com/whyranoid/domain/model/post/Post.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ data class Post(
val id: Long,
val imageUrl: String,
val likeCount: Int,
val isLiked: Boolean,
val contents: String,
val author: User,
val date: Long = 0L,
Expand All @@ -17,6 +18,7 @@ data class Post(
likeCount = 3,
contents = "오늘도 상쾌한 달리기~",
author = User.DUMMY,
isLiked = false
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.whyranoid.domain.repository

interface CommunityRepository {

suspend fun likePost(postId: Long, likerId: Long): Result<Long>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.whyranoid.domain.usecase

import com.whyranoid.domain.repository.AccountRepository
import com.whyranoid.domain.repository.CommunityRepository
import kotlinx.coroutines.flow.first

class LikePostUseCase(
private val communityRepository: CommunityRepository,
private val accountRepository: AccountRepository
) {

suspend operator fun invoke(postId: Long): Result<Long> {
val uid = requireNotNull(accountRepository.uId.first())
return communityRepository.likePost(postId, uid)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,15 @@ import androidx.compose.ui.unit.dp
import com.whyranoid.domain.model.post.Post
import com.whyranoid.presentation.icons.buttoniconpack.CommentButtonIcon
import com.whyranoid.presentation.icons.buttoniconpack.HeartButtonIcon
import com.whyranoid.presentation.theme.WalkieColor
import com.whyranoid.presentation.theme.WalkieTypography

@Composable
fun PostContentItem(post: Post) {
fun PostContentItem(
post: Post,
onLikeClicked: (Long) -> Unit = {}
) {

Column(
modifier = Modifier
.fillMaxWidth()
Expand All @@ -43,11 +48,11 @@ fun PostContentItem(post: Post) {
modifier = Modifier
.size(20.dp)
.clickable {

}
,
onLikeClicked(post.id)
},
imageVector = HeartButtonIcon,
contentDescription = "좋아요 버튼",
tint = if (post.isLiked) WalkieColor.Primary else WalkieColor.GrayBorder
)

Spacer(modifier = Modifier.size(16.dp))
Expand All @@ -57,8 +62,7 @@ fun PostContentItem(post: Post) {
.size(20.dp)
.clickable {

}
,
},
imageVector = CommentButtonIcon,
contentDescription = "댓글 버튼",
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,10 @@ import coil.compose.AsyncImage
import com.whyranoid.domain.model.post.Post

@Composable
fun PostItem(post: Post) {
fun PostItem(
post: Post,
onLikeClicked: (Long) -> Unit = {},
) {
Column(
modifier = Modifier
.fillMaxHeight()
Expand All @@ -36,7 +39,9 @@ fun PostItem(post: Post) {
contentScale = ContentScale.Crop
)

PostContentItem(post)
PostContentItem(post) {
onLikeClicked(it)
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,9 @@ fun CommunityScreen(

state.posts.getDataOrNull()?.forEach { post ->
item {
PostItem(post = post)
PostItem(post = post) { postId ->
viewModel.likePost(postId)
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import com.whyranoid.domain.model.post.Post
import com.whyranoid.domain.model.user.User
import com.whyranoid.domain.usecase.GetMyFollowingUseCase
import com.whyranoid.domain.usecase.GetFollowingsPostsUseCase
import com.whyranoid.domain.usecase.LikePostUseCase
import com.whyranoid.presentation.model.UiState
import org.orbitmvi.orbit.ContainerHost
import org.orbitmvi.orbit.syntax.simple.intent
Expand All @@ -22,7 +23,8 @@ data class CommunityScreenState(

class CommunityScreenViewModel(
private val getMyFollowingUseCase: GetMyFollowingUseCase,
private val getFollowingsPostsUseCase: GetFollowingsPostsUseCase
private val getFollowingsPostsUseCase: GetFollowingsPostsUseCase,
private val likePostUseCase: LikePostUseCase
) : ViewModel(), ContainerHost<CommunityScreenState, CommunityScreenSideEffect> {

override val container =
Expand All @@ -44,7 +46,6 @@ class CommunityScreenViewModel(

fun getPosts() = intent {
val result = getFollowingsPostsUseCase()
println("결과 : $result")
result.onSuccess { posts ->
reduce {
state.copy(
Expand All @@ -56,4 +57,31 @@ class CommunityScreenViewModel(
}
}
}

fun likePost(postId: Long) = intent {
val result = likePostUseCase(postId)

result.onSuccess { updatedLikeCount ->

reduce {
state.copy(
posts = UiState.Success(
state.posts.getDataOrNull()?.map {
if (it.id == postId) {
it.copy(
likeCount = if (updatedLikeCount == -1L) it.likeCount - 1 else updatedLikeCount.toInt(),
isLiked = it.isLiked.not()
)
} else {
it
}
} ?: emptyList()
)
)
}
}.onFailure {
// TODO: Error handling
}

}
}

0 comments on commit 4b81878

Please sign in to comment.