Skip to content

Commit

Permalink
Merge pull request #583 from Orange-OpenSource/572-update-odstopappba…
Browse files Browse the repository at this point in the history
…r-api

572 - Update OdsTopAppBar and OdsLargeTopAppBar APIs
  • Loading branch information
paulinea authored Jul 21, 2023
2 parents c35c8ec + 3f28e7b commit de40c39
Show file tree
Hide file tree
Showing 19 changed files with 775 additions and 395 deletions.
127 changes: 66 additions & 61 deletions app/src/main/java/com/orange/ods/app/ui/MainTopAppBar.kt
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,8 @@ package com.orange.ods.app.ui

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.RowScope
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material.Icon
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowBack
import androidx.compose.material3.ExperimentalMaterial3Api
Expand All @@ -37,13 +35,14 @@ import com.orange.ods.app.R
import com.orange.ods.app.domain.recipes.LocalRecipes
import com.orange.ods.app.ui.components.utilities.clickOnElement
import com.orange.ods.app.ui.utilities.extension.isDarkModeEnabled
import com.orange.ods.compose.component.appbar.top.OdsLargeTopAppBar
import com.orange.ods.compose.component.appbar.top.OdsTopAppBar
import com.orange.ods.compose.component.appbar.top.OdsLargeTopAppBarInternal
import com.orange.ods.compose.component.appbar.top.OdsTopAppBarActionButton
import com.orange.ods.compose.component.appbar.top.OdsTopAppBarOverflowMenuBox
import com.orange.ods.compose.component.appbar.top.OdsTopAppBarInternal
import com.orange.ods.compose.component.appbar.top.OdsTopAppBarNavigationIcon
import com.orange.ods.compose.component.appbar.top.OdsTopAppBarOverflowMenuActionItem
import com.orange.ods.compose.component.content.OdsComponentContent
import com.orange.ods.compose.component.list.OdsListItem
import com.orange.ods.compose.component.list.OdsRadioButtonTrailing
import com.orange.ods.compose.component.menu.OdsDropdownMenuItem
import com.orange.ods.compose.component.textfield.search.OdsSearchTextField
import com.orange.ods.compose.text.OdsTextH6
import com.orange.ods.compose.theme.OdsTheme
Expand All @@ -63,37 +62,34 @@ fun MainTopAppBar(
val showSearchAction = topAppBarState.titleRes.value == R.string.navigation_item_search

val title = stringResource(id = topAppBarState.titleRes.value)
val navigationIcon: (@Composable () -> Unit)? = if (shouldShowUpNavigationIcon && topAppBarState.isNavigationIconEnabled) {
{
Icon(
imageVector = Icons.Filled.ArrowBack,
contentDescription = stringResource(id = R.string.top_app_bar_back_icon_desc)
)
}
} else null
val navigationIcon = if (shouldShowUpNavigationIcon && topAppBarState.isNavigationIconEnabled) {
OdsTopAppBarNavigationIcon(Icons.Filled.ArrowBack, stringResource(id = R.string.top_app_bar_back_icon_desc), upPress)
} else {
null
}

val actions: @Composable RowScope.() -> Unit = {
if (showSearchAction) {
TopAppBarSearchAction(searchedText = topAppBarState.searchedText)
} else {
TopAppBarActions(topAppBarState, onSearchActionClick) { changeThemeDialogVisible = true }
}
val actions = if (showSearchAction) {
listOf(getTopAppBarSearchTextFieldAction(searchedText = topAppBarState.searchedText))
} else {
getTopAppBarActions(topAppBarState, onSearchActionClick) { changeThemeDialogVisible = true }
}

val overflowMenuActions = getTopAppBarOverflowMenuActions(topAppBarState)

if (topAppBarState.isLarge) {
OdsLargeTopAppBar(
OdsLargeTopAppBarInternal(
title = title,
navigationIcon = navigationIcon,
onNavigationIconClick = upPress,
actions = actions,
overflowMenuActions = overflowMenuActions,
scrollBehavior = if (topAppBarState.hasScrollBehavior) scrollBehavior else null
)
} else {
OdsTopAppBar(
OdsTopAppBarInternal(
title = title,
navigationIcon = navigationIcon,
onNavigationIconClick = upPress,
actions = actions,
overflowMenuActions = overflowMenuActions,
elevated = false // elevation is managed in [MainScreen] cause of tabs
)
}
Expand All @@ -111,91 +107,100 @@ fun MainTopAppBar(
}
}


@Composable
private fun TopAppBarSearchAction(searchedText: MutableState<TextFieldValue>) {
val focusRequester = remember { FocusRequester() }
OdsSearchTextField(
value = searchedText.value,
onValueChange = { value ->
searchedText.value = value
},
placeholder = stringResource(id = R.string.search_text_field_hint),
modifier = Modifier
.fillMaxWidth()
.focusRequester(focusRequester)
)
LaunchedEffect(Unit) {
focusRequester.requestFocus()
private fun getTopAppBarSearchTextFieldAction(searchedText: MutableState<TextFieldValue>): OdsComponentContent {
return object : OdsComponentContent() {

@Composable
override fun Content() {
val focusRequester = remember { FocusRequester() }
OdsSearchTextField(
value = searchedText.value,
onValueChange = { value ->
searchedText.value = value
},
placeholder = stringResource(id = R.string.search_text_field_hint),
modifier = Modifier
.fillMaxWidth()
.focusRequester(focusRequester)
)
LaunchedEffect(Unit) {
focusRequester.requestFocus()
}
}
}
}

@Composable
private fun TopAppBarActions(state: MainTopAppBarState, onSearchActionClick: () -> Unit, onChangeThemeActionClick: () -> Unit) {
state.actions.value.forEach { action ->
private fun getTopAppBarActions(
state: MainTopAppBarState,
onSearchActionClick: () -> Unit,
onChangeThemeActionClick: () -> Unit
): List<OdsTopAppBarActionButton> {
return state.actions.value.mapNotNull { action ->
when (action) {
TopAppBarConfiguration.Action.Search -> TopAppBarSearchActionButton(onClick = onSearchActionClick)
TopAppBarConfiguration.Action.Theme -> TopAppBarChangeThemeActionButton(onClick = onChangeThemeActionClick)
TopAppBarConfiguration.Action.Mode -> TopAppBarChangeModeActionButton()
TopAppBarConfiguration.Action.OverflowMenu -> TopAppBarOverflowMenuBox()
is TopAppBarConfiguration.Action.Custom -> TopAppBarCustomActionButton(action = action)
TopAppBarConfiguration.Action.Search -> getTopAppBarSearchAction(onClick = onSearchActionClick)
TopAppBarConfiguration.Action.Theme -> getTopAppBarChangeThemeAction(onClick = onChangeThemeActionClick)
TopAppBarConfiguration.Action.Mode -> getTopAppBarChangeModeAction()
TopAppBarConfiguration.Action.OverflowMenu -> null
is TopAppBarConfiguration.Action.Custom -> getTopAppBarCustomAction(action = action)
}
}
}

@Composable
private fun TopAppBarChangeThemeActionButton(onClick: () -> Unit) {
OdsTopAppBarActionButton(
private fun getTopAppBarChangeThemeAction(onClick: () -> Unit): OdsTopAppBarActionButton {
return OdsTopAppBarActionButton(
onClick = onClick,
painter = painterResource(id = R.drawable.ic_palette),
contentDescription = stringResource(id = R.string.top_app_bar_action_change_mode_to_dark_desc)
)
}

@Composable
private fun TopAppBarChangeModeActionButton() {
private fun getTopAppBarChangeModeAction(): OdsTopAppBarActionButton {
val configuration = LocalConfiguration.current
val themeManager = LocalThemeManager.current

val painterRes = if (configuration.isDarkModeEnabled) R.drawable.ic_ui_light_mode else R.drawable.ic_ui_dark_mode
val iconDesc =
if (configuration.isDarkModeEnabled) R.string.top_app_bar_action_change_mode_to_light_desc else R.string.top_app_bar_action_change_mode_to_dark_desc

OdsTopAppBarActionButton(
return OdsTopAppBarActionButton(
onClick = { themeManager.darkModeEnabled = !configuration.isDarkModeEnabled },
painter = painterResource(id = painterRes),
contentDescription = stringResource(id = iconDesc)
)
}

@Composable
private fun TopAppBarSearchActionButton(onClick: () -> Unit) {
OdsTopAppBarActionButton(
private fun getTopAppBarSearchAction(onClick: () -> Unit): OdsTopAppBarActionButton {
return OdsTopAppBarActionButton(
onClick = onClick,
painter = painterResource(id = R.drawable.ic_search),
contentDescription = stringResource(id = R.string.search_content_description)
)
}

@Composable
private fun TopAppBarOverflowMenuBox() {
val context = LocalContext.current
OdsTopAppBarOverflowMenuBox(
overflowIconContentDescription = stringResource(id = R.string.component_app_bars_top_element_overflow_menu)
) {
LocalRecipes.current.forEach { recipe ->
OdsDropdownMenuItem(
private fun getTopAppBarOverflowMenuActions(state: MainTopAppBarState): List<OdsTopAppBarOverflowMenuActionItem> {
return if (state.actions.value.contains(TopAppBarConfiguration.Action.OverflowMenu)) {
val context = LocalContext.current
LocalRecipes.current.map { recipe ->
OdsTopAppBarOverflowMenuActionItem(
text = recipe.title,
onClick = { clickOnElement(context, recipe.title) }
)
}
} else {
emptyList()
}
}

@Composable
private fun TopAppBarCustomActionButton(action: TopAppBarConfiguration.Action.Custom) {
private fun getTopAppBarCustomAction(action: TopAppBarConfiguration.Action.Custom): OdsTopAppBarActionButton {
val context = LocalContext.current
OdsTopAppBarActionButton(
return OdsTopAppBarActionButton(
onClick = { clickOnElement(context, action.name) },
painter = painterResource(id = action.iconResId),
contentDescription = action.name
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ import com.orange.ods.app.ui.components.utilities.ComponentCustomizationBottomSh
import com.orange.ods.app.ui.utilities.NavigationItem
import com.orange.ods.app.ui.utilities.composable.*
import com.orange.ods.compose.OdsComposable
import com.orange.ods.compose.component.appbar.top.OdsTopAppBarActionButton
import com.orange.ods.compose.component.appbar.top.OdsTopAppBarNavigationIcon
import com.orange.ods.compose.component.chip.OdsChoiceChip
import com.orange.ods.compose.component.chip.OdsChoiceChipsFlowRow
import com.orange.ods.compose.component.list.OdsListItem
Expand Down Expand Up @@ -107,41 +109,29 @@ fun ComponentTopAppBar(variant: Variant) {
title(context.getString(R.string.component_app_bars_top_regular))

if (isNavigationIconEnabled) {
composable(name = "navigationIcon") {
FunctionCallCode(
name = "Icon",
parameters = {
simple("imageVector", "<image vector>")
contentDescription(context.getString(R.string.top_app_bar_back_icon_desc))
}
)
classInstance("navigationIcon", OdsTopAppBarNavigationIcon::class.java) {
simple("imageVector", "<image vector>")
contentDescription(context.getString(R.string.top_app_bar_back_icon_desc))
}
}

composable(name = "actions") {
list("actions") {
repeat(actionCount.value) {
FunctionCallCode(
name = OdsComposable.OdsTopAppBarActionButton.name,
parameters = {
onClick()
painter()
contentDescription("icon description")
}
)
classInstance(OdsTopAppBarActionButton::class.java) {
onClick()
painter()
contentDescription("icon description")
}
}
if (isOverflowMenuEnabled) {
FunctionCallCode(
name = OdsComposable.OdsTopAppBarOverflowMenuBox.name,
parameters = { string("overflowIconContentDescription", "Open overflow menu") }
) {
for (i in 1..2) {
FunctionCallCode(
name = OdsComposable.OdsDropdownMenuItem.name,
parameters = {
text("Menu $i")
onClick()
}
)
}

if (isOverflowMenuEnabled) {
list("overflowMenuActions") {
for (i in 1..2) {
// The classInstance method displays the original type of type aliases, that's why function is used instead
function("OdsTopAppBarOverflowMenuActionItem") {
text("Menu $i")
onClick()
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ import com.orange.ods.app.ui.components.utilities.clickOnElement
import com.orange.ods.app.ui.utilities.composable.CodeImplementationColumn
import com.orange.ods.app.ui.utilities.composable.FunctionCallCode
import com.orange.ods.compose.OdsComposable
import com.orange.ods.compose.component.divider.OdsDivider
import com.orange.ods.compose.component.list.OdsIconTrailing
import com.orange.ods.compose.component.list.OdsListItem
import com.orange.ods.compose.component.list.OdsSwitchTrailing
Expand Down Expand Up @@ -79,6 +78,8 @@ fun MenuDropdown() {
text = stringResource(id = R.string.component_menu_dropdown_description)
)

val dividerIndex = 1

Box(modifier = Modifier.padding(top = dimensionResource(id = R.dimen.spacing_s))) {
OdsListItem(
modifier = Modifier.padding(top = dimensionResource(id = R.dimen.spacing_s)),
Expand All @@ -90,18 +91,22 @@ fun MenuDropdown() {
contentDescription = stringResource(id = R.string.component_menu_show_ingredients),
)
)
OdsDropdownMenu(expanded = menuExpanded, onDismissRequest = { menuExpanded = false }, offset = DpOffset(x = (-100).dp, y = (-10).dp)) {
recipes.take(MenuDropdownCustomizationState.MenuItemCount).forEachIndexed { index, recipe ->

val items = recipes.take(MenuDropdownCustomizationState.MenuItemCount)
.mapIndexed { index, recipe ->
OdsDropdownMenuItem(
text = recipe.title,
icon = if (hasIcons && recipe.iconResId != null) painterResource(id = recipe.iconResId) else null,
divider = hasDividerExample && index == dividerIndex,
onClick = { clickOnElement(context, recipe.title) }
)
if (hasDividerExample && index == 2) {
OdsDivider()
}
}
}
OdsDropdownMenu(
items = items,
expanded = menuExpanded,
onDismissRequest = { menuExpanded = false },
offset = DpOffset(x = (-100).dp, y = (-10).dp)
)
}

CodeImplementationColumn(
Expand All @@ -113,22 +118,18 @@ fun MenuDropdown() {
parameters = {
stringRepresentation("expanded", menuExpanded)
lambda("onDismissRequest")
}
) {
recipes.take(2).forEachIndexed { index, recipe ->
FunctionCallCode(
name = OdsComposable.OdsDropdownMenuItem.name,
parameters = {
string("text", recipe.title)
onClick()
if (hasIcons && recipe.iconResId != null) icon()
list("items") {
recipes.take(2).forEachIndexed { index, recipe ->
classInstance(OdsDropdownMenuItem::class.java) {
string("text", recipe.title)
if (hasIcons && recipe.iconResId != null) icon()
if (hasDividerExample && index == dividerIndex) stringRepresentation("divider", true)
onClick()
}
}
)
if (hasDividerExample && index == 0) {
FunctionCallCode(name = OdsComposable.OdsDivider.name)
}
}
}
)
}
}
}
Expand Down
Loading

0 comments on commit de40c39

Please sign in to comment.