Commit 68f8fbdf authored by MozLando's avatar MozLando
Browse files

Merge #4524

4524: Closes #4486: Migrate feature-findinpage to browser-state r=pocmo a=csadilek

The changes need for R-B are in this PR: https://github.com/mozilla-mobile/reference-browser/pull/910



Will open a PR for Fenix, once it's back on 15.0.0-SNAPSHOTs and this lands.

Co-authored-by: default avatarChristian Sadilek <christian.sadilek@gmail.com>
parents c47acdf3 db17a20e
Loading
Loading
Loading
Loading
+8 −1
Original line number Diff line number Diff line
@@ -21,8 +21,14 @@ android {
    }
}

tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all {
    kotlinOptions.freeCompilerArgs += [
            "-Xuse-experimental=kotlinx.coroutines.ExperimentalCoroutinesApi"
    ]
}

dependencies {
    implementation project(':browser-session')
    implementation project(':browser-state')
    implementation project(':concept-engine')
    implementation project(':support-ktx')
    implementation project(':ui-icons')
@@ -32,6 +38,7 @@ dependencies {

    testImplementation Dependencies.androidx_test_core
    testImplementation Dependencies.androidx_test_junit
    testImplementation Dependencies.testing_coroutines
    testImplementation Dependencies.testing_robolectric
    testImplementation Dependencies.testing_mockito
    testImplementation project(':support-test')
+12 −12
Original line number Diff line number Diff line
@@ -5,8 +5,8 @@
package mozilla.components.feature.findinpage

import androidx.annotation.VisibleForTesting
import mozilla.components.browser.session.Session
import mozilla.components.browser.session.SessionManager
import mozilla.components.browser.state.state.SessionState
import mozilla.components.browser.state.store.BrowserStore
import mozilla.components.concept.engine.EngineView
import mozilla.components.feature.findinpage.internal.FindInPageInteractor
import mozilla.components.feature.findinpage.internal.FindInPagePresenter
@@ -15,18 +15,18 @@ import mozilla.components.support.base.feature.BackHandler
import mozilla.components.support.base.feature.LifecycleAwareFeature

/**
 * Feature implementation that will keep a [FindInPageView] in sync with a bound [Session].
 * Feature implementation that will keep a [FindInPageView] in sync with a bound [SessionState].
 */
class FindInPageFeature(
    sessionManager: SessionManager,
    store: BrowserStore,
    view: FindInPageView,
    engineView: EngineView,
    private val onClose: (() -> Unit)? = null
) : LifecycleAwareFeature, BackHandler {
    @VisibleForTesting internal var presenter = FindInPagePresenter(view)
    @VisibleForTesting internal var interactor = FindInPageInteractor(this, sessionManager, view, engineView)
    @VisibleForTesting internal var presenter = FindInPagePresenter(store, view)
    @VisibleForTesting internal var interactor = FindInPageInteractor(this, view, engineView)

    private var session: Session? = null
    private var session: SessionState? = null

    override fun start() {
        presenter.start()
@@ -39,10 +39,10 @@ class FindInPageFeature(
    }

    /**
     * Binds this feature to the given [Session]. Until unbound the [FindInPageView] will be updated presenting the
     * current "Find in Page" state.
     * Binds this feature to the given [SessionState]. Until unbound the [FindInPageView] will be
     * updated presenting the current "Find in Page" state.
     */
    fun bind(session: Session) {
    fun bind(session: SessionState) {
        this.session = session

        presenter.bind(session)
@@ -62,8 +62,8 @@ class FindInPageFeature(
    }

    /**
     * Unbinds the feature from a previously bound [Session]. The [FindInPageView] will be cleared and not be updated
     * to present the "Find in Page" state anymore.
     * Unbinds the feature from a previously bound [SessionState]. The [FindInPageView] will be
     * cleared and not be updated to present the "Find in Page" state anymore.
     */
    fun unbind() {
        session = null
+3 −5
Original line number Diff line number Diff line
@@ -4,8 +4,7 @@

package mozilla.components.feature.findinpage.internal

import mozilla.components.browser.session.Session
import mozilla.components.browser.session.SessionManager
import mozilla.components.browser.state.state.SessionState
import mozilla.components.concept.engine.EngineSession
import mozilla.components.concept.engine.EngineView
import mozilla.components.feature.findinpage.FindInPageFeature
@@ -22,7 +21,6 @@ import mozilla.components.support.ktx.android.view.hideKeyboard
 */
internal class FindInPageInteractor(
    private val feature: FindInPageFeature,
    private val sessionManager: SessionManager,
    private val view: FindInPageView,
    private val engineView: EngineView?
) : FindInPageView.Listener {
@@ -36,8 +34,8 @@ internal class FindInPageInteractor(
        view.listener = null
    }

    fun bind(session: Session) {
        engineSession = sessionManager.getEngineSession(session)
    fun bind(session: SessionState) {
        engineSession = session.engineState.engineSession
    }

    override fun onPreviousResult() {
+30 −25
Original line number Diff line number Diff line
@@ -4,49 +4,54 @@

package mozilla.components.feature.findinpage.internal

import mozilla.components.browser.session.Session
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.cancel
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.mapNotNull
import mozilla.components.browser.state.selector.findTabOrCustomTab
import mozilla.components.browser.state.state.SessionState
import mozilla.components.browser.state.store.BrowserStore
import mozilla.components.feature.findinpage.view.FindInPageView
import mozilla.components.lib.state.ext.flowScoped
import mozilla.components.support.ktx.kotlinx.coroutines.flow.ifChanged

/**
 * Presenter implementation that will subscribe to a [Session] and update the view whenever the [Session.FindResult]
 * changes.
 * Presenter that will observe [SessionState] changes and update the view whenever
 * a find result was added.
 */
internal class FindInPagePresenter(
    private val store: BrowserStore,
    private val view: FindInPageView
) : Session.Observer {
    private var started: Boolean = false
    private var session: Session? = null
) {
    @Volatile
    internal var session: SessionState? = null

    private var scope: CoroutineScope? = null

    fun start() {
        session?.register(this, view = view.asView())
        started = true
        scope = store.flowScoped { flow ->
            flow.mapNotNull { state -> session?.let { state.findTabOrCustomTab(it.id) } }
                .ifChanged { it.content.findResults }
                .collect {
                    val results = it.content.findResults
                    if (results.isNotEmpty()) {
                        view.displayResult(results.last())
                    }
                }
        }
    }

    fun stop() {
        session?.unregister(this)
        started = false
        scope?.cancel()
    }

    fun bind(session: Session) {
        this.session?.unregister(this)
    fun bind(session: SessionState) {
        this.session = session

        if (started) {
            // Only register now if we are started already. Otherwise let start() handle that.
            session.register(this, view = view.asView())
        }

        view.focus()
    }

    override fun onFindResult(session: Session, result: Session.FindResult) {
        view.displayResult(result)
    }

    fun unbind() {
        view.clear()

        session?.unregister(this)
        session = null
        this.session = null
    }
}
+2 −2
Original line number Diff line number Diff line
@@ -15,7 +15,7 @@ import android.widget.TextView
import androidx.annotation.VisibleForTesting
import androidx.appcompat.widget.AppCompatImageButton
import androidx.constraintlayout.widget.ConstraintLayout
import mozilla.components.browser.session.Session
import mozilla.components.browser.state.state.content.FindResultState
import mozilla.components.feature.findinpage.R
import mozilla.components.support.ktx.android.view.hideKeyboard
import mozilla.components.support.ktx.android.view.showKeyboard
@@ -82,7 +82,7 @@ class FindInPageBar @JvmOverloads constructor(
        resultsCountTextView.contentDescription = null
    }

    override fun displayResult(result: Session.FindResult) {
    override fun displayResult(result: FindResultState) {
        with(result) {
            val ordinal = if (numberOfMatches > 0) activeMatchOrdinal + 1 else activeMatchOrdinal
            resultsCountTextView.text = String.format(resultFormat, ordinal, numberOfMatches)
Loading