Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
.externalNativeBuild
.cxx
*.iml
.idea/artifacts
.idea/caches
.idea/compiler.xml
.idea/deviceManager.xml
Expand Down Expand Up @@ -40,3 +41,6 @@ app/src/main/res/raw/changelog.md

# Mustache output
Module.md

# Kotlin Multiplatform
.kotlin/
2 changes: 1 addition & 1 deletion .idea/.name

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

2 changes: 1 addition & 1 deletion app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ fun updateBuildConfig() {
gradle.projectsEvaluated {
tasks["preBuild"].apply {
dependsOn(":checkDocumentation")
dependsOn(":checkNotice")
//dependsOn(":checkNotice")
dependsOn(tasks["updateAppChangelog"])
}
updateBuildConfig()
Expand Down
4 changes: 2 additions & 2 deletions app/src/main/java/com/orange/ouds/app/OudsApplication.kt
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import com.google.firebase.Firebase
import com.google.firebase.crashlytics.crashlytics
import com.orange.ouds.theme.orange.OrangeFontFamily
import com.orange.ouds.theme.orange.OrangeHelveticaNeueArabic
import com.orange.ouds.theme.orange.OrangeHelveticaNeueLatin
import com.orange.ouds.theme.orange.preloadDownloadableFontFamilies
import dagger.hilt.android.HiltAndroidApp

@HiltAndroidApp
Expand All @@ -39,7 +39,7 @@ class OudsApplication : Application() {
// Thus we use the Android Downloadable Fonts feature to retrieve the files on a remote server.
// However the preferred way of using the Helvetica Neue font in the Orange themes is configuring
// bundled font files with `OrangeHelveticaNeueLatin.Bundled` and/or `OrangeHelveticaNeueArabic.Bundled`.
OrangeFontFamily.preloadDownloadableFontFamilies(this, listOf(OrangeHelveticaNeueLatin.Downloadable, OrangeHelveticaNeueArabic.Downloadable)) {
preloadDownloadableFontFamilies(this, listOf(OrangeHelveticaNeueLatin.Downloadable, OrangeHelveticaNeueArabic.Downloadable)) {
areDownloadableOrangeFontFamiliesPreloaded = true
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,13 @@ package com.orange.ouds.app.ui
import androidx.annotation.StringRes
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.PreviewLightDark
Expand Down Expand Up @@ -53,7 +51,7 @@ fun ChangeThemeSettingsDialog(themeState: ThemeState, onThemeSettingsChange: (Ou

@Composable
private fun ChangeThemeSettingsDialogContent(themeState: ThemeState, onThemeSettingsChange: (OudsThemeSettings) -> Unit) {
var themeSettings by rememberSaveable { mutableStateOf(themeState.settings) }
var themeSettings by rememberSaveable(stateSaver = OudsThemeSettings.Saver) { mutableStateOf(themeState.settings) }
DialogContent(
title = stringResource(R.string.app_themeSettingsDialog_label)
) {
Expand Down
7 changes: 4 additions & 3 deletions app/src/main/java/com/orange/ouds/app/ui/ThemeState.kt
Original file line number Diff line number Diff line change
Expand Up @@ -64,17 +64,18 @@ class ThemeState(
save = { state ->
with(state) {
listOf(
settings,
with(OudsThemeSettings.Saver) { save(settings) },
themeNames,
currentThemeName,
areDownloadableOrangeFontFamilyPreloaded
)
}
},
restore = { list ->
restore = { list: List<Any?> ->
val settings = list[0]?.let { OudsThemeSettings.Saver.restore(it) }
@Suppress("UNCHECKED_CAST")
ThemeState(
list[0] as OudsThemeSettings,
settings as OudsThemeSettings,
list[1] as List<String>,
list[2] as String,
list[3] as Boolean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,11 @@ package com.orange.ouds.app.ui.components

import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.WindowInsetsSides
import androidx.compose.foundation.layout.asPaddingValues
import androidx.compose.foundation.layout.consumeWindowInsets
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.only
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.statusBars
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,15 @@ class ThemeDrawableResources(val theme: OudsThemeContract) {
else -> error(ThemeDrawableResources::call)
}

val close: Int
@DrawableRes
get() = when (theme) {
is OrangeTheme, is OrangeCompactTheme -> R.drawable.ic_orange_close
is SoshTheme -> R.drawable.ic_sosh_close
is WireframeTheme -> R.drawable.ic_wireframe_close
else -> error(ThemeDrawableResources::close)
}

val filters: Int
@DrawableRes
get() = when (theme) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.input.TextFieldValue
import androidx.compose.ui.unit.Dp
import com.orange.ouds.app.R
import com.orange.ouds.app.ui.utilities.LocalThemeDrawableResources
import com.orange.ouds.core.component.OudsFilterChip
import com.orange.ouds.core.component.OudsSwitchItem
import com.orange.ouds.core.component.OudsTextInput
Expand Down Expand Up @@ -128,7 +129,7 @@ fun CustomizationFilterChips(
} else {
true
}

Row(
modifier = Modifier
.fillMaxWidth()
Expand Down Expand Up @@ -202,7 +203,7 @@ fun CustomizationTextInput(
keyboardOptions = keyboardOptions,
trailingIconButton = if (value.text.isNotEmpty()) {
OudsTextInputTrailingIconButton(
painter = painterResource(com.orange.ouds.theme.orange.R.drawable.ic_orange_component_tag_close),
painter = painterResource(id = LocalThemeDrawableResources.current.close),
contentDescription = stringResource(R.string.app_components_common_textInputClearIcon_a11y),
onClick = {
onValueChange(value.copy(text = resetValue))
Expand Down
8 changes: 5 additions & 3 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ import com.orange.ouds.gradle.releaseVersion
plugins {
kotlin("jvm")
alias(libs.plugins.compose.compiler) apply false
alias(libs.plugins.compose.multiplatform) apply false
id(libs.plugins.kotlin.multiplatform.get().pluginId) apply false
id(libs.plugins.firebase.appdistribution.get().pluginId) apply false
alias(libs.plugins.firebase.crashlytics) apply false
alias(libs.plugins.google.services) apply false
Expand All @@ -35,9 +37,9 @@ dependencies {
dokka(project(":core"))
dokka(project(":global-raw-tokens"))
dokka(project(":theme-contract"))
dokka(project(":theme-orange"))
dokka(project(":theme-orange-compact"))
dokka(project(":theme-sosh"))
// dokka(project(":theme-orange"))
// dokka(project(":theme-orange-compact"))
// dokka(project(":theme-sosh"))
dokka(project(":theme-wireframe"))
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,6 @@ enum class Component {
TextInput -> listOf("OudsTextInput")
}

return filenames.map { "${project.rootProject.projectDir}/core/src/main/java/com/orange/ouds/core/component/$it.kt" }
return filenames.map { "${project.rootProject.projectDir}/core/src/commonMain/kotlin/com/orange/ouds/core/component/$it.kt" }
}
}
142 changes: 142 additions & 0 deletions buildSrc/src/main/kotlin/kmp-maven-central-publish.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
/*
* Software Name: OUDS Android
* SPDX-FileCopyrightText: Copyright (c) Orange SA
* SPDX-License-Identifier: MIT
*
* This software is distributed under the MIT license,
* the text of which is available at https://opensource.org/license/MIT/
* or see the "LICENSE" file for more details.
*
* Software description: Android library of reusable graphical components
*/

import com.orange.ouds.gradle.Environment
import com.orange.ouds.gradle.MavenCentralPublishPluginExtension
import com.orange.ouds.gradle.artifactId
import com.orange.ouds.gradle.isSnapshot
import org.gradle.api.publish.maven.MavenPublication

plugins {
`maven-publish`
signing
}

val pluginExtension: MavenCentralPublishPluginExtension?
get() = extensions.findByName(MavenCentralPublishPluginExtension.NAME) as? MavenCentralPublishPluginExtension?

apply {
if (pluginExtension == null) {
extensions.create<MavenCentralPublishPluginExtension>(MavenCentralPublishPluginExtension.NAME)
}
}

afterEvaluate {
// Register dokkaJar task if dokkaGenerate exists
if (tasks.findByName("dokkaGenerate") != null) {
tasks.register<Jar>("dokkaJar") {
dependsOn(tasks["dokkaGenerate"])
from(layout.buildDirectory.dir("dokka"))
destinationDirectory = layout.buildDirectory.dir("outputs")
archiveClassifier.set("javadoc")
}
}

if (pluginExtension?.enabled == true) {
publishing {
val groupId = "com.orange.ouds.kmp"
val baseArtifactId = pluginExtension?.artifactId ?: project.artifactId
val version = project.version.toString()

// Configure all KMP auto-generated publications
publications.withType<MavenPublication>().configureEach {
// Override the groupId for all publications
this.groupId = groupId

// Add "ouds-" prefix to all artifact IDs
// kotlinMultiplatform publication gets the base name (e.g., "ouds-foundation")
// Platform-specific publications get suffixes (e.g., "ouds-foundation-android", "ouds-foundation-iosarm64")
val prefixedArtifactId = if (this.artifactId.startsWith("ouds-")) {
this.artifactId
} else {
"ouds-${this.artifactId}"
}
this.artifactId = prefixedArtifactId

// Attach Dokka javadoc jar only to the main kotlinMultiplatform publication
// Platform-specific publications (Android, iOS) don't need separate javadoc
// since they share the same documentation with the main publication
if (this.name == "kotlinMultiplatform" && tasks.findByName("dokkaGenerate") != null) {
val dokkaJar = layout.buildDirectory.file("outputs/${project.name}-${project.version}-javadoc.jar")
val dokkaArtifact = this@afterEvaluate.artifacts.add("default", dokkaJar) {
type = "jar"
builtBy(tasks["dokkaJar"])
}
artifact(dokkaArtifact)
}

// Configure POM metadata for all publications
pom {
configurePom(this@configureEach.artifactId)
}
}

repositories {
maven {
val releasesRepositoryUrl = "https://ossrh-staging-api.central.sonatype.com/service/local/staging/deploy/maven2/"
val snapshotsRepositoryUrl = "https://central.sonatype.com/repository/maven-snapshots"
url = uri(if (isSnapshot) snapshotsRepositoryUrl else releasesRepositoryUrl)
credentials {
val (username, password) = Environment.getVariablesOrNull("CENTRAL_PUBLISHER_PORTAL_USERNAME", "CENTRAL_PUBLISHER_PORTAL_PASSWORD")
this.username = username
this.password = password
}
}
}
}

signing {
val (signingKeyId, signingSecretKey, signingPassword) = Environment.getVariablesOrNull(
"GNUPG_SIGNING_KEY_ID",
"GNUPG_SIGNING_SECRET_KEY",
"GNUPG_SIGNING_PASSWORD"
)

// Only configure signing if credentials are available
if (signingKeyId != null && signingSecretKey != null && signingPassword != null) {
useInMemoryPgpKeys(signingKeyId, signingSecretKey, signingPassword)
// Sign all publications
sign(publishing.publications)
}
}
}
}

private fun MavenPom.configurePom(artifactId: String) {
val description = "Orange Unified Design System for Android"
val gitHubUrl = "https://github.com/Orange-OpenSource/ouds-android"

name.set(artifactId)
this.description.set(description)
url.set(gitHubUrl)
licenses {
license {
name.set("MIT License")
url.set("https://github.com/Orange-OpenSource/ouds-android/blob/main/LICENSE")
}
}
scm {
url.set(gitHubUrl)
connection.set("scm:git:git://github.com/Orange-OpenSource/ouds-android.git")
developerConnection.set("scm:git:ssh://git@github.com/Orange-OpenSource/ouds-android.git")
}
developers {
developer {
name.set("Pauline Auvray")
email.set("pauline.auvray@orange.com")
}
developer {
name.set("Florent Maitre")
email.set("florent.maitre@orange.com")
}
}
}
6 changes: 4 additions & 2 deletions buildSrc/src/main/kotlin/maven-central-publish.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import com.orange.ouds.gradle.artifactId
import com.orange.ouds.gradle.isSnapshot

plugins {
id("com.android.library")
// id("com.android.library")
`maven-publish`
signing
}
Expand Down Expand Up @@ -68,7 +68,9 @@ afterEvaluate {
}

create<MavenPublication>(MavenCentralPublishPluginExtension.VARIANT) {
from(components["release"])
// Use "kotlin" component for KMP projects, "release" for Android library projects
val componentName = if (components.findByName("kotlin") != null) "kotlin" else "release"
from(components[componentName])
this.groupId = groupId
this.artifactId = artifactId
this.version = version
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.ui.platform.LocalInspectionMode
import androidx.compose.ui.tooling.preview.Devices
import app.cash.paparazzi.DeviceConfig
import app.cash.paparazzi.Environment
import app.cash.paparazzi.Paparazzi
import app.cash.paparazzi.detectEnvironment
import com.android.ide.common.rendering.api.SessionParams
import com.orange.ouds.core.utilities.OudsPreviewDevice
import com.orange.ouds.theme.OudsThemeContract
Expand Down Expand Up @@ -68,6 +70,7 @@ abstract class OudsSnapshotTest(val theme: OudsThemeContract, widthDp: Int = -1,

@get:Rule
val paparazzi = Paparazzi(
environment = detectEnvironment().filterResources(),
renderingMode = SessionParams.RenderingMode.SHRINK,
deviceConfig = with(deviceConfig) {
val width = if (widthDp > 0) (widthDp * density.dpiValue / 160f).toInt() else screenWidth
Expand Down Expand Up @@ -123,3 +126,18 @@ abstract class OudsSnapshotTest(val theme: OudsThemeContract, widthDp: Int = -1,
}
}
}

private fun Environment.filterResources(): Environment {
return copy(
resourcePackageNames = resourcePackageNames.filter { packageName ->
val resourceName = "$packageName.R"
try {
Class.forName(resourceName)
true
} catch (_: ClassNotFoundException) {
println("Skipping resource '$resourceName': not found in classpath. Test should proceed without any problem.")
false
}
}
)
}
Loading