Fixes #290: Integrate new Fenix architecture
parent
8af55652be
commit
273f33b244
@ -0,0 +1,24 @@
|
|||||||
|
/* 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
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import mozilla.components.service.fretboard.ExperimentDescriptor
|
||||||
|
|
||||||
|
const val EXPERIMENTS_JSON_FILENAME = "experiments.json"
|
||||||
|
const val EXPERIMENTS_BASE_URL = "https://settings.prod.mozaws.net/v1"
|
||||||
|
const val EXPERIMENTS_BUCKET_NAME = "main"
|
||||||
|
// TODO Change this after fenix-experiments is created
|
||||||
|
const val EXPERIMENTS_COLLECTION_NAME = "focus-experiments"
|
||||||
|
|
||||||
|
object Experiments {
|
||||||
|
val AATestDescriptor = ExperimentDescriptor("AAtest")
|
||||||
|
}
|
||||||
|
|
||||||
|
val Context.app: FenixApplication
|
||||||
|
get() = applicationContext as FenixApplication
|
||||||
|
|
||||||
|
fun Context.isInExperiment(descriptor: ExperimentDescriptor): Boolean =
|
||||||
|
app.fretboard.isInExperiment(this, descriptor)
|
@ -0,0 +1,67 @@
|
|||||||
|
/* 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.search
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import kotlinx.android.synthetic.main.fragment_browser.*
|
||||||
|
import mozilla.components.browser.toolbar.BrowserToolbar
|
||||||
|
import mozilla.components.support.base.log.logger.Logger
|
||||||
|
import org.mozilla.fenix.mvi.Action
|
||||||
|
import org.mozilla.fenix.mvi.ActionBusFactory
|
||||||
|
import org.mozilla.fenix.mvi.Change
|
||||||
|
import org.mozilla.fenix.mvi.Reducer
|
||||||
|
import org.mozilla.fenix.mvi.UIComponent
|
||||||
|
import org.mozilla.fenix.mvi.ViewState
|
||||||
|
|
||||||
|
class SearchComponent(
|
||||||
|
private val container: ViewGroup,
|
||||||
|
override val bus: ActionBusFactory,
|
||||||
|
private val onEditComplete: (View) -> Unit,
|
||||||
|
override var initialState: SearchState = SearchState("")
|
||||||
|
) :
|
||||||
|
UIComponent<SearchState, SearchAction, SearchChange>(bus) {
|
||||||
|
|
||||||
|
override val reducer: Reducer<SearchState, SearchChange> = { state, change ->
|
||||||
|
when (change) {
|
||||||
|
is SearchChange.Changed -> state // TODO handle state changes here
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun initView() = SearchUIView(container, bus)
|
||||||
|
init {
|
||||||
|
setup()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getView(): BrowserToolbar = uiView.toolbar
|
||||||
|
fun editMode() = getView().editMode()
|
||||||
|
|
||||||
|
@SuppressLint("CheckResult")
|
||||||
|
fun setup(): SearchComponent {
|
||||||
|
render(reducer)
|
||||||
|
getUserInteractionEvents<SearchAction>()
|
||||||
|
.subscribe {
|
||||||
|
Logger("SearchComponent").debug(it.toString())
|
||||||
|
when (it) {
|
||||||
|
is SearchAction.EditComplete -> {
|
||||||
|
onEditComplete.invoke(getView())
|
||||||
|
}
|
||||||
|
else -> {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data class SearchState(val term: String) : ViewState
|
||||||
|
sealed class SearchAction : Action {
|
||||||
|
object UrlClicked : SearchAction()
|
||||||
|
object EditComplete : SearchAction()
|
||||||
|
}
|
||||||
|
|
||||||
|
sealed class SearchChange : Change {
|
||||||
|
object Changed : SearchChange()
|
||||||
|
}
|
@ -0,0 +1,79 @@
|
|||||||
|
/* 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.search
|
||||||
|
|
||||||
|
import androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
import androidx.constraintlayout.widget.ConstraintLayout.LayoutParams.PARENT_ID
|
||||||
|
import androidx.constraintlayout.widget.ConstraintLayout.LayoutParams.UNSET
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
|
import kotlinx.android.synthetic.main.fragment_search.*
|
||||||
|
import mozilla.components.support.base.log.logger.Logger
|
||||||
|
import org.jetbrains.anko.constraint.layout.ConstraintSetBuilder.Side.BOTTOM
|
||||||
|
import org.jetbrains.anko.constraint.layout.ConstraintSetBuilder.Side.TOP
|
||||||
|
import org.jetbrains.anko.constraint.layout.applyConstraintSet
|
||||||
|
import org.mozilla.fenix.Experiments.AATestDescriptor
|
||||||
|
import org.mozilla.fenix.isInExperiment
|
||||||
|
|
||||||
|
internal fun SearchFragment.layoutComponents(layout: ConstraintLayout) {
|
||||||
|
context?.let {
|
||||||
|
when {
|
||||||
|
it.isInExperiment(AATestDescriptor) -> {
|
||||||
|
setInExperimentConstraints(layout)
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
setOutOfExperimentConstraints(layout)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // we're unattached if context is null
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun SearchFragment.setInExperimentConstraints(layout: ConstraintLayout) {
|
||||||
|
Logger.debug("Loading in experiment constraints")
|
||||||
|
layout.applyConstraintSet {
|
||||||
|
toolbar_wrapper {
|
||||||
|
connect(
|
||||||
|
TOP to TOP of UNSET,
|
||||||
|
BOTTOM to TOP of pill_wrapper
|
||||||
|
)
|
||||||
|
}
|
||||||
|
awesomeBar {
|
||||||
|
connect(
|
||||||
|
TOP to TOP of PARENT_ID,
|
||||||
|
BOTTOM to TOP of toolbar_wrapper
|
||||||
|
)
|
||||||
|
}
|
||||||
|
(awesomeBar.layoutManager as? LinearLayoutManager)?.reverseLayout = true
|
||||||
|
pill_wrapper {
|
||||||
|
connect(
|
||||||
|
BOTTOM to BOTTOM of PARENT_ID
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun SearchFragment.setOutOfExperimentConstraints(layout: ConstraintLayout) {
|
||||||
|
Logger.debug("Loading out of experiment constraints")
|
||||||
|
layout.applyConstraintSet {
|
||||||
|
toolbar_wrapper {
|
||||||
|
connect(
|
||||||
|
TOP to TOP of PARENT_ID,
|
||||||
|
BOTTOM to TOP of UNSET
|
||||||
|
)
|
||||||
|
}
|
||||||
|
awesomeBar {
|
||||||
|
connect(
|
||||||
|
TOP to TOP of UNSET,
|
||||||
|
TOP to BOTTOM of toolbar_wrapper,
|
||||||
|
BOTTOM to TOP of pill_wrapper
|
||||||
|
)
|
||||||
|
}
|
||||||
|
(awesomeBar.layoutManager as? LinearLayoutManager)?.reverseLayout = false
|
||||||
|
pill_wrapper {
|
||||||
|
connect(
|
||||||
|
BOTTOM to BOTTOM of PARENT_ID
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,72 @@
|
|||||||
|
/* 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.search
|
||||||
|
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
|
import io.reactivex.functions.Consumer
|
||||||
|
import kotlinx.android.synthetic.main.fragment_search.view.*
|
||||||
|
import mozilla.components.browser.toolbar.BrowserToolbar
|
||||||
|
import mozilla.components.feature.awesomebar.AwesomeBarFeature
|
||||||
|
import mozilla.components.feature.awesomebar.provider.SearchSuggestionProvider
|
||||||
|
import mozilla.components.support.ktx.android.content.res.pxToDp
|
||||||
|
import org.mozilla.fenix.R
|
||||||
|
import org.mozilla.fenix.ext.components
|
||||||
|
import org.mozilla.fenix.mvi.ActionBusFactory
|
||||||
|
import org.mozilla.fenix.mvi.UIView
|
||||||
|
|
||||||
|
class SearchUIView(container: ViewGroup, bus: ActionBusFactory) :
|
||||||
|
UIView<SearchState>(container, bus) {
|
||||||
|
|
||||||
|
override val view: BrowserToolbar = LayoutInflater.from(container.context)
|
||||||
|
.inflate(R.layout.component_search, container, true)
|
||||||
|
.findViewById(R.id.toolbar)
|
||||||
|
|
||||||
|
private val urlBackground = LayoutInflater.from(container.context)
|
||||||
|
.inflate(R.layout.layout_url_backround, container, false)
|
||||||
|
|
||||||
|
init {
|
||||||
|
view.apply {
|
||||||
|
onUrlClicked = {
|
||||||
|
bus.emit(SearchAction::class.java, SearchAction.UrlClicked)
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
browserActionMargin = resources.pxToDp(browserActionMarginDp)
|
||||||
|
urlBoxView = urlBackground
|
||||||
|
urlBoxMargin = this.resources.pxToDp(urlBoxMarginDp)
|
||||||
|
|
||||||
|
textColor = ContextCompat.getColor(context, R.color.searchText)
|
||||||
|
textSize = toolbarTextSizeSp
|
||||||
|
hint = context.getString(R.string.search_hint)
|
||||||
|
hintColor = ContextCompat.getColor(context, R.color.searchText)
|
||||||
|
}
|
||||||
|
|
||||||
|
with(container.context) {
|
||||||
|
AwesomeBarFeature(container.rootView.awesomeBar, view, null,
|
||||||
|
onEditComplete = { bus.emit(SearchAction::class.java, SearchAction.EditComplete) })
|
||||||
|
.addClipboardProvider(this, components.useCases.sessionUseCases.loadUrl)
|
||||||
|
.addSearchProvider(
|
||||||
|
components.search.searchEngineManager.getDefaultSearchEngine(this),
|
||||||
|
components.useCases.searchUseCases.defaultSearch,
|
||||||
|
SearchSuggestionProvider.Mode.MULTIPLE_SUGGESTIONS
|
||||||
|
)
|
||||||
|
.addSessionProvider(
|
||||||
|
components.core.sessionManager,
|
||||||
|
components.useCases.tabsUseCases.selectTab
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun updateView() = Consumer<SearchState> {
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val toolbarTextSizeSp = 14f
|
||||||
|
const val browserActionMarginDp = 8
|
||||||
|
const val urlBoxMarginDp = 8
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<mozilla.components.browser.toolbar.BrowserToolbar
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:id="@+id/toolbar"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="40dp"
|
||||||
|
android:layout_margin="8dp"
|
||||||
|
android:clickable="true"
|
||||||
|
android:focusable="true"
|
||||||
|
android:focusableInTouchMode="true"/>
|
Loading…
Reference in New Issue