1
0
Fork 0

Consodilate private browsing code

master
Tiger Oakes 2019-08-07 16:02:08 -04:00 committed by Jeff Boek
parent a239f1f073
commit 52542708aa
15 changed files with 174 additions and 237 deletions

View File

@ -6,54 +6,45 @@ package org.mozilla.fenix
import org.mozilla.fenix.utils.Settings import org.mozilla.fenix.utils.Settings
/**
* Enum that represents whether or not private browsing is active.
*/
enum class BrowsingMode {
Normal, Private;
/**
* Returns true if the [BrowsingMode] is [Private]
*/
val isPrivate get() = this == Private
companion object {
/**
* Convert a boolean into a [BrowsingMode].
* True corresponds to [Private] and false corresponds to [Normal].
*/
fun fromBoolean(isPrivate: Boolean) = if (isPrivate) Private else Normal
}
}
interface BrowsingModeManager { interface BrowsingModeManager {
enum class Mode { var mode: BrowsingMode
Normal, Private;
fun isPrivate(): Boolean = this == Private
}
val isPrivate: Boolean
var mode: Mode
}
interface BrowserModeStorage {
fun setMode(mode: BrowsingModeManager.Mode)
fun currentMode(): BrowsingModeManager.Mode
}
fun Settings.createBrowserModeStorage(): BrowserModeStorage = object : BrowserModeStorage {
override fun currentMode(): BrowsingModeManager.Mode {
return if (this@createBrowserModeStorage.usePrivateMode) {
BrowsingModeManager.Mode.Private
} else {
BrowsingModeManager.Mode.Normal
}
}
override fun setMode(mode: BrowsingModeManager.Mode) {
this@createBrowserModeStorage.setPrivateMode(mode == BrowsingModeManager.Mode.Private)
}
} }
class DefaultBrowsingModeManager( class DefaultBrowsingModeManager(
private val storage: BrowserModeStorage, private val settings: Settings,
private val modeDidChange: (BrowsingModeManager.Mode) -> Unit private val modeDidChange: (BrowsingMode) -> Unit
) : BrowsingModeManager { ) : BrowsingModeManager {
override val isPrivate: Boolean override var mode: BrowsingMode
get() = mode == BrowsingModeManager.Mode.Private get() = BrowsingMode.fromBoolean(settings.usePrivateMode)
override var mode: BrowsingModeManager.Mode
get() = storage.currentMode()
set(value) { set(value) {
storage.setMode(value) settings.setPrivateMode(value.isPrivate)
modeDidChange(mode) modeDidChange(value)
} }
} }
class CustomTabBrowsingModeManager : BrowsingModeManager { class CustomTabBrowsingModeManager : BrowsingModeManager {
override val isPrivate = false override var mode
override var mode: BrowsingModeManager.Mode get() = BrowsingMode.Normal
get() = BrowsingModeManager.Mode.Normal set(_) { /* no-op */ }
set(_) { return }
} }

View File

@ -76,7 +76,8 @@ open class HomeActivity : AppCompatActivity(), ShareFragment.TabsSharedCallback
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
components.publicSuffixList.prefetch() components.publicSuffixList.prefetch()
setupThemeAndBrowsingMode() browsingModeManager = createBrowsingModeManager()
themeManager = createThemeManager(browsingModeManager.mode)
setContentView(R.layout.activity_home) setContentView(R.layout.activity_home)
@ -101,18 +102,6 @@ open class HomeActivity : AppCompatActivity(), ShareFragment.TabsSharedCallback
handleOpenedFromExternalSourceIfNecessary(intent) handleOpenedFromExternalSourceIfNecessary(intent)
} }
private fun setupThemeAndBrowsingMode() {
browsingModeManager = createBrowsingModeManager()
themeManager = createThemeManager(
when (browsingModeManager.isPrivate) {
true -> ThemeManager.Theme.Private
false -> ThemeManager.Theme.Normal
}
)
setTheme(themeManager.currentTheme)
ThemeManager.applyStatusBarTheme(window, themeManager, this)
}
private fun setupToolbarAndNavigation() { private fun setupToolbarAndNavigation() {
// Add ids to this that we don't want to have a toolbar back button // Add ids to this that we don't want to have a toolbar back button
val appBarConfiguration = AppBarConfiguration.Builder().build() val appBarConfiguration = AppBarConfiguration.Builder().build()
@ -288,13 +277,12 @@ open class HomeActivity : AppCompatActivity(), ShareFragment.TabsSharedCallback
engine: SearchEngine?, engine: SearchEngine?,
forceSearch: Boolean forceSearch: Boolean
) { ) {
val isPrivate = this.browsingModeManager.isPrivate val mode = browsingModeManager.mode
val loadUrlUseCase = if (newTab) { val loadUrlUseCase = if (newTab) {
if (isPrivate) { when (mode) {
components.useCases.tabsUseCases.addPrivateTab BrowsingMode.Private -> components.useCases.tabsUseCases.addPrivateTab
} else { BrowsingMode.Normal -> components.useCases.tabsUseCases.addTab
components.useCases.tabsUseCases.addTab
} }
} else components.useCases.sessionUseCases.loadUrl } else components.useCases.sessionUseCases.loadUrl
@ -305,7 +293,7 @@ open class HomeActivity : AppCompatActivity(), ShareFragment.TabsSharedCallback
searchTerms, searchTerms,
Session.Source.USER_ENTERED, Session.Source.USER_ENTERED,
true, true,
isPrivate, mode.isPrivate,
searchEngine = engine searchEngine = engine
) )
} else components.useCases.searchUseCases.defaultSearch.invoke(searchTerms, engine) } else components.useCases.searchUseCases.defaultSearch.invoke(searchTerms, engine)
@ -331,10 +319,9 @@ open class HomeActivity : AppCompatActivity(), ShareFragment.TabsSharedCallback
} }
fun updateThemeForSession(session: Session) { fun updateThemeForSession(session: Session) {
if (session.private && !themeManager.currentTheme.isPrivate()) { val sessionMode = BrowsingMode.fromBoolean(session.private)
browsingModeManager.mode = BrowsingModeManager.Mode.Private if (sessionMode != browsingModeManager.mode) {
} else if (!session.private && themeManager.currentTheme.isPrivate()) { browsingModeManager.mode = sessionMode
browsingModeManager.mode = BrowsingModeManager.Mode.Normal
} }
} }
@ -342,26 +329,24 @@ open class HomeActivity : AppCompatActivity(), ShareFragment.TabsSharedCallback
return if (isCustomTab) { return if (isCustomTab) {
CustomTabBrowsingModeManager() CustomTabBrowsingModeManager()
} else { } else {
DefaultBrowsingModeManager(Settings.getInstance(this).createBrowserModeStorage()) { DefaultBrowsingModeManager(Settings.getInstance(this)) { mode ->
themeManager.setTheme( themeManager.currentTheme = mode
when (it.isPrivate()) {
true -> ThemeManager.Theme.Private
false -> ThemeManager.Theme.Normal
}
)
} }
} }
} }
private fun createThemeManager(currentTheme: ThemeManager.Theme): ThemeManager { private fun createThemeManager(currentTheme: BrowsingMode): ThemeManager {
return if (isCustomTab) { val themeManager = if (isCustomTab) {
CustomTabThemeManager() CustomTabThemeManager()
} else { } else {
DefaultThemeManager(currentTheme) { DefaultThemeManager(currentTheme) {
setTheme(it) themeManager.setActivityTheme(this)
recreate() recreate()
} }
} }
themeManager.setActivityTheme(this)
themeManager.applyStatusBarTheme(this)
return themeManager
} }
private fun subscribeToSessions(): SessionManager.Observer { private fun subscribeToSessions(): SessionManager.Observer {

View File

@ -13,17 +13,50 @@ import android.os.Build.VERSION.SDK_INT
import android.util.TypedValue import android.util.TypedValue
import android.view.View import android.view.View
import android.view.Window import android.view.Window
import androidx.core.content.ContextCompat import androidx.annotation.StyleRes
import org.mozilla.fenix.ext.getColorFromAttr
interface ThemeManager { abstract class ThemeManager {
enum class Theme {
Normal, Private;
fun isPrivate(): Boolean = this == Private abstract var currentTheme: BrowsingMode
/**
* Returns the style resource corresponding to the [currentTheme].
*/
@get:StyleRes
val currentThemeResource get() = when (currentTheme) {
BrowsingMode.Normal -> R.style.NormalTheme
BrowsingMode.Private -> R.style.PrivateTheme
} }
val currentTheme: Theme /**
fun setTheme(theme: Theme) * Handles status bar theme change since the window does not dynamically recreate
*/
fun applyStatusBarTheme(activity: Activity) = applyStatusBarTheme(activity.window, activity)
fun applyStatusBarTheme(window: Window, context: Context) {
when (currentTheme) {
BrowsingMode.Normal -> {
when (context.resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK) {
Configuration.UI_MODE_NIGHT_UNDEFINED, // We assume light here per Android doc's recommendation
Configuration.UI_MODE_NIGHT_NO -> {
updateLightSystemBars(window, context)
}
Configuration.UI_MODE_NIGHT_YES -> {
clearLightSystemBars(window)
updateNavigationBar(window, context)
}
}
}
BrowsingMode.Private -> {
clearLightSystemBars(window)
updateNavigationBar(window, context)
}
}
}
fun setActivityTheme(activity: Activity) {
activity.setTheme(currentThemeResource)
}
companion object { companion object {
fun resolveAttribute(attribute: Int, context: Context): Int { fun resolveAttribute(attribute: Int, context: Context): Int {
@ -34,53 +67,12 @@ interface ThemeManager {
return typedValue.resourceId return typedValue.resourceId
} }
// Handles status bar theme change since the window does not dynamically recreate private fun updateLightSystemBars(window: Window, context: Context) {
fun applyStatusBarTheme(
window: Window,
themeManager: ThemeManager,
context: Context
) {
when (themeManager.currentTheme) {
ThemeManager.Theme.Normal -> {
when (context.resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK) {
Configuration.UI_MODE_NIGHT_NO -> {
updateLightSystemBars(window, context)
}
Configuration.UI_MODE_NIGHT_YES -> {
window.decorView.systemUiVisibility =
window.decorView.systemUiVisibility and
View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR.inv() and
View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR.inv()
updateNavigationBar(window, context)
}
Configuration.UI_MODE_NIGHT_UNDEFINED -> {
// We assume light here per Android doc's recommendation
updateLightSystemBars(window, context)
}
}
}
ThemeManager.Theme.Private -> {
window.decorView.systemUiVisibility = window.decorView.systemUiVisibility and
View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR.inv() and
View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR.inv()
updateNavigationBar(window, context)
}
}
}
private fun updateLightSystemBars(
window: Window,
context: Context
) {
if (SDK_INT >= Build.VERSION_CODES.M) { if (SDK_INT >= Build.VERSION_CODES.M) {
window.statusBarColor = ContextCompat window.statusBarColor = context.getColorFromAttr(android.R.attr.statusBarColor)
.getColor(
context, resolveAttribute(android.R.attr.statusBarColor, context)
)
window.decorView.systemUiVisibility = window.decorView.systemUiVisibility =
window.decorView.systemUiVisibility or window.decorView.systemUiVisibility or View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR
} else { } else {
window.statusBarColor = Color.BLACK window.statusBarColor = Color.BLACK
} }
@ -88,54 +80,40 @@ interface ThemeManager {
if (SDK_INT >= Build.VERSION_CODES.O) { if (SDK_INT >= Build.VERSION_CODES.O) {
// API level can display handle light navigation bar color // API level can display handle light navigation bar color
window.decorView.systemUiVisibility = window.decorView.systemUiVisibility =
window.decorView.systemUiVisibility or window.decorView.systemUiVisibility or View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR
View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR
updateNavigationBar(window, context) updateNavigationBar(window, context)
} }
} }
private fun updateNavigationBar( private fun clearLightSystemBars(window: Window) {
window: Window, if (SDK_INT >= Build.VERSION_CODES.M) {
context: Context window.decorView.systemUiVisibility = window.decorView.systemUiVisibility and
) { View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR.inv() and
window.navigationBarColor = ContextCompat View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR.inv()
.getColor( }
context, resolveAttribute(R.attr.foundation, context) }
)
private fun updateNavigationBar(window: Window, context: Context) {
window.navigationBarColor = context.getColorFromAttr(R.attr.foundation)
} }
} }
} }
val ThemeManager.currentThemeResource: Int
get() = when (currentTheme) {
ThemeManager.Theme.Normal -> R.style.NormalTheme
ThemeManager.Theme.Private -> R.style.PrivateTheme
}
fun Activity.setTheme(theme: ThemeManager.Theme) {
val themeCode = when (theme) {
ThemeManager.Theme.Normal -> R.style.NormalTheme
ThemeManager.Theme.Private -> R.style.PrivateTheme
}
setTheme(themeCode)
}
class DefaultThemeManager( class DefaultThemeManager(
private var _currentTheme: ThemeManager.Theme, currentTheme: BrowsingMode,
private val onThemeChanged: (ThemeManager.Theme) -> Unit private val onThemeChanged: (BrowsingMode) -> Unit
) : ThemeManager { ) : ThemeManager() {
override val currentTheme: ThemeManager.Theme override var currentTheme: BrowsingMode = currentTheme
get() = _currentTheme set(value) {
if (currentTheme != value) {
override fun setTheme(theme: ThemeManager.Theme) { field = value
if (theme == _currentTheme) return onThemeChanged(value)
_currentTheme = theme }
onThemeChanged(theme) }
}
} }
class CustomTabThemeManager : ThemeManager { class CustomTabThemeManager : ThemeManager() {
override val currentTheme = ThemeManager.Theme.Normal override var currentTheme
override fun setTheme(theme: ThemeManager.Theme) { /* noop */ } get() = BrowsingMode.Normal
set(_) { /* noop */ }
} }

View File

@ -115,7 +115,7 @@ abstract class BaseBrowserFragment : Fragment(), BackHandler, SessionManager.Obs
val view = inflater.inflate(R.layout.fragment_browser, container, false) val view = inflater.inflate(R.layout.fragment_browser, container, false)
val activity = activity as HomeActivity val activity = activity as HomeActivity
ThemeManager.applyStatusBarTheme(activity.window, activity.themeManager, activity) activity.themeManager.applyStatusBarTheme(activity)
val appLink = requireComponents.useCases.appLinksUseCases.appLinkRedirect val appLink = requireComponents.useCases.appLinksUseCases.appLinkRedirect
browserStore = StoreProvider.get(this) { browserStore = StoreProvider.get(this) {
@ -151,6 +151,7 @@ abstract class BaseBrowserFragment : Fragment(), BackHandler, SessionManager.Obs
val browserToolbarController = DefaultBrowserToolbarController( val browserToolbarController = DefaultBrowserToolbarController(
context!!, context!!,
findNavController(), findNavController(),
(activity as HomeActivity).browsingModeManager,
findInPageLauncher = { findInPageIntegration.withFeature { it.launch() } }, findInPageLauncher = { findInPageIntegration.withFeature { it.launch() } },
nestedScrollQuickActionView = nestedScrollQuickAction, nestedScrollQuickActionView = nestedScrollQuickAction,
engineView = engineView, engineView = engineView,
@ -302,12 +303,8 @@ abstract class BaseBrowserFragment : Fragment(), BackHandler, SessionManager.Obs
} else { } else {
activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_USER activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_USER
activity?.exitImmersiveModeIfNeeded() activity?.exitImmersiveModeIfNeeded()
(activity as HomeActivity).let { activity: HomeActivity -> (activity as? HomeActivity)?.let { activity ->
ThemeManager.applyStatusBarTheme( activity.themeManager.applyStatusBarTheme(activity)
activity.window,
activity.themeManager,
activity
)
} }
toolbar.visibility = View.VISIBLE toolbar.visibility = View.VISIBLE
nestedScrollQuickAction.visibility = View.VISIBLE nestedScrollQuickAction.visibility = View.VISIBLE

View File

@ -18,7 +18,6 @@ import androidx.navigation.fragment.findNavController
import androidx.transition.TransitionInflater import androidx.transition.TransitionInflater
import com.google.android.material.snackbar.Snackbar import com.google.android.material.snackbar.Snackbar
import kotlinx.android.synthetic.main.component_search.* import kotlinx.android.synthetic.main.component_search.*
import kotlinx.android.synthetic.main.fragment_browser.*
import kotlinx.android.synthetic.main.fragment_browser.view.* import kotlinx.android.synthetic.main.fragment_browser.view.*
import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.Dispatchers.Main import kotlinx.coroutines.Dispatchers.Main
@ -148,7 +147,7 @@ class BrowserFragment : BaseBrowserFragment(), BackHandler {
view = view view = view
) )
if ((activity as HomeActivity).browsingModeManager.isPrivate) { if ((activity as HomeActivity).browsingModeManager.mode.isPrivate) {
// We need to update styles for private mode programmatically for now: // We need to update styles for private mode programmatically for now:
// https://github.com/mozilla-mobile/android-components/issues/3400 // https://github.com/mozilla-mobile/android-components/issues/3400
themeReaderViewControlsForPrivateMode(view.readerViewControlsBar) themeReaderViewControlsForPrivateMode(view.readerViewControlsBar)

View File

@ -14,8 +14,8 @@ import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.ObsoleteCoroutinesApi import kotlinx.coroutines.ObsoleteCoroutinesApi
import mozilla.components.browser.session.Session import mozilla.components.browser.session.Session
import mozilla.components.concept.engine.EngineView import mozilla.components.concept.engine.EngineView
import org.mozilla.fenix.BrowsingMode
import org.mozilla.fenix.BrowsingModeManager import org.mozilla.fenix.BrowsingModeManager
import org.mozilla.fenix.HomeActivity
import org.mozilla.fenix.R import org.mozilla.fenix.R
import org.mozilla.fenix.browser.BrowserFragment import org.mozilla.fenix.browser.BrowserFragment
import org.mozilla.fenix.browser.BrowserFragmentDirections import org.mozilla.fenix.browser.BrowserFragmentDirections
@ -38,6 +38,7 @@ interface BrowserToolbarController {
class DefaultBrowserToolbarController( class DefaultBrowserToolbarController(
private val context: Context, private val context: Context,
private val navController: NavController, private val navController: NavController,
private val browsingModeManager: BrowsingModeManager,
private val findInPageLauncher: () -> Unit, private val findInPageLauncher: () -> Unit,
private val nestedScrollQuickActionView: NestedScrollView, private val nestedScrollQuickActionView: NestedScrollView,
private val engineView: EngineView, private val engineView: EngineView,
@ -91,11 +92,15 @@ class DefaultBrowserToolbarController(
navController.nav(R.id.browserFragment, directions) navController.nav(R.id.browserFragment, directions)
} }
} }
ToolbarMenu.Item.NewPrivateTab -> { ToolbarMenu.Item.NewTab -> {
val directions = BrowserFragmentDirections val directions = BrowserFragmentDirections.actionBrowserFragmentToSearchFragment(null)
.actionBrowserFragmentToSearchFragment(null)
navController.nav(R.id.browserFragment, directions) navController.nav(R.id.browserFragment, directions)
(context as HomeActivity).browsingModeManager.mode = BrowsingModeManager.Mode.Private browsingModeManager.mode = BrowsingMode.Normal
}
ToolbarMenu.Item.NewPrivateTab -> {
val directions = BrowserFragmentDirections.actionBrowserFragmentToSearchFragment(null)
navController.nav(R.id.browserFragment, directions)
browsingModeManager.mode = BrowsingMode.Private
} }
ToolbarMenu.Item.FindInPage -> { ToolbarMenu.Item.FindInPage -> {
bottomSheetBehavior.state = BottomSheetBehavior.STATE_COLLAPSED bottomSheetBehavior.state = BottomSheetBehavior.STATE_COLLAPSED
@ -111,13 +116,6 @@ class DefaultBrowserToolbarController(
ToolbarMenu.Item.Help -> { ToolbarMenu.Item.Help -> {
context.components.useCases.tabsUseCases.addTab.invoke(getSupportUrl()) context.components.useCases.tabsUseCases.addTab.invoke(getSupportUrl())
} }
ToolbarMenu.Item.NewTab -> {
val directions = BrowserFragmentDirections
.actionBrowserFragmentToSearchFragment(null)
navController.nav(R.id.browserFragment, directions)
(context as HomeActivity).browsingModeManager.mode =
BrowsingModeManager.Mode.Normal
}
ToolbarMenu.Item.SaveToCollection -> { ToolbarMenu.Item.SaveToCollection -> {
context.components.analytics.metrics context.components.analytics.metrics
.track(Event.CollectionSaveButtonPressed(TELEMETRY_BROWSER_IDENTIFIER)) .track(Event.CollectionSaveButtonPressed(TELEMETRY_BROWSER_IDENTIFIER))

View File

@ -11,6 +11,7 @@ import mozilla.components.browser.menu.item.BrowserMenuHighlightableItem
import mozilla.components.browser.menu.item.BrowserMenuImageText import mozilla.components.browser.menu.item.BrowserMenuImageText
import mozilla.components.browser.menu.item.BrowserMenuItemToolbar import mozilla.components.browser.menu.item.BrowserMenuItemToolbar
import mozilla.components.browser.menu.item.BrowserMenuSwitch import mozilla.components.browser.menu.item.BrowserMenuSwitch
import org.mozilla.fenix.BrowsingMode
import org.mozilla.fenix.HomeActivity import org.mozilla.fenix.HomeActivity
import org.mozilla.fenix.R import org.mozilla.fenix.R
import org.mozilla.fenix.ThemeManager import org.mozilla.fenix.ThemeManager
@ -178,7 +179,7 @@ class DefaultToolbarMenu(
} }
) )
if ((context.asActivity() as? HomeActivity)?.browsingModeManager?.isPrivate == false) { if ((context.asActivity() as? HomeActivity)?.browsingModeManager?.mode == BrowsingMode.Normal) {
items.add( items.add(
BrowserMenuImageText( BrowserMenuImageText(
context.getString(R.string.browser_menu_save_to_collection), context.getString(R.string.browser_menu_save_to_collection),

View File

@ -51,11 +51,10 @@ import org.jetbrains.anko.constraint.layout.ConstraintSetBuilder.Side.START
import org.jetbrains.anko.constraint.layout.ConstraintSetBuilder.Side.TOP import org.jetbrains.anko.constraint.layout.ConstraintSetBuilder.Side.TOP
import org.jetbrains.anko.constraint.layout.applyConstraintSet import org.jetbrains.anko.constraint.layout.applyConstraintSet
import org.mozilla.fenix.BrowserDirection import org.mozilla.fenix.BrowserDirection
import org.mozilla.fenix.BrowsingModeManager import org.mozilla.fenix.BrowsingMode
import org.mozilla.fenix.FenixViewModelProvider import org.mozilla.fenix.FenixViewModelProvider
import org.mozilla.fenix.HomeActivity import org.mozilla.fenix.HomeActivity
import org.mozilla.fenix.R import org.mozilla.fenix.R
import org.mozilla.fenix.ThemeManager
import org.mozilla.fenix.collections.CreateCollectionViewModel import org.mozilla.fenix.collections.CreateCollectionViewModel
import org.mozilla.fenix.collections.SaveCollectionStep import org.mozilla.fenix.collections.SaveCollectionStep
import org.mozilla.fenix.components.FenixSnackbar import org.mozilla.fenix.components.FenixSnackbar
@ -88,8 +87,11 @@ import kotlin.math.roundToInt
@SuppressWarnings("TooManyFunctions", "LargeClass") @SuppressWarnings("TooManyFunctions", "LargeClass")
class HomeFragment : Fragment(), AccountObserver { class HomeFragment : Fragment(), AccountObserver {
private val bus = ActionBusFactory.get(this) private val bus = ActionBusFactory.get(this)
private val browsingModeManager get() = (activity as HomeActivity).browsingModeManager
private val singleSessionObserver = object : Session.Observer { private val singleSessionObserver = object : Session.Observer {
override fun onTitleChanged(session: Session, title: String) { override fun onTitleChanged(session: Session, title: String) {
if (deleteAllSessionsJob == null) emitSessionChanges() if (deleteAllSessionsJob == null) emitSessionChanges()
@ -195,7 +197,7 @@ class HomeFragment : Fragment(), AccountObserver {
ActionBusFactory.get(this).logMergedObservables() ActionBusFactory.get(this).logMergedObservables()
val activity = activity as HomeActivity val activity = activity as HomeActivity
ThemeManager.applyStatusBarTheme(activity.window, activity.themeManager, activity) activity.themeManager.applyStatusBarTheme(activity)
postponeEnterTransition() postponeEnterTransition()
sessionControlComponent.view.viewTreeObserver.addOnPreDrawListener(preDrawListener) sessionControlComponent.view.viewTreeObserver.addOnPreDrawListener(preDrawListener)
@ -251,30 +253,22 @@ class HomeFragment : Fragment(), AccountObserver {
requireComponents.analytics.metrics.track(Event.SearchBarTapped(Event.SearchBarTapped.Source.HOME)) requireComponents.analytics.metrics.track(Event.SearchBarTapped(Event.SearchBarTapped.Source.HOME))
} }
val isPrivate = (activity as HomeActivity).browsingModeManager.isPrivate val isPrivate = browsingModeManager.mode.isPrivate
privateBrowsingButton.contentDescription = privateBrowsingButton.contentDescription =
contentDescriptionForPrivateBrowsingButton(isPrivate) contentDescriptionForPrivateBrowsingButton(isPrivate)
privateBrowsingButton.setOnClickListener { privateBrowsingButton.setOnClickListener {
invokePendingDeleteJobs() invokePendingDeleteJobs()
val browsingModeManager = (activity as HomeActivity).browsingModeManager val invertedMode = BrowsingMode.fromBoolean(!browsingModeManager.mode.isPrivate)
val newMode = when (browsingModeManager.mode) {
BrowsingModeManager.Mode.Normal -> BrowsingModeManager.Mode.Private
BrowsingModeManager.Mode.Private -> BrowsingModeManager.Mode.Normal
}
if (onboarding.userHasBeenOnboarded()) { if (onboarding.userHasBeenOnboarded()) {
val mode =
if (newMode == BrowsingModeManager.Mode.Private) Mode.Private else Mode.Normal
getManagedEmitter<SessionControlChange>().onNext( getManagedEmitter<SessionControlChange>().onNext(
SessionControlChange.ModeChange( SessionControlChange.ModeChange(Mode.fromBrowsingMode(invertedMode))
mode
)
) )
} }
browsingModeManager.mode = newMode browsingModeManager.mode = invertedMode
} }
// We need the shadow to be above the components. // We need the shadow to be above the components.
@ -339,9 +333,7 @@ class HomeFragment : Fragment(), AccountObserver {
private fun handleTabAction(action: TabAction) { private fun handleTabAction(action: TabAction) {
Do exhaustive when (action) { Do exhaustive when (action) {
is TabAction.SaveTabGroup -> { is TabAction.SaveTabGroup -> {
if ((activity as HomeActivity).browsingModeManager.isPrivate) { if ((activity as HomeActivity).browsingModeManager.mode.isPrivate) return
return
}
invokePendingDeleteJobs() invokePendingDeleteJobs()
showCollectionCreationFragment(action.selectedTabSessionId) showCollectionCreationFragment(action.selectedTabSessionId)
} }
@ -671,9 +663,8 @@ class HomeFragment : Fragment(), AccountObserver {
} }
private fun getListOfSessions(): List<Session> { private fun getListOfSessions(): List<Session> {
val isPrivate = (activity as HomeActivity).browsingModeManager.isPrivate val isPrivate = browsingModeManager.mode.isPrivate
val notPendingDeletion: (Session) -> Boolean = val notPendingDeletion = { session: Session -> session.id != pendingSessionDeletion?.sessionId }
{ it.id != pendingSessionDeletion?.sessionId }
return sessionManager.filteredSessions(isPrivate, notPendingDeletion) return sessionManager.filteredSessions(isPrivate, notPendingDeletion)
} }
@ -730,10 +721,8 @@ class HomeFragment : Fragment(), AccountObserver {
Mode.Onboarding(OnboardingState.SignedOutCanAutoSignIn(availableAccounts[0])) Mode.Onboarding(OnboardingState.SignedOutCanAutoSignIn(availableAccounts[0]))
} }
} }
} else if ((activity as HomeActivity).browsingModeManager.isPrivate) {
Mode.Private
} else { } else {
Mode.Normal Mode.fromBrowsingMode(browsingModeManager.mode)
} }
private fun emitAccountChanges() { private fun emitAccountChanges() {

View File

@ -14,16 +14,17 @@ import io.reactivex.Observer
import kotlinx.android.parcel.Parcelize import kotlinx.android.parcel.Parcelize
import mozilla.components.browser.session.Session import mozilla.components.browser.session.Session
import mozilla.components.service.fxa.sharing.ShareableAccount import mozilla.components.service.fxa.sharing.ShareableAccount
import org.mozilla.fenix.BrowsingMode
import org.mozilla.fenix.ext.components import org.mozilla.fenix.ext.components
import org.mozilla.fenix.mvi.ViewState
import org.mozilla.fenix.mvi.Change
import mozilla.components.feature.tab.collections.TabCollection as ACTabCollection
import mozilla.components.feature.tab.collections.Tab as ComponentTab
import org.mozilla.fenix.mvi.Action import org.mozilla.fenix.mvi.Action
import org.mozilla.fenix.mvi.ActionBusFactory import org.mozilla.fenix.mvi.ActionBusFactory
import org.mozilla.fenix.mvi.Change
import org.mozilla.fenix.mvi.UIComponent import org.mozilla.fenix.mvi.UIComponent
import org.mozilla.fenix.mvi.UIComponentViewModelBase import org.mozilla.fenix.mvi.UIComponentViewModelBase
import org.mozilla.fenix.mvi.UIComponentViewModelProvider import org.mozilla.fenix.mvi.UIComponentViewModelProvider
import org.mozilla.fenix.mvi.ViewState
import mozilla.components.feature.tab.collections.Tab as ComponentTab
import mozilla.components.feature.tab.collections.TabCollection as ACTabCollection
class SessionControlComponent( class SessionControlComponent(
private val container: ViewGroup, private val container: ViewGroup,
@ -83,6 +84,13 @@ sealed class Mode {
object Normal : Mode() object Normal : Mode()
object Private : Mode() object Private : Mode()
data class Onboarding(val state: OnboardingState) : 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( data class SessionControlState(

View File

@ -6,7 +6,7 @@ package org.mozilla.fenix.library
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.findNavController
import org.mozilla.fenix.BrowsingModeManager import org.mozilla.fenix.BrowsingMode
import org.mozilla.fenix.HomeActivity import org.mozilla.fenix.HomeActivity
import org.mozilla.fenix.R import org.mozilla.fenix.R
import org.mozilla.fenix.ext.components import org.mozilla.fenix.ext.components
@ -29,11 +29,7 @@ abstract class LibraryPageFragment<T> : Fragment() {
} }
} }
(activity as HomeActivity).browsingModeManager.mode = if (private) { (activity as HomeActivity).browsingModeManager.mode = BrowsingMode.fromBoolean(private)
BrowsingModeManager.Mode.Private
} else {
BrowsingModeManager.Mode.Normal
}
(activity as HomeActivity).supportActionBar?.hide() (activity as HomeActivity).supportActionBar?.hide()
} }
} }

View File

@ -9,7 +9,7 @@ import androidx.navigation.NavController
import mozilla.components.concept.storage.BookmarkNode import mozilla.components.concept.storage.BookmarkNode
import mozilla.components.concept.storage.BookmarkNodeType import mozilla.components.concept.storage.BookmarkNodeType
import org.mozilla.fenix.BrowserDirection import org.mozilla.fenix.BrowserDirection
import org.mozilla.fenix.BrowsingModeManager import org.mozilla.fenix.BrowsingMode
import org.mozilla.fenix.HomeActivity import org.mozilla.fenix.HomeActivity
import org.mozilla.fenix.R import org.mozilla.fenix.R
import org.mozilla.fenix.components.FenixSnackbarPresenter import org.mozilla.fenix.components.FenixSnackbarPresenter
@ -125,8 +125,7 @@ class BookmarkFragmentInteractor(
override fun openInNewTab(item: BookmarkNode) { override fun openInNewTab(item: BookmarkNode) {
require(item.type == BookmarkNodeType.ITEM) require(item.type == BookmarkNodeType.ITEM)
item.url?.let { url -> item.url?.let { url ->
activity?.browsingModeManager?.mode = activity?.browsingModeManager?.mode = BrowsingMode.Normal
BrowsingModeManager.Mode.Normal
activity?.openToBrowserAndLoad( activity?.openToBrowserAndLoad(
searchTermOrURL = url, searchTermOrURL = url,
newTab = true, newTab = true,
@ -139,8 +138,7 @@ class BookmarkFragmentInteractor(
override fun openInPrivateTab(item: BookmarkNode) { override fun openInPrivateTab(item: BookmarkNode) {
require(item.type == BookmarkNodeType.ITEM) require(item.type == BookmarkNodeType.ITEM)
item.url?.let { url -> item.url?.let { url ->
activity?.browsingModeManager?.mode = activity?.browsingModeManager?.mode = BrowsingMode.Private
BrowsingModeManager.Mode.Private
activity?.openToBrowserAndLoad( activity?.openToBrowserAndLoad(
searchTermOrURL = url, searchTermOrURL = url,
newTab = true, newTab = true,

View File

@ -27,7 +27,7 @@ import kotlinx.coroutines.launch
import mozilla.components.lib.state.ext.consumeFrom import mozilla.components.lib.state.ext.consumeFrom
import mozilla.components.support.base.feature.BackHandler import mozilla.components.support.base.feature.BackHandler
import org.mozilla.fenix.BrowserDirection import org.mozilla.fenix.BrowserDirection
import org.mozilla.fenix.BrowsingModeManager import org.mozilla.fenix.BrowsingMode
import org.mozilla.fenix.HomeActivity import org.mozilla.fenix.HomeActivity
import org.mozilla.fenix.R import org.mozilla.fenix.R
import org.mozilla.fenix.components.Components import org.mozilla.fenix.components.Components
@ -194,7 +194,7 @@ class HistoryFragment : LibraryPageFragment<HistoryItem>(), BackHandler {
} }
(activity as HomeActivity).apply { (activity as HomeActivity).apply {
browsingModeManager.mode = BrowsingModeManager.Mode.Private browsingModeManager.mode = BrowsingMode.Private
supportActionBar?.hide() supportActionBar?.hide()
} }
nav( nav(

View File

@ -105,7 +105,7 @@ class SearchFragment : Fragment(), BackHandler {
view.toolbar_component_wrapper, view.toolbar_component_wrapper,
searchInteractor, searchInteractor,
historyStorageProvider(), historyStorageProvider(),
(activity as HomeActivity).browsingModeManager.isPrivate (activity as HomeActivity).browsingModeManager.mode.isPrivate
) )
startPostponedEnterTransition() startPostponedEnterTransition()

View File

@ -36,7 +36,6 @@ import org.mozilla.fenix.HomeActivity
import org.mozilla.fenix.IntentReceiverActivity import org.mozilla.fenix.IntentReceiverActivity
import org.mozilla.fenix.R import org.mozilla.fenix.R
import org.mozilla.fenix.browser.BrowserFragment import org.mozilla.fenix.browser.BrowserFragment
import org.mozilla.fenix.currentThemeResource
import org.mozilla.fenix.exceptions.ExceptionDomains import org.mozilla.fenix.exceptions.ExceptionDomains
import org.mozilla.fenix.ext.components import org.mozilla.fenix.ext.components
import org.mozilla.fenix.ext.requireComponents import org.mozilla.fenix.ext.requireComponents

View File

@ -22,6 +22,7 @@ import mozilla.components.feature.session.SessionUseCases
import mozilla.components.feature.tabs.TabsUseCases import mozilla.components.feature.tabs.TabsUseCases
import org.junit.Before import org.junit.Before
import org.junit.Test import org.junit.Test
import org.mozilla.fenix.BrowsingMode
import org.mozilla.fenix.BrowsingModeManager import org.mozilla.fenix.BrowsingModeManager
import org.mozilla.fenix.HomeActivity import org.mozilla.fenix.HomeActivity
import org.mozilla.fenix.R import org.mozilla.fenix.R
@ -33,7 +34,6 @@ import org.mozilla.fenix.components.Analytics
import org.mozilla.fenix.components.metrics.Event import org.mozilla.fenix.components.metrics.Event
import org.mozilla.fenix.components.metrics.MetricController import org.mozilla.fenix.components.metrics.MetricController
import org.mozilla.fenix.ext.components import org.mozilla.fenix.ext.components
import org.mozilla.fenix.ext.metrics
import org.mozilla.fenix.ext.nav import org.mozilla.fenix.ext.nav
import org.mozilla.fenix.home.sessioncontrol.Tab import org.mozilla.fenix.home.sessioncontrol.Tab
import org.mozilla.fenix.home.sessioncontrol.TabCollection import org.mozilla.fenix.home.sessioncontrol.TabCollection
@ -44,6 +44,7 @@ class DefaultBrowserToolbarControllerTest {
private var context: HomeActivity = mockk(relaxed = true) private var context: HomeActivity = mockk(relaxed = true)
private var analytics: Analytics = mockk(relaxed = true) private var analytics: Analytics = mockk(relaxed = true)
private val browsingModeManager: BrowsingModeManager = mockk(relaxed = true)
private var navController: NavController = mockk(relaxed = true) private var navController: NavController = mockk(relaxed = true)
private var findInPageLauncher: () -> Unit = mockk(relaxed = true) private var findInPageLauncher: () -> Unit = mockk(relaxed = true)
private val nestedScrollQuickActionView: NestedScrollView = mockk(relaxed = true) private val nestedScrollQuickActionView: NestedScrollView = mockk(relaxed = true)
@ -64,6 +65,7 @@ class DefaultBrowserToolbarControllerTest {
controller = DefaultBrowserToolbarController( controller = DefaultBrowserToolbarController(
context = context, context = context,
navController = navController, navController = navController,
browsingModeManager = browsingModeManager,
findInPageLauncher = findInPageLauncher, findInPageLauncher = findInPageLauncher,
nestedScrollQuickActionView = nestedScrollQuickActionView, nestedScrollQuickActionView = nestedScrollQuickActionView,
engineView = engineView, engineView = engineView,
@ -213,11 +215,9 @@ class DefaultBrowserToolbarControllerTest {
@Test @Test
fun handleToolbarNewPrivateTabPress() { fun handleToolbarNewPrivateTabPress() {
val browsingModeManager: BrowsingModeManager = mockk(relaxed = true)
val item = ToolbarMenu.Item.NewPrivateTab val item = ToolbarMenu.Item.NewPrivateTab
every { context.browsingModeManager } returns browsingModeManager every { browsingModeManager.mode } returns BrowsingMode.Normal
every { browsingModeManager.mode } returns BrowsingModeManager.Mode.Normal
controller.handleToolbarItemInteraction(item) controller.handleToolbarItemInteraction(item)
@ -227,7 +227,7 @@ class DefaultBrowserToolbarControllerTest {
.actionBrowserFragmentToSearchFragment(null) .actionBrowserFragmentToSearchFragment(null)
navController.nav(R.id.browserFragment, directions) navController.nav(R.id.browserFragment, directions)
} }
verify { browsingModeManager.mode = BrowsingModeManager.Mode.Private } verify { browsingModeManager.mode = BrowsingMode.Private }
} }
@Test @Test
@ -281,11 +281,9 @@ class DefaultBrowserToolbarControllerTest {
@Test @Test
fun handleToolbarNewTabPress() { fun handleToolbarNewTabPress() {
val browsingModeManager: BrowsingModeManager = mockk(relaxed = true)
val item = ToolbarMenu.Item.NewTab val item = ToolbarMenu.Item.NewTab
every { context.browsingModeManager } returns browsingModeManager every { browsingModeManager.mode } returns BrowsingMode.Private
every { browsingModeManager.mode } returns BrowsingModeManager.Mode.Private
controller.handleToolbarItemInteraction(item) controller.handleToolbarItemInteraction(item)
@ -295,7 +293,7 @@ class DefaultBrowserToolbarControllerTest {
.actionBrowserFragmentToSearchFragment(null) .actionBrowserFragmentToSearchFragment(null)
navController.nav(R.id.browserFragment, directions) navController.nav(R.id.browserFragment, directions)
} }
verify { browsingModeManager.mode = BrowsingModeManager.Mode.Normal } verify { browsingModeManager.mode = BrowsingMode.Normal }
} }
@Test @Test