Fixes #290: Integrate new Fenix architecture
parent
8af55652be
commit
273f33b244
|
@ -104,6 +104,7 @@ dependencies {
|
|||
implementation Deps.mozilla_concept_toolbar
|
||||
|
||||
implementation Deps.mozilla_browser_awesomebar
|
||||
implementation Deps.mozilla_feature_downloads
|
||||
implementation Deps.mozilla_browser_domains
|
||||
implementation Deps.mozilla_browser_engine_gecko_nightly
|
||||
implementation Deps.mozilla_browser_session
|
||||
|
@ -116,6 +117,7 @@ dependencies {
|
|||
implementation Deps.mozilla_feature_session
|
||||
implementation Deps.mozilla_feature_toolbar
|
||||
implementation Deps.mozilla_feature_tabs
|
||||
implementation Deps.mozilla_service_fretboard
|
||||
|
||||
implementation Deps.mozilla_support_ktx
|
||||
|
||||
|
|
|
@ -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)
|
|
@ -5,15 +5,50 @@
|
|||
package org.mozilla.fenix
|
||||
|
||||
import android.app.Application
|
||||
import android.content.Context
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.launch
|
||||
import mozilla.components.service.fretboard.Fretboard
|
||||
import mozilla.components.service.fretboard.ValuesProvider
|
||||
import mozilla.components.service.fretboard.source.kinto.KintoExperimentSource
|
||||
import mozilla.components.service.fretboard.storage.flatfile.FlatFileExperimentStorage
|
||||
import mozilla.components.support.base.log.Log
|
||||
import mozilla.components.support.base.log.logger.Logger
|
||||
import mozilla.components.support.base.log.sink.AndroidLogSink
|
||||
import org.mozilla.fenix.components.Components
|
||||
import java.io.File
|
||||
|
||||
class FenixApplication : Application() {
|
||||
lateinit var fretboard: Fretboard
|
||||
|
||||
val components by lazy { Components(this) }
|
||||
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
Log.addSink(AndroidLogSink())
|
||||
|
||||
setupCrashReporting()
|
||||
loadExperiments()
|
||||
}
|
||||
|
||||
private fun loadExperiments() {
|
||||
val experimentsFile = File(filesDir, EXPERIMENTS_JSON_FILENAME)
|
||||
val experimentSource = KintoExperimentSource(
|
||||
EXPERIMENTS_BASE_URL, EXPERIMENTS_BUCKET_NAME, EXPERIMENTS_COLLECTION_NAME
|
||||
)
|
||||
fretboard = Fretboard(experimentSource, FlatFileExperimentStorage(experimentsFile),
|
||||
object : ValuesProvider() {
|
||||
override fun getClientId(context: Context): String {
|
||||
return "10" // hardcode clientId to determine in or out of experiment
|
||||
}
|
||||
})
|
||||
fretboard.loadExperiments()
|
||||
Logger.debug("Bucket is ${fretboard.getUserBucket(this@FenixApplication)}")
|
||||
Logger.debug("Experiments active: ${fretboard.getExperimentsMap(this@FenixApplication)}")
|
||||
GlobalScope.launch(Dispatchers.IO) {
|
||||
fretboard.updateExperiments()
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupCrashReporting() {
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
/* 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.app.Activity
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
/* 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.browser
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
import android.transition.TransitionInflater
|
||||
|
@ -10,6 +12,7 @@ import android.view.LayoutInflater
|
|||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.accessibility.AccessibilityManager
|
||||
import androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||
import androidx.fragment.app.Fragment
|
||||
import kotlinx.android.synthetic.main.fragment_browser.*
|
||||
import mozilla.components.feature.downloads.DownloadsFeature
|
||||
|
@ -19,7 +22,6 @@ import mozilla.components.support.ktx.android.arch.lifecycle.addObservers
|
|||
import org.mozilla.fenix.R
|
||||
import org.mozilla.fenix.components.toolbar.ToolbarIntegration
|
||||
import org.mozilla.fenix.ext.requireComponents
|
||||
import androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||
|
||||
class BrowserFragment : Fragment() {
|
||||
|
||||
|
@ -40,6 +42,7 @@ class BrowserFragment : Fragment() {
|
|||
sharedElementEnterTransition = TransitionInflater.from(context).inflateTransition(android.R.transition.move)
|
||||
}
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
|
@ -60,17 +63,6 @@ class BrowserFragment : Fragment() {
|
|||
engineView
|
||||
)
|
||||
|
||||
lifecycle.addObserver(
|
||||
ToolbarIntegration(
|
||||
requireContext(),
|
||||
toolbar,
|
||||
requireComponents.toolbar.shippedDomainsProvider,
|
||||
requireComponents.core.historyStorage
|
||||
)
|
||||
)
|
||||
|
||||
lifecycle.addObservers(sessionFeature)
|
||||
|
||||
// Stop toolbar from collapsing if TalkBack is enabled
|
||||
val accessibilityManager = context?.getSystemService(Context.ACCESSIBILITY_SERVICE) as AccessibilityManager
|
||||
if (accessibilityManager.isEnabled) {
|
||||
|
@ -80,7 +72,11 @@ class BrowserFragment : Fragment() {
|
|||
|
||||
lifecycle.addObservers(
|
||||
downloadsFeature,
|
||||
sessionFeature
|
||||
sessionFeature,
|
||||
ToolbarIntegration(requireContext(),
|
||||
toolbar,
|
||||
requireComponents.toolbar.shippedDomainsProvider,
|
||||
requireComponents.core.historyStorage)
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
/* 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.components
|
||||
|
||||
import android.content.Context
|
||||
|
|
|
@ -5,20 +5,15 @@
|
|||
package org.mozilla.fenix.components.toolbar
|
||||
|
||||
import android.content.Context
|
||||
import android.view.LayoutInflater
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.view.ViewCompat
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import androidx.lifecycle.LifecycleObserver
|
||||
import androidx.lifecycle.OnLifecycleEvent
|
||||
import androidx.navigation.Navigation
|
||||
import androidx.navigation.fragment.FragmentNavigator
|
||||
import mozilla.components.browser.domains.autocomplete.DomainAutocompleteProvider
|
||||
import mozilla.components.browser.toolbar.BrowserToolbar
|
||||
import mozilla.components.concept.storage.HistoryStorage
|
||||
import mozilla.components.feature.toolbar.ToolbarAutocompleteFeature
|
||||
import mozilla.components.feature.toolbar.ToolbarFeature
|
||||
import mozilla.components.support.ktx.android.content.res.pxToDp
|
||||
import org.mozilla.fenix.R
|
||||
import org.mozilla.fenix.ext.application
|
||||
import org.mozilla.fenix.ext.components
|
||||
|
@ -33,11 +28,6 @@ class ToolbarIntegration(
|
|||
init {
|
||||
toolbar.setMenuBuilder(context.components.toolbar.menuBuilder)
|
||||
|
||||
toolbar.browserActionMargin = toolbar.resources.pxToDp(browserActionMarginDp)
|
||||
toolbar.textColor = ContextCompat.getColor(context, R.color.searchText)
|
||||
toolbar.urlBoxView = LayoutInflater.from(context).inflate(R.layout.layout_url_backround, null)
|
||||
toolbar.urlBoxMargin = toolbar.resources.pxToDp(urlBoxMargin)
|
||||
|
||||
val home = BrowserToolbar.Button(
|
||||
context.resources.getDrawable(
|
||||
R.drawable.ic_home,
|
||||
|
@ -49,15 +39,6 @@ class ToolbarIntegration(
|
|||
|
||||
toolbar.addBrowserAction(home)
|
||||
|
||||
toolbar.onUrlClicked = {
|
||||
val extras = FragmentNavigator.Extras.Builder().addSharedElement(
|
||||
toolbar, ViewCompat.getTransitionName(toolbar)!!
|
||||
).build()
|
||||
Navigation.findNavController(toolbar)
|
||||
.navigate(R.id.action_browserFragment_to_searchFragment, null, null, extras)
|
||||
false
|
||||
}
|
||||
|
||||
ToolbarAutocompleteFeature(toolbar).apply {
|
||||
addDomainProvider(domainAutocompleteProvider)
|
||||
addHistoryStorageProvider(historyStorage)
|
||||
|
|
|
@ -28,13 +28,16 @@ class HomeFragment : Fragment() {
|
|||
savedInstanceState: Bundle?
|
||||
): View? {
|
||||
val view = inflater.inflate(R.layout.fragment_home, container, false)
|
||||
SessionsComponent(view.homeLayout, ActionBusFactory.get(this)).setup()
|
||||
SessionsComponent(view.homeLayout, ActionBusFactory.get(this))
|
||||
ActionBusFactory.get(this).logMergedObservables()
|
||||
return view
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
layoutComponents(view.homeLayout)
|
||||
|
||||
val searchIcon = requireComponents.search.searchEngineManager.getDefaultSearchEngine(requireContext()).let {
|
||||
BitmapDrawable(resources, it.icon)
|
||||
}
|
||||
|
@ -45,7 +48,6 @@ class HomeFragment : Fragment() {
|
|||
toolbar.setOnClickListener { it ->
|
||||
Navigation.findNavController(it).navigate(R.id.action_homeFragment_to_searchFragment, null, null)
|
||||
}
|
||||
layoutComponents(homeLayout)
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
|
|
@ -7,16 +7,19 @@ package org.mozilla.fenix.home.sessions
|
|||
import android.annotation.SuppressLint
|
||||
import android.view.ViewGroup
|
||||
import mozilla.components.browser.session.Session
|
||||
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.UIComponent
|
||||
import org.mozilla.fenix.mvi.ViewState
|
||||
|
||||
class SessionsComponent(private val container: ViewGroup, override val bus: ActionBusFactory) :
|
||||
UIComponent<SessionsState, SessionsAction, SessionsChange>(bus) {
|
||||
|
||||
class SessionsComponent(
|
||||
private val container: ViewGroup,
|
||||
override val bus: ActionBusFactory,
|
||||
override var initialState: SessionsState = SessionsState(emptyList())
|
||||
) :
|
||||
UIComponent<SessionsState, SessionsAction, SessionsChange>(bus) {
|
||||
|
||||
override val reducer: (SessionsState, SessionsChange) -> SessionsState = { state, change ->
|
||||
when (change) {
|
||||
|
@ -26,9 +29,17 @@ class SessionsComponent(private val container: ViewGroup, override val bus: Acti
|
|||
|
||||
override fun initView() = SessionsUIView(container, bus)
|
||||
|
||||
init {
|
||||
setup()
|
||||
}
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
fun setup(): SessionsComponent {
|
||||
render(reducer)
|
||||
getUserInteractionEvents<SessionsAction>()
|
||||
.subscribe {
|
||||
Logger("SessionsComponent").debug(it.toString())
|
||||
}
|
||||
return this
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,13 +1,17 @@
|
|||
/* 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.sessions
|
||||
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import androidx.constraintlayout.widget.ConstraintLayout.LayoutParams.PARENT_ID
|
||||
import kotlinx.android.synthetic.main.component_sessions.*
|
||||
import kotlinx.android.synthetic.main.fragment_home.*
|
||||
import org.jetbrains.anko.constraint.layout.ConstraintSetBuilder.Side.TOP
|
||||
import org.jetbrains.anko.constraint.layout.ConstraintSetBuilder.Side.BOTTOM
|
||||
import org.jetbrains.anko.constraint.layout.ConstraintSetBuilder.Side.START
|
||||
import org.jetbrains.anko.constraint.layout.ConstraintSetBuilder.Side.END
|
||||
import org.jetbrains.anko.constraint.layout.ConstraintSetBuilder.Side.START
|
||||
import org.jetbrains.anko.constraint.layout.ConstraintSetBuilder.Side.TOP
|
||||
import org.jetbrains.anko.constraint.layout.applyConstraintSet
|
||||
import org.mozilla.fenix.home.HomeFragment
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@ class SessionsUIView(container: ViewGroup, bus: ActionBusFactory) :
|
|||
.findViewById(R.id.session_list)
|
||||
|
||||
private val sessionsAdapter = SessionsAdapter()
|
||||
|
||||
init {
|
||||
view.apply {
|
||||
layoutManager = LinearLayoutManager(container.context)
|
||||
|
|
|
@ -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()
|
||||
}
|
|
@ -1,72 +1,64 @@
|
|||
/* 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.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.navigation.Navigation
|
||||
import kotlinx.android.synthetic.main.fragment_search.*
|
||||
import kotlinx.android.synthetic.main.fragment_search.view.*
|
||||
import mozilla.components.browser.domains.autocomplete.ShippedDomainsProvider
|
||||
import mozilla.components.feature.awesomebar.AwesomeBarFeature
|
||||
import mozilla.components.feature.awesomebar.provider.SearchSuggestionProvider
|
||||
import org.mozilla.fenix.R
|
||||
import org.mozilla.fenix.components.toolbar.ToolbarIntegration
|
||||
import org.mozilla.fenix.ext.requireComponents
|
||||
import org.mozilla.fenix.mvi.ActionBusFactory
|
||||
|
||||
class SearchFragment : Fragment() {
|
||||
private lateinit var awesomeBarFeature: AwesomeBarFeature
|
||||
private lateinit var searchComponent: SearchComponent
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View? {
|
||||
return inflater.inflate(R.layout.fragment_search, container, false)
|
||||
val view = inflater.inflate(R.layout.fragment_search, container, false)
|
||||
searchComponent = SearchComponent(view.toolbar_wrapper, ActionBusFactory.get(this),
|
||||
{ v -> transitionToBrowser(v) })
|
||||
return view
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
toolbar.editMode()
|
||||
searchComponent.editMode()
|
||||
}
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
layoutComponents(view.search_layout)
|
||||
|
||||
lifecycle.addObserver(
|
||||
ToolbarIntegration(
|
||||
requireContext(),
|
||||
toolbar,
|
||||
ShippedDomainsProvider().also { it.initialize(requireContext()) },
|
||||
requireComponents.core.historyStorage
|
||||
requireContext(),
|
||||
searchComponent.getView(),
|
||||
ShippedDomainsProvider().also { it.initialize(requireContext()) },
|
||||
requireComponents.core.historyStorage
|
||||
)
|
||||
)
|
||||
|
||||
awesomeBarFeature = AwesomeBarFeature(awesomeBar, toolbar, null, onEditComplete = ::userDidSearch)
|
||||
.addClipboardProvider(requireContext(), requireComponents.useCases.sessionUseCases.loadUrl)
|
||||
.addSearchProvider(
|
||||
requireComponents.search.searchEngineManager.getDefaultSearchEngine(requireContext()),
|
||||
requireComponents.useCases.searchUseCases.defaultSearch,
|
||||
SearchSuggestionProvider.Mode.MULTIPLE_SUGGESTIONS)
|
||||
.addSessionProvider(
|
||||
requireComponents.core.sessionManager,
|
||||
requireComponents.useCases.tabsUseCases.selectTab)
|
||||
|
||||
toolbar_wrapper.clipToOutline = false
|
||||
toolbar.apply {
|
||||
textColor = ContextCompat.getColor(context, R.color.searchText)
|
||||
textSize = toolbarTextSizeSp
|
||||
hint = context.getString(R.string.search_hint)
|
||||
hintColor = ContextCompat.getColor(context, R.color.searchText)
|
||||
}
|
||||
}
|
||||
|
||||
private fun userDidSearch() {
|
||||
Navigation.findNavController(toolbar).navigate(R.id.action_searchFragment_to_browserFragment, null, null)
|
||||
private fun transitionToBrowser(toolbar: View) {
|
||||
Navigation.findNavController(toolbar)
|
||||
.navigate(R.id.action_searchFragment_to_browserFragment, null, null)
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
|
|
@ -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"/>
|
|
@ -1,6 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/session_list"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
|
|
|
@ -8,9 +8,10 @@
|
|||
xmlns:mozac="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".search.SearchFragment">
|
||||
tools:context=".search.SearchFragment"
|
||||
android:id="@+id/search_layout">
|
||||
|
||||
<FrameLayout
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/toolbar_wrapper"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
|
@ -21,17 +22,7 @@
|
|||
android:outlineProvider="paddedBounds"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<mozilla.components.browser.toolbar.BrowserToolbar
|
||||
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" />
|
||||
</FrameLayout>
|
||||
app:layout_constraintTop_toTopOf="parent"/>
|
||||
|
||||
<mozilla.components.browser.awesomebar.BrowserAwesomeBar
|
||||
android:id="@+id/awesomeBar"
|
||||
|
|
|
@ -13,7 +13,8 @@
|
|||
|
||||
<fragment android:id="@+id/searchFragment" android:name="org.mozilla.fenix.search.SearchFragment"
|
||||
android:label="fragment_search" tools:layout="@layout/fragment_search">
|
||||
<action android:id="@+id/action_searchFragment_to_browserFragment" app:destination="@id/browserFragment"/>
|
||||
<action android:id="@+id/action_searchFragment_to_browserFragment" app:destination="@id/browserFragment"
|
||||
app:popUpTo="@id/homeFragment"/>
|
||||
</fragment>
|
||||
|
||||
<fragment android:id="@+id/browserFragment" android:name="org.mozilla.fenix.browser.BrowserFragment"
|
||||
|
|
|
@ -73,6 +73,8 @@ object Deps {
|
|||
const val mozilla_feature_prompts = "org.mozilla.components:feature-prompts:${Versions.mozilla_android_components}"
|
||||
const val mozilla_feature_toolbar = "org.mozilla.components:feature-toolbar:${Versions.mozilla_android_components}"
|
||||
|
||||
const val mozilla_service_fretboard = "org.mozilla.components:service-fretboard:${Versions.mozilla_android_components}"
|
||||
|
||||
const val mozilla_lib_crash = "org.mozilla.components:lib-crash:${Versions.mozilla_android_components}"
|
||||
|
||||
const val mozilla_support_ktx = "org.mozilla.components:support-ktx:${Versions.mozilla_android_components}"
|
||||
|
|
Loading…
Reference in New Issue