Commit 8690c00d authored by MozLando's avatar MozLando
Browse files

Merge #5153

5153: Closes #5058: Migrate UserInteractionHandler from reference-browser to support-base r=jonalmeida a=gabrielluong

This fixes #5058. 

- Copies BackHandler to UserInteractionHandler, and add onHomePressed from [`UserInteractionHandler`](https://github.com/mozilla-mobile/reference-browser/blob/master/app/src/main/java/org/mozilla/reference/browser/UserInteractionHandler.kt

).
- Added Deprecated message for BackHandler
- Introduces a generic UserInteractionHandler to handle any user interactions such as the existing 'back' button pressed, and 'home' button pressed.
Co-authored-by: default avatarGabriel Luong <gabriel.luong@gmail.com>
parents 665e199b 04437de5
......@@ -23,7 +23,7 @@ import mozilla.components.browser.state.state.CustomTabActionButtonConfig
import mozilla.components.browser.state.state.CustomTabMenuItem
import mozilla.components.browser.toolbar.BrowserToolbar
import mozilla.components.concept.toolbar.Toolbar
import mozilla.components.support.base.feature.BackHandler
import mozilla.components.support.base.feature.UserInteractionHandler
import mozilla.components.support.base.feature.LifecycleAwareFeature
import mozilla.components.support.ktx.android.content.share
import mozilla.components.support.ktx.android.view.setNavigationBarTheme
......@@ -33,6 +33,7 @@ import mozilla.components.support.utils.ColorUtils.getReadableTextColor
/**
* Initializes and resets the Toolbar for a Custom Tab based on the CustomTabConfig.
*/
@Suppress("LargeClass")
class CustomTabsToolbarFeature(
private val sessionManager: SessionManager,
private val toolbar: BrowserToolbar,
......@@ -42,7 +43,7 @@ class CustomTabsToolbarFeature(
private val window: Window? = null,
private val shareListener: (() -> Unit)? = null,
private val closeListener: () -> Unit
) : LifecycleAwareFeature, BackHandler {
) : LifecycleAwareFeature, UserInteractionHandler {
private val context
get() = toolbar.context
internal var initialized = false
......
......@@ -11,7 +11,7 @@ import mozilla.components.concept.engine.EngineView
import mozilla.components.feature.findinpage.internal.FindInPageInteractor
import mozilla.components.feature.findinpage.internal.FindInPagePresenter
import mozilla.components.feature.findinpage.view.FindInPageView
import mozilla.components.support.base.feature.BackHandler
import mozilla.components.support.base.feature.UserInteractionHandler
import mozilla.components.support.base.feature.LifecycleAwareFeature
/**
......@@ -22,7 +22,7 @@ class FindInPageFeature(
view: FindInPageView,
engineView: EngineView,
private val onClose: (() -> Unit)? = null
) : LifecycleAwareFeature, BackHandler {
) : LifecycleAwareFeature, UserInteractionHandler {
@VisibleForTesting internal var presenter = FindInPagePresenter(store, view)
@VisibleForTesting internal var interactor = FindInPageInteractor(this, view, engineView)
......
......@@ -9,7 +9,7 @@ import android.content.Context
import androidx.annotation.MainThread
import androidx.annotation.VisibleForTesting
import androidx.fragment.app.FragmentManager
import mozilla.components.support.base.feature.BackHandler
import mozilla.components.support.base.feature.UserInteractionHandler
import mozilla.components.support.base.feature.LifecycleAwareFeature
import mozilla.components.support.base.feature.OnNeedToRequestPermissions
import mozilla.components.support.base.feature.PermissionsFeature
......@@ -35,7 +35,7 @@ class QrFeature(
private val fragmentManager: FragmentManager,
private val onScanResult: OnScanResult = { },
override val onNeedToRequestPermissions: OnNeedToRequestPermissions = { }
) : LifecycleAwareFeature, BackHandler, PermissionsFeature {
) : LifecycleAwareFeature, UserInteractionHandler, PermissionsFeature {
private var containerViewId: Int = 0
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
......
......@@ -18,7 +18,7 @@ import mozilla.components.feature.readerview.internal.ReaderViewControlsPresente
import mozilla.components.feature.readerview.view.ReaderViewControlsView
import mozilla.components.feature.readerview.ReaderViewFeature.ColorScheme.LIGHT
import mozilla.components.feature.readerview.ReaderViewFeature.FontType.SERIF
import mozilla.components.support.base.feature.BackHandler
import mozilla.components.support.base.feature.UserInteractionHandler
import mozilla.components.support.base.feature.LifecycleAwareFeature
import mozilla.components.support.webextensions.WebExtensionController
import org.json.JSONObject
......@@ -48,7 +48,7 @@ class ReaderViewFeature(
private val sessionManager: SessionManager,
controlsView: ReaderViewControlsView,
private val onReaderViewAvailableChange: OnReaderViewAvailableChange = { }
) : SelectionAwareSessionObserver(sessionManager), LifecycleAwareFeature, BackHandler {
) : SelectionAwareSessionObserver(sessionManager), LifecycleAwareFeature, UserInteractionHandler {
@VisibleForTesting
// This is an internal var to make it mutable for unit testing purposes only
......
......@@ -7,7 +7,7 @@ package mozilla.components.feature.session
import mozilla.components.browser.session.SelectionAwareSessionObserver
import mozilla.components.browser.session.Session
import mozilla.components.browser.session.SessionManager
import mozilla.components.support.base.feature.BackHandler
import mozilla.components.support.base.feature.UserInteractionHandler
import mozilla.components.support.base.feature.LifecycleAwareFeature
/**
......@@ -18,7 +18,7 @@ open class FullScreenFeature(
private val sessionUseCases: SessionUseCases,
private val sessionId: String? = null,
private val fullScreenChanged: (Boolean) -> Unit
) : SelectionAwareSessionObserver(sessionManager), LifecycleAwareFeature, BackHandler {
) : SelectionAwareSessionObserver(sessionManager), LifecycleAwareFeature, UserInteractionHandler {
/**
* Starts the feature and a observer to listen for fullscreen changes.
......
......@@ -6,7 +6,7 @@ package mozilla.components.feature.session
import mozilla.components.browser.session.SessionManager
import mozilla.components.concept.engine.EngineView
import mozilla.components.support.base.feature.BackHandler
import mozilla.components.support.base.feature.UserInteractionHandler
import mozilla.components.support.base.feature.LifecycleAwareFeature
/**
......@@ -17,7 +17,7 @@ class SessionFeature(
private val goBackUseCase: SessionUseCases.GoBackUseCase,
engineView: EngineView,
private val sessionId: String? = null
) : LifecycleAwareFeature, BackHandler {
) : LifecycleAwareFeature, UserInteractionHandler {
internal val presenter = EngineViewPresenter(sessionManager, engineView, sessionId)
/**
......
......@@ -9,7 +9,7 @@ import mozilla.components.browser.state.store.BrowserStore
import mozilla.components.concept.toolbar.Toolbar
import mozilla.components.feature.session.SessionUseCases
import mozilla.components.lib.publicsuffixlist.PublicSuffixList
import mozilla.components.support.base.feature.BackHandler
import mozilla.components.support.base.feature.UserInteractionHandler
import mozilla.components.support.base.feature.LifecycleAwareFeature
/**
......@@ -28,7 +28,7 @@ class ToolbarFeature(
searchUseCase: SearchUseCase? = null,
customTabId: String? = null,
urlRenderConfiguration: UrlRenderConfiguration? = null
) : LifecycleAwareFeature, BackHandler {
) : LifecycleAwareFeature, UserInteractionHandler {
private val presenter = ToolbarPresenter(toolbar, store, customTabId, urlRenderConfiguration)
private val interactor = ToolbarInteractor(toolbar, loadUrlUseCase, searchUseCase)
......
......@@ -7,11 +7,19 @@ package mozilla.components.support.base.feature
/**
* Generic interface for fragments, features and other components that want to handle 'back' button presses.
*/
@Deprecated("Use `UserInteractionHandler` instead.")
interface BackHandler {
/**
* Called when this [BackHandler] gets the option to handle the user pressing the back key.
* Called when this [UserInteractionHandler] gets the option to handle the user pressing the back key.
*
* Returns true if this [BackHandler] consumed the event and no other components need to be notified.
* Returns true if this [UserInteractionHandler] consumed the event and no other components need to be notified.
*/
@Deprecated(
"Use `UserInteractionHandler` instead.",
ReplaceWith(
"onBackPressed()",
"mozilla.components.support.base.feature.UserInteractionHandler"
)
)
fun onBackPressed(): Boolean
}
/* 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 mozilla.components.support.base.feature
import android.app.Activity
/**
* Generic interface for fragments, features and other components that want to handle user
* interactions such as 'back' or 'home' button presses.
*/
interface UserInteractionHandler {
/**
* Called when this [UserInteractionHandler] gets the option to handle the user pressing the back key.
*
* Returns true if this [UserInteractionHandler] consumed the event and no other components need to be notified.
*/
fun onBackPressed(): Boolean
/**
* In most cases, when the home button is pressed, we invoke this callback to inform the app that the user
* is going to leave the app.
*
* See also [Activity.onUserLeaveHint] for more details.
*/
fun onHomePressed(): Boolean = false
}
......@@ -138,14 +138,15 @@ class ViewBoundFeatureWrapper<T : LifecycleAwareFeature>() {
}
/**
* Convenient method for invoking [BackHandler.onBackPressed] on a wrapped [LifecycleAwareFeature] that implements
* [BackHandler]. Returns false if the [LifecycleAwareFeature] was cleared already.
* Convenient method for invoking [UserInteractionHandler.onBackPressed] on a wrapped
* [LifecycleAwareFeature] that implements [UserInteractionHandler]. Returns false if
* the [LifecycleAwareFeature] was cleared already.
*/
@Synchronized
fun onBackPressed(): Boolean {
val feature = feature ?: return false
if (feature !is BackHandler) {
if (feature !is UserInteractionHandler) {
throw IllegalAccessError("Feature does not implement BackHandler interface")
}
......
......@@ -36,7 +36,7 @@ class ViewBoundFeatureWrapperTest {
@Test
fun `onBackPressed is forwarded to feature`() {
val feature = MockFeatureWithBackHandler(onBackPressed = true)
val feature = MockFeatureWithUserInteractionHandler(onBackPressed = true)
val wrapper = ViewBoundFeatureWrapper(
feature = feature,
......@@ -48,7 +48,7 @@ class ViewBoundFeatureWrapperTest {
assertTrue(feature.onBackPressedInvoked)
assertFalse(ViewBoundFeatureWrapper(
feature = MockFeatureWithBackHandler(onBackPressed = false),
feature = MockFeatureWithUserInteractionHandler(onBackPressed = false),
owner = MockedLifecycleOwner(MockedLifecycle(Lifecycle.State.CREATED)),
view = mock()
).onBackPressed())
......@@ -379,9 +379,9 @@ private open class MockFeature : LifecycleAwareFeature {
}
}
private class MockFeatureWithBackHandler(
private class MockFeatureWithUserInteractionHandler(
private val onBackPressed: Boolean = false
) : MockFeature(), BackHandler {
) : MockFeature(), UserInteractionHandler {
var onBackPressedInvoked = false
private set
......
......@@ -55,6 +55,10 @@ permalink: /changelog/
`.set()` (rather than `.add()`). This has been corrected, but it may result
in changes in the sent data if using string list items longer than 20 bytes.
* **support-base**
* Deprecated `BackHandler` interface. Use the `UserInteractionHandler.onBackPressed` instead.
* Added generic `UserInteractionHandler` interface for fragments, features and other components that want to handle user interactions such as ‘back’ or 'home' button presses.
# 22.0.0
* [Commits](https://github.com/mozilla-mobile/android-components/compare/v22.0.0...master)
......
......@@ -26,7 +26,7 @@ import mozilla.components.feature.session.SessionFeature
import mozilla.components.feature.session.SwipeRefreshFeature
import mozilla.components.feature.sitepermissions.SitePermissionsFeature
import mozilla.components.feature.toolbar.ToolbarFeature
import mozilla.components.support.base.feature.BackHandler
import mozilla.components.support.base.feature.UserInteractionHandler
import mozilla.components.support.base.feature.LifecycleAwareFeature
import mozilla.components.support.base.feature.PermissionsFeature
import mozilla.components.support.base.feature.ViewBoundFeatureWrapper
......@@ -41,7 +41,7 @@ import org.mozilla.samples.browser.integration.FindInPageIntegration
* This class only contains shared code focused on the main browsing content.
* UI code specific to the app or to custom tabs can be found in the subclasses.
*/
abstract class BaseBrowserFragment : Fragment(), BackHandler {
abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler {
private val sessionFeature = ViewBoundFeatureWrapper<SessionFeature>()
private val toolbarFeature = ViewBoundFeatureWrapper<ToolbarFeature>()
private val downloadsFeature = ViewBoundFeatureWrapper<DownloadsFeature>()
......
......@@ -15,7 +15,7 @@ import mozilla.components.feature.intent.ext.getSessionId
import mozilla.components.browser.tabstray.BrowserTabsTray
import mozilla.components.concept.engine.EngineView
import mozilla.components.concept.tabstray.TabsTray
import mozilla.components.support.base.feature.BackHandler
import mozilla.components.support.base.feature.UserInteractionHandler
import mozilla.components.support.utils.SafeIntent
import org.mozilla.samples.browser.ext.components
......@@ -51,7 +51,7 @@ open class BrowserActivity : AppCompatActivity(), ComponentCallbacks2 {
override fun onBackPressed() {
supportFragmentManager.fragments.forEach {
if (it is BackHandler && it.onBackPressed()) {
if (it is UserInteractionHandler && it.onBackPressed()) {
return
}
}
......
......@@ -16,7 +16,7 @@ import mozilla.components.feature.tabs.WindowFeature
import mozilla.components.feature.tabs.toolbar.TabsToolbarFeature
import mozilla.components.feature.toolbar.ToolbarAutocompleteFeature
import mozilla.components.feature.toolbar.WebExtensionToolbarFeature
import mozilla.components.support.base.feature.BackHandler
import mozilla.components.support.base.feature.UserInteractionHandler
import mozilla.components.support.base.feature.ViewBoundFeatureWrapper
import org.mozilla.samples.browser.ext.components
import org.mozilla.samples.browser.integration.ReaderViewIntegration
......@@ -24,7 +24,7 @@ import org.mozilla.samples.browser.integration.ReaderViewIntegration
/**
* Fragment used for browsing the web within the main app.
*/
class BrowserFragment : BaseBrowserFragment(), BackHandler {
class BrowserFragment : BaseBrowserFragment(), UserInteractionHandler {
private val thumbnailsFeature = ViewBoundFeatureWrapper<ThumbnailsFeature>()
private val readerViewFeature = ViewBoundFeatureWrapper<ReaderViewIntegration>()
private val webExtToolbarFeature = ViewBoundFeatureWrapper<WebExtensionToolbarFeature>()
......
......@@ -23,7 +23,7 @@ import mozilla.components.feature.pwa.feature.WebAppActivityFeature
import mozilla.components.feature.pwa.feature.WebAppHideToolbarFeature
import mozilla.components.feature.pwa.feature.WebAppSiteControlsFeature
import mozilla.components.lib.state.ext.consumeFrom
import mozilla.components.support.base.feature.BackHandler
import mozilla.components.support.base.feature.UserInteractionHandler
import mozilla.components.support.base.feature.ViewBoundFeatureWrapper
import mozilla.components.support.ktx.android.arch.lifecycle.addObservers
import org.mozilla.samples.browser.ext.components
......@@ -31,7 +31,7 @@ import org.mozilla.samples.browser.ext.components
/**
* Fragment used for browsing within an external app, such as for custom tabs and PWAs.
*/
class ExternalAppBrowserFragment : BaseBrowserFragment(), BackHandler {
class ExternalAppBrowserFragment : BaseBrowserFragment(), UserInteractionHandler {
private val customTabsToolbarFeature = ViewBoundFeatureWrapper<CustomTabsToolbarFeature>()
private val hideToolbarFeature = ViewBoundFeatureWrapper<WebAppHideToolbarFeature>()
......@@ -123,7 +123,7 @@ class ExternalAppBrowserFragment : BaseBrowserFragment(), BackHandler {
/**
* Calls [onBackPressed] for features in the base class first,
* before trying to call the external app [BackHandler].
* before trying to call the external app [UserInteractionHandler].
*/
override fun onBackPressed(): Boolean =
super.onBackPressed() || customTabsToolbarFeature.onBackPressed()
......
......@@ -11,13 +11,13 @@ import android.view.ViewGroup
import androidx.fragment.app.Fragment
import kotlinx.android.synthetic.main.fragment_tabstray.*
import mozilla.components.feature.tabs.tabstray.TabsFeature
import mozilla.components.support.base.feature.BackHandler
import mozilla.components.support.base.feature.UserInteractionHandler
import org.mozilla.samples.browser.ext.components
/**
* A fragment for displaying the tabs tray.
*/
class TabsTrayFragment : Fragment(), BackHandler {
class TabsTrayFragment : Fragment(), UserInteractionHandler {
private var tabsFeature: TabsFeature? = null
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View =
......
......@@ -10,14 +10,15 @@ import mozilla.components.browser.state.store.BrowserStore
import mozilla.components.concept.engine.EngineView
import mozilla.components.feature.findinpage.FindInPageFeature
import mozilla.components.feature.findinpage.view.FindInPageView
import mozilla.components.support.base.feature.BackHandler
import mozilla.components.support.base.feature.UserInteractionHandler
import mozilla.components.support.base.feature.LifecycleAwareFeature
@Suppress("UndocumentedPublicClass")
class FindInPageIntegration(
private val store: BrowserStore,
private val view: FindInPageView,
engineView: EngineView
) : LifecycleAwareFeature, BackHandler {
) : LifecycleAwareFeature, UserInteractionHandler {
private val feature = FindInPageFeature(store, view, engineView, ::onClose)
override fun start() {
......
......@@ -12,10 +12,11 @@ import mozilla.components.browser.toolbar.BrowserToolbar
import mozilla.components.concept.engine.Engine
import mozilla.components.feature.readerview.ReaderViewFeature
import mozilla.components.feature.readerview.view.ReaderViewControlsView
import mozilla.components.support.base.feature.BackHandler
import mozilla.components.support.base.feature.UserInteractionHandler
import mozilla.components.support.base.feature.LifecycleAwareFeature
import org.mozilla.samples.browser.R
@Suppress("UndocumentedPublicClass")
class ReaderViewIntegration(
context: Context,
engine: Engine,
......@@ -23,7 +24,7 @@ class ReaderViewIntegration(
toolbar: BrowserToolbar,
view: ReaderViewControlsView,
readerViewAppearanceButton: FloatingActionButton
) : LifecycleAwareFeature, BackHandler {
) : LifecycleAwareFeature, UserInteractionHandler {
private var readerViewButtonVisible = false
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment