1
0
mirror of https://github.com/KokaKiwi/BarInsta synced 2024-11-22 06:37:30 +00:00

Add update favorite logic in ProfileFragmentViewModel and corresponding test

This commit is contained in:
Ammar Githam 2021-06-24 20:41:48 +09:00
parent edb03ba3d8
commit 63df44624e
4 changed files with 117 additions and 49 deletions

View File

@ -3,7 +3,6 @@ package awais.instagrabber.fragments.main;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.Intent; import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Typeface; import android.graphics.Typeface;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
@ -54,7 +53,6 @@ import java.util.Objects;
import java.util.Set; import java.util.Set;
import awais.instagrabber.R; import awais.instagrabber.R;
import awais.instagrabber.UserSearchNavGraphDirections;
import awais.instagrabber.activities.MainActivity; import awais.instagrabber.activities.MainActivity;
import awais.instagrabber.adapters.FeedAdapterV2; import awais.instagrabber.adapters.FeedAdapterV2;
import awais.instagrabber.adapters.HighlightsAdapter; import awais.instagrabber.adapters.HighlightsAdapter;
@ -69,8 +67,6 @@ import awais.instagrabber.db.repositories.FavoriteRepository;
import awais.instagrabber.dialogs.PostsLayoutPreferencesDialogFragment; import awais.instagrabber.dialogs.PostsLayoutPreferencesDialogFragment;
import awais.instagrabber.dialogs.ProfilePicDialogFragment; import awais.instagrabber.dialogs.ProfilePicDialogFragment;
import awais.instagrabber.fragments.PostViewV2Fragment; import awais.instagrabber.fragments.PostViewV2Fragment;
import awais.instagrabber.fragments.UserSearchFragment;
import awais.instagrabber.fragments.UserSearchFragmentDirections;
import awais.instagrabber.managers.DirectMessagesManager; import awais.instagrabber.managers.DirectMessagesManager;
import awais.instagrabber.managers.InboxManager; import awais.instagrabber.managers.InboxManager;
import awais.instagrabber.models.HighlightModel; import awais.instagrabber.models.HighlightModel;
@ -131,7 +127,7 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe
private MenuItem blockMenuItem, restrictMenuItem, chainingMenuItem; private MenuItem blockMenuItem, restrictMenuItem, chainingMenuItem;
private MenuItem muteStoriesMenuItem, mutePostsMenuItem, removeFollowerMenuItem; private MenuItem muteStoriesMenuItem, mutePostsMenuItem, removeFollowerMenuItem;
private MenuItem shareLinkMenuItem; private MenuItem shareLinkMenuItem;
// private MenuItem shareDmMenuItem; // private MenuItem shareDmMenuItem;
private boolean accountIsUpdated = false; private boolean accountIsUpdated = false;
private boolean postsSetupDone = false; private boolean postsSetupDone = false;
private Set<Media> selectedFeedModels; private Set<Media> selectedFeedModels;
@ -470,10 +466,10 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe
if (shareLinkMenuItem != null) { if (shareLinkMenuItem != null) {
shareLinkMenuItem.setVisible(profileModel != null && !TextUtils.isEmpty(profileModel.getUsername())); shareLinkMenuItem.setVisible(profileModel != null && !TextUtils.isEmpty(profileModel.getUsername()));
} }
// shareDmMenuItem = menu.findItem(R.id.share_dm); // shareDmMenuItem = menu.findItem(R.id.share_dm);
// if (shareDmMenuItem != null) { // if (shareDmMenuItem != null) {
// shareDmMenuItem.setVisible(profileModel != null && profileModel.getPk() != 0L); // shareDmMenuItem.setVisible(profileModel != null && profileModel.getPk() != 0L);
// } // }
} }
@Override @Override
@ -586,20 +582,20 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe
startActivity(Intent.createChooser(sharingIntent, null)); startActivity(Intent.createChooser(sharingIntent, null));
return true; return true;
} else if (itemId == R.id.share_dm) { } else if (itemId == R.id.share_dm) {
// final UserSearchNavGraphDirections.ActionGlobalUserSearch actionGlobalUserSearch = UserSearchFragmentDirections // final UserSearchNavGraphDirections.ActionGlobalUserSearch actionGlobalUserSearch = UserSearchFragmentDirections
// .actionGlobalUserSearch() // .actionGlobalUserSearch()
// .setTitle(getString(R.string.share)) // .setTitle(getString(R.string.share))
// .setActionLabel(getString(R.string.send)) // .setActionLabel(getString(R.string.send))
// .setShowGroups(true) // .setShowGroups(true)
// .setMultiple(true) // .setMultiple(true)
// .setSearchMode(UserSearchFragment.SearchMode.RAVEN); // .setSearchMode(UserSearchFragment.SearchMode.RAVEN);
// final NavController navController = NavHostFragment.findNavController(ProfileFragment.this); // final NavController navController = NavHostFragment.findNavController(ProfileFragment.this);
// try { // try {
// navController.navigate(actionGlobalUserSearch); // navController.navigate(actionGlobalUserSearch);
// } catch (Exception e) { // } catch (Exception e) {
// Log.e(TAG, "setupShare: ", e); // Log.e(TAG, "setupShare: ", e);
// } // }
// return true; // return true;
return false; return false;
} }
return super.onOptionsItemSelected(item); return super.onOptionsItemSelected(item);
@ -750,7 +746,9 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe
if (throwable != null || favorite == null) { if (throwable != null || favorite == null) {
profileDetailsBinding.favChip.setChipIconResource(R.drawable.ic_outline_star_plus_24); profileDetailsBinding.favChip.setChipIconResource(R.drawable.ic_outline_star_plus_24);
profileDetailsBinding.favChip.setText(R.string.add_to_favorites); profileDetailsBinding.favChip.setText(R.string.add_to_favorites);
Log.e(TAG, "setProfileDetails: ", throwable); if (throwable != null) {
Log.e(TAG, "setProfileDetails: ", throwable);
}
return; return;
} }
profileDetailsBinding.favChip.setChipIconResource(R.drawable.ic_star_check_24); profileDetailsBinding.favChip.setChipIconResource(R.drawable.ic_star_check_24);
@ -1063,9 +1061,9 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe
if (shareLinkMenuItem != null) { if (shareLinkMenuItem != null) {
shareLinkMenuItem.setVisible(!TextUtils.isEmpty(profileModel.getUsername())); shareLinkMenuItem.setVisible(!TextUtils.isEmpty(profileModel.getUsername()));
} }
// if (shareDmMenuItem != null) { // if (shareDmMenuItem != null) {
// shareDmMenuItem.setVisible(profileModel.getPk() != 0L); // shareDmMenuItem.setVisible(profileModel.getPk() != 0L);
// } // }
} }
} }

View File

@ -1,15 +1,19 @@
package awais.instagrabber.viewmodels package awais.instagrabber.viewmodels
import android.os.Bundle import android.os.Bundle
import android.util.Log
import androidx.lifecycle.* import androidx.lifecycle.*
import androidx.savedstate.SavedStateRegistryOwner import androidx.savedstate.SavedStateRegistryOwner
import awais.instagrabber.db.entities.Favorite
import awais.instagrabber.db.repositories.AccountRepository import awais.instagrabber.db.repositories.AccountRepository
import awais.instagrabber.db.repositories.FavoriteRepository import awais.instagrabber.db.repositories.FavoriteRepository
import awais.instagrabber.managers.DirectMessagesManager import awais.instagrabber.managers.DirectMessagesManager
import awais.instagrabber.models.Resource import awais.instagrabber.models.Resource
import awais.instagrabber.models.enums.FavoriteType
import awais.instagrabber.repositories.responses.User import awais.instagrabber.repositories.responses.User
import awais.instagrabber.repositories.responses.directmessages.RankedRecipient import awais.instagrabber.repositories.responses.directmessages.RankedRecipient
import awais.instagrabber.utils.ControlledRunner import awais.instagrabber.utils.ControlledRunner
import awais.instagrabber.utils.extensions.TAG
import awais.instagrabber.webservices.* import awais.instagrabber.webservices.*
import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
@ -22,14 +26,16 @@ class ProfileFragmentViewModel(
mediaRepository: MediaRepository, mediaRepository: MediaRepository,
graphQLRepository: GraphQLRepository, graphQLRepository: GraphQLRepository,
accountRepository: AccountRepository, accountRepository: AccountRepository,
favoriteRepository: FavoriteRepository, private val favoriteRepository: FavoriteRepository,
ioDispatcher: CoroutineDispatcher, ioDispatcher: CoroutineDispatcher,
) : ViewModel() { ) : ViewModel() {
private val _currentUser = MutableLiveData<Resource<User?>>(Resource.loading(null)) private val _currentUser = MutableLiveData<Resource<User?>>(Resource.loading(null))
private val _isFavorite = MutableLiveData(false)
private var messageManager: DirectMessagesManager? = null private var messageManager: DirectMessagesManager? = null
val currentUser: LiveData<Resource<User?>> = _currentUser val currentUser: LiveData<Resource<User?>> = _currentUser
val isLoggedIn: LiveData<Boolean> = currentUser.map { it.data != null } val isLoggedIn: LiveData<Boolean> = currentUser.map { it.data != null }
val isFavorite: LiveData<Boolean> = _isFavorite
private val currentUserAndStateUsernameLiveData: LiveData<Pair<Resource<User?>, Resource<String?>>> = private val currentUserAndStateUsernameLiveData: LiveData<Pair<Resource<User?>, Resource<String?>>> =
object : MediatorLiveData<Pair<Resource<User?>, Resource<String?>>>() { object : MediatorLiveData<Pair<Resource<User?>, Resource<String?>>>() {
@ -78,12 +84,40 @@ class ProfileFragmentViewModel(
} }
} }
emit(Resource.success(fetchedUser)) emit(Resource.success(fetchedUser))
if (fetchedUser != null) {
checkAndInsertFavorite(fetchedUser)
}
} catch (e: Exception) { } catch (e: Exception) {
emit(Resource.error(e.message, null)) emit(Resource.error(e.message, null))
Log.e(TAG, "fetching user: ", e)
} }
} }
} }
private suspend fun checkAndInsertFavorite(fetchedUser: User) {
try {
val favorite = favoriteRepository.getFavorite(fetchedUser.username, FavoriteType.USER)
if (favorite == null) {
_isFavorite.postValue(false)
return
}
_isFavorite.postValue(true)
favoriteRepository.insertOrUpdateFavorite(
Favorite(
favorite.id,
fetchedUser.username,
FavoriteType.USER,
fetchedUser.fullName,
fetchedUser.profilePicUrl,
favorite.dateAdded
)
)
} catch (e: Exception) {
_isFavorite.postValue(false)
Log.e(TAG, "checkAndInsertFavorite: ", e)
}
}
/** /**
* Username of profile without '`@`' * Username of profile without '`@`'
*/ */

View File

@ -156,28 +156,16 @@ open class AccountDaoAdapter : AccountDao {
} }
} }
open class FavoriteDaoAdapter: FavoriteDao { open class FavoriteDaoAdapter : FavoriteDao {
override suspend fun getAllFavorites(): List<Favorite> { override suspend fun getAllFavorites(): List<Favorite> = emptyList()
TODO("Not yet implemented")
}
override suspend fun findFavoriteByQueryAndType(query: String, type: FavoriteType): Favorite? { override suspend fun findFavoriteByQueryAndType(query: String, type: FavoriteType): Favorite? = null
TODO("Not yet implemented")
}
override suspend fun insertFavorites(vararg favorites: Favorite) { override suspend fun insertFavorites(vararg favorites: Favorite) {}
TODO("Not yet implemented")
}
override suspend fun updateFavorites(vararg favorites: Favorite) { override suspend fun updateFavorites(vararg favorites: Favorite) {}
TODO("Not yet implemented")
}
override suspend fun deleteFavorites(vararg favorites: Favorite) { override suspend fun deleteFavorites(vararg favorites: Favorite) {}
TODO("Not yet implemented")
}
override suspend fun deleteAllFavorites() { override suspend fun deleteAllFavorites() {}
TODO("Not yet implemented")
}
} }

View File

@ -7,10 +7,12 @@ import awais.instagrabber.MainCoroutineScopeRule
import awais.instagrabber.common.* import awais.instagrabber.common.*
import awais.instagrabber.db.datasources.AccountDataSource import awais.instagrabber.db.datasources.AccountDataSource
import awais.instagrabber.db.datasources.FavoriteDataSource import awais.instagrabber.db.datasources.FavoriteDataSource
import awais.instagrabber.db.entities.Favorite
import awais.instagrabber.db.repositories.AccountRepository import awais.instagrabber.db.repositories.AccountRepository
import awais.instagrabber.db.repositories.FavoriteRepository import awais.instagrabber.db.repositories.FavoriteRepository
import awais.instagrabber.getOrAwaitValue import awais.instagrabber.getOrAwaitValue
import awais.instagrabber.models.Resource import awais.instagrabber.models.Resource
import awais.instagrabber.models.enums.FavoriteType
import awais.instagrabber.repositories.responses.FriendshipStatus import awais.instagrabber.repositories.responses.FriendshipStatus
import awais.instagrabber.repositories.responses.User import awais.instagrabber.repositories.responses.User
import awais.instagrabber.webservices.* import awais.instagrabber.webservices.*
@ -18,9 +20,9 @@ import kotlinx.coroutines.ExperimentalCoroutinesApi
import org.json.JSONException import org.json.JSONException
import org.junit.Rule import org.junit.Rule
import org.junit.Test import org.junit.Test
import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Assertions.*
import org.junit.jupiter.api.Assertions.assertNull
import org.junit.runner.RunWith import org.junit.runner.RunWith
import java.time.LocalDateTime
@RunWith(AndroidJUnit4::class) @RunWith(AndroidJUnit4::class)
internal class ProfileFragmentViewModelTest { internal class ProfileFragmentViewModelTest {
@ -233,4 +235,50 @@ internal class ProfileFragmentViewModelTest {
} }
assertEquals(testPublicUser1, profile.data) assertEquals(testPublicUser1, profile.data)
} }
@ExperimentalCoroutinesApi
@Test
fun `should update favorite in db if fetched user is a favorite`() {
val state = SavedStateHandle(
mutableMapOf<String, Any?>(
"username" to testPublicUser.username
)
)
val favorite = Favorite(
1,
testPublicUser.username,
FavoriteType.USER,
testPublicUser.username,
"test url",
LocalDateTime.now()
)
val graphQLRepository = object : GraphQLRepository(GraphQLServiceAdapter()) {
override suspend fun fetchUser(username: String): User = testPublicUser
}
var updateFavoriteCalled = false
val favoriteRepository = FavoriteRepository(FavoriteDataSource(object : FavoriteDaoAdapter() {
override suspend fun findFavoriteByQueryAndType(query: String, type: FavoriteType): Favorite = favorite
override suspend fun updateFavorites(vararg favorites: Favorite) {
updateFavoriteCalled = true
}
}))
val viewModel = ProfileFragmentViewModel(
state,
UserRepository(UserServiceAdapter()),
FriendshipRepository(FriendshipServiceAdapter()),
StoriesRepository(StoriesServiceAdapter()),
MediaRepository(MediaServiceAdapter()),
graphQLRepository,
AccountRepository(AccountDataSource(AccountDaoAdapter())),
favoriteRepository,
coroutineScope.dispatcher,
)
viewModel.setCurrentUser(Resource.success(null))
assertEquals(false, viewModel.isLoggedIn.getOrAwaitValue())
var profile = viewModel.profile.getOrAwaitValue()
while (profile.status == Resource.Status.LOADING) {
profile = viewModel.profile.getOrAwaitValue()
}
assertTrue(updateFavoriteCalled)
}
} }