Skip to content

Commit

Permalink
Merge pull request #741 from Orange-OpenSource/develop
Browse files Browse the repository at this point in the history
Release 0.18.0
  • Loading branch information
florentmaitre committed Dec 11, 2023
2 parents 4f11267 + c5f1f2e commit 8433eab
Show file tree
Hide file tree
Showing 466 changed files with 10,391 additions and 4,661 deletions.
3 changes: 3 additions & 0 deletions .idea/codeStyles/Project.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion DEVELOP.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ repositories {

```groovy
dependencies {
implementation 'com.orange.ods.android:ods-lib:0.17.0'
implementation 'com.orange.ods.android:ods-lib:0.18.0'
}
```

Expand Down
2 changes: 0 additions & 2 deletions NOTICE.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ in whole or part of, in any medium, except as required for reasonable and custom
and reproducing the content of the NOTICE and DOCUMENTATION files.
Any use or displaying shall constitute an infringement under intellectual property laws of France and international conventions.

app/src/main/res/drawable/ic_address_book.xml
app/src/main/res/drawable/ic_coffee.xml
app/src/main/res/drawable/ic_component_atom.xml
app/src/main/res/drawable/ic_cooking_pot.xml
Expand All @@ -18,7 +17,6 @@ app/src/main/res/drawable/ic_ice_cream.xml
app/src/main/res/drawable/ic_info.xml
app/src/main/res/drawable/ic_launcher_foreground.xml
app/src/main/res/drawable/ic_module_molecule.xml
app/src/main/res/drawable/ic_notification.xml
app/src/main/res/drawable/ic_palette.xml
app/src/main/res/drawable/ic_play_outline.xml
app/src/main/res/drawable/ic_restaurant.xml
Expand Down
4 changes: 3 additions & 1 deletion app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ android {
minSdk = Versions.minSdk
targetSdk = Versions.targetSdk
val versionCodeProperty = project.findTypedProperty<String>("versionCode")
versionCode = versionCodeProperty?.toInt() ?: 9
versionCode = versionCodeProperty?.toInt() ?: 10
versionName = version.toString()
val versionNameSuffixProperty = project.findTypedProperty<String>("versionNameSuffix")
versionNameSuffix = versionNameSuffixProperty
Expand Down Expand Up @@ -90,6 +90,7 @@ android {
}

firebaseAppDistribution {
appId = "1:212698857200:android:67d1403d02a72f4d5ecc35"
releaseNotesFile = Firebase_gradle.AppDistribution.releaseNotesFilePath
groups = project.findTypedProperty("appDistributionGroup")
}
Expand Down Expand Up @@ -127,6 +128,7 @@ dependencies {
implementation(project(":lib"))
implementation(project(":lib-xml"))
implementation(project(":theme-innovation-cup"))
implementation(project(":module-about"))

implementation(Dependencies.accompanistSystemUiController)
implementation(Dependencies.activityCompose)
Expand Down
8 changes: 8 additions & 0 deletions app/src/main/java/com/orange/ods/app/OdsApplication.kt
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,24 @@ import android.app.Application
import com.google.firebase.crashlytics.ktx.crashlytics
import com.google.firebase.ktx.Firebase
import dagger.hilt.android.HiltAndroidApp
import timber.log.Timber

@HiltAndroidApp
class OdsApplication : Application() {

override fun onCreate() {
super.onCreate()
initializeCrashlytics()
initializeLogger()
}

private fun initializeCrashlytics() {
Firebase.crashlytics.setCrashlyticsCollectionEnabled(!BuildConfig.DEBUG)
}

private fun initializeLogger() {
if (BuildConfig.DEBUG) {
Timber.plant(Timber.DebugTree())
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import android.content.Context
import com.orange.ods.app.R
import com.orange.ods.app.domain.recipes.Recipe
import com.orange.ods.app.domain.recipes.RecipesRepository
import com.orange.ods.app.ui.utilities.extension.contentAsString
import com.orange.ods.extension.contentAsString
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow
import timber.log.Timber
Expand Down
4 changes: 2 additions & 2 deletions app/src/main/java/com/orange/ods/app/ui/AppBar.kt
Original file line number Diff line number Diff line change
Expand Up @@ -32,15 +32,15 @@ fun AppBar(
title = title,
navigationIcon = getNavigationIcon(upPress),
actions = actions,
overflowMenuActions = overflowMenuActions,
overflowMenuItems = overflowMenuItems,
scrollBehavior = if (hasScrollBehavior) scrollBehavior else null
)
} else {
OdsTopAppBarInternal(
title = title,
navigationIcon = getNavigationIcon(upPress),
actions = actions,
overflowMenuActions = overflowMenuActions,
overflowMenuItems = overflowMenuItems,
elevated = false // elevation is managed in MainScreen cause of tabs
)
}
Expand Down
29 changes: 8 additions & 21 deletions app/src/main/java/com/orange/ods/app/ui/AppBarActions.kt
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,8 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.input.TextFieldValue
import com.orange.ods.app.R
import com.orange.ods.app.ui.AppBarAction.Companion.defaultActions
import com.orange.ods.app.ui.utilities.UiString
import com.orange.ods.app.ui.utilities.extension.isDarkModeEnabled
import com.orange.ods.compose.component.appbar.top.OdsTopAppBarActionButton
import com.orange.ods.compose.component.appbar.top.OdsTopAppBarOverflowMenuActionItem
import com.orange.ods.compose.component.appbar.top.OdsTopAppBar
import com.orange.ods.compose.component.content.OdsComponentContent
import com.orange.ods.compose.component.textfield.search.OdsSearchTextField

Expand All @@ -45,23 +43,12 @@ enum class AppBarAction {
}
}

data class AppBarOverflowMenuAction(
val title: UiString,
val onClick: () -> Unit
) {
@Composable
fun getOdsTopAppBarOverflowMenuAction() = OdsTopAppBarOverflowMenuActionItem(
text = title.asString(),
onClick = onClick
)
}

@Composable
fun getDefaultActions(onActionClick: (AppBarAction) -> Unit): List<OdsTopAppBarActionButton> =
fun getDefaultActions(onActionClick: (AppBarAction) -> Unit): List<OdsTopAppBar.ActionButton> =
defaultActions.map { it.getOdsTopAppBarAction(onActionClick = onActionClick) }

@Composable
fun getHomeActions(onActionClick: (AppBarAction) -> Unit): List<OdsTopAppBarActionButton> =
fun getHomeActions(onActionClick: (AppBarAction) -> Unit): List<OdsTopAppBar.ActionButton> =
listOf(getSearchAction(onActionClick)) + getDefaultActions(onActionClick = onActionClick)

@Composable
Expand All @@ -87,28 +74,28 @@ fun getSearchFieldAction(onTextChange: (TextFieldValue) -> Unit): OdsComponentCo
}

@Composable
private fun getSearchAction(onClick: (AppBarAction) -> Unit) = OdsTopAppBarActionButton(
private fun getSearchAction(onClick: (AppBarAction) -> Unit) = OdsTopAppBar.ActionButton(
onClick = { onClick(AppBarAction.Search) },
painter = painterResource(id = R.drawable.ic_search),
contentDescription = stringResource(id = R.string.search_content_description)
)

@Composable
private fun getChangeThemeAction(onClick: (AppBarAction) -> Unit) = OdsTopAppBarActionButton(
private fun getChangeThemeAction(onClick: (AppBarAction) -> Unit) = OdsTopAppBar.ActionButton(
onClick = { onClick(AppBarAction.ChangeTheme) },
painter = painterResource(id = R.drawable.ic_palette),
contentDescription = stringResource(id = R.string.top_app_bar_action_change_mode_to_dark_desc)
contentDescription = stringResource(id = R.string.top_app_bar_action_change_theme_desc)
)

@Composable
private fun getChangeModeAction(onClick: (AppBarAction) -> Unit): OdsTopAppBarActionButton {
private fun getChangeModeAction(onClick: (AppBarAction) -> Unit): OdsTopAppBar.ActionButton {
val configuration = LocalConfiguration.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

return OdsTopAppBarActionButton(
return OdsTopAppBar.ActionButton(
onClick = { onClick(AppBarAction.ChangeMode) },
painter = painterResource(id = painterRes),
contentDescription = stringResource(id = iconDesc)
Expand Down
99 changes: 38 additions & 61 deletions app/src/main/java/com/orange/ods/app/ui/AppBarState.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@

package com.orange.ods.app.ui

import android.os.Bundle
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowBack
import androidx.compose.runtime.Composable
Expand All @@ -22,29 +21,23 @@ import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.input.TextFieldValue
import androidx.navigation.NavBackStackEntry
import androidx.navigation.NavController
import androidx.navigation.compose.currentBackStackEntryAsState
import com.orange.ods.app.R
import com.orange.ods.app.domain.recipes.LocalRecipes
import com.orange.ods.app.ui.AppBarAction.Companion.defaultActions
import com.orange.ods.app.ui.AppBarState.Companion.CustomDefaultConfiguration
import com.orange.ods.app.ui.components.appbars.top.TopAppBarCustomizationState
import com.orange.ods.app.ui.components.utilities.clickOnElement
import com.orange.ods.app.ui.utilities.NavigationItem
import com.orange.ods.compose.component.appbar.top.OdsTopAppBarActionButton
import com.orange.ods.compose.component.appbar.top.OdsTopAppBarNavigationIcon
import com.orange.ods.compose.component.appbar.top.OdsTopAppBarOverflowMenuActionItem
import com.orange.ods.compose.component.appbar.top.OdsTopAppBar
import com.orange.ods.compose.component.content.OdsComponentContent
import com.orange.ods.extension.orElse
import com.orange.ods.compose.component.menu.OdsDropdownMenu
import kotlin.math.max

val LocalAppBarManager = staticCompositionLocalOf<AppBarManager> { error("CompositionLocal AppBarManager not present") }

interface AppBarManager {
val searchedText: TextFieldValue

fun setCustomAppBar(appBarConfiguration: AppBarConfiguration)
fun setCustomAppBar(customAppBarConfiguration: CustomAppBarConfiguration)

fun updateAppBarTabs(tabsConfiguration: TabsConfiguration)
fun clearAppBarTabs()
Expand All @@ -53,67 +46,44 @@ interface AppBarManager {
/**
* AppBar state source of truth.
*
* The app bar is managed according to the [Screen] displayed except when its type is [ScreenType.WithCustomizableTopAppBar]. In this case, the app bar is
* displayed according to the provided [AppBarConfiguration].
* The app bar is managed according to the [Screen] displayed except if it has a custom app bar or if the screen cannot be found in the app [Screen]s (for
* example an about module screen). In this case, the app bar is displayed according to the provided [CustomAppBarConfiguration].
*/
class AppBarState(
private val navController: NavController,
private val navigationState: AppNavigationState,
private val searchText: MutableState<TextFieldValue>,
private val customAppBarConfiguration: MutableState<AppBarConfiguration>,
private val customAppBarConfiguration: MutableState<CustomAppBarConfiguration>,
val tabsState: AppBarTabsState
) : AppBarManager {

companion object {
val CustomDefaultConfiguration = AppBarConfiguration(
isLarge = false,
largeTitleRes = R.string.empty,
scrollBehavior = TopAppBarCustomizationState.ScrollBehavior.Collapsible,
isNavigationIconEnabled = true,
actionCount = defaultActions.size,
isOverflowMenuEnabled = false
)
}

private val currentBackStackEntry: NavBackStackEntry?
@Composable get() = navController.currentBackStackEntryAsState().value

private val currentScreenRoute: String?
@Composable get() = currentBackStackEntry?.destination?.route

private val currentScreenRouteArgs: Bundle?
@Composable get() = currentBackStackEntry?.arguments

private val currentScreen: Screen?
@Composable get() = currentScreenRoute?.let { getScreen(it, currentScreenRouteArgs) }

private val isCustom: Boolean
@Composable get() = currentScreen?.hasCustomAppBar.orElse { false }
@Composable get() = navigationState.currentScreen?.hasCustomAppBar != false

private val showNavigationIcon: Boolean
@Composable get() = (isCustom && customAppBarConfiguration.value.isNavigationIconEnabled)
|| (!isCustom && currentScreen?.isHome == false)
|| (!isCustom && navigationState.currentScreen?.isHome(navigationState.previousRoute) == false)

val isLarge: Boolean
@Composable get() = currentScreen?.isLargeAppBar == true
@Composable get() = navigationState.currentScreen?.isLargeAppBar == true

val title: String
@Composable get() = if (isCustom) {
stringResource(id = customAppBarConfiguration.value.largeTitleRes)
customAppBarConfiguration.value.title
} else {
currentScreen?.title?.asString().orEmpty()
navigationState.currentScreen?.title?.asString().orEmpty()
}

val actions: List<OdsComponentContent<Nothing>>
@Composable get() {
val screenAppBarActions = currentScreen?.getAppBarActions { searchText.value = it }.orEmpty()
val screenAppBarActions = navigationState.currentScreen?.getAppBarActions(navigationState.previousRoute) { searchText.value = it }.orEmpty()
return if (isCustom) {
val context = LocalContext.current
val customActionCount = max(0, customAppBarConfiguration.value.actionCount - AppBarAction.defaultActions.size)
val customActions = NavigationItem.values()
val customActions = NavigationItem.entries
.take(customActionCount)
.map {
val contentDescription = stringResource(id = it.textResId)
OdsTopAppBarActionButton(painter = painterResource(id = it.iconResId), contentDescription = contentDescription) {
OdsTopAppBar.ActionButton(painter = painterResource(id = it.iconResId), contentDescription = contentDescription) {
clickOnElement(context, contentDescription)
}
}
Expand All @@ -123,11 +93,11 @@ class AppBarState(
}
}

val overflowMenuActions: List<OdsTopAppBarOverflowMenuActionItem>
val overflowMenuItems: List<OdsDropdownMenu.Item>
@Composable get() = if (isCustom && customAppBarConfiguration.value.isOverflowMenuEnabled) {
val context = LocalContext.current
LocalRecipes.current.map { recipe ->
OdsTopAppBarOverflowMenuActionItem(
OdsDropdownMenu.Item(
text = recipe.title,
onClick = { clickOnElement(context, recipe.title) }
)
Expand All @@ -141,7 +111,7 @@ class AppBarState(

@Composable
fun getNavigationIcon(upPress: () -> Unit) = if (showNavigationIcon) {
OdsTopAppBarNavigationIcon(Icons.Filled.ArrowBack, stringResource(id = R.string.top_app_bar_back_icon_desc), upPress)
OdsTopAppBar.NavigationIcon(Icons.Filled.ArrowBack, stringResource(id = R.string.top_app_bar_back_icon_desc), upPress)
} else {
null
}
Expand All @@ -153,8 +123,8 @@ class AppBarState(
override val searchedText: TextFieldValue
get() = searchText.value

override fun setCustomAppBar(appBarConfiguration: AppBarConfiguration) {
customAppBarConfiguration.value = appBarConfiguration
override fun setCustomAppBar(customAppBarConfiguration: CustomAppBarConfiguration) {
this.customAppBarConfiguration.value = customAppBarConfiguration
}

override fun updateAppBarTabs(tabsConfiguration: TabsConfiguration) {
Expand All @@ -169,19 +139,26 @@ class AppBarState(

@Composable
fun rememberAppBarState(
navController: NavController,
navigationState: AppNavigationState,
searchedText: MutableState<TextFieldValue> = remember { mutableStateOf(TextFieldValue("")) },
customAppBarConfiguration: MutableState<AppBarConfiguration> = remember { mutableStateOf(CustomDefaultConfiguration) },
customAppBarConfiguration: MutableState<CustomAppBarConfiguration> = remember { mutableStateOf(CustomAppBarConfiguration.Default) },
tabsState: AppBarTabsState = rememberAppBarTabsState()
) = remember(navController, searchedText, customAppBarConfiguration, tabsState) {
AppBarState(navController, searchedText, customAppBarConfiguration, tabsState)
) = remember(navigationState, searchedText, customAppBarConfiguration, tabsState) {
AppBarState(navigationState, searchedText, customAppBarConfiguration, tabsState)
}

data class AppBarConfiguration constructor(
val isLarge: Boolean,
val largeTitleRes: Int,
val scrollBehavior: TopAppBarCustomizationState.ScrollBehavior,
val isNavigationIconEnabled: Boolean,
data class CustomAppBarConfiguration constructor(
val title: String,
val actionCount: Int,
val isOverflowMenuEnabled: Boolean
)
val isNavigationIconEnabled: Boolean = true,
val isLarge: Boolean = false,
val scrollBehavior: TopAppBarCustomizationState.ScrollBehavior = TopAppBarCustomizationState.ScrollBehavior.Collapsible,
val isOverflowMenuEnabled: Boolean = false
) {
companion object {
val Default = CustomAppBarConfiguration(
title = "",
actionCount = defaultActions.size,
)
}
}
Loading

0 comments on commit 8433eab

Please sign in to comment.