From ed8ca2da0239a21a5a7d68572599f8cdc452a877 Mon Sep 17 00:00:00 2001 From: Ammar Githam Date: Wed, 9 Jun 2021 09:09:40 +0900 Subject: [PATCH] More groundwork for ProfileFragmentViewModel --- .../dialogs/ProfilePicDialogFragment.java | 2 +- .../fragments/main/ProfileFragment.java | 9 +++++-- .../settings/MorePreferencesFragment.java | 2 +- .../viewmodels/AppStateViewModel.java | 2 +- .../viewmodels/ProfileFragmentViewModel.kt | 23 +++++++++++++++- .../viewmodels/UserSearchViewModel.java | 2 +- .../webservices/UserRepository.kt | 15 +++++++++-- .../ProfileFragmentViewModelTest.kt | 27 +++++++++++++++++-- 8 files changed, 71 insertions(+), 11 deletions(-) diff --git a/app/src/main/java/awais/instagrabber/dialogs/ProfilePicDialogFragment.java b/app/src/main/java/awais/instagrabber/dialogs/ProfilePicDialogFragment.java index 9605fcf8..94a67ec7 100644 --- a/app/src/main/java/awais/instagrabber/dialogs/ProfilePicDialogFragment.java +++ b/app/src/main/java/awais/instagrabber/dialogs/ProfilePicDialogFragment.java @@ -132,7 +132,7 @@ public class ProfilePicDialogFragment extends DialogFragment { private void fetchAvatar() { if (isLoggedIn) { - final UserRepository repository = UserRepository.INSTANCE; + final UserRepository repository = UserRepository.Companion.getInstance(); repository.getUserInfo(id, CoroutineUtilsKt.getContinuation((user, throwable) -> AppExecutors.INSTANCE.getMainThread().execute(() -> { if (throwable != null) { final Context context = getContext(); diff --git a/app/src/main/java/awais/instagrabber/fragments/main/ProfileFragment.java b/app/src/main/java/awais/instagrabber/fragments/main/ProfileFragment.java index 9ed477af..5069404d 100644 --- a/app/src/main/java/awais/instagrabber/fragments/main/ProfileFragment.java +++ b/app/src/main/java/awais/instagrabber/fragments/main/ProfileFragment.java @@ -90,6 +90,7 @@ import awais.instagrabber.utils.Utils; import awais.instagrabber.viewmodels.AppStateViewModel; import awais.instagrabber.viewmodels.HighlightsViewModel; import awais.instagrabber.viewmodels.ProfileFragmentViewModel; +import awais.instagrabber.viewmodels.ProfileFragmentViewModelFactory; import awais.instagrabber.webservices.DirectMessagesService; import awais.instagrabber.webservices.FriendshipService; import awais.instagrabber.webservices.GraphQLService; @@ -336,14 +337,18 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe directMessagesService = isLoggedIn ? DirectMessagesService.INSTANCE : null; storiesService = isLoggedIn ? StoriesService.INSTANCE : null; mediaService = isLoggedIn ? MediaService.INSTANCE : null; - userRepository = isLoggedIn ? UserRepository.INSTANCE : null; + userRepository = isLoggedIn ? UserRepository.Companion.getInstance() : null; graphQLService = isLoggedIn ? null : GraphQLService.INSTANCE; final Context context = getContext(); if (context == null) return; accountRepository = AccountRepository.getInstance(AccountDataSource.getInstance(context)); favoriteRepository = FavoriteRepository.getInstance(FavoriteDataSource.getInstance(context)); appStateViewModel = new ViewModelProvider(fragmentActivity).get(AppStateViewModel.class); - viewModel = new ViewModelProvider(this).get(ProfileFragmentViewModel.class); + viewModel = new ViewModelProvider(this, new ProfileFragmentViewModelFactory( + UserRepository.Companion.getInstance(), + this, + getArguments() + )).get(ProfileFragmentViewModel.class); setHasOptionsMenu(true); } diff --git a/app/src/main/java/awais/instagrabber/fragments/settings/MorePreferencesFragment.java b/app/src/main/java/awais/instagrabber/fragments/settings/MorePreferencesFragment.java index a20e57d2..b3962054 100644 --- a/app/src/main/java/awais/instagrabber/fragments/settings/MorePreferencesFragment.java +++ b/app/src/main/java/awais/instagrabber/fragments/settings/MorePreferencesFragment.java @@ -285,7 +285,7 @@ public class MorePreferencesFragment extends BasePreferencesFragment { // adds cookies to database for quick access final long uid = CookieUtils.getUserIdFromCookie(cookie); - final UserRepository userRepository = UserRepository.INSTANCE; + final UserRepository userRepository = UserRepository.Companion.getInstance(); userRepository.getUserInfo(uid, CoroutineUtilsKt.getContinuation((user, throwable) -> AppExecutors.INSTANCE.getMainThread().execute(() -> { if (throwable != null) { Log.e(TAG, "Error fetching user info", throwable); diff --git a/app/src/main/java/awais/instagrabber/viewmodels/AppStateViewModel.java b/app/src/main/java/awais/instagrabber/viewmodels/AppStateViewModel.java index 7cebb0a0..856063d0 100644 --- a/app/src/main/java/awais/instagrabber/viewmodels/AppStateViewModel.java +++ b/app/src/main/java/awais/instagrabber/viewmodels/AppStateViewModel.java @@ -33,7 +33,7 @@ public class AppStateViewModel extends AndroidViewModel { cookie = settingsHelper.getString(Constants.COOKIE); final boolean isLoggedIn = !TextUtils.isEmpty(cookie) && CookieUtils.getUserIdFromCookie(cookie) != 0; if (!isLoggedIn) return; - userRepository = UserRepository.INSTANCE; + userRepository = UserRepository.Companion.getInstance(); // final AccountRepository accountRepository = AccountRepository.getInstance(AccountDataSource.getInstance(application)); fetchProfileDetails(); } diff --git a/app/src/main/java/awais/instagrabber/viewmodels/ProfileFragmentViewModel.kt b/app/src/main/java/awais/instagrabber/viewmodels/ProfileFragmentViewModel.kt index 47f33264..904c5240 100644 --- a/app/src/main/java/awais/instagrabber/viewmodels/ProfileFragmentViewModel.kt +++ b/app/src/main/java/awais/instagrabber/viewmodels/ProfileFragmentViewModel.kt @@ -1,10 +1,16 @@ package awais.instagrabber.viewmodels +import android.os.Bundle +import android.util.Log import androidx.lifecycle.* +import androidx.savedstate.SavedStateRegistryOwner import awais.instagrabber.repositories.responses.User +import awais.instagrabber.utils.extensions.TAG +import awais.instagrabber.webservices.UserRepository class ProfileFragmentViewModel( state: SavedStateHandle, + userRepository: UserRepository, ) : ViewModel() { private val _profile = MutableLiveData() val profile: LiveData = _profile @@ -16,6 +22,21 @@ class ProfileFragmentViewModel( private set init { - // Log.d(TAG, state.keys().toString()) + Log.d(TAG, "${state.keys()} $userRepository") + } +} + +@Suppress("UNCHECKED_CAST") +class ProfileFragmentViewModelFactory( + private val userRepository: UserRepository, + owner: SavedStateRegistryOwner, + defaultArgs: Bundle? = null, +) : AbstractSavedStateViewModelFactory(owner, defaultArgs) { + override fun create( + key: String, + modelClass: Class, + handle: SavedStateHandle, + ): T { + return ProfileFragmentViewModel(handle, userRepository) as T } } diff --git a/app/src/main/java/awais/instagrabber/viewmodels/UserSearchViewModel.java b/app/src/main/java/awais/instagrabber/viewmodels/UserSearchViewModel.java index 9e964865..d46986e8 100644 --- a/app/src/main/java/awais/instagrabber/viewmodels/UserSearchViewModel.java +++ b/app/src/main/java/awais/instagrabber/viewmodels/UserSearchViewModel.java @@ -70,7 +70,7 @@ public class UserSearchViewModel extends ViewModel { if (TextUtils.isEmpty(csrfToken) || viewerId <= 0 || TextUtils.isEmpty(deviceUuid)) { throw new IllegalArgumentException("User is not logged in!"); } - userRepository = UserRepository.INSTANCE; + userRepository = UserRepository.Companion.getInstance(); directMessagesService = DirectMessagesService.INSTANCE; rankedRecipientsCache = RankedRecipientsCache.INSTANCE; if ((rankedRecipientsCache.isFailed() || rankedRecipientsCache.isExpired()) && !rankedRecipientsCache.isUpdateInitiated()) { diff --git a/app/src/main/java/awais/instagrabber/webservices/UserRepository.kt b/app/src/main/java/awais/instagrabber/webservices/UserRepository.kt index 860fd71a..1a3b7b05 100644 --- a/app/src/main/java/awais/instagrabber/webservices/UserRepository.kt +++ b/app/src/main/java/awais/instagrabber/webservices/UserRepository.kt @@ -7,8 +7,7 @@ import awais.instagrabber.repositories.responses.UserSearchResponse import awais.instagrabber.webservices.RetrofitFactory.retrofit import java.util.* -object UserRepository { - private val service: UserService = retrofit.create(UserService::class.java) +class UserRepository(private val service: UserService) { suspend fun getUserInfo(uid: Long): User { val response = service.getUserInfo(uid) @@ -26,4 +25,16 @@ object UserRepository { val timezoneOffset = TimeZone.getDefault().rawOffset.toFloat() / 1000 return service.search(timezoneOffset, query) } + + companion object { + @Volatile + private var INSTANCE: UserRepository? = null + + fun getInstance(): UserRepository { + return INSTANCE ?: synchronized(this) { + val service: UserService = retrofit.create(UserService::class.java) + UserRepository(service).also { INSTANCE = it } + } + } + } } \ No newline at end of file diff --git a/app/src/test/java/awais/instagrabber/viewmodels/ProfileFragmentViewModelTest.kt b/app/src/test/java/awais/instagrabber/viewmodels/ProfileFragmentViewModelTest.kt index 32013e9d..5aaaaec6 100644 --- a/app/src/test/java/awais/instagrabber/viewmodels/ProfileFragmentViewModelTest.kt +++ b/app/src/test/java/awais/instagrabber/viewmodels/ProfileFragmentViewModelTest.kt @@ -2,17 +2,40 @@ package awais.instagrabber.viewmodels import androidx.lifecycle.SavedStateHandle import androidx.test.ext.junit.runners.AndroidJUnit4 +import awais.instagrabber.repositories.UserService +import awais.instagrabber.repositories.responses.FriendshipStatus +import awais.instagrabber.repositories.responses.UserSearchResponse +import awais.instagrabber.repositories.responses.WrappedUser +import awais.instagrabber.webservices.UserRepository import org.junit.Test import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) internal class ProfileFragmentViewModelTest { + private val userService = object: UserService { + override suspend fun getUserInfo(uid: Long): WrappedUser { + TODO("Not yet implemented") + } + + override suspend fun getUsernameInfo(username: String): WrappedUser { + TODO("Not yet implemented") + } + + override suspend fun getUserFriendship(uid: Long): FriendshipStatus { + TODO("Not yet implemented") + } + + override suspend fun search(timezoneOffset: Float, query: String): UserSearchResponse { + TODO("Not yet implemented") + } + } + @Test fun testNoUsernameNoCurrentUser() { val state = SavedStateHandle(mutableMapOf( "username" to "" )) - val viewModel = ProfileFragmentViewModel(state) - + val userRepository = UserRepository(userService) + val viewModel = ProfileFragmentViewModel(state, userRepository) } } \ No newline at end of file