From 5a1698a424ede4ffd36be79c399172c7e0ed4064 Mon Sep 17 00:00:00 2001 From: Florent Maitre Date: Fri, 20 Dec 2024 11:53:45 +0100 Subject: [PATCH] Refactor getTokens method now that OudsKeyToken exists --- .../ouds/app/ui/tokens/TokenCategory.kt | 20 ++-- .../ouds/app/ui/tokens/TokenProperty.kt | 111 ++++++++++++++---- .../ui/tokens/TokenPropertyIllustration.kt | 3 +- .../orange/ouds/app/ui/utilities/KClassExt.kt | 82 +------------ 4 files changed, 99 insertions(+), 117 deletions(-) diff --git a/app/src/main/java/com/orange/ouds/app/ui/tokens/TokenCategory.kt b/app/src/main/java/com/orange/ouds/app/ui/tokens/TokenCategory.kt index cfbff986..15002602 100644 --- a/app/src/main/java/com/orange/ouds/app/ui/tokens/TokenCategory.kt +++ b/app/src/main/java/com/orange/ouds/app/ui/tokens/TokenCategory.kt @@ -16,11 +16,11 @@ import androidx.annotation.DrawableRes import androidx.annotation.StringRes import androidx.compose.runtime.Immutable import com.orange.ouds.app.R -import com.orange.ouds.app.ui.utilities.getTokenName import com.orange.ouds.theme.tokens.OudsBorderKeyToken import com.orange.ouds.theme.tokens.OudsColorKeyToken import com.orange.ouds.theme.tokens.OudsElevationKeyToken import com.orange.ouds.theme.tokens.OudsGridKeyToken +import com.orange.ouds.theme.tokens.OudsKeyToken import com.orange.ouds.theme.tokens.OudsOpacityKeyToken import com.orange.ouds.theme.tokens.OudsSizeKeyToken import com.orange.ouds.theme.tokens.OudsSpaceKeyToken @@ -50,7 +50,7 @@ sealed class TokenCategory( R.string.app_tokens_border_label, R.drawable.ic_border, R.string.app_tokens_border_description_text, - getTokenValueCode(), + getTokenValueCode(OudsBorderKeyToken.Width.None), listOf(TokenProperty.BorderWidth, TokenProperty.BorderRadius, TokenProperty.BorderStyle), ) @@ -58,7 +58,7 @@ sealed class TokenCategory( R.string.app_tokens_color_label, R.drawable.ic_palette, R.string.app_tokens_color_description_text, - getTokenValueCode(), + getTokenValueCode(OudsColorKeyToken.Action.Disabled), listOf( TokenProperty.ColorAction, TokenProperty.ColorAlways, @@ -81,7 +81,7 @@ sealed class TokenCategory( R.string.app_tokens_dimension_space_label, R.drawable.ic_dimension, R.string.app_tokens_dimension_space_description_text, - getTokenValueCode(), + getTokenValueCode(OudsSpaceKeyToken.Scaled.None), listOf( TokenProperty.SpaceScaled, TokenProperty.SpaceFixed, @@ -97,7 +97,7 @@ sealed class TokenCategory( R.string.app_tokens_dimension_size_label, R.drawable.ic_dimension, R.string.app_tokens_dimension_size_description_text, - getTokenValueCode(), + getTokenValueCode(OudsSizeKeyToken.Icon.Decorative.ExtraExtraSmall), listOf(TokenProperty.SizeIconDecorative, TokenProperty.SizeIconWithText), ) } @@ -106,7 +106,7 @@ sealed class TokenCategory( R.string.app_tokens_elevation_label, R.drawable.ic_layers, R.string.app_tokens_elevation_description_text, - getTokenValueCode(), + getTokenValueCode(OudsElevationKeyToken.None), listOf(TokenProperty.Elevation) ) @@ -114,7 +114,7 @@ sealed class TokenCategory( R.string.app_tokens_grid_label, R.drawable.ic_menu_grid, R.string.app_tokens_grid_description_text, - getTokenValueCode(), + getTokenValueCode(OudsGridKeyToken.MinWidth), listOf(TokenProperty.Grid) ) @@ -122,7 +122,7 @@ sealed class TokenCategory( R.string.app_tokens_opacity_label, R.drawable.ic_filter_effects, R.string.app_tokens_opacity_description_text, - getTokenValueCode(), + getTokenValueCode(OudsOpacityKeyToken.Invisible), listOf(TokenProperty.Opacity) ) @@ -130,9 +130,9 @@ sealed class TokenCategory( R.string.app_tokens_typography_label, R.drawable.ic_typography, R.string.app_tokens_typography_description_text, - getTokenValueCode(), + getTokenValueCode(OudsTypographyKeyToken.Display.Large), listOf(TokenProperty.Typography) ) } -private inline fun getTokenValueCode() = "${T::class.getTokenName()}.value" \ No newline at end of file +private fun getTokenValueCode(keyToken: OudsKeyToken) = "${keyToken.name}.value" \ No newline at end of file diff --git a/app/src/main/java/com/orange/ouds/app/ui/tokens/TokenProperty.kt b/app/src/main/java/com/orange/ouds/app/ui/tokens/TokenProperty.kt index 9940a412..9a60bceb 100644 --- a/app/src/main/java/com/orange/ouds/app/ui/tokens/TokenProperty.kt +++ b/app/src/main/java/com/orange/ouds/app/ui/tokens/TokenProperty.kt @@ -14,12 +14,13 @@ package com.orange.ouds.app.ui.tokens import androidx.annotation.StringRes import com.orange.ouds.app.R -import com.orange.ouds.app.ui.utilities.getTokenName -import com.orange.ouds.app.ui.utilities.getTokens +import com.orange.ouds.app.ui.utilities.getSealedSubclasses +import com.orange.ouds.core.theme.value import com.orange.ouds.theme.tokens.OudsBorderKeyToken import com.orange.ouds.theme.tokens.OudsColorKeyToken import com.orange.ouds.theme.tokens.OudsElevationKeyToken import com.orange.ouds.theme.tokens.OudsGridKeyToken +import com.orange.ouds.theme.tokens.OudsKeyToken import com.orange.ouds.theme.tokens.OudsOpacityKeyToken import com.orange.ouds.theme.tokens.OudsSizeKeyToken import com.orange.ouds.theme.tokens.OudsSpaceKeyToken @@ -34,91 +35,91 @@ sealed class TokenProperty( data object BorderRadius : TokenProperty( nameRes = R.string.app_tokens_border_radius_label, - tokens = OudsBorderKeyToken.Radius::class.getTokens(), + tokens = getTokens(), categoryClass = TokenCategory.Border::class ) data object BorderStyle : TokenProperty( nameRes = R.string.app_tokens_border_style_label, - tokens = OudsBorderKeyToken.Style::class.getTokens(), + tokens = getTokens(), categoryClass = TokenCategory.Border::class ) data object BorderWidth : TokenProperty( nameRes = R.string.app_tokens_border_width_label, - tokens = OudsBorderKeyToken.Width::class.getTokens(), + tokens = getTokens(), categoryClass = TokenCategory.Border::class ) data object ColorAction : TokenProperty( nameRes = R.string.app_tokens_color_action_label, - tokens = OudsColorKeyToken.Action::class.getTokens(), + tokens = getTokens(), categoryClass = TokenCategory.Color::class ) data object ColorAlways : TokenProperty( nameRes = R.string.app_tokens_color_always_label, - tokens = OudsColorKeyToken.Always::class.getTokens(), + tokens = getTokens(), categoryClass = TokenCategory.Color::class ) data object ColorBackground : TokenProperty( nameRes = R.string.app_tokens_color_background_label, - tokens = OudsColorKeyToken.Background::class.getTokens(), + tokens = getTokens(), categoryClass = TokenCategory.Color::class ) data object ColorBorder : TokenProperty( nameRes = R.string.app_tokens_color_border_label, - tokens = OudsColorKeyToken.Border::class.getTokens(), + tokens = getTokens(), categoryClass = TokenCategory.Color::class ) data object ColorContent : TokenProperty( nameRes = R.string.app_tokens_color_content_label, - tokens = OudsColorKeyToken.Content::class.getTokens(), + tokens = getTokens(), categoryClass = TokenCategory.Color::class ) data object ColorDecorative : TokenProperty( nameRes = R.string.app_tokens_color_decorative_label, - tokens = OudsColorKeyToken.Decorative::class.getTokens(), + tokens = getTokens(), categoryClass = TokenCategory.Color::class ) data object ColorOverlay : TokenProperty( nameRes = R.string.app_tokens_color_overlay_label, - tokens = OudsColorKeyToken.Overlay::class.getTokens(), + tokens = getTokens(), categoryClass = TokenCategory.Color::class ) data object ColorSurface : TokenProperty( nameRes = R.string.app_tokens_color_surface_label, - tokens = OudsColorKeyToken.Surface::class.getTokens(), + tokens = getTokens(), categoryClass = TokenCategory.Color::class ) data object Elevation : TokenProperty( nameRes = null, - tokens = OudsElevationKeyToken::class.getTokens(), + tokens = getTokens(), categoryClass = TokenCategory.Elevation::class ) data object Grid : TokenProperty( nameRes = null, - tokens = OudsGridKeyToken::class.getTokens(), + tokens = getTokens(), categoryClass = TokenCategory.Grid::class ) data object Opacity : TokenProperty( nameRes = null, - tokens = OudsOpacityKeyToken::class.getTokens(), + tokens = getTokens(), categoryClass = TokenCategory.Opacity::class ) data object SizeIconDecorative : TokenProperty( nameRes = R.string.app_tokens_dimension_size_iconDecorative_label, - tokens = OudsSizeKeyToken.Icon.Decorative::class.getTokens(), + tokens = getTokens(), categoryClass = TokenCategory.Dimension.Size::class ) @@ -137,60 +138,118 @@ sealed class TokenProperty( OudsSizeKeyToken.Icon.WithLabel.Medium::class, OudsSizeKeyToken.Icon.WithLabel.Small::class, ).flatMap { keyTokenClass -> - keyTokenClass.getTokens(tokenName = { it.getTokenName(OudsSizeKeyToken.Icon::class).removePrefix("With") }) + getTokens(keyTokenClass, tokenName = { it.getRelativeName(OudsSizeKeyToken.Icon::class).removePrefix("With") }) }, categoryClass = TokenCategory.Dimension.Size::class ) data object SpaceColumnGap : TokenProperty( nameRes = R.string.app_tokens_dimension_space_columnGap_label, - tokens = OudsSpaceKeyToken.ColumnGap::class.getTokens(recursive = false), + tokens = getTokens(recursive = false), categoryClass = TokenCategory.Dimension.Space::class ) data object SpaceFixed : TokenProperty( nameRes = R.string.app_tokens_dimension_space_fixed_label, - tokens = OudsSpaceKeyToken.Fixed::class.getTokens(), + tokens = getTokens(), categoryClass = TokenCategory.Dimension.Space::class ) data object SpacePaddingInline : TokenProperty( nameRes = R.string.app_tokens_dimension_space_paddingInline_label, - tokens = OudsSpaceKeyToken.PaddingInline::class.getTokens(recursive = false), + tokens = getTokens(recursive = false), categoryClass = TokenCategory.Dimension.Space::class ) data object SpacePaddingInset : TokenProperty( nameRes = R.string.app_tokens_dimension_space_paddingInset_label, - tokens = OudsSpaceKeyToken.Inset::class.getTokens(), + tokens = getTokens(), categoryClass = TokenCategory.Dimension.Space::class ) data object SpacePaddingStack : TokenProperty( nameRes = R.string.app_tokens_dimension_space_paddingStack_label, - tokens = OudsSpaceKeyToken.PaddingBlock::class.getTokens(recursive = false), + tokens = getTokens(recursive = false), categoryClass = TokenCategory.Dimension.Space::class ) data object SpaceRowGap : TokenProperty( nameRes = R.string.app_tokens_dimension_space_rowGap_label, - tokens = OudsSpaceKeyToken.RowGap::class.getTokens(recursive = false), + tokens = getTokens(recursive = false), categoryClass = TokenCategory.Dimension.Space::class ) data object SpaceScaled : TokenProperty( nameRes = R.string.app_tokens_dimension_space_scaled_label, - tokens = OudsSpaceKeyToken.Scaled::class.getTokens(), + tokens = getTokens(), categoryClass = TokenCategory.Dimension.Space::class ) data object Typography : TokenProperty( nameRes = null, - tokens = OudsTypographyKeyToken::class.getTokens(), + tokens = getTokens(), categoryClass = TokenCategory.Typography::class ) } +inline fun getTokens( + recursive: Boolean = true, + noinline tokenName: (T) -> String = { it.getRelativeName(T::class) } +): List> where T : OudsKeyToken { + return getTokens(T::class, recursive, tokenName) +} + +fun getTokens( + clazz: KClass, + recursive: Boolean = true, + tokenName: (T) -> String = { it.getRelativeName(clazz) } +): List> where T : OudsKeyToken { + return clazz.getSealedSubclasses(recursive) + .mapNotNull { it.objectInstance } + .sortedBy { keyToken -> + when (keyToken) { + is OudsBorderKeyToken.Radius -> keyToken.order + is OudsBorderKeyToken.Width -> keyToken.order + is OudsElevationKeyToken -> keyToken.order + is OudsOpacityKeyToken -> keyToken.order + is OudsSizeKeyToken.Icon -> keyToken.order + is OudsSpaceKeyToken.ColumnGap -> keyToken.order + is OudsSpaceKeyToken.Fixed -> keyToken.order + is OudsSpaceKeyToken.Inset -> keyToken.order + is OudsSpaceKeyToken.PaddingBlock -> keyToken.order + is OudsSpaceKeyToken.PaddingInline -> keyToken.order + is OudsSpaceKeyToken.RowGap -> keyToken.order + is OudsSpaceKeyToken.Scaled -> keyToken.order + else -> 0 + } + }.map { keyToken -> + Token( + name = tokenName(keyToken), + value = { + when (keyToken) { + is OudsBorderKeyToken.Radius -> keyToken.value + is OudsBorderKeyToken.Style -> keyToken.value + is OudsBorderKeyToken.Width -> keyToken.value + is OudsColorKeyToken -> keyToken.value + is OudsElevationKeyToken -> keyToken.value + is OudsGridKeyToken -> keyToken.value + is OudsOpacityKeyToken -> keyToken.value + is OudsSizeKeyToken -> keyToken.value + is OudsSpaceKeyToken -> keyToken.value + is OudsTypographyKeyToken -> keyToken.value + else -> null + } + } + ) + } +} + +fun T.getRelativeName(parent: KClass): String where T : S, S : OudsKeyToken { + val parentPackageName = parent.java.`package`?.name.orEmpty() + val prefix = parent.qualifiedName.orEmpty().removePrefix("$parentPackageName.") + return name.removePrefix("$prefix.") +} + val OudsBorderKeyToken.Radius.order: Int get() = when (this) { OudsBorderKeyToken.Radius.None -> 0 diff --git a/app/src/main/java/com/orange/ouds/app/ui/tokens/TokenPropertyIllustration.kt b/app/src/main/java/com/orange/ouds/app/ui/tokens/TokenPropertyIllustration.kt index ee49a358..10dc9af2 100644 --- a/app/src/main/java/com/orange/ouds/app/ui/tokens/TokenPropertyIllustration.kt +++ b/app/src/main/java/com/orange/ouds/app/ui/tokens/TokenPropertyIllustration.kt @@ -43,7 +43,6 @@ import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import com.orange.ouds.app.R -import com.orange.ouds.app.ui.utilities.getTokens import com.orange.ouds.core.theme.value import com.orange.ouds.foundation.extensions.asOrNull import com.orange.ouds.foundation.extensions.orElse @@ -137,7 +136,7 @@ fun SizeIconWithTextIllustrationRow(size: Dp, tokenName: String) { contentDescription = null ) val tokenTypography = tokenName.split('.').take(2).joinToString(".") - val style = OudsTypographyKeyToken::class.getTokens() + val style = getTokens() .asOrNull>>() ?.firstOrNull { typographyToken -> typographyToken.name.replace(".Strong", "") == tokenTypography diff --git a/app/src/main/java/com/orange/ouds/app/ui/utilities/KClassExt.kt b/app/src/main/java/com/orange/ouds/app/ui/utilities/KClassExt.kt index 2c661a2b..5509c50c 100644 --- a/app/src/main/java/com/orange/ouds/app/ui/utilities/KClassExt.kt +++ b/app/src/main/java/com/orange/ouds/app/ui/utilities/KClassExt.kt @@ -12,88 +12,12 @@ package com.orange.ouds.app.ui.utilities -import com.orange.ouds.app.ui.tokens.Token -import com.orange.ouds.app.ui.tokens.order -import com.orange.ouds.core.theme.value -import com.orange.ouds.foundation.extensions.asOrNull -import com.orange.ouds.foundation.extensions.orElse -import com.orange.ouds.theme.tokens.OudsBorderKeyToken -import com.orange.ouds.theme.tokens.OudsColorKeyToken -import com.orange.ouds.theme.tokens.OudsElevationKeyToken -import com.orange.ouds.theme.tokens.OudsGridKeyToken -import com.orange.ouds.theme.tokens.OudsOpacityKeyToken -import com.orange.ouds.theme.tokens.OudsSizeKeyToken -import com.orange.ouds.theme.tokens.OudsSpaceKeyToken -import com.orange.ouds.theme.tokens.OudsTypographyKeyToken import kotlin.reflect.KClass -fun KClass<*>.getTokens( - recursive: Boolean = true, - tokenName: (KClass<*>) -> String = { it.getTokenName(this) } -): List> { - return getNestedObjects(getRootKeyTokenSuperclass(), recursive).sortedBy { keyToken -> - when (keyToken) { - is OudsBorderKeyToken.Radius -> keyToken.order - is OudsBorderKeyToken.Width -> keyToken.order - is OudsElevationKeyToken -> keyToken.order - is OudsOpacityKeyToken -> keyToken.order - is OudsSizeKeyToken.Icon -> keyToken.order - is OudsSpaceKeyToken.ColumnGap -> keyToken.order - is OudsSpaceKeyToken.Fixed -> keyToken.order - is OudsSpaceKeyToken.Inset -> keyToken.order - is OudsSpaceKeyToken.PaddingBlock -> keyToken.order - is OudsSpaceKeyToken.PaddingInline -> keyToken.order - is OudsSpaceKeyToken.RowGap -> keyToken.order - is OudsSpaceKeyToken.Scaled -> keyToken.order - else -> 0 - } - }.map { keyToken -> - Token( - name = tokenName(keyToken::class), - value = { - when (keyToken) { - is OudsBorderKeyToken.Radius -> keyToken.value - is OudsBorderKeyToken.Style -> keyToken.value - is OudsBorderKeyToken.Width -> keyToken.value - is OudsColorKeyToken -> keyToken.value - is OudsElevationKeyToken -> keyToken.value - is OudsGridKeyToken -> keyToken.value - is OudsOpacityKeyToken -> keyToken.value - is OudsSizeKeyToken -> keyToken.value - is OudsSpaceKeyToken -> keyToken.value - is OudsTypographyKeyToken -> keyToken.value - else -> null - } - } - ) - } -} - -fun KClass<*>.getTokenName(fromParent: KClass<*>? = null): String { - val prefix = if (fromParent != null) "${fromParent.qualifiedName.orEmpty()}." else "${java.`package`?.name.orEmpty()}." - - return qualifiedName.orEmpty() - .removePrefix(prefix) - .removeSuffix(".Companion") -} - -private fun KClass<*>.getNestedObjects(clazz: KClass, recursive: Boolean = true): List { - return getNestedClasses(recursive).mapNotNull { it.objectInstance }.filterIsInstance(clazz.java) -} - -private fun KClass<*>.getNestedClasses(recursive: Boolean = true): List> { +fun KClass.getSealedSubclasses(recursive: Boolean = true): List> { return if (recursive) { - nestedClasses + nestedClasses.flatMap { it.getNestedClasses(recursive = true) } + sealedSubclasses + sealedSubclasses.flatMap { it.getSealedSubclasses(recursive = true) } } else { - nestedClasses.toList() + sealedSubclasses.toList() } } - -private fun KClass<*>.getRootKeyTokenSuperclass(): KClass<*> { - return supertypes.firstOrNull() - ?.classifier - ?.asOrNull>() - ?.takeIf { it != Any::class } - ?.getRootKeyTokenSuperclass() - .orElse { this } -}