No issue: Move signedIn tracking to BookmarksSharedViewModel (#4755)
parent
7f328a6dc4
commit
ee1f040e53
|
@ -112,7 +112,7 @@ open class FenixApplication : Application() {
|
||||||
|
|
||||||
components.core.sessionManager.register(NotificationSessionObserver(this))
|
components.core.sessionManager.register(NotificationSessionObserver(this))
|
||||||
|
|
||||||
if ((System.currentTimeMillis() - this.settings().lastPlacesStorageMaintenance) > ONE_DAY_MILLIS) {
|
if ((System.currentTimeMillis() - settings().lastPlacesStorageMaintenance) > ONE_DAY_MILLIS) {
|
||||||
runStorageMaintenance()
|
runStorageMaintenance()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -123,7 +123,7 @@ open class FenixApplication : Application() {
|
||||||
// run maintenance on one - arbitrarily using bookmarks.
|
// run maintenance on one - arbitrarily using bookmarks.
|
||||||
components.core.bookmarksStorage.runMaintenance()
|
components.core.bookmarksStorage.runMaintenance()
|
||||||
}
|
}
|
||||||
this.settings().lastPlacesStorageMaintenance = System.currentTimeMillis()
|
settings().lastPlacesStorageMaintenance = System.currentTimeMillis()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun registerRxExceptionHandling() {
|
private fun registerRxExceptionHandling() {
|
||||||
|
|
|
@ -13,7 +13,6 @@ import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.fragment.app.activityViewModels
|
import androidx.fragment.app.activityViewModels
|
||||||
import androidx.lifecycle.Observer
|
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.navigation.NavDirections
|
import androidx.navigation.NavDirections
|
||||||
|
@ -29,6 +28,7 @@ import kotlinx.coroutines.ObsoleteCoroutinesApi
|
||||||
import kotlinx.coroutines.isActive
|
import kotlinx.coroutines.isActive
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.awaitAll
|
import kotlinx.coroutines.awaitAll
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
import mozilla.appservices.places.BookmarkRoot
|
import mozilla.appservices.places.BookmarkRoot
|
||||||
import mozilla.components.concept.storage.BookmarkNode
|
import mozilla.components.concept.storage.BookmarkNode
|
||||||
import mozilla.components.concept.storage.BookmarkNodeType
|
import mozilla.components.concept.storage.BookmarkNodeType
|
||||||
|
@ -49,12 +49,11 @@ import org.mozilla.fenix.ext.urlToTrimmedHost
|
||||||
import org.mozilla.fenix.library.LibraryPageFragment
|
import org.mozilla.fenix.library.LibraryPageFragment
|
||||||
import org.mozilla.fenix.utils.allowUndo
|
import org.mozilla.fenix.utils.allowUndo
|
||||||
|
|
||||||
@SuppressWarnings("TooManyFunctions", "LargeClass")
|
@Suppress("TooManyFunctions", "LargeClass")
|
||||||
class BookmarkFragment : LibraryPageFragment<BookmarkNode>(), BackHandler, AccountObserver {
|
class BookmarkFragment : LibraryPageFragment<BookmarkNode>(), BackHandler {
|
||||||
|
|
||||||
private lateinit var bookmarkStore: BookmarkFragmentStore
|
private lateinit var bookmarkStore: BookmarkFragmentStore
|
||||||
private lateinit var bookmarkView: BookmarkView
|
private lateinit var bookmarkView: BookmarkView
|
||||||
private lateinit var signInView: SignInView
|
|
||||||
private lateinit var bookmarkInteractor: BookmarkFragmentInteractor
|
private lateinit var bookmarkInteractor: BookmarkFragmentInteractor
|
||||||
|
|
||||||
private val sharedViewModel: BookmarksSharedViewModel by activityViewModels {
|
private val sharedViewModel: BookmarksSharedViewModel by activityViewModels {
|
||||||
|
@ -62,10 +61,14 @@ class BookmarkFragment : LibraryPageFragment<BookmarkNode>(), BackHandler, Accou
|
||||||
}
|
}
|
||||||
private val desktopFolders by lazy { DesktopFolders(context!!, showMobileRoot = false) }
|
private val desktopFolders by lazy { DesktopFolders(context!!, showMobileRoot = false) }
|
||||||
|
|
||||||
var currentRoot: BookmarkNode? = null
|
|
||||||
lateinit var initialJob: Job
|
lateinit var initialJob: Job
|
||||||
private var pendingBookmarkDeletionJob: (suspend () -> Unit)? = null
|
private var pendingBookmarkDeletionJob: (suspend () -> Unit)? = null
|
||||||
private var pendingBookmarksToDelete: MutableSet<BookmarkNode> = mutableSetOf()
|
private var pendingBookmarksToDelete: MutableSet<BookmarkNode> = mutableSetOf()
|
||||||
|
private val refreshOnSignInListener = object : AccountObserver {
|
||||||
|
override fun onAuthenticated(account: OAuthAccount, authType: AuthType) {
|
||||||
|
lifecycleScope.launch { refreshBookmarks() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private val metrics
|
private val metrics
|
||||||
get() = context?.components?.analytics?.metrics
|
get() = context?.components?.analytics?.metrics
|
||||||
|
@ -92,7 +95,9 @@ class BookmarkFragment : LibraryPageFragment<BookmarkNode>(), BackHandler, Accou
|
||||||
)
|
)
|
||||||
|
|
||||||
bookmarkView = BookmarkView(view.bookmarkLayout, bookmarkInteractor)
|
bookmarkView = BookmarkView(view.bookmarkLayout, bookmarkInteractor)
|
||||||
signInView = SignInView(view.bookmarkLayout, bookmarkInteractor)
|
|
||||||
|
val signInView = SignInView(view.bookmarkLayout, findNavController())
|
||||||
|
sharedViewModel.signedIn.observe(viewLifecycleOwner, signInView)
|
||||||
|
|
||||||
lifecycle.addObserver(
|
lifecycle.addObserver(
|
||||||
BookmarkDeselectNavigationListener(
|
BookmarkDeselectNavigationListener(
|
||||||
|
@ -112,11 +117,6 @@ class BookmarkFragment : LibraryPageFragment<BookmarkNode>(), BackHandler, Accou
|
||||||
consumeFrom(bookmarkStore) {
|
consumeFrom(bookmarkStore) {
|
||||||
bookmarkView.update(it)
|
bookmarkView.update(it)
|
||||||
}
|
}
|
||||||
sharedViewModel.apply {
|
|
||||||
signedIn.observe(this@BookmarkFragment, Observer<Boolean> {
|
|
||||||
signInView.update(it)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
@ -129,7 +129,10 @@ class BookmarkFragment : LibraryPageFragment<BookmarkNode>(), BackHandler, Accou
|
||||||
super.onResume()
|
super.onResume()
|
||||||
|
|
||||||
(activity as? AppCompatActivity)?.supportActionBar?.show()
|
(activity as? AppCompatActivity)?.supportActionBar?.show()
|
||||||
checkIfSignedIn()
|
context?.components?.backgroundServices?.accountManager?.let { accountManager ->
|
||||||
|
sharedViewModel.observeAccountManager(accountManager, owner = this)
|
||||||
|
accountManager.register(refreshOnSignInListener, owner = this)
|
||||||
|
}
|
||||||
|
|
||||||
val currentGuid = BookmarkFragmentArgs.fromBundle(arguments!!).currentRoot.ifEmpty { BookmarkRoot.Mobile.id }
|
val currentGuid = BookmarkFragmentArgs.fromBundle(arguments!!).currentRoot.ifEmpty { BookmarkRoot.Mobile.id }
|
||||||
|
|
||||||
|
@ -137,26 +140,20 @@ class BookmarkFragment : LibraryPageFragment<BookmarkNode>(), BackHandler, Accou
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun loadInitialBookmarkFolder(currentGuid: String): Job {
|
private fun loadInitialBookmarkFolder(currentGuid: String): Job {
|
||||||
return viewLifecycleOwner.lifecycleScope.launch(IO) {
|
return viewLifecycleOwner.lifecycleScope.launch(Main) {
|
||||||
currentRoot = requireContext().bookmarkStorage
|
val currentRoot = withContext(IO) {
|
||||||
.getTree(currentGuid)?.let { desktopFolders.withOptionalDesktopFolders(it) }!!
|
requireContext().bookmarkStorage
|
||||||
|
.getTree(currentGuid)
|
||||||
|
?.let { desktopFolders.withOptionalDesktopFolders(it) }!!
|
||||||
|
}
|
||||||
|
|
||||||
if (!isActive) return@launch
|
if (isActive) {
|
||||||
launch(Main) {
|
bookmarkInteractor.onBookmarksChanged(currentRoot)
|
||||||
bookmarkInteractor.onBookmarksChanged(currentRoot!!)
|
|
||||||
sharedViewModel.selectedFolder = currentRoot
|
sharedViewModel.selectedFolder = currentRoot
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun checkIfSignedIn() {
|
|
||||||
context?.components?.backgroundServices?.accountManager?.let {
|
|
||||||
it.register(this, owner = this)
|
|
||||||
it.authenticatedAccount()?.let { bookmarkInteractor.onSignedIn() }
|
|
||||||
?: bookmarkInteractor.onSignedOut()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
|
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
|
||||||
when (val mode = bookmarkStore.state.mode) {
|
when (val mode = bookmarkStore.state.mode) {
|
||||||
BookmarkFragmentState.Mode.Normal -> {
|
BookmarkFragmentState.Mode.Normal -> {
|
||||||
|
@ -229,17 +226,6 @@ class BookmarkFragment : LibraryPageFragment<BookmarkNode>(), BackHandler, Accou
|
||||||
return bookmarkView.onBackPressed()
|
return bookmarkView.onBackPressed()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onAuthenticated(account: OAuthAccount, authType: AuthType) {
|
|
||||||
bookmarkInteractor.onSignedIn()
|
|
||||||
lifecycleScope.launch {
|
|
||||||
refreshBookmarks()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onLoggedOut() {
|
|
||||||
bookmarkInteractor.onSignedOut()
|
|
||||||
}
|
|
||||||
|
|
||||||
private suspend fun refreshBookmarks() {
|
private suspend fun refreshBookmarks() {
|
||||||
// The bookmark tree in our 'state' can be null - meaning, no bookmark tree has been selected.
|
// The bookmark tree in our 'state' can be null - meaning, no bookmark tree has been selected.
|
||||||
// If that's the case, we don't know what node to refresh, and so we bail out.
|
// If that's the case, we don't know what node to refresh, and so we bail out.
|
||||||
|
@ -274,7 +260,7 @@ class BookmarkFragment : LibraryPageFragment<BookmarkNode>(), BackHandler, Accou
|
||||||
private fun deleteMulti(selected: Set<BookmarkNode>, eventType: Event = Event.RemoveBookmarks) {
|
private fun deleteMulti(selected: Set<BookmarkNode>, eventType: Event = Event.RemoveBookmarks) {
|
||||||
pendingBookmarksToDelete.addAll(selected)
|
pendingBookmarksToDelete.addAll(selected)
|
||||||
|
|
||||||
val bookmarkTree = currentRoot!! - pendingBookmarksToDelete
|
val bookmarkTree = sharedViewModel.selectedFolder!! - pendingBookmarksToDelete
|
||||||
bookmarkInteractor.onBookmarksChanged(bookmarkTree)
|
bookmarkInteractor.onBookmarksChanged(bookmarkTree)
|
||||||
|
|
||||||
val deleteOperation: (suspend () -> Unit) = {
|
val deleteOperation: (suspend () -> Unit) = {
|
||||||
|
|
|
@ -26,7 +26,7 @@ class BookmarkFragmentInteractor(
|
||||||
private val viewModel: BookmarksSharedViewModel,
|
private val viewModel: BookmarksSharedViewModel,
|
||||||
private val bookmarksController: BookmarkController,
|
private val bookmarksController: BookmarkController,
|
||||||
private val metrics: MetricController
|
private val metrics: MetricController
|
||||||
) : BookmarkViewInteractor, SignInInteractor {
|
) : BookmarkViewInteractor {
|
||||||
|
|
||||||
override fun onBookmarksChanged(node: BookmarkNode) {
|
override fun onBookmarksChanged(node: BookmarkNode) {
|
||||||
bookmarkStore.dispatch(BookmarkFragmentAction.Change(node))
|
bookmarkStore.dispatch(BookmarkFragmentAction.Change(node))
|
||||||
|
@ -96,18 +96,6 @@ class BookmarkFragmentInteractor(
|
||||||
bookmarksController.handleBackPressed()
|
bookmarksController.handleBackPressed()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onSignInPressed() {
|
|
||||||
bookmarksController.handleSigningIn()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onSignedIn() {
|
|
||||||
viewModel.signedIn.postValue(true)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onSignedOut() {
|
|
||||||
viewModel.signedIn.postValue(false)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun open(item: BookmarkNode) {
|
override fun open(item: BookmarkNode) {
|
||||||
Do exhaustive when (item.type) {
|
Do exhaustive when (item.type) {
|
||||||
BookmarkNodeType.ITEM -> {
|
BookmarkNodeType.ITEM -> {
|
||||||
|
|
|
@ -4,11 +4,53 @@
|
||||||
|
|
||||||
package org.mozilla.fenix.library.bookmarks
|
package org.mozilla.fenix.library.bookmarks
|
||||||
|
|
||||||
|
import androidx.lifecycle.LifecycleOwner
|
||||||
|
import androidx.lifecycle.LiveData
|
||||||
import androidx.lifecycle.MutableLiveData
|
import androidx.lifecycle.MutableLiveData
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import mozilla.components.concept.storage.BookmarkNode
|
import mozilla.components.concept.storage.BookmarkNode
|
||||||
|
import mozilla.components.concept.sync.AccountObserver
|
||||||
|
import mozilla.components.concept.sync.AuthType
|
||||||
|
import mozilla.components.concept.sync.OAuthAccount
|
||||||
|
import mozilla.components.service.fxa.manager.FxaAccountManager
|
||||||
|
|
||||||
class BookmarksSharedViewModel : ViewModel() {
|
/**
|
||||||
var signedIn = MutableLiveData<Boolean>().apply { postValue(true) }
|
* [ViewModel] that shares data between various bookmarks fragments.
|
||||||
|
*/
|
||||||
|
class BookmarksSharedViewModel : ViewModel(), AccountObserver {
|
||||||
|
|
||||||
|
private val signedInMutable = MutableLiveData(true)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether or not the user is signed in.
|
||||||
|
*/
|
||||||
|
val signedIn: LiveData<Boolean> get() = signedInMutable
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The currently selected bookmark root.
|
||||||
|
*/
|
||||||
var selectedFolder: BookmarkNode? = null
|
var selectedFolder: BookmarkNode? = null
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the [signedIn] boolean once the account observer sees that the user logged in.
|
||||||
|
*/
|
||||||
|
override fun onAuthenticated(account: OAuthAccount, authType: AuthType) {
|
||||||
|
signedInMutable.postValue(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the [signedIn] boolean once the account observer sees that the user logged out.
|
||||||
|
*/
|
||||||
|
override fun onLoggedOut() {
|
||||||
|
signedInMutable.postValue(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun observeAccountManager(accountManager: FxaAccountManager, owner: LifecycleOwner) {
|
||||||
|
accountManager.register(this, owner = owner)
|
||||||
|
if (accountManager.authenticatedAccount() != null) {
|
||||||
|
signedInMutable.postValue(true)
|
||||||
|
} else {
|
||||||
|
signedInMutable.postValue(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,20 +7,18 @@ package org.mozilla.fenix.library.bookmarks
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
import androidx.core.view.isGone
|
||||||
|
import androidx.lifecycle.Observer
|
||||||
|
import androidx.navigation.NavController
|
||||||
import com.google.android.material.button.MaterialButton
|
import com.google.android.material.button.MaterialButton
|
||||||
import kotlinx.android.extensions.LayoutContainer
|
import kotlinx.android.extensions.LayoutContainer
|
||||||
import org.mozilla.fenix.R
|
import org.mozilla.fenix.R
|
||||||
|
import org.mozilla.fenix.ext.components
|
||||||
interface SignInInteractor {
|
|
||||||
fun onSignInPressed()
|
|
||||||
fun onSignedIn()
|
|
||||||
fun onSignedOut()
|
|
||||||
}
|
|
||||||
|
|
||||||
class SignInView(
|
class SignInView(
|
||||||
private val container: ViewGroup,
|
private val container: ViewGroup,
|
||||||
private val interactor: SignInInteractor
|
private val navController: NavController
|
||||||
) : LayoutContainer {
|
) : LayoutContainer, Observer<Boolean> {
|
||||||
|
|
||||||
override val containerView: View?
|
override val containerView: View?
|
||||||
get() = container
|
get() = container
|
||||||
|
@ -31,11 +29,14 @@ class SignInView(
|
||||||
|
|
||||||
init {
|
init {
|
||||||
view.setOnClickListener {
|
view.setOnClickListener {
|
||||||
interactor.onSignInPressed()
|
view.context.components.services.launchPairingSignIn(view.context, navController)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun update(signedIn: Boolean) {
|
/**
|
||||||
view.visibility = if (signedIn) View.GONE else View.VISIBLE
|
* Hides or shows the sign-in button. Should be called whenever the sign-in state changes.
|
||||||
|
*/
|
||||||
|
override fun onChanged(signedIn: Boolean) {
|
||||||
|
view.isGone = signedIn
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,6 +32,7 @@ import kotlinx.android.synthetic.main.fragment_edit_bookmark.*
|
||||||
import kotlinx.coroutines.Dispatchers.IO
|
import kotlinx.coroutines.Dispatchers.IO
|
||||||
import kotlinx.coroutines.Dispatchers.Main
|
import kotlinx.coroutines.Dispatchers.Main
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
import mozilla.appservices.places.UrlParseFailed
|
import mozilla.appservices.places.UrlParseFailed
|
||||||
import mozilla.components.concept.storage.BookmarkInfo
|
import mozilla.components.concept.storage.BookmarkInfo
|
||||||
import mozilla.components.concept.storage.BookmarkNode
|
import mozilla.components.concept.storage.BookmarkNode
|
||||||
|
@ -75,40 +76,40 @@ class EditBookmarkFragment : Fragment() {
|
||||||
activity?.supportActionBar?.show()
|
activity?.supportActionBar?.show()
|
||||||
|
|
||||||
guidToEdit = EditBookmarkFragmentArgs.fromBundle(arguments!!).guidToEdit
|
guidToEdit = EditBookmarkFragmentArgs.fromBundle(arguments!!).guidToEdit
|
||||||
lifecycleScope.launch(IO) {
|
lifecycleScope.launch(Main) {
|
||||||
val context = requireContext()
|
val context = requireContext()
|
||||||
bookmarkNode = context.components.core.bookmarksStorage.getTree(guidToEdit)
|
|
||||||
bookmarkParent = sharedViewModel.selectedFolder
|
|
||||||
?: bookmarkNode?.parentGuid
|
|
||||||
?.let { context.components.core.bookmarksStorage.getTree(it) }
|
|
||||||
?.let { DesktopFolders(context, showMobileRoot = true).withRootTitle(it) }
|
|
||||||
|
|
||||||
launch(Main) {
|
withContext(IO) {
|
||||||
when (bookmarkNode?.type) {
|
val bookmarksStorage = context.components.core.bookmarksStorage
|
||||||
BookmarkNodeType.FOLDER -> {
|
bookmarkNode = bookmarksStorage.getTree(guidToEdit)
|
||||||
activity?.title = getString(R.string.edit_bookmark_folder_fragment_title)
|
bookmarkParent = sharedViewModel.selectedFolder
|
||||||
bookmarkUrlEdit.visibility = View.GONE
|
?: bookmarkNode?.parentGuid
|
||||||
bookmarkUrlLabel.visibility = View.GONE
|
?.let { bookmarksStorage.getTree(it) }
|
||||||
}
|
?.let { DesktopFolders(context, showMobileRoot = true).withRootTitle(it) }
|
||||||
BookmarkNodeType.ITEM -> {
|
}
|
||||||
activity?.title = getString(R.string.edit_bookmark_fragment_title)
|
|
||||||
}
|
when (bookmarkNode?.type) {
|
||||||
else -> throw IllegalArgumentException()
|
BookmarkNodeType.FOLDER -> {
|
||||||
|
activity?.title = getString(R.string.edit_bookmark_folder_fragment_title)
|
||||||
|
bookmarkUrlEdit.visibility = View.GONE
|
||||||
|
bookmarkUrlLabel.visibility = View.GONE
|
||||||
}
|
}
|
||||||
|
BookmarkNodeType.ITEM -> {
|
||||||
|
activity?.title = getString(R.string.edit_bookmark_fragment_title)
|
||||||
|
}
|
||||||
|
else -> throw IllegalArgumentException()
|
||||||
|
}
|
||||||
|
|
||||||
if (bookmarkNode != null) {
|
bookmarkNode?.let { bookmarkNode ->
|
||||||
bookmarkNameEdit.setText(bookmarkNode!!.title)
|
bookmarkNameEdit.setText(bookmarkNode.title)
|
||||||
bookmarkUrlEdit.setText(bookmarkNode!!.url)
|
bookmarkUrlEdit.setText(bookmarkNode.url)
|
||||||
|
|
||||||
if (sharedViewModel.selectedFolder != null && bookmarkNode?.title != null) {
|
if (sharedViewModel.selectedFolder != null && bookmarkNode.title != null) {
|
||||||
val bookmarkPair = Pair(bookmarkNode?.title, bookmarkNode?.url)
|
updateBookmarkNode(bookmarkNode.title to bookmarkNode.url)
|
||||||
updateBookmarkNode(bookmarkPair)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bookmarkParent?.let { node ->
|
bookmarkParent?.let { node ->
|
||||||
launch(Main) {
|
|
||||||
bookmarkFolderSelector.text = node.title
|
bookmarkFolderSelector.text = node.title
|
||||||
bookmarkFolderSelector.setOnClickListener {
|
bookmarkFolderSelector.setOnClickListener {
|
||||||
sharedViewModel.selectedFolder = null
|
sharedViewModel.selectedFolder = null
|
||||||
|
@ -120,7 +121,6 @@ class EditBookmarkFragment : Fragment() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
updateBookmarkFromObservableInput()
|
updateBookmarkFromObservableInput()
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,6 @@ import android.view.ViewGroup
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.fragment.app.activityViewModels
|
import androidx.fragment.app.activityViewModels
|
||||||
import androidx.lifecycle.Observer
|
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.navigation.fragment.findNavController
|
import androidx.navigation.fragment.findNavController
|
||||||
|
@ -27,9 +26,6 @@ import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import mozilla.appservices.places.BookmarkRoot
|
import mozilla.appservices.places.BookmarkRoot
|
||||||
import mozilla.components.concept.storage.BookmarkNode
|
import mozilla.components.concept.storage.BookmarkNode
|
||||||
import mozilla.components.concept.sync.AccountObserver
|
|
||||||
import mozilla.components.concept.sync.AuthType
|
|
||||||
import mozilla.components.concept.sync.OAuthAccount
|
|
||||||
import org.mozilla.fenix.R
|
import org.mozilla.fenix.R
|
||||||
import org.mozilla.fenix.ext.components
|
import org.mozilla.fenix.ext.components
|
||||||
import org.mozilla.fenix.ext.nav
|
import org.mozilla.fenix.ext.nav
|
||||||
|
@ -38,16 +34,12 @@ import org.mozilla.fenix.library.bookmarks.BookmarksSharedViewModel
|
||||||
import org.mozilla.fenix.library.bookmarks.DesktopFolders
|
import org.mozilla.fenix.library.bookmarks.DesktopFolders
|
||||||
import org.mozilla.fenix.library.bookmarks.SignInView
|
import org.mozilla.fenix.library.bookmarks.SignInView
|
||||||
|
|
||||||
@SuppressWarnings("TooManyFunctions")
|
class SelectBookmarkFolderFragment : Fragment() {
|
||||||
class SelectBookmarkFolderFragment : Fragment(), AccountObserver {
|
|
||||||
|
|
||||||
private val sharedViewModel: BookmarksSharedViewModel by activityViewModels {
|
private val sharedViewModel: BookmarksSharedViewModel by activityViewModels {
|
||||||
ViewModelProvider.NewInstanceFactory() // this is a workaround for #4652
|
ViewModelProvider.NewInstanceFactory() // this is a workaround for #4652
|
||||||
}
|
}
|
||||||
private var folderGuid: String? = null
|
|
||||||
private var bookmarkNode: BookmarkNode? = null
|
private var bookmarkNode: BookmarkNode? = null
|
||||||
private lateinit var signInView: SignInView
|
|
||||||
private lateinit var bookmarkInteractor: SelectBookmarkFolderInteractor
|
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
@ -57,30 +49,19 @@ class SelectBookmarkFolderFragment : Fragment(), AccountObserver {
|
||||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||||
val view = inflater.inflate(R.layout.fragment_select_bookmark_folder, container, false)
|
val view = inflater.inflate(R.layout.fragment_select_bookmark_folder, container, false)
|
||||||
|
|
||||||
bookmarkInteractor = SelectBookmarkFolderInteractor(
|
val signInView = SignInView(view.selectBookmarkLayout, findNavController())
|
||||||
context!!,
|
sharedViewModel.signedIn.observe(viewLifecycleOwner, signInView)
|
||||||
findNavController(),
|
|
||||||
sharedViewModel
|
|
||||||
)
|
|
||||||
signInView = SignInView(view.selectBookmarkLayout, bookmarkInteractor)
|
|
||||||
|
|
||||||
return view
|
return view
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
|
||||||
super.onViewCreated(view, savedInstanceState)
|
|
||||||
sharedViewModel.signedIn.observe(this@SelectBookmarkFolderFragment, Observer<Boolean> {
|
|
||||||
signInView.update(it)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
super.onResume()
|
super.onResume()
|
||||||
activity?.title = getString(R.string.bookmark_select_folder_fragment_label)
|
activity?.title = getString(R.string.bookmark_select_folder_fragment_label)
|
||||||
(activity as? AppCompatActivity)?.supportActionBar?.show()
|
(activity as? AppCompatActivity)?.supportActionBar?.show()
|
||||||
|
|
||||||
folderGuid = SelectBookmarkFolderFragmentArgs.fromBundle(arguments!!).folderGuid ?: BookmarkRoot.Root.id
|
val accountManager = requireComponents.backgroundServices.accountManager
|
||||||
checkIfSignedIn()
|
sharedViewModel.observeAccountManager(accountManager, owner = this)
|
||||||
|
|
||||||
lifecycleScope.launch(Main) {
|
lifecycleScope.launch(Main) {
|
||||||
bookmarkNode = withContext(IO) {
|
bookmarkNode = withContext(IO) {
|
||||||
|
@ -96,13 +77,6 @@ class SelectBookmarkFolderFragment : Fragment(), AccountObserver {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun checkIfSignedIn() {
|
|
||||||
val accountManager = requireComponents.backgroundServices.accountManager
|
|
||||||
accountManager.register(this, owner = this)
|
|
||||||
accountManager.authenticatedAccount()?.let { bookmarkInteractor.onSignedIn() }
|
|
||||||
?: bookmarkInteractor.onSignedOut()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
|
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
|
||||||
val args: SelectBookmarkFolderFragmentArgs by navArgs()
|
val args: SelectBookmarkFolderFragmentArgs by navArgs()
|
||||||
if (!args.visitedAddBookmark) {
|
if (!args.visitedAddBookmark) {
|
||||||
|
@ -125,11 +99,4 @@ class SelectBookmarkFolderFragment : Fragment(), AccountObserver {
|
||||||
else -> super.onOptionsItemSelected(item)
|
else -> super.onOptionsItemSelected(item)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
override fun onAuthenticated(account: OAuthAccount, authType: AuthType) {
|
|
||||||
bookmarkInteractor.onSignedIn()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onLoggedOut() {
|
|
||||||
bookmarkInteractor.onSignedOut()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,30 +0,0 @@
|
||||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
||||||
|
|
||||||
package org.mozilla.fenix.library.bookmarks.selectfolder
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import androidx.navigation.NavController
|
|
||||||
import org.mozilla.fenix.ext.components
|
|
||||||
import org.mozilla.fenix.library.bookmarks.BookmarksSharedViewModel
|
|
||||||
import org.mozilla.fenix.library.bookmarks.SignInInteractor
|
|
||||||
|
|
||||||
class SelectBookmarkFolderInteractor(
|
|
||||||
private val context: Context,
|
|
||||||
private val navController: NavController,
|
|
||||||
private val sharedViewModel: BookmarksSharedViewModel
|
|
||||||
) : SignInInteractor {
|
|
||||||
|
|
||||||
override fun onSignInPressed() {
|
|
||||||
context.components.services.launchPairingSignIn(context, navController)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onSignedIn() {
|
|
||||||
sharedViewModel.signedIn.postValue(true)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onSignedOut() {
|
|
||||||
sharedViewModel.signedIn.postValue(false)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -217,31 +217,4 @@ class BookmarkFragmentInteractorTest {
|
||||||
bookmarkController.handleBackPressed()
|
bookmarkController.handleBackPressed()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `clicked sign in on bookmarks screen`() {
|
|
||||||
interactor.onSignInPressed()
|
|
||||||
|
|
||||||
verify {
|
|
||||||
bookmarkController.handleSigningIn()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `got signed in signal on bookmarks screen`() {
|
|
||||||
interactor.onSignedIn()
|
|
||||||
|
|
||||||
verify {
|
|
||||||
sharedViewModel.signedIn.postValue(true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `got signed out signal on bookmarks screen`() {
|
|
||||||
interactor.onSignedOut()
|
|
||||||
|
|
||||||
verify {
|
|
||||||
sharedViewModel.signedIn.postValue(false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,63 @@
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
package org.mozilla.fenix.library.bookmarks
|
||||||
|
|
||||||
|
import androidx.lifecycle.LifecycleOwner
|
||||||
|
import io.mockk.every
|
||||||
|
import io.mockk.mockk
|
||||||
|
import io.mockk.verify
|
||||||
|
import kotlinx.coroutines.ObsoleteCoroutinesApi
|
||||||
|
import mozilla.components.concept.sync.AuthType
|
||||||
|
import mozilla.components.service.fxa.manager.FxaAccountManager
|
||||||
|
import mozilla.components.support.test.mock
|
||||||
|
import org.junit.Assert.assertFalse
|
||||||
|
import org.junit.Assert.assertTrue
|
||||||
|
import org.junit.Before
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
import org.mozilla.fenix.TestApplication
|
||||||
|
import org.robolectric.RobolectricTestRunner
|
||||||
|
import org.robolectric.annotation.Config
|
||||||
|
|
||||||
|
@ObsoleteCoroutinesApi
|
||||||
|
@RunWith(RobolectricTestRunner::class)
|
||||||
|
@Config(application = TestApplication::class)
|
||||||
|
internal class BookmarksSharedViewModelTest {
|
||||||
|
|
||||||
|
private lateinit var viewModel: BookmarksSharedViewModel
|
||||||
|
|
||||||
|
@Before
|
||||||
|
fun setup() {
|
||||||
|
viewModel = BookmarksSharedViewModel()
|
||||||
|
viewModel.signedIn.observeForever { }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `onAuthenticated and onLoggedOut modify signedIn value`() {
|
||||||
|
viewModel.onLoggedOut()
|
||||||
|
assertFalse(viewModel.signedIn.value!!)
|
||||||
|
|
||||||
|
viewModel.onAuthenticated(mock(), AuthType.Existing)
|
||||||
|
assertTrue(viewModel.signedIn.value!!)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `observeAccountManager registers observer`() {
|
||||||
|
val accountManager: FxaAccountManager = mockk(relaxed = true)
|
||||||
|
val lifecycleOwner: LifecycleOwner = mockk()
|
||||||
|
|
||||||
|
every { accountManager.authenticatedAccount() } returns null
|
||||||
|
viewModel.observeAccountManager(accountManager, lifecycleOwner)
|
||||||
|
|
||||||
|
verify { accountManager.register(viewModel, lifecycleOwner) }
|
||||||
|
assertFalse(viewModel.signedIn.value!!)
|
||||||
|
|
||||||
|
every { accountManager.authenticatedAccount() } returns mockk()
|
||||||
|
viewModel.observeAccountManager(accountManager, lifecycleOwner)
|
||||||
|
|
||||||
|
verify { accountManager.register(viewModel, lifecycleOwner) }
|
||||||
|
assertTrue(viewModel.signedIn.value!!)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue