Bug 1940630 - Add search selector toolbar action as a custom toolbar action r=android-reviewers,petru
- Add a CustomAction to the toolbar action concept to allow for displaying a provided composable content. - Add a SearchSelector toolbar action that can display a menu. - Provide an usage example in sample-toolbar Differential Revision: https://phabricator.services.mozilla.com/D233608
This commit is contained in:
@@ -11,8 +11,8 @@ 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.compose.ui.platform.LocalContext
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.content.res.ResourcesCompat
|
||||
import androidx.core.view.isVisible
|
||||
@@ -40,17 +40,22 @@ import mozilla.components.browser.menu2.BrowserMenuController
|
||||
import mozilla.components.browser.toolbar.BrowserToolbar
|
||||
import mozilla.components.browser.toolbar.display.DisplayToolbar
|
||||
import mozilla.components.compose.base.theme.AcornTheme
|
||||
import mozilla.components.compose.browser.toolbar.concept.Action.CustomAction
|
||||
import mozilla.components.compose.browser.toolbar.store.BrowserEditToolbarAction
|
||||
import mozilla.components.compose.browser.toolbar.store.BrowserToolbarAction
|
||||
import mozilla.components.compose.browser.toolbar.store.BrowserToolbarState
|
||||
import mozilla.components.compose.browser.toolbar.store.BrowserToolbarStore
|
||||
import mozilla.components.compose.browser.toolbar.store.DisplayState
|
||||
import mozilla.components.compose.browser.toolbar.store.EditState
|
||||
import mozilla.components.compose.browser.toolbar.ui.SearchSelector
|
||||
import mozilla.components.concept.menu.Side
|
||||
import mozilla.components.concept.menu.candidate.DecorativeTextMenuCandidate
|
||||
import mozilla.components.concept.menu.candidate.DividerMenuCandidate
|
||||
import mozilla.components.concept.menu.candidate.DrawableMenuIcon
|
||||
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
|
||||
@@ -486,18 +491,63 @@ class ToolbarActivity : AppCompatActivity() {
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("LongMethod")
|
||||
private fun setupComposeToolbar() {
|
||||
showToolbar(isCompose = true)
|
||||
|
||||
val header = DecorativeTextMenuCandidate(
|
||||
text = "This time search in:",
|
||||
)
|
||||
val bookmarks = TextMenuCandidate(
|
||||
"Bookmarks",
|
||||
start = DrawableMenuIcon(this, iconsR.drawable.mozac_ic_bookmark_tray_24),
|
||||
) { /* Do nothing */ }
|
||||
val tabs = TextMenuCandidate(
|
||||
"Tabs",
|
||||
start = DrawableMenuIcon(this, iconsR.drawable.mozac_ic_tab_tray_24),
|
||||
) { /* Do nothing */ }
|
||||
val history = TextMenuCandidate(
|
||||
"History",
|
||||
start = DrawableMenuIcon(this, iconsR.drawable.mozac_ic_history_24),
|
||||
) { /* Do nothing */ }
|
||||
val settings = TextMenuCandidate(
|
||||
"Search settings",
|
||||
start = DrawableMenuIcon(this, iconsR.drawable.mozac_ic_settings_24),
|
||||
) { /* Do nothing */ }
|
||||
|
||||
val items = listOf(header, bookmarks, tabs, history, settings)
|
||||
val menuController = BrowserMenuController().apply {
|
||||
submitList(items)
|
||||
}
|
||||
|
||||
binding.composeToolbar.setContent {
|
||||
AcornTheme {
|
||||
val store = remember {
|
||||
BrowserToolbarStore()
|
||||
BrowserToolbarStore(
|
||||
initialState = BrowserToolbarState(
|
||||
displayState = DisplayState(hint = "Search or enter address"),
|
||||
editState = EditState(
|
||||
editActionsStart = listOf(
|
||||
CustomAction(
|
||||
content = {
|
||||
SearchSelector(
|
||||
onClick = {},
|
||||
menu = menuController,
|
||||
icon = ContextCompat.getDrawable(
|
||||
LocalContext.current,
|
||||
iconsR.drawable.mozac_ic_search_24,
|
||||
),
|
||||
)
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
val uiState by store.observeAsState(initialValue = store.state) { it }
|
||||
|
||||
BrowserToolbar(
|
||||
store = store,
|
||||
onDisplayMenuClicked = {},
|
||||
onDisplayToolbarClick = {
|
||||
store.dispatch(BrowserToolbarAction.ToggleEditMode(editMode = true))
|
||||
@@ -509,9 +559,6 @@ class ToolbarActivity : AppCompatActivity() {
|
||||
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,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,10 +5,13 @@
|
||||
package org.mozilla.samples.toolbar.compose
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
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
|
||||
import mozilla.components.compose.browser.toolbar.store.BrowserToolbarStore
|
||||
import mozilla.components.lib.state.ext.observeAsState
|
||||
|
||||
/**
|
||||
* A customizable toolbar for browsers.
|
||||
@@ -23,38 +26,37 @@ import mozilla.components.compose.browser.toolbar.BrowserToolbarDefaults
|
||||
* 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(
|
||||
store: BrowserToolbarStore,
|
||||
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) {
|
||||
val uiState by store.observeAsState(initialValue = store.state) { it }
|
||||
|
||||
val input = when (val editText = uiState.editState.editText) {
|
||||
null -> url
|
||||
else -> editText
|
||||
}
|
||||
|
||||
if (editMode) {
|
||||
if (uiState.editMode) {
|
||||
BrowserEditToolbar(
|
||||
url = input,
|
||||
colors = colors.editToolbarColors,
|
||||
editActionsStart = uiState.editState.editActionsStart,
|
||||
editActionsEnd = uiState.editState.editActionsEnd,
|
||||
onUrlCommitted = { text -> onTextCommit(text) },
|
||||
onUrlEdit = { text -> onTextEdit(text) },
|
||||
)
|
||||
} else {
|
||||
BrowserDisplayToolbar(
|
||||
url = url.takeIf { it.isNotEmpty() } ?: hint,
|
||||
url = url.takeIf { it.isNotEmpty() } ?: uiState.displayState.hint,
|
||||
colors = colors.displayToolbarColors,
|
||||
onUrlClicked = {
|
||||
onDisplayToolbarClick()
|
||||
|
||||
Reference in New Issue
Block a user