Create first production version (1.0.0) #5

Merged
Antoine_Jaury_KSK merged 36 commits from release/1.0.0 into develop 2026-11-10 17:50:20 +01:00
12 changed files with 172 additions and 30 deletions
Showing only changes of commit abeb484258 - Show all commits

No files matched your search

+9
View File
@@ -1,9 +1,18 @@
plugins {
id("gwenedeg.kmp.library")
id("gwenedeg.compose")
}
kotlin {
androidLibrary {
namespace = "bzh.ajaury.chombev.core.accessibility"
}
sourceSets {
commonMain.dependencies {
// UI - Compose
implementation(libs.compose.runtime)
implementation(libs.compose.ui)
}
}
}
@@ -0,0 +1,7 @@
package bzh.ajaury.chombev.core.accessibility.ui
import androidx.compose.runtime.Composable
/** No-op: the font scale already follows the system setting. */
@Composable
actual fun ProvideDynamicTypeFontScale(content: @Composable () -> Unit) = content()
@@ -0,0 +1,13 @@
package bzh.ajaury.chombev.core.accessibility.ui
import androidx.compose.runtime.Composable
/**
* Applies the system text size to [content] as soon as the user changes it.
*
* Only needed on iOS, see its implementation. Every Compose scene must be wrapped: the root one
* and each dialog or bottom sheet, which iOS renders in a scene of its own that does not inherit
* the font scale provided by the root one.
*/
@Composable
expect fun ProvideDynamicTypeFontScale(content: @Composable () -> Unit)
@@ -0,0 +1,80 @@
package bzh.ajaury.chombev.core.accessibility.ui
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.unit.Density
import platform.Foundation.NSNotificationCenter
import platform.Foundation.NSOperationQueue
import platform.UIKit.UIApplication
import platform.UIKit.UIContentSizeCategoryAccessibilityExtraExtraExtraLarge
import platform.UIKit.UIContentSizeCategoryAccessibilityExtraExtraLarge
import platform.UIKit.UIContentSizeCategoryAccessibilityExtraLarge
import platform.UIKit.UIContentSizeCategoryAccessibilityLarge
import platform.UIKit.UIContentSizeCategoryAccessibilityMedium
import platform.UIKit.UIContentSizeCategoryDidChangeNotification
import platform.UIKit.UIContentSizeCategoryExtraExtraExtraLarge
import platform.UIKit.UIContentSizeCategoryExtraExtraLarge
import platform.UIKit.UIContentSizeCategoryExtraLarge
import platform.UIKit.UIContentSizeCategoryExtraSmall
import platform.UIKit.UIContentSizeCategoryLarge
import platform.UIKit.UIContentSizeCategoryMedium
import platform.UIKit.UIContentSizeCategorySmall
/**
* Applies the system text size (Dynamic Type) to [content] as soon as the user changes it.
*
* Compose Multiplatform reads the font scale once, when the Compose scene is created, so a change
* made in the iOS settings only shows once the scene is created again: after the app restarts for
* the root scene, or when it is opened again for a dialog or bottom sheet. Workaround for CMP-10365
* (https://youtrack.jetbrains.com/issue/CMP-10365), fixed in Compose Multiplatform 1.13.0: remove
* it once the project is upgraded.
*/
@Composable
actual fun ProvideDynamicTypeFontScale(content: @Composable () -> Unit) {
var contentSizeCategory by remember {
mutableStateOf(UIApplication.sharedApplication.preferredContentSizeCategory)
}
DisposableEffect(Unit) {
val notificationCenter = NSNotificationCenter.defaultCenter
val observer = notificationCenter.addObserverForName(
name = UIContentSizeCategoryDidChangeNotification,
`object` = null,
queue = NSOperationQueue.mainQueue,
) { _ ->
contentSizeCategory = UIApplication.sharedApplication.preferredContentSizeCategory
}
onDispose { notificationCenter.removeObserver(observer) }
}
val density = LocalDensity.current
// Only the font scale is overridden: the pixel density stays the one Compose computed.
val fontScale = contentSizeCategoryToFontScale[contentSizeCategory] ?: density.fontScale
CompositionLocalProvider(
LocalDensity provides Density(density = density.density, fontScale = fontScale),
content = content,
)
}
// Same mapping as Compose Multiplatform (`uiContentSizeCategoryToFontScaleMap`, which is private),
// so that the font scale matches the one Compose computes when the scene is created.
private val contentSizeCategoryToFontScale = mapOf(
UIContentSizeCategoryExtraSmall to 0.8f,
UIContentSizeCategorySmall to 0.85f,
UIContentSizeCategoryMedium to 0.9f,
UIContentSizeCategoryLarge to 1f,
UIContentSizeCategoryExtraLarge to 1.1f,
UIContentSizeCategoryExtraExtraLarge to 1.2f,
UIContentSizeCategoryExtraExtraExtraLarge to 1.3f,
UIContentSizeCategoryAccessibilityMedium to 1.4f,
UIContentSizeCategoryAccessibilityLarge to 1.5f,
UIContentSizeCategoryAccessibilityExtraLarge to 1.6f,
UIContentSizeCategoryAccessibilityExtraExtraLarge to 1.7f,
UIContentSizeCategoryAccessibilityExtraExtraExtraLarge to 1.8f,
)
@@ -0,0 +1,7 @@
package bzh.ajaury.chombev.core.accessibility.ui
import androidx.compose.runtime.Composable
/** No-op: the font scale already follows the system setting. */
@Composable
actual fun ProvideDynamicTypeFontScale(content: @Composable () -> Unit) = content()
@@ -0,0 +1,7 @@
package bzh.ajaury.chombev.core.accessibility.ui
import androidx.compose.runtime.Composable
/** No-op: the font scale already follows the system setting. */
@Composable
actual fun ProvideDynamicTypeFontScale(content: @Composable () -> Unit) = content()
+3
View File
@@ -13,6 +13,9 @@ kotlin {
implementation(libs.compose.uiToolingPreview)
}
commonMain.dependencies {
// Core modules
implementation(projects.core.accessibility)
// Data modules
implementation(projects.data.preferences)
implementation(projects.data.resources)
@@ -33,6 +33,7 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.Dialog
import androidx.compose.ui.window.DialogProperties
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import bzh.ajaury.chombev.core.accessibility.ui.ProvideDynamicTypeFontScale
import bzh.ajaury.chombev.onboarding.model.OnboardingLevel
import bzh.ajaury.chombev.onboarding.ui.components.OnboardingInfoPage
import bzh.ajaury.chombev.onboarding.ui.components.OnboardingLevelPage
@@ -90,19 +91,21 @@ fun OnboardingScreen(
// The content sizes itself against the window rather than the platform default width.
properties = DialogProperties(usePlatformDefaultWidth = false),
) {
Surface(
modifier = Modifier
.sizeIn(maxWidth = DIALOG_MAX_WIDTH, maxHeight = DIALOG_MAX_HEIGHT)
.fillMaxSize(fraction = DIALOG_WINDOW_FRACTION),
shape = MaterialTheme.shapes.extraLarge,
color = MaterialTheme.colorScheme.surfaceContainerHigh,
) {
OnboardingContent(
uiState = uiState,
onLevelSelected = onLevelSelected,
onFinish = onFinish,
onClose = onDismiss,
)
ProvideDynamicTypeFontScale {
Surface(
modifier = Modifier
.sizeIn(maxWidth = DIALOG_MAX_WIDTH, maxHeight = DIALOG_MAX_HEIGHT)
.fillMaxSize(fraction = DIALOG_WINDOW_FRACTION),
shape = MaterialTheme.shapes.extraLarge,
color = MaterialTheme.colorScheme.surfaceContainerHigh,
) {
OnboardingContent(
uiState = uiState,
onLevelSelected = onLevelSelected,
onFinish = onFinish,
onClose = onDismiss,
)
}
}
}
} else {
@@ -14,6 +14,7 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import bzh.ajaury.chombev.core.accessibility.ui.ProvideDynamicTypeFontScale
import bzh.ajaury.chombev.player.ui.components.LabeledSlider
import bzh.ajaury.chombev.preferences.model.PlaybackPreferences
import bzh.ajaury.chombev.preferences.ui.PreferenceToggle
@@ -50,14 +51,16 @@ fun PlaybackSpeedBottomSheet(
onDismissRequest = onDismiss,
sheetState = sheetState,
) {
PlaybackSpeedContent(
speed = speed,
breakSeconds = breakSeconds,
autoPause = autoPause,
onSpeedChange = onSpeedChange,
onBreakChange = onBreakChange,
onAutoPauseChange = onAutoPauseChange,
)
ProvideDynamicTypeFontScale {
PlaybackSpeedContent(
speed = speed,
breakSeconds = breakSeconds,
autoPause = autoPause,
onSpeedChange = onSpeedChange,
onBreakChange = onBreakChange,
onAutoPauseChange = onAutoPauseChange,
)
}
}
}
@@ -32,6 +32,7 @@ import androidx.compose.ui.semantics.setProgress
import androidx.compose.ui.semantics.stateDescription
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import bzh.ajaury.chombev.core.accessibility.ui.ProvideDynamicTypeFontScale
import bzh.ajaury.chombev.preferences.model.SubtitlePreferences
import bzh.ajaury.chombev.resources.generated.resources.Res
import bzh.ajaury.chombev.resources.generated.resources.subtitle_marked_letters_description
@@ -68,14 +69,16 @@ fun SubtitlePreferencesBottomSheet(
onDismissRequest = onDismiss,
sheetState = sheetState,
) {
SubtitlePreferencesContent(
subtitlePreferences = subtitlePreferences,
onShowTranscriptionChange = onShowTranscriptionChange,
onShowTranslationChange = onShowTranslationChange,
onShowMarkedLettersChange = onShowPhoneticMarkerChange,
onTextSizeDecrease = onTextSizeDecrease,
onTextSizeIncrease = onTextSizeIncrease,
)
ProvideDynamicTypeFontScale {
SubtitlePreferencesContent(
subtitlePreferences = subtitlePreferences,
onShowTranscriptionChange = onShowTranscriptionChange,
onShowTranslationChange = onShowTranslationChange,
onShowMarkedLettersChange = onShowPhoneticMarkerChange,
onTextSizeDecrease = onTextSizeDecrease,
onTextSizeIncrease = onTextSizeIncrease,
)
}
}
}
+1
View File
@@ -35,6 +35,7 @@ kotlin {
}
commonMain.dependencies {
// Core modules
implementation(projects.core.accessibility)
implementation(projects.core.coroutines)
implementation(projects.core.logging)
implementation(projects.core.model)
@@ -1,6 +1,12 @@
package bzh.ajaury.chombev
import androidx.compose.ui.window.ComposeUIViewController
import bzh.ajaury.chombev.core.accessibility.ui.ProvideDynamicTypeFontScale
@Suppress("ktlint:standard:function-naming")
fun MainViewController() = ComposeUIViewController { App() }
fun MainViewController() =
ComposeUIViewController {
ProvideDynamicTypeFontScale {
App()
}
}