diff --git a/app/src/main/java/com/isolaatti/profile/domain/entity/UserProfile.kt b/app/src/main/java/com/isolaatti/profile/domain/entity/UserProfile.kt index 6e97894..c04242a 100644 --- a/app/src/main/java/com/isolaatti/profile/domain/entity/UserProfile.kt +++ b/app/src/main/java/com/isolaatti/profile/domain/entity/UserProfile.kt @@ -14,7 +14,7 @@ data class UserProfile( val numberOfLikes: Int, val numberOfPosts: Int, val isUserItself: Boolean, - val followingThisUser: Boolean, + var followingThisUser: Boolean, val thisUserIsFollowingMe: Boolean, val profileImageId: String?, val descriptionText: String?, diff --git a/app/src/main/java/com/isolaatti/profile/domain/use_case/FollowUser.kt b/app/src/main/java/com/isolaatti/profile/domain/use_case/FollowUser.kt new file mode 100644 index 0000000..db3bb8e --- /dev/null +++ b/app/src/main/java/com/isolaatti/profile/domain/use_case/FollowUser.kt @@ -0,0 +1,16 @@ +package com.isolaatti.profile.domain.use_case + +import com.isolaatti.followers.domain.FollowersRepository +import com.isolaatti.utils.Resource +import kotlinx.coroutines.flow.Flow +import javax.inject.Inject + +class FollowUser @Inject constructor(private val followersRepository: FollowersRepository) { + operator fun invoke(userId: Int, follow: Boolean): Flow> { + return if(follow) { + followersRepository.followUser(userId) + } else { + followersRepository.unfollowUser(userId) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/isolaatti/profile/presentation/ProfileViewModel.kt b/app/src/main/java/com/isolaatti/profile/presentation/ProfileViewModel.kt index bc027b3..b054fa7 100644 --- a/app/src/main/java/com/isolaatti/profile/presentation/ProfileViewModel.kt +++ b/app/src/main/java/com/isolaatti/profile/presentation/ProfileViewModel.kt @@ -8,6 +8,7 @@ import com.isolaatti.images.common.domain.entity.Image import com.isolaatti.posting.posts.presentation.PostListingViewModelBase import com.isolaatti.posting.posts.presentation.UpdateEvent import com.isolaatti.profile.domain.entity.UserProfile +import com.isolaatti.profile.domain.use_case.FollowUser import com.isolaatti.profile.domain.use_case.GetProfile import com.isolaatti.profile.domain.use_case.GetProfilePosts import com.isolaatti.profile.domain.use_case.SetProfileImage @@ -24,7 +25,8 @@ import javax.inject.Inject class ProfileViewModel @Inject constructor( private val getProfileUseCase: GetProfile, private val getProfilePostsUseCase: GetProfilePosts, - private val setProfileImageUC: SetProfileImage + private val setProfileImageUC: SetProfileImage, + private val followUserUC: FollowUser ) : PostListingViewModelBase() { private val _profile = MutableLiveData() val profile: LiveData get() = _profile @@ -35,6 +37,8 @@ class ProfileViewModel @Inject constructor( private val toRetry: MutableList = mutableListOf() + val followingLoading: MutableLiveData = MutableLiveData() + // runs the lists of "Runnable" one by one and clears list. After this is executed, // caller should report as handled @@ -60,14 +64,7 @@ class ProfileViewModel @Inject constructor( is Resource.Success -> { _profile.postValue(it.data!!) followingState.postValue( - it.data.let {user-> - when { - user.followingThisUser && user.thisUserIsFollowingMe -> FollowingState.MutuallyFollowing - user.followingThisUser -> FollowingState.FollowingThisUser - user.thisUserIsFollowingMe -> FollowingState.ThisUserIsFollowingMe - else -> FollowingState.NotMutuallyFollowing - } - } + it.data.let { user-> getFollowingState(user.followingThisUser, user.thisUserIsFollowingMe) } ) } } @@ -75,6 +72,15 @@ class ProfileViewModel @Inject constructor( } } + private fun getFollowingState(followingThisUser: Boolean, userIsFollowingMe: Boolean): FollowingState { + return when { + followingThisUser && userIsFollowingMe -> FollowingState.MutuallyFollowing + followingThisUser -> FollowingState.FollowingThisUser + userIsFollowingMe -> FollowingState.ThisUserIsFollowingMe + else -> FollowingState.NotMutuallyFollowing + } + } + fun setProfileImage(image: Image) { viewModelScope.launch { setProfileImageUC(image).onEach { @@ -83,6 +89,28 @@ class ProfileViewModel @Inject constructor( } } + fun followUser() { + val currentProfile = _profile.value ?: return + val following = currentProfile.followingThisUser + viewModelScope.launch { + followUserUC(profileId, !following).onEach { + when(it) { + is Resource.Error -> { + followingLoading.postValue(false) + } + is Resource.Loading -> { + followingLoading.postValue(true) + } + is Resource.Success -> { + followingLoading.postValue(false) + _profile.postValue(currentProfile.apply { followingThisUser = !following }) + followingState.postValue(getFollowingState(!following, currentProfile.thisUserIsFollowingMe)) + } + } + }.flowOn(Dispatchers.IO).launchIn(this) + } + } + override fun getFeed(refresh: Boolean) { viewModelScope.launch { if(refresh) { diff --git a/app/src/main/java/com/isolaatti/profile/ui/ProfileMainFragment.kt b/app/src/main/java/com/isolaatti/profile/ui/ProfileMainFragment.kt index 0c63b11..724b686 100644 --- a/app/src/main/java/com/isolaatti/profile/ui/ProfileMainFragment.kt +++ b/app/src/main/java/com/isolaatti/profile/ui/ProfileMainFragment.kt @@ -284,6 +284,11 @@ class ProfileMainFragment : Fragment() { audioPlayerConnector.playPauseAudio(audio) } } + + viewBinding.followButton.setOnClickListener { + it.isEnabled = false + viewModel.followUser() + } } private fun setObservers() { @@ -300,6 +305,9 @@ class ProfileMainFragment : Fragment() { viewModel.errorLoading.observe(viewLifecycleOwner) { errorViewModel.error.postValue(it) } + viewModel.followingLoading.observe(viewLifecycleOwner) { + viewBinding.followButton.isEnabled = !it + } } private fun getData() {