Bug 1940625 - Show compose-browser-toolbar as an option in samples-toolbar r=android-reviewers,petru

Differential Revision: https://phabricator.services.mozilla.com/D233603
This commit is contained in:
Gabriel Luong
2025-02-19 03:24:27 +00:00
parent a112290343
commit ada5444ba8
5 changed files with 135 additions and 0 deletions

View File

@@ -26,6 +26,11 @@ android {
buildFeatures {
viewBinding true
compose true
}
composeOptions {
kotlinCompilerExtensionVersion = Versions.compose_compiler
}
namespace 'org.mozilla.samples.toolbar'
@@ -39,6 +44,8 @@ dependencies {
implementation project(':browser-menu')
implementation project(':browser-menu2')
implementation project(':browser-domains')
implementation project(':browser-state')
implementation project(':compose-browser-toolbar')
implementation project(':ui-colors')
implementation project(':ui-tabcounter')
@@ -53,6 +60,7 @@ dependencies {
implementation ComponentsDependencies.kotlin_coroutines
implementation ComponentsDependencies.androidx_appcompat
implementation ComponentsDependencies.androidx_compose_ui
implementation ComponentsDependencies.androidx_core_ktx
implementation ComponentsDependencies.androidx_recyclerview
}

View File

@@ -31,6 +31,7 @@ enum class ToolbarConfiguration(val label: String) {
PRIVATE_MODE("Private Mode"),
FENIX("Fenix"),
FENIX_CUSTOMTAB("Fenix (Custom Tab)"),
COMPOSE_TOOLBAR("Compose Toolbar"),
}
class ConfigurationAdapter(

View File

@@ -11,8 +11,11 @@ import android.view.ViewGroup
import android.widget.Toast
import androidx.annotation.DrawableRes
import androidx.appcompat.app.AppCompatActivity
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.core.content.ContextCompat
import androidx.core.content.res.ResourcesCompat
import androidx.core.view.isVisible
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.Observer
import androidx.recyclerview.widget.LinearLayoutManager
@@ -36,6 +39,9 @@ import mozilla.components.browser.menu.item.SimpleBrowserMenuItem
import mozilla.components.browser.menu2.BrowserMenuController
import mozilla.components.browser.toolbar.BrowserToolbar
import mozilla.components.browser.toolbar.display.DisplayToolbar
import mozilla.components.compose.browser.toolbar.store.BrowserEditToolbarAction
import mozilla.components.compose.browser.toolbar.store.BrowserToolbarAction
import mozilla.components.compose.browser.toolbar.store.BrowserToolbarStore
import mozilla.components.concept.menu.Side
import mozilla.components.concept.menu.candidate.DividerMenuCandidate
import mozilla.components.concept.menu.candidate.DrawableMenuIcon
@@ -43,10 +49,12 @@ import mozilla.components.concept.menu.candidate.NestedMenuCandidate
import mozilla.components.concept.menu.candidate.TextMenuCandidate
import mozilla.components.concept.toolbar.Toolbar
import mozilla.components.feature.toolbar.ToolbarAutocompleteFeature
import mozilla.components.lib.state.ext.observeAsState
import mozilla.components.support.ktx.android.content.res.resolveAttribute
import mozilla.components.support.ktx.android.view.hideKeyboard
import mozilla.components.support.ktx.util.URLStringUtils
import mozilla.components.ui.tabcounter.TabCounter
import org.mozilla.samples.toolbar.compose.BrowserToolbar
import org.mozilla.samples.toolbar.databinding.ActivityToolbarBinding
import mozilla.components.browser.menu.R as menuR
import mozilla.components.browser.toolbar.R as toolbarR
@@ -81,6 +89,7 @@ class ToolbarActivity : AppCompatActivity() {
ToolbarConfiguration.PRIVATE_MODE -> setupDefaultToolbar(private = true)
ToolbarConfiguration.FENIX -> setupFenixToolbar()
ToolbarConfiguration.FENIX_CUSTOMTAB -> setupFenixCustomTabToolbar()
ToolbarConfiguration.COMPOSE_TOOLBAR -> setupComposeToolbar()
}
val recyclerView: RecyclerView = findViewById(R.id.recyclerView)
@@ -105,6 +114,8 @@ class ToolbarActivity : AppCompatActivity() {
* A very simple toolbar with mostly default values.
*/
private fun setupDefaultToolbar(private: Boolean = false) {
showToolbar()
binding.toolbar.setBackgroundColor(
ContextCompat.getColor(this, colorsR.color.photonBlue80),
)
@@ -118,6 +129,8 @@ class ToolbarActivity : AppCompatActivity() {
* A toolbar that looks like Firefox Focus on tablets.
*/
private fun setupFocusTabletToolbar() {
showToolbar()
// //////////////////////////////////////////////////////////////////////////////////////////
// Use the iconic gradient background
// //////////////////////////////////////////////////////////////////////////////////////////
@@ -191,6 +204,8 @@ class ToolbarActivity : AppCompatActivity() {
* A custom browser menu.
*/
private fun setupCustomMenu() {
showToolbar()
binding.toolbar.setBackgroundColor(
ContextCompat.getColor(this, colorsR.color.photonBlue80),
)
@@ -224,6 +239,8 @@ class ToolbarActivity : AppCompatActivity() {
* A toolbar that looks like Firefox Focus on phones.
*/
private fun setupFocusPhoneToolbar() {
showToolbar()
// //////////////////////////////////////////////////////////////////////////////////////////
// Use the iconic gradient background
// //////////////////////////////////////////////////////////////////////////////////////////
@@ -314,6 +331,8 @@ class ToolbarActivity : AppCompatActivity() {
*/
@Suppress("MagicNumber")
fun setupFenixToolbar() {
showToolbar()
binding.toolbar.setBackgroundColor(0xFFFFFFFF.toInt())
binding.toolbar.display.indicators = listOf(
@@ -400,6 +419,8 @@ class ToolbarActivity : AppCompatActivity() {
@OptIn(DelicateCoroutinesApi::class) // GlobalScope usage
@Suppress("MagicNumber")
fun setupFenixCustomTabToolbar() {
showToolbar()
binding.toolbar.setBackgroundColor(0xFFFFFFFF.toInt())
binding.toolbar.display.indicators = listOf(
@@ -464,6 +485,40 @@ class ToolbarActivity : AppCompatActivity() {
}
}
private fun setupComposeToolbar() {
showToolbar(isCompose = true)
binding.composeToolbar.setContent {
val store = remember {
BrowserToolbarStore()
}
val uiState by store.observeAsState(initialValue = store.state) { it }
BrowserToolbar(
onDisplayMenuClicked = {},
onDisplayToolbarClick = {
store.dispatch(BrowserToolbarAction.ToggleEditMode(editMode = true))
},
onTextEdit = { text ->
store.dispatch(BrowserEditToolbarAction.UpdateEditText(text = text))
},
onTextCommit = {
store.dispatch(BrowserToolbarAction.ToggleEditMode(editMode = false))
},
url = "https://www.mozilla.org/en-US/firefox/mobile/",
hint = "Search or enter address",
editMode = uiState.editMode,
editText = uiState.editState.editText,
)
}
}
private fun showToolbar(isCompose: Boolean = false) {
binding.toolbar.isVisible = !isCompose
binding.composeToolbar.isVisible = isCompose
}
// For testing purposes
private var forward = true
private var back = true

View File

@@ -0,0 +1,65 @@
/* 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.samples.toolbar.compose
import androidx.compose.runtime.Composable
import mozilla.components.compose.browser.toolbar.BrowserDisplayToolbar
import mozilla.components.compose.browser.toolbar.BrowserEditToolbar
import mozilla.components.compose.browser.toolbar.BrowserToolbarColors
import mozilla.components.compose.browser.toolbar.BrowserToolbarDefaults
/**
* A customizable toolbar for browsers.
*
* The toolbar can switch between two modes: display and edit. The display mode displays the current
* URL and controls for navigation. In edit mode the current URL can be edited. Those two modes are
* implemented by the [BrowserDisplayToolbar] and [BrowserEditToolbar] composables.
*
* @param onDisplayMenuClicked Invoked when the user clicks on the menu button in "display" mode.
* @param onTextEdit Invoked when the user edits the text in the toolbar in "edit" mode.
* @param onTextCommit Invoked when the user has finished editing the URL and wants
* to commit the entered text.
* @param onDisplayToolbarClick Invoked when the user clicks on the URL in "display" mode.
* @param colors The color scheme the browser toolbar will use for the UI.
* @param hint Text displayed in the toolbar when there's no URL to display (no tab or empty URL)
* @param editMode Whether the toolbar is in "edit" or "display" mode.
* @param editText The text the user is editing in "edit" mode.
*/
@Suppress("MagicNumber")
@Composable
fun BrowserToolbar(
onDisplayMenuClicked: () -> Unit,
onDisplayToolbarClick: () -> Unit,
onTextEdit: (String) -> Unit,
onTextCommit: (String) -> Unit,
colors: BrowserToolbarColors = BrowserToolbarDefaults.colors(),
url: String = "",
hint: String = "",
editMode: Boolean = false,
editText: String? = null,
) {
val input = when (editText) {
null -> url
else -> editText
}
if (editMode) {
BrowserEditToolbar(
url = input,
colors = colors.editToolbarColors,
onUrlCommitted = { text -> onTextCommit(text) },
onUrlEdit = { text -> onTextEdit(text) },
)
} else {
BrowserDisplayToolbar(
url = url.takeIf { it.isNotEmpty() } ?: hint,
colors = colors.displayToolbarColors,
onUrlClicked = {
onDisplayToolbarClick()
},
onMenuClicked = { onDisplayMenuClicked() },
)
}
}

View File

@@ -14,6 +14,12 @@
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<androidx.compose.ui.platform.ComposeView
android:id="@+id/composeToolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"