Skip to content
This repository has been archived by the owner on Feb 20, 2023. It is now read-only.

Commit

Permalink
No issue: Extract home fragment mode (#5343)
Browse files Browse the repository at this point in the history
  • Loading branch information
NotWoods authored and sblatz committed Sep 23, 2019
1 parent 72eed21 commit cb77015
Show file tree
Hide file tree
Showing 6 changed files with 245 additions and 94 deletions.
104 changes: 37 additions & 67 deletions app/src/main/java/org/mozilla/fenix/home/HomeFragment.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
package org.mozilla.fenix.home

import android.animation.Animator
import android.content.Context
import android.content.DialogInterface
import android.graphics.drawable.BitmapDrawable
import android.os.Bundle
Expand Down Expand Up @@ -49,7 +48,6 @@ import mozilla.components.browser.session.SessionManager
import mozilla.components.concept.sync.AccountObserver
import mozilla.components.concept.sync.AuthType
import mozilla.components.concept.sync.OAuthAccount
import mozilla.components.concept.sync.Profile
import mozilla.components.feature.media.ext.getSession
import mozilla.components.feature.media.ext.pauseIfPlaying
import mozilla.components.feature.media.ext.playIfPaused
Expand All @@ -72,17 +70,15 @@ import org.mozilla.fenix.components.FenixSnackbar
import org.mozilla.fenix.components.PrivateShortcutCreateManager
import org.mozilla.fenix.components.TabCollectionStorage
import org.mozilla.fenix.components.metrics.Event
import org.mozilla.fenix.ext.metrics
import org.mozilla.fenix.ext.components
import org.mozilla.fenix.ext.metrics
import org.mozilla.fenix.ext.nav
import org.mozilla.fenix.ext.requireComponents
import org.mozilla.fenix.ext.sessionsOfType
import org.mozilla.fenix.ext.settings
import org.mozilla.fenix.ext.toTab
import org.mozilla.fenix.home.sessioncontrol.CollectionAction
import org.mozilla.fenix.home.sessioncontrol.Mode
import org.mozilla.fenix.home.sessioncontrol.OnboardingAction
import org.mozilla.fenix.home.sessioncontrol.OnboardingState
import org.mozilla.fenix.home.sessioncontrol.SessionControlAction
import org.mozilla.fenix.home.sessioncontrol.SessionControlChange
import org.mozilla.fenix.home.sessioncontrol.SessionControlComponent
Expand All @@ -103,7 +99,7 @@ import org.mozilla.fenix.utils.allowUndo
import org.mozilla.fenix.whatsnew.WhatsNew

@SuppressWarnings("TooManyFunctions", "LargeClass")
class HomeFragment : Fragment(), AccountObserver {
class HomeFragment : Fragment() {

private val bus = ActionBusFactory.get(this)

Expand Down Expand Up @@ -141,6 +137,7 @@ class HomeFragment : Fragment(), AccountObserver {

private val onboarding by lazy { FenixOnboarding(requireContext()) }
private lateinit var sessionControlComponent: SessionControlComponent
private lateinit var currentMode: CurrentMode

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Expand All @@ -167,7 +164,12 @@ class HomeFragment : Fragment(), AccountObserver {
): View? {
val view = inflater.inflate(R.layout.fragment_home, container, false)

val mode = currentMode(view.context)
currentMode = CurrentMode(
view.context,
onboarding,
browsingModeManager,
getManagedEmitter()
)

sessionControlComponent = SessionControlComponent(
view.homeLayout,
Expand All @@ -178,10 +180,10 @@ class HomeFragment : Fragment(), AccountObserver {
) {
SessionControlViewModel(
SessionControlState(
listOf(),
setOf(),
emptyList(),
emptySet(),
requireComponents.core.tabCollectionStorage.cachedTabCollections,
mode
currentMode.getCurrentMode()
)
)
}
Expand Down Expand Up @@ -304,17 +306,28 @@ class HomeFragment : Fragment(), AccountObserver {
getManagedEmitter<SessionControlChange>().onNext(
SessionControlChange.Change(
tabs = getListOfSessions().toTabs(),
mode = currentMode(context),
mode = currentMode.getCurrentMode(),
collections = components.core.tabCollectionStorage.cachedTabCollections
)
)

(activity as AppCompatActivity).supportActionBar?.hide()
components.backgroundServices.accountManager.register(this, owner = this)

if (context.settings.showPrivateModeContextualFeatureRecommender &&
browsingModeManager.mode.isPrivate
) {
requireComponents.backgroundServices.accountManager.register(currentMode, owner = this)
requireComponents.backgroundServices.accountManager.register(object : AccountObserver {
override fun onAuthenticated(account: OAuthAccount, authType: AuthType) {
if (authType != AuthType.Existing) {
view?.let {
FenixSnackbar.make(it, Snackbar.LENGTH_SHORT).setText(
it.context.getString(R.string.onboarding_firefox_account_sync_is_on)
).show()
}
}
}
}, owner = this)

if (context.settings().showPrivateModeContextualFeatureRecommender &&
browsingModeManager.mode.isPrivate) {
recommendPrivateBrowsingShortcut()
}
}
Expand All @@ -330,14 +343,8 @@ class HomeFragment : Fragment(), AccountObserver {
private fun handleOnboardingAction(action: OnboardingAction) {
Do exhaustive when (action) {
is OnboardingAction.Finish -> {
onboarding.finish()
homeLayout?.progress = 0F
val mode = currentMode(requireContext())
getManagedEmitter<SessionControlChange>().onNext(
SessionControlChange.ModeChange(
mode
)
)
hideOnboarding()
}
}
}
Expand All @@ -346,7 +353,7 @@ class HomeFragment : Fragment(), AccountObserver {
private fun handleTabAction(action: TabAction) {
Do exhaustive when (action) {
is TabAction.SaveTabGroup -> {
if ((activity as HomeActivity).browsingModeManager.mode.isPrivate) return
if (browsingModeManager.mode.isPrivate) return
invokePendingDeleteJobs()
saveTabToCollection(action.selectedTabSessionId)
}
Expand Down Expand Up @@ -429,7 +436,7 @@ class HomeFragment : Fragment(), AccountObserver {
is TabAction.ShareTabs -> {
invokePendingDeleteJobs()
val shareTabs = sessionManager
.sessionsOfType(private = (activity as HomeActivity).browsingModeManager.mode.isPrivate)
.sessionsOfType(private = browsingModeManager.mode.isPrivate)
.map { ShareTab(it.url, it.title) }
.toList()
share(tabs = shareTabs)
Expand Down Expand Up @@ -616,10 +623,12 @@ class HomeFragment : Fragment(), AccountObserver {
}

private fun hideOnboardingIfNeeded() {
if (!onboarding.userHasBeenOnboarded()) {
onboarding.finish()
emitModeChanges()
}
if (!onboarding.userHasBeenOnboarded()) hideOnboarding()
}

private fun hideOnboarding() {
onboarding.finish()
currentMode.emitModeChanges()
}

private fun setupHomeMenu() {
Expand Down Expand Up @@ -811,45 +820,6 @@ class HomeFragment : Fragment(), AccountObserver {
nav(R.id.homeFragment, directions)
}

private fun currentMode(context: Context): Mode = if (!onboarding.userHasBeenOnboarded()) {
val accountManager = requireComponents.backgroundServices.accountManager
val account = accountManager.authenticatedAccount()
if (account != null) {
Mode.Onboarding(OnboardingState.SignedIn)
} else {
val availableAccounts = accountManager.shareableAccounts(context)
if (availableAccounts.isEmpty()) {
Mode.Onboarding(OnboardingState.SignedOutNoAutoSignIn)
} else {
Mode.Onboarding(OnboardingState.SignedOutCanAutoSignIn(availableAccounts[0]))
}
}
} else {
Mode.fromBrowsingMode(browsingModeManager.mode)
}

private fun emitModeChanges() {
context?.let {
val mode = currentMode(it)
getManagedEmitter<SessionControlChange>().onNext(SessionControlChange.ModeChange(mode))
}
}

override fun onAuthenticated(account: OAuthAccount, authType: AuthType) {
if (authType != AuthType.Existing) {
view?.let {
FenixSnackbar.make(it, Snackbar.LENGTH_SHORT).setText(
it.context.getString(R.string.onboarding_firefox_account_sync_is_on)
).show()
}
}
emitModeChanges()
}

override fun onAuthenticationProblems() = emitModeChanges()
override fun onLoggedOut() = emitModeChanges()
override fun onProfileUpdated(profile: Profile) = emitModeChanges()

private fun scrollAndAnimateCollection(
tabsAddedToCollectionSize: Int,
changedCollection: TabCollection? = null
Expand Down
81 changes: 81 additions & 0 deletions app/src/main/java/org/mozilla/fenix/home/Mode.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/* 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.home

import android.content.Context
import io.reactivex.Observer
import mozilla.components.concept.sync.AccountObserver
import mozilla.components.concept.sync.AuthType
import mozilla.components.concept.sync.OAuthAccount
import mozilla.components.concept.sync.Profile
import mozilla.components.service.fxa.sharing.ShareableAccount
import org.mozilla.fenix.browser.browsingmode.BrowsingMode
import org.mozilla.fenix.browser.browsingmode.BrowsingModeManager
import org.mozilla.fenix.ext.components
import org.mozilla.fenix.home.sessioncontrol.SessionControlChange
import org.mozilla.fenix.onboarding.FenixOnboarding

/**
* Describes various states of the home fragment UI.
*/
sealed class Mode {
object Normal : Mode()
object Private : Mode()
data class Onboarding(val state: OnboardingState) : Mode()

companion object {
fun fromBrowsingMode(browsingMode: BrowsingMode) = when (browsingMode) {
BrowsingMode.Normal -> Normal
BrowsingMode.Private -> Private
}
}
}

/**
* Describes various onboarding states.
*/
sealed class OnboardingState {
// Signed out, without an option to auto-login using a shared FxA account.
object SignedOutNoAutoSignIn : OnboardingState()
// Signed out, with an option to auto-login into a shared FxA account.
data class SignedOutCanAutoSignIn(val withAccount: ShareableAccount) : OnboardingState()
// Signed in.
object SignedIn : OnboardingState()
}

class CurrentMode(
private val context: Context,
private val onboarding: FenixOnboarding,
private val browsingModeManager: BrowsingModeManager,
private val emitter: Observer<SessionControlChange>
) : AccountObserver {

private val accountManager = context.components.backgroundServices.accountManager

fun getCurrentMode() = if (onboarding.userHasBeenOnboarded()) {
Mode.fromBrowsingMode(browsingModeManager.mode)
} else {
val account = accountManager.authenticatedAccount()
if (account != null) {
Mode.Onboarding(OnboardingState.SignedIn)
} else {
val availableAccounts = accountManager.shareableAccounts(context)
if (availableAccounts.isEmpty()) {
Mode.Onboarding(OnboardingState.SignedOutNoAutoSignIn)
} else {
Mode.Onboarding(OnboardingState.SignedOutCanAutoSignIn(availableAccounts[0]))
}
}
}

fun emitModeChanges() {
emitter.onNext(SessionControlChange.ModeChange(getCurrentMode()))
}

override fun onAuthenticated(account: OAuthAccount, authType: AuthType) = emitModeChanges()
override fun onAuthenticationProblems() = emitModeChanges()
override fun onLoggedOut() = emitModeChanges()
override fun onProfileUpdated(profile: Profile) = emitModeChanges()
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import androidx.recyclerview.widget.RecyclerView
import io.reactivex.Observer
import kotlinx.android.synthetic.main.tab_list_row.*
import mozilla.components.feature.media.state.MediaState
import org.mozilla.fenix.home.OnboardingState
import org.mozilla.fenix.home.sessioncontrol.viewholders.CollectionHeaderViewHolder
import org.mozilla.fenix.home.sessioncontrol.viewholders.CollectionViewHolder
import org.mozilla.fenix.home.sessioncontrol.viewholders.NoContentMessageViewHolder
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,8 @@ import androidx.recyclerview.widget.RecyclerView
import io.reactivex.Observer
import mozilla.components.browser.session.Session
import mozilla.components.feature.media.state.MediaState
import mozilla.components.service.fxa.sharing.ShareableAccount
import org.mozilla.fenix.browser.browsingmode.BrowsingMode
import org.mozilla.fenix.ext.components
import org.mozilla.fenix.home.Mode
import org.mozilla.fenix.mvi.Action
import org.mozilla.fenix.mvi.ActionBusFactory
import org.mozilla.fenix.mvi.Change
Expand Down Expand Up @@ -64,31 +63,6 @@ fun List<Tab>.toSessionBundle(context: Context): MutableList<Session> {
return sessionBundle
}

/**
* Describes various onboarding states.
*/
sealed class OnboardingState {
// Signed out, without an option to auto-login using a shared FxA account.
object SignedOutNoAutoSignIn : OnboardingState()
// Signed out, with an option to auto-login into a shared FxA account.
data class SignedOutCanAutoSignIn(val withAccount: ShareableAccount) : OnboardingState()
// Signed in.
object SignedIn : OnboardingState()
}

sealed class Mode {
object Normal : Mode()
object Private : Mode()
data class Onboarding(val state: OnboardingState) : Mode()

companion object {
fun fromBrowsingMode(browsingMode: BrowsingMode) = when (browsingMode) {
BrowsingMode.Normal -> Normal
BrowsingMode.Private -> Private
}
}
}

data class SessionControlState(
val tabs: List<Tab>,
val expandedCollections: Set<Long>,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import io.reactivex.Observable
import io.reactivex.Observer
import io.reactivex.functions.Consumer
import org.mozilla.fenix.R
import org.mozilla.fenix.home.Mode
import org.mozilla.fenix.home.OnboardingState
import org.mozilla.fenix.mvi.UIView

val noTabMessage = AdapterItem.NoContentMessage(
Expand Down
Loading

0 comments on commit cb77015

Please sign in to comment.