Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[AN] refactor: 채팅 리팩터링 #361

Merged
merged 11 commits into from
Aug 12, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import com.happy.friendogly.data.repository.WebSocketRepositoryImpl
import com.happy.friendogly.data.repository.WoofRepositoryImpl
import com.happy.friendogly.data.source.AddressDataSource
import com.happy.friendogly.data.source.AuthDataSource
import com.happy.friendogly.data.source.ChatDataSource
import com.happy.friendogly.data.source.ClubDataSource
import com.happy.friendogly.data.source.KakaoLoginDataSource
import com.happy.friendogly.data.source.MemberDataSource
Expand All @@ -37,6 +38,8 @@ import com.happy.friendogly.domain.usecase.DeleteAddressUseCase
import com.happy.friendogly.domain.usecase.DeleteClubMemberUseCase
import com.happy.friendogly.domain.usecase.DeleteTokenUseCase
import com.happy.friendogly.domain.usecase.GetAddressUseCase
import com.happy.friendogly.domain.usecase.GetChatListUseCase
import com.happy.friendogly.domain.usecase.GetChatMemberUseCase
import com.happy.friendogly.domain.usecase.GetClubUseCase
import com.happy.friendogly.domain.usecase.GetFootprintInfoUseCase
import com.happy.friendogly.domain.usecase.GetFootprintMarkBtnInfoUseCase
Expand All @@ -55,8 +58,12 @@ import com.happy.friendogly.domain.usecase.PostFootprintUseCase
import com.happy.friendogly.domain.usecase.PostKakaoLoginUseCase
import com.happy.friendogly.domain.usecase.PostMemberUseCase
import com.happy.friendogly.domain.usecase.PostPetUseCase
import com.happy.friendogly.domain.usecase.PublishEnterUseCase
import com.happy.friendogly.domain.usecase.PublishLeaveUseCase
import com.happy.friendogly.domain.usecase.PublishSendMessageUseCase
import com.happy.friendogly.domain.usecase.SaveAddressUseCase
import com.happy.friendogly.domain.usecase.SaveJwtTokenUseCase
import com.happy.friendogly.domain.usecase.SubScribeMessageUseCase
import com.happy.friendogly.kakao.source.KakaoLoginDataSourceImpl
import com.happy.friendogly.local.di.AddressModule
import com.happy.friendogly.local.di.TokenManager
Expand All @@ -67,6 +74,7 @@ import com.happy.friendogly.remote.api.BaseUrl
import com.happy.friendogly.remote.api.WebSocketService
import com.happy.friendogly.remote.di.RemoteModule
import com.happy.friendogly.remote.source.AuthDataSourceImpl
import com.happy.friendogly.remote.source.ChatDataSourceImpl
import com.happy.friendogly.remote.source.ClubDataSourceImpl
import com.happy.friendogly.remote.source.MemberDataSourceImpl
import com.happy.friendogly.remote.source.PetDataSourceImpl
Expand Down Expand Up @@ -152,6 +160,7 @@ class AppModule(context: Context) {
private val petDataSource: PetDataSource = PetDataSourceImpl(service = petService)
private val webSocketDataSource: WebSocketDataSource =
WebSocketDataSourceImpl(service = webSocketService)
private val chatDataSource: ChatDataSource = ChatDataSourceImpl(service = chatService)

// repository
private val authRepository: AuthRepository = AuthRepositoryImpl(source = authDataSource)
Expand All @@ -166,7 +175,7 @@ class AppModule(context: Context) {
AddressRepositoryImpl(addressDataSource = addressDataSource)
val webSocketRepository: WebSocketRepository =
WebSocketRepositoryImpl(source = webSocketDataSource)
val chatRepository: ChatRepository = ChatRepositoryImpl(service = chatService)
private val chatRepository: ChatRepository = ChatRepositoryImpl(source = chatDataSource)

// use case
val postKakaoLoginUseCase: PostKakaoLoginUseCase =
Expand Down Expand Up @@ -205,6 +214,17 @@ class AppModule(context: Context) {
val saveAddressUseCase: SaveAddressUseCase = SaveAddressUseCase(repository = addressRepository)
val deleteAddressUseCase: DeleteAddressUseCase =
DeleteAddressUseCase(repository = addressRepository)
val getChatListUseCase: GetChatListUseCase = GetChatListUseCase(repository = chatRepository)
val getChatMemberUseCase: GetChatMemberUseCase =
GetChatMemberUseCase(repository = chatRepository)
val publishEnterUseCase: PublishEnterUseCase =
PublishEnterUseCase(repository = webSocketRepository)
val publishSendUseCase: PublishSendMessageUseCase =
PublishSendMessageUseCase(repository = webSocketRepository)
val publishLeaveUseCase: PublishLeaveUseCase =
PublishLeaveUseCase(repository = webSocketRepository)
val subScribeMessageUseCase: SubScribeMessageUseCase =
SubScribeMessageUseCase(repository = webSocketRepository)

companion object {
private var instance: AppModule? = null
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@ fun MessageDto.toOther(): Message.Other =
Message.Other(
memberId = senderMemberId,
name = senderName,
content = content!!,
content = content ?: "",
dateTime = createdAt,
profileUrl = profilePictureUrl,
)

fun MessageDto.toMine(): Message.Mine =
Message.Mine(
content = content!!,
content = content ?: "",
dateTime = createdAt,
)

Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,16 @@
package com.happy.friendogly.data.repository

import com.happy.friendogly.data.mapper.toDomain
import com.happy.friendogly.data.source.ChatDataSource
import com.happy.friendogly.domain.model.ChatMember
import com.happy.friendogly.domain.model.ChatRooms
import com.happy.friendogly.domain.repository.ChatRepository
import com.happy.friendogly.remote.api.ChatService
import com.happy.friendogly.remote.mapper.toData

class ChatRepositoryImpl(private val service: ChatService) : ChatRepository {
override suspend fun getChatList(): Result<ChatRooms> =
runCatching {
service.getChatList().data.toData().toDomain()
}
class ChatRepositoryImpl(private val source: ChatDataSource) : ChatRepository {
override suspend fun getChatList(): Result<ChatRooms> = source.getChatList().mapCatching { it.toDomain() }

override suspend fun getMembers(chatRoomId: Long): Result<List<ChatMember>> =
runCatching {
service.getChatMembers(chatRoomId).data.map { it.toData() }.map { it.toDomain() }
source.getMembers(chatRoomId).mapCatching { member ->
member.map { it.toDomain() }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.happy.friendogly.data.repository

import com.happy.friendogly.data.mapper.toEnter
import com.happy.friendogly.data.mapper.toLeave
import com.happy.friendogly.data.mapper.toMine
import com.happy.friendogly.data.mapper.toOther
import com.happy.friendogly.data.model.MessageTypeDto
import com.happy.friendogly.data.source.WebSocketDataSource
Expand All @@ -11,7 +12,7 @@ import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map

class WebSocketRepositoryImpl(private val source: WebSocketDataSource) : WebSocketRepository {
override suspend fun publishInvite(memberId: Long) = source.publishInvite(memberId)
override suspend fun publishEnter(memberId: Long) = source.publishEnter(memberId)

override suspend fun publishSend(
chatRoomId: Long,
Expand All @@ -20,12 +21,17 @@ class WebSocketRepositoryImpl(private val source: WebSocketDataSource) : WebSock

override suspend fun publishLeave(chatRoomId: Long) = source.publishLeave(chatRoomId)

override suspend fun subscribeMessage(chatRoomId: Long): Flow<ChatComponent> =
override suspend fun subscribeMessage(
chatRoomId: Long,
myMemberId: Long,
): Flow<ChatComponent> =
source.subscribeMessage(chatRoomId).map {
when (it.messageType) {
MessageTypeDto.ENTER -> it.toEnter()
MessageTypeDto.LEAVE -> it.toLeave()
MessageTypeDto.CHAT -> it.toOther()
MessageTypeDto.CHAT -> {
if (myMemberId == it.senderMemberId) it.toMine() else it.toOther()
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.happy.friendogly.data.source

import com.happy.friendogly.data.model.ChatMemberDto
import com.happy.friendogly.data.model.ChatRoomListDto

interface ChatDataSource {
suspend fun getChatList(): Result<ChatRoomListDto>

suspend fun getMembers(chatRoomId: Long): Result<List<ChatMemberDto>>
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@ import com.happy.friendogly.data.model.MessageDto
import kotlinx.coroutines.flow.Flow

interface WebSocketDataSource {
suspend fun publishInvite(memberId: Long)
suspend fun publishEnter(memberId: Long): Result<Unit>

suspend fun publishSend(
chatRoomId: Long,
content: String,
)
): Result<Unit>

suspend fun publishLeave(chatRoomId: Long)
suspend fun publishLeave(chatRoomId: Long): Result<Unit>

suspend fun subscribeMessage(chatRoomId: Long): Flow<MessageDto>
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,17 @@ import com.happy.friendogly.domain.model.ChatComponent
import kotlinx.coroutines.flow.Flow

interface WebSocketRepository {
suspend fun publishInvite(chatRoomId: Long)
suspend fun publishEnter(chatRoomId: Long): Result<Unit>

suspend fun publishSend(
chatRoomId: Long,
content: String,
)
): Result<Unit>

suspend fun publishLeave(chatRoomId: Long)
suspend fun publishLeave(chatRoomId: Long): Result<Unit>

suspend fun subscribeMessage(chatRoomId: Long): Flow<ChatComponent>
suspend fun subscribeMessage(
chatRoomId: Long,
myMemberId: Long,
): Flow<ChatComponent>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.happy.friendogly.domain.usecase

import com.happy.friendogly.domain.model.ChatRooms
import com.happy.friendogly.domain.repository.ChatRepository

class GetChatListUseCase(
val repository: ChatRepository,
) {
suspend operator fun invoke(): Result<ChatRooms> = repository.getChatList()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.happy.friendogly.domain.usecase

import com.happy.friendogly.domain.model.ChatMember
import com.happy.friendogly.domain.repository.ChatRepository

class GetChatMemberUseCase(
val repository: ChatRepository,
) {
suspend operator fun invoke(chatRoomId: Long): Result<List<ChatMember>> = repository.getMembers(chatRoomId)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.happy.friendogly.domain.usecase

import com.happy.friendogly.domain.repository.WebSocketRepository

class PublishEnterUseCase(
private val repository: WebSocketRepository,
) {
suspend operator fun invoke(chatRoomId: Long): Result<Unit> = repository.publishEnter(chatRoomId)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.happy.friendogly.domain.usecase

import com.happy.friendogly.domain.repository.WebSocketRepository

class PublishLeaveUseCase(
private val repository: WebSocketRepository,
) {
suspend operator fun invoke(chatRoomId: Long): Result<Unit> = repository.publishLeave(chatRoomId)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.happy.friendogly.domain.usecase

import com.happy.friendogly.domain.repository.WebSocketRepository

class PublishSendMessageUseCase(
private val repository: WebSocketRepository,
) {
suspend operator fun invoke(
chatRoomId: Long,
content: String,
): Result<Unit> = repository.publishSend(chatRoomId, content)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.happy.friendogly.domain.usecase

import com.happy.friendogly.domain.model.ChatComponent
import com.happy.friendogly.domain.repository.WebSocketRepository
import kotlinx.coroutines.flow.Flow

class SubScribeMessageUseCase(private val repository: WebSocketRepository) {
suspend operator fun invoke(
chatRoomId: Long,
myMemberId: Long,
): Flow<ChatComponent> = repository.subscribeMessage(chatRoomId, myMemberId)
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class ChatListFragment :
ChatListNavigationAction {
private val viewModel: ChatListViewModel by viewModels {
ChatListViewModel.factory(
AppModule.getInstance().chatRepository,
AppModule.getInstance().getChatListUseCase,
)
}
private lateinit var adapter: ChatListAdapter
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,34 +4,35 @@ import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.viewModelScope
import com.happy.friendogly.domain.repository.ChatRepository
import com.happy.friendogly.domain.usecase.GetChatListUseCase
import com.happy.friendogly.presentation.base.BaseViewModel
import com.happy.friendogly.presentation.base.BaseViewModelFactory
import com.happy.friendogly.presentation.ui.chatlist.uimodel.ChatListUiModel
import kotlinx.coroutines.launch

class ChatListViewModel(
private val chatRepository: ChatRepository,
private val getChatListUseCase: GetChatListUseCase,
) : BaseViewModel() {
private val _chats: MutableLiveData<List<ChatListUiModel>> = MutableLiveData()
val chats: LiveData<List<ChatListUiModel>> get() = _chats

var memberId: Long = 0L
private set

fun getChats() {
viewModelScope.launch {
chatRepository.getChatList().onSuccess { room ->
getChatListUseCase.invoke().onSuccess { room ->
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

getChatListUseCase() 이렇게 써도 좋을 것 같아요~~

_chats.value = room.chatRooms.map { it.toUiModel() }
memberId = room.myMemberId
}
}
}

companion object {
fun factory(chatRepository: ChatRepository): ViewModelProvider.Factory {
fun factory(getChatListUseCase: GetChatListUseCase): ViewModelProvider.Factory {
return BaseViewModelFactory { _ ->
ChatListViewModel(
chatRepository,
getChatListUseCase,
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,10 @@ class ChatListAdapter(private val chatListNavigationAction: ChatListNavigationAc
private val chatListNavigationAction: ChatListNavigationAction,
) : RecyclerView.ViewHolder(binding.root) {
fun bind(item: ChatListUiModel) {
Glide.with(itemView.context).load(item.imageUrl).transform(CenterCrop())
.into(binding.ivChatGroup)
if (item.imageUrl?.isNotBlank() == true) {
Glide.with(itemView.context).load(item.imageUrl).transform(CenterCrop())
.into(binding.ivChatGroup)
}
binding.tvChatTitle.text = item.title
binding.tvChatBody.text = item.body
binding.tvChatMemberCount.text = item.numberOfPeople.toString()
Expand Down
Loading
Loading