From ad66cb0460d61882545fb48904c67c268e4fb3c0 Mon Sep 17 00:00:00 2001 From: Femi Ogundipe Date: Tue, 17 Mar 2026 12:32:30 +0100 Subject: [PATCH 1/7] Add 'Increase app text size' option to settings and implement 1.25x scaling --- .../java/be/scri/activities/MainActivity.kt | 14 ++++++++++++++ app/src/main/java/be/scri/App.kt | 6 ++++++ .../main/java/be/scri/helpers/PreferencesHelper.kt | 14 ++++++++++++++ .../scri/ui/common/components/ClickableItemComp.kt | 3 --- .../ui/common/components/SwitchableItemComp.kt | 1 - .../be/scri/ui/screens/settings/SettingsScreen.kt | 11 +++++++++++ .../scri/ui/screens/settings/SettingsViewModel.kt | 8 ++++++++ app/src/main/java/be/scri/ui/theme/ScribeTheme.kt | 5 ++++- 8 files changed, 57 insertions(+), 5 deletions(-) diff --git a/app/src/keyboards/java/be/scri/activities/MainActivity.kt b/app/src/keyboards/java/be/scri/activities/MainActivity.kt index 053fa08d..fc88a706 100644 --- a/app/src/keyboards/java/be/scri/activities/MainActivity.kt +++ b/app/src/keyboards/java/be/scri/activities/MainActivity.kt @@ -55,6 +55,14 @@ class MainActivity : ComponentActivity() { .getUserDarkModePreference(context) == AppCompatDelegate.MODE_NIGHT_YES, ) } + + val isIncreaseTextSize = + remember { + mutableStateOf( + PreferencesHelper.getIncreaseTextSizePreference(context), + ) + } + val pagerState = rememberPagerState { bottomBarScreens.size @@ -82,13 +90,19 @@ class MainActivity : ComponentActivity() { ScribeTheme( useDarkTheme = isDarkMode.value, + isIncreaseTextSize = isIncreaseTextSize.value, ) { ScribeApp( pagerState = pagerState, isDarkTheme = isDarkMode.value, + isIncreaseTextSize = isIncreaseTextSize.value, onDarkModeChange = { darkMode -> updateTheme(darkMode) }, + onIncreaseTextSizeChange = { increaseTextSize -> + PreferencesHelper.setIncreaseTextSizePreference(context, increaseTextSize) + isIncreaseTextSize.value = increaseTextSize + }, resetHints = { isHintChangedMap[0] = true isHintChangedMap[1] = true diff --git a/app/src/main/java/be/scri/App.kt b/app/src/main/java/be/scri/App.kt index 982cce74..90ad5b3d 100644 --- a/app/src/main/java/be/scri/App.kt +++ b/app/src/main/java/be/scri/App.kt @@ -69,11 +69,13 @@ fun ScribeApp( pagerState: PagerState, navController: NavHostController, onDarkModeChange: (Boolean) -> Unit, + onIncreaseTextSizeChange: (Boolean) -> Unit, resetHints: () -> Unit, @SuppressLint("ComposeUnstableCollections") isHintChanged: Map, onDismiss: (Int) -> Unit, context: Context, isDarkTheme: Boolean, + isIncreaseTextSize: Boolean, modifier: Modifier = Modifier, downloadViewModel: DataDownloadViewModel = viewModel(), ) { @@ -87,6 +89,7 @@ fun ScribeApp( ScribeTheme( useDarkTheme = isDarkTheme, + isIncreaseTextSize = isIncreaseTextSize, ) { Scaffold( bottomBar = { @@ -151,6 +154,9 @@ fun ScribeApp( onDarkModeChange = { isDarkMode -> onDarkModeChange(isDarkMode) }, + onIncreaseTextSizeChange = { increaseTextSize -> + onIncreaseTextSizeChange(increaseTextSize) + }, onLanguageSettingsClick = { language -> navController.navigate( "${Screen.LanguageSettings.route}/$language", diff --git a/app/src/main/java/be/scri/helpers/PreferencesHelper.kt b/app/src/main/java/be/scri/helpers/PreferencesHelper.kt index f5da00b1..da921eca 100644 --- a/app/src/main/java/be/scri/helpers/PreferencesHelper.kt +++ b/app/src/main/java/be/scri/helpers/PreferencesHelper.kt @@ -28,6 +28,7 @@ object PreferencesHelper { private const val WORD_BY_WORD_DELETION = "word_by_word_deletion" private const val DEFAULT_CURRENCY = "default_currency" private const val HOLD_FOR_ALT_KEYS = "hold_for_alt_keys" + private const val INCREASE_TEXT_SIZE = "increase_text_size" /** * Sets the translation source language for a given language. @@ -592,4 +593,17 @@ object PreferencesHelper { val sharedPref = context.getSharedPreferences(SCRIBE_PREFS, Context.MODE_PRIVATE) return sharedPref.getBoolean(getLanguageSpecificPreferenceKey(HOLD_FOR_ALT_KEYS, language), true) } + + fun setIncreaseTextSizePreference( + context: Context, + increaseTextSize: Boolean, + ) { + val sharedPref = context.getSharedPreferences("app_preferences", Context.MODE_PRIVATE) + sharedPref.edit { putBoolean(INCREASE_TEXT_SIZE, increaseTextSize) } + } + + fun getIncreaseTextSizePreference(context: Context): Boolean { + val sharedPref = context.getSharedPreferences("app_preferences", Context.MODE_PRIVATE) + return sharedPref.getBoolean(INCREASE_TEXT_SIZE, false) + } } diff --git a/app/src/main/java/be/scri/ui/common/components/ClickableItemComp.kt b/app/src/main/java/be/scri/ui/common/components/ClickableItemComp.kt index c57f658a..91881871 100644 --- a/app/src/main/java/be/scri/ui/common/components/ClickableItemComp.kt +++ b/app/src/main/java/be/scri/ui/common/components/ClickableItemComp.kt @@ -20,7 +20,6 @@ import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.painterResource import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp import be.scri.R /** @@ -55,7 +54,6 @@ fun ClickableItemComp( Text( text = title, modifier = Modifier.weight(1f), - fontSize = 16.sp, color = MaterialTheme.colorScheme.onSurface, style = MaterialTheme.typography.bodyMedium, ) @@ -73,7 +71,6 @@ fun ClickableItemComp( if (!desc.isNullOrEmpty()) { Text( text = desc, - fontSize = 12.sp, color = Color.Gray, style = MaterialTheme.typography.bodySmall, modifier = Modifier.padding(top = 4.dp), diff --git a/app/src/main/java/be/scri/ui/common/components/SwitchableItemComp.kt b/app/src/main/java/be/scri/ui/common/components/SwitchableItemComp.kt index 2f0ee42b..adf3179c 100644 --- a/app/src/main/java/be/scri/ui/common/components/SwitchableItemComp.kt +++ b/app/src/main/java/be/scri/ui/common/components/SwitchableItemComp.kt @@ -49,7 +49,6 @@ fun SwitchableItemComp( Text( text = title, modifier = Modifier.weight(1f), - fontSize = 16.sp, color = MaterialTheme.colorScheme.onSurface, style = MaterialTheme.typography.bodyMedium, ) diff --git a/app/src/main/java/be/scri/ui/screens/settings/SettingsScreen.kt b/app/src/main/java/be/scri/ui/screens/settings/SettingsScreen.kt index ff53ca5d..e542e209 100644 --- a/app/src/main/java/be/scri/ui/screens/settings/SettingsScreen.kt +++ b/app/src/main/java/be/scri/ui/screens/settings/SettingsScreen.kt @@ -34,6 +34,7 @@ import be.scri.ui.screens.settings.SettingsUtil.getLocalizedLanguageName @Composable fun SettingsScreen( onDarkModeChange: (Boolean) -> Unit, + onIncreaseTextSizeChange: (Boolean) -> Unit, onLanguageSettingsClick: (String) -> Unit, context: Context, modifier: Modifier = Modifier, @@ -47,6 +48,7 @@ fun SettingsScreen( val vibrateOnKeypress by viewModel.vibrateOnKeypress.collectAsState() val popupOnKeypress by viewModel.popupOnKeypress.collectAsState() val isUserDarkMode by viewModel.isUserDarkMode.collectAsState() + val isIncreaseTextSize by viewModel.isIncreaseTextSize.collectAsState() val lifecycleOwner = LocalLifecycleOwner.current @@ -85,6 +87,15 @@ fun SettingsScreen( onDarkModeChange(newDarkMode) }, ), + ScribeItem.SwitchItem( + title = R.string.app_settings_menu_increase_text_size, + desc = R.string.app_settings_menu_increase_text_size_description, + state = isIncreaseTextSize, + onToggle = { newIncreaseTextSize -> + viewModel.setIncreaseTextSize(newIncreaseTextSize) + onIncreaseTextSizeChange(newIncreaseTextSize) + }, + ), ), ) diff --git a/app/src/main/java/be/scri/ui/screens/settings/SettingsViewModel.kt b/app/src/main/java/be/scri/ui/screens/settings/SettingsViewModel.kt index e631e55a..a51d6d6e 100644 --- a/app/src/main/java/be/scri/ui/screens/settings/SettingsViewModel.kt +++ b/app/src/main/java/be/scri/ui/screens/settings/SettingsViewModel.kt @@ -33,6 +33,8 @@ class SettingsViewModel( private val _holdForAltKeys = MutableStateFlow(sharedPrefs.getBoolean("hold_for_alt_keys", false)) val holdForAltKeys: StateFlow = _holdForAltKeys + private val _isIncreaseTextSize = MutableStateFlow(sharedPrefs.getBoolean("increase_text_size", false)) + val isIncreaseTextSize: StateFlow = _isIncreaseTextSize init { viewModelScope.launch { refreshSettings(context) } @@ -56,5 +58,11 @@ class SettingsViewModel( */ fun setLightDarkMode(value: Boolean) { _isUserDarkMode.value = value + sharedPrefs.edit().putBoolean("dark_mode", value).apply() + } + + fun setIncreaseTextSize(value: Boolean) { + _isIncreaseTextSize.value = value + sharedPrefs.edit().putBoolean("increase_text_size", value).apply() } } diff --git a/app/src/main/java/be/scri/ui/theme/ScribeTheme.kt b/app/src/main/java/be/scri/ui/theme/ScribeTheme.kt index a3a17e3e..1e6a76af 100644 --- a/app/src/main/java/be/scri/ui/theme/ScribeTheme.kt +++ b/app/src/main/java/be/scri/ui/theme/ScribeTheme.kt @@ -47,6 +47,7 @@ private val DarkColors = @Composable fun ScribeTheme( useDarkTheme: Boolean, + isIncreaseTextSize: Boolean = false, @Suppress("ktlint:standard:annotation") content: @Composable() () -> Unit, ) { @@ -57,9 +58,11 @@ fun ScribeTheme( DarkColors } + val typography = if (isIncreaseTextSize) createTypography(1.25f) else ScribeTypography + MaterialTheme( colorScheme = colors, content = content, - typography = ScribeTypography, + typography = typography, ) } From bec6f7888a237d592a394e91188c3cb5ce1b4149 Mon Sep 17 00:00:00 2001 From: Femi Ogundipe Date: Tue, 17 Mar 2026 14:50:56 +0100 Subject: [PATCH 2/7] Add 'Increase app text size' option to settings and implement 1.25x scaling --- .../java/be/scri/helpers/PreferencesHelper.kt | 12 ++++++++++++ .../scri/ui/screens/settings/SettingsScreen.kt | 4 ++-- .../ui/screens/settings/SettingsViewModel.kt | 8 +++++++- .../main/java/be/scri/ui/theme/Typography.kt | 17 ++++++++++------- 4 files changed, 31 insertions(+), 10 deletions(-) diff --git a/app/src/main/java/be/scri/helpers/PreferencesHelper.kt b/app/src/main/java/be/scri/helpers/PreferencesHelper.kt index da921eca..7a43b973 100644 --- a/app/src/main/java/be/scri/helpers/PreferencesHelper.kt +++ b/app/src/main/java/be/scri/helpers/PreferencesHelper.kt @@ -594,6 +594,12 @@ object PreferencesHelper { return sharedPref.getBoolean(getLanguageSpecificPreferenceKey(HOLD_FOR_ALT_KEYS, language), true) } + /** + * Saves the user's "Increase Text Size" preference. + * + * @param context The application context used to access SharedPreferences. + * @param increaseTextSize `true` to enable larger text size, `false` to use default size. + */ fun setIncreaseTextSizePreference( context: Context, increaseTextSize: Boolean, @@ -602,6 +608,12 @@ object PreferencesHelper { sharedPref.edit { putBoolean(INCREASE_TEXT_SIZE, increaseTextSize) } } + /** + * Retrieves the user's "Increase Text Size" preference. + * + * @param context The application context used to access SharedPreferences. + * @return `true` if larger text size is enabled, `false` otherwise. + */ fun getIncreaseTextSizePreference(context: Context): Boolean { val sharedPref = context.getSharedPreferences("app_preferences", Context.MODE_PRIVATE) return sharedPref.getBoolean(INCREASE_TEXT_SIZE, false) diff --git a/app/src/main/java/be/scri/ui/screens/settings/SettingsScreen.kt b/app/src/main/java/be/scri/ui/screens/settings/SettingsScreen.kt index e542e209..d87a0c3c 100644 --- a/app/src/main/java/be/scri/ui/screens/settings/SettingsScreen.kt +++ b/app/src/main/java/be/scri/ui/screens/settings/SettingsScreen.kt @@ -88,8 +88,8 @@ fun SettingsScreen( }, ), ScribeItem.SwitchItem( - title = R.string.app_settings_menu_increase_text_size, - desc = R.string.app_settings_menu_increase_text_size_description, + title = R.string.i18n_app_settings_menu_increase_text_size, + desc = R.string.i18n_app_settings_menu_increase_text_size_description, state = isIncreaseTextSize, onToggle = { newIncreaseTextSize -> viewModel.setIncreaseTextSize(newIncreaseTextSize) diff --git a/app/src/main/java/be/scri/ui/screens/settings/SettingsViewModel.kt b/app/src/main/java/be/scri/ui/screens/settings/SettingsViewModel.kt index a51d6d6e..13c40b73 100644 --- a/app/src/main/java/be/scri/ui/screens/settings/SettingsViewModel.kt +++ b/app/src/main/java/be/scri/ui/screens/settings/SettingsViewModel.kt @@ -8,6 +8,7 @@ import androidx.lifecycle.viewModelScope import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.launch +import androidx.core.content.edit /** This files handles the state and business logic for the settings screen. */ class SettingsViewModel( @@ -61,8 +62,13 @@ class SettingsViewModel( sharedPrefs.edit().putBoolean("dark_mode", value).apply() } + /** + * Updates the text size preference setting. + * + * @param value `true` if text size should be increased, `false` otherwise. + */ fun setIncreaseTextSize(value: Boolean) { _isIncreaseTextSize.value = value - sharedPrefs.edit().putBoolean("increase_text_size", value).apply() + sharedPrefs.edit { putBoolean("increase_text_size", value) } } } diff --git a/app/src/main/java/be/scri/ui/theme/Typography.kt b/app/src/main/java/be/scri/ui/theme/Typography.kt index c3d110a3..2cf5510f 100644 --- a/app/src/main/java/be/scri/ui/theme/Typography.kt +++ b/app/src/main/java/be/scri/ui/theme/Typography.kt @@ -6,23 +6,26 @@ import androidx.compose.material3.Typography import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.font.FontFamily import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.TextUnit import androidx.compose.ui.unit.sp -/** - * Text styles for the application. - */ -val ScribeTypography = - Typography( +private fun TextUnit.scaled(scale: Float): TextUnit = if (isSp) (value * scale).sp else this + +fun createTypography(scale: Float): Typography { + return Typography( bodyMedium = TextStyle( fontFamily = FontFamily.SansSerif, fontWeight = FontWeight.Normal, - fontSize = 16.sp, + fontSize = 16.sp.scaled(scale), ), headlineMedium = TextStyle( fontFamily = FontFamily.SansSerif, fontWeight = FontWeight.Bold, - fontSize = 20.sp, + fontSize = 20.sp.scaled(scale), ), ) +} + +val ScribeTypography = createTypography(1f) From b49c1d9c3371f53f0a5ef714c6fc32e0432adcfc Mon Sep 17 00:00:00 2001 From: Femi Ogundipe Date: Tue, 17 Mar 2026 14:52:58 +0100 Subject: [PATCH 3/7] Add 'Increase app text size' option to settings and implement 1.25x scaling --- app/src/main/java/be/scri/ui/theme/Typography.kt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/src/main/java/be/scri/ui/theme/Typography.kt b/app/src/main/java/be/scri/ui/theme/Typography.kt index 2cf5510f..0c28ddcd 100644 --- a/app/src/main/java/be/scri/ui/theme/Typography.kt +++ b/app/src/main/java/be/scri/ui/theme/Typography.kt @@ -1,5 +1,9 @@ // SPDX-License-Identifier: GPL-3.0-or-later +/** + * Text styles for the application. + */ + package be.scri.ui.theme import androidx.compose.material3.Typography From 2e10124be159c49fb480930b1df1460fc14a6446 Mon Sep 17 00:00:00 2001 From: Femi Ogundipe Date: Tue, 17 Mar 2026 15:05:54 +0100 Subject: [PATCH 4/7] fix 'dangling toplevel KDoc' --- app/src/main/java/be/scri/ui/theme/Typography.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/be/scri/ui/theme/Typography.kt b/app/src/main/java/be/scri/ui/theme/Typography.kt index 0c28ddcd..52475497 100644 --- a/app/src/main/java/be/scri/ui/theme/Typography.kt +++ b/app/src/main/java/be/scri/ui/theme/Typography.kt @@ -1,8 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -/** - * Text styles for the application. - */ package be.scri.ui.theme @@ -32,4 +29,7 @@ fun createTypography(scale: Float): Typography { ) } +/** + * Text styles for the application. + */ val ScribeTypography = createTypography(1f) From b924a0a44885485b5bf3fb1bc5a038d391494e0f Mon Sep 17 00:00:00 2001 From: Femi Ogundipe Date: Tue, 17 Mar 2026 16:15:41 +0100 Subject: [PATCH 5/7] Refactor Typography.kt to use expression body for createTypography function --- ...SettingsScreenInstallKeyboardButtonTest.kt | 8 ++ .../SettingsScreenInstrumentedTest.kt | 85 ++++++++++++++++++- .../ui/screens/settings/SettingsViewModel.kt | 2 +- .../main/java/be/scri/ui/theme/Typography.kt | 41 ++++++--- 4 files changed, 124 insertions(+), 12 deletions(-) diff --git a/app/src/androidTestKeyboards/kotlin/be/scri/ui/screens/settings/SettingsScreenInstallKeyboardButtonTest.kt b/app/src/androidTestKeyboards/kotlin/be/scri/ui/screens/settings/SettingsScreenInstallKeyboardButtonTest.kt index 5497704b..f29f859d 100644 --- a/app/src/androidTestKeyboards/kotlin/be/scri/ui/screens/settings/SettingsScreenInstallKeyboardButtonTest.kt +++ b/app/src/androidTestKeyboards/kotlin/be/scri/ui/screens/settings/SettingsScreenInstallKeyboardButtonTest.kt @@ -43,6 +43,7 @@ class SettingsScreenInstallKeyboardButtonTest { SettingsScreen( onDarkModeChange = {}, onLanguageSettingsClick = {}, + onIncreaseTextSizeChange = {}, context = context, viewModel = mockViewModel, ) @@ -68,6 +69,7 @@ class SettingsScreenInstallKeyboardButtonTest { SettingsScreen( onDarkModeChange = {}, onLanguageSettingsClick = {}, + onIncreaseTextSizeChange = {}, context = context, viewModel = mockViewModel, ) @@ -90,6 +92,7 @@ class SettingsScreenInstallKeyboardButtonTest { SettingsScreen( onDarkModeChange = {}, onLanguageSettingsClick = {}, + onIncreaseTextSizeChange = {}, context = context, viewModel = mockViewModel, ) @@ -113,6 +116,7 @@ class SettingsScreenInstallKeyboardButtonTest { SettingsScreen( onDarkModeChange = {}, onLanguageSettingsClick = {}, + onIncreaseTextSizeChange = {}, context = context, viewModel = mockViewModel, ) @@ -137,6 +141,7 @@ class SettingsScreenInstallKeyboardButtonTest { SettingsScreen( onDarkModeChange = {}, onLanguageSettingsClick = {}, + onIncreaseTextSizeChange = {}, context = context, viewModel = mockViewModel, ) @@ -160,6 +165,7 @@ class SettingsScreenInstallKeyboardButtonTest { SettingsScreen( onDarkModeChange = {}, onLanguageSettingsClick = {}, + onIncreaseTextSizeChange = {}, context = context, viewModel = mockViewModel, ) @@ -186,6 +192,7 @@ class SettingsScreenInstallKeyboardButtonTest { SettingsScreen( onDarkModeChange = {}, onLanguageSettingsClick = {}, + onIncreaseTextSizeChange = {}, context = context, viewModel = mockViewModel, ) @@ -210,6 +217,7 @@ class SettingsScreenInstallKeyboardButtonTest { SettingsScreen( onDarkModeChange = {}, onLanguageSettingsClick = {}, + onIncreaseTextSizeChange = {}, context = context, viewModel = mockViewModel, ) diff --git a/app/src/androidTestKeyboards/kotlin/be/scri/ui/screens/settings/SettingsScreenInstrumentedTest.kt b/app/src/androidTestKeyboards/kotlin/be/scri/ui/screens/settings/SettingsScreenInstrumentedTest.kt index 8589b125..1069a8bd 100644 --- a/app/src/androidTestKeyboards/kotlin/be/scri/ui/screens/settings/SettingsScreenInstrumentedTest.kt +++ b/app/src/androidTestKeyboards/kotlin/be/scri/ui/screens/settings/SettingsScreenInstrumentedTest.kt @@ -39,6 +39,7 @@ class SettingsScreenInstrumentedTest { private lateinit var context: Context private lateinit var mockViewModel: SettingsViewModel private lateinit var onDarkModeChangeMock: (Boolean) -> Unit + private lateinit var onIncreaseTextSizeChangeMock: (Boolean) -> Unit private lateinit var onLanguageSettingsClickMock: (String) -> Unit @Before @@ -46,6 +47,7 @@ class SettingsScreenInstrumentedTest { context = InstrumentationRegistry.getInstrumentation().targetContext mockViewModel = mockk(relaxed = true) onDarkModeChangeMock = mockk(relaxed = true) + onIncreaseTextSizeChangeMock = mockk(relaxed = true) onLanguageSettingsClickMock = mockk(relaxed = true) // Setup comprehensive mock returns for all StateFlow properties @@ -54,9 +56,11 @@ class SettingsScreenInstrumentedTest { every { mockViewModel.vibrateOnKeypress } returns MutableStateFlow(false) every { mockViewModel.popupOnKeypress } returns MutableStateFlow(false) every { mockViewModel.isUserDarkMode } returns MutableStateFlow(false) + every { mockViewModel.isIncreaseTextSize } returns MutableStateFlow(false) every { mockViewModel.refreshSettings(any()) } returns Unit every { mockViewModel.setLightDarkMode(any()) } returns Unit + every { mockViewModel.setIncreaseTextSize(any()) } returns Unit } private fun setTestContent(content: @Composable () -> Unit) { @@ -73,6 +77,7 @@ class SettingsScreenInstrumentedTest { setTestContent { SettingsScreen( onDarkModeChange = onDarkModeChangeMock, + onIncreaseTextSizeChange = onIncreaseTextSizeChangeMock, onLanguageSettingsClick = onLanguageSettingsClickMock, context = context, ) @@ -88,6 +93,7 @@ class SettingsScreenInstrumentedTest { setTestContent { SettingsScreen( onDarkModeChange = onDarkModeChangeMock, + onIncreaseTextSizeChange = onIncreaseTextSizeChangeMock, onLanguageSettingsClick = onLanguageSettingsClickMock, context = context, ) @@ -103,6 +109,7 @@ class SettingsScreenInstrumentedTest { setTestContent { SettingsScreen( onDarkModeChange = onDarkModeChangeMock, + onIncreaseTextSizeChange = onIncreaseTextSizeChangeMock, onLanguageSettingsClick = onLanguageSettingsClickMock, context = context, ) @@ -118,6 +125,7 @@ class SettingsScreenInstrumentedTest { setTestContent { SettingsScreen( onDarkModeChange = onDarkModeChangeMock, + onIncreaseTextSizeChange = onIncreaseTextSizeChangeMock, onLanguageSettingsClick = onLanguageSettingsClickMock, context = context, ) @@ -128,6 +136,26 @@ class SettingsScreenInstrumentedTest { .assertIsDisplayed() } + @Test + fun settingsScreen_displaysIncreaseTextSizeSwitch() { + setTestContent { + SettingsScreen( + onDarkModeChange = onDarkModeChangeMock, + onIncreaseTextSizeChange = onIncreaseTextSizeChangeMock, + onLanguageSettingsClick = onLanguageSettingsClickMock, + context = context, + ) + } + + composeTestRule + .onNodeWithText(context.getString(R.string.i18n_app_settings_menu_increase_text_size)) + .assertIsDisplayed() + + composeTestRule + .onNodeWithText(context.getString(R.string.i18n_app_settings_menu_increase_text_size_description)) + .assertIsDisplayed() + } + @Test fun settingsScreen_whenKeyboardNotInstalled_showsInstallButton() { every { mockViewModel.isKeyboardInstalled } returns MutableStateFlow(false) @@ -135,6 +163,7 @@ class SettingsScreenInstrumentedTest { setTestContent { SettingsScreen( onDarkModeChange = onDarkModeChangeMock, + onIncreaseTextSizeChange = onIncreaseTextSizeChangeMock, onLanguageSettingsClick = onLanguageSettingsClickMock, context = context, viewModel = mockViewModel, @@ -156,6 +185,7 @@ class SettingsScreenInstrumentedTest { setTestContent { SettingsScreen( onDarkModeChange = onDarkModeChangeMock, + onIncreaseTextSizeChange = onIncreaseTextSizeChangeMock, onLanguageSettingsClick = onLanguageSettingsClickMock, context = context, viewModel = mockViewModel, @@ -183,6 +213,7 @@ class SettingsScreenInstrumentedTest { setTestContent { SettingsScreen( onDarkModeChange = onDarkModeChangeMock, + onIncreaseTextSizeChange = onIncreaseTextSizeChangeMock, onLanguageSettingsClick = onLanguageSettingsClickMock, context = context, viewModel = mockViewModel, @@ -206,12 +237,14 @@ class SettingsScreenInstrumentedTest { every { mockViewModelSpy.vibrateOnKeypress } returns MutableStateFlow(false) every { mockViewModelSpy.popupOnKeypress } returns MutableStateFlow(false) every { mockViewModelSpy.isUserDarkMode } returns MutableStateFlow(false) + every { mockViewModelSpy.isIncreaseTextSize } returns MutableStateFlow(false) every { mockViewModelSpy.refreshSettings(any()) } returns Unit every { mockViewModelSpy.setLightDarkMode(any()) } returns Unit setTestContent { SettingsScreen( onDarkModeChange = onDarkModeChangeMock, + onIncreaseTextSizeChange = onIncreaseTextSizeChangeMock, onLanguageSettingsClick = onLanguageSettingsClickMock, context = context, viewModel = mockViewModelSpy, @@ -227,7 +260,7 @@ class SettingsScreenInstrumentedTest { composeTestRule .onAllNodes(hasClickAction() and !hasText(darkModeText)) .filterToOne( - !hasText("App language") and !hasText("Install keyboards"), + !hasText("App language") and !hasText("Install keyboards") and !hasText("Increase app text size"), ).performClick() composeTestRule.waitForIdle() @@ -236,6 +269,48 @@ class SettingsScreenInstrumentedTest { verify(timeout = 3000) { onDarkModeChangeMock(true) } } + @Test + fun settingsScreen_increaseTextSizeToggle_triggersCallbacks() { + every { mockViewModel.isIncreaseTextSize } returns MutableStateFlow(false) + val mockViewModelSpy = spyk(mockViewModel) + + every { mockViewModelSpy.languages } returns MutableStateFlow(emptyList()) + every { mockViewModelSpy.isKeyboardInstalled } returns MutableStateFlow(false) + every { mockViewModelSpy.vibrateOnKeypress } returns MutableStateFlow(false) + every { mockViewModelSpy.popupOnKeypress } returns MutableStateFlow(false) + every { mockViewModelSpy.isUserDarkMode } returns MutableStateFlow(false) + every { mockViewModelSpy.isIncreaseTextSize } returns MutableStateFlow(false) + every { mockViewModelSpy.refreshSettings(any()) } returns Unit + every { mockViewModelSpy.setIncreaseTextSize(any()) } returns Unit + + setTestContent { + SettingsScreen( + onDarkModeChange = onDarkModeChangeMock, + onIncreaseTextSizeChange = onIncreaseTextSizeChangeMock, + onLanguageSettingsClick = onLanguageSettingsClickMock, + context = context, + viewModel = mockViewModelSpy, + ) + } + + val increaseTextSizeText = "Increase app text size" + + composeTestRule + .onNodeWithText(increaseTextSizeText) + .assertIsDisplayed() + + composeTestRule + .onAllNodes(hasClickAction() and !hasText(increaseTextSizeText)) + .filterToOne( + !hasText("App language") and !hasText("Install keyboards") and !hasText("Dark mode"), + ).performClick() + + composeTestRule.waitForIdle() + + verify(timeout = 3000) { mockViewModelSpy.setIncreaseTextSize(true) } + verify(timeout = 3000) { onIncreaseTextSizeChangeMock(true) } + } + @Test fun settingsScreen_refreshSettings_whenLifecycleResumes() { val mockViewModelSpy = spyk(mockViewModel) @@ -245,12 +320,14 @@ class SettingsScreenInstrumentedTest { every { mockViewModelSpy.vibrateOnKeypress } returns MutableStateFlow(false) every { mockViewModelSpy.popupOnKeypress } returns MutableStateFlow(false) every { mockViewModelSpy.isUserDarkMode } returns MutableStateFlow(false) + every { mockViewModelSpy.isIncreaseTextSize } returns MutableStateFlow(false) every { mockViewModelSpy.refreshSettings(any()) } returns Unit every { mockViewModelSpy.setLightDarkMode(any()) } returns Unit setTestContent { SettingsScreen( onDarkModeChange = onDarkModeChangeMock, + onIncreaseTextSizeChange = onIncreaseTextSizeChangeMock, onLanguageSettingsClick = onLanguageSettingsClickMock, context = context, viewModel = mockViewModelSpy, @@ -265,6 +342,7 @@ class SettingsScreenInstrumentedTest { setTestContent { SettingsScreen( onDarkModeChange = onDarkModeChangeMock, + onIncreaseTextSizeChange = onIncreaseTextSizeChangeMock, onLanguageSettingsClick = onLanguageSettingsClickMock, context = context, ) @@ -280,6 +358,7 @@ class SettingsScreenInstrumentedTest { setTestContent { SettingsScreen( onDarkModeChange = onDarkModeChangeMock, + onIncreaseTextSizeChange = onIncreaseTextSizeChangeMock, onLanguageSettingsClick = onLanguageSettingsClickMock, context = context, ) @@ -298,6 +377,7 @@ class SettingsScreenInstrumentedTest { setTestContent { SettingsScreen( onDarkModeChange = onDarkModeChangeMock, + onIncreaseTextSizeChange = onIncreaseTextSizeChangeMock, onLanguageSettingsClick = onLanguageSettingsClickMock, context = context, ) @@ -317,6 +397,7 @@ class SettingsScreenInstrumentedTest { setTestContent { SettingsScreen( onDarkModeChange = onDarkModeChangeMock, + onIncreaseTextSizeChange = onIncreaseTextSizeChangeMock, onLanguageSettingsClick = onLanguageSettingsClickMock, context = context, viewModel = mockViewModel, @@ -338,6 +419,7 @@ class SettingsScreenInstrumentedTest { setTestContent { SettingsScreen( onDarkModeChange = onDarkModeChangeMock, + onIncreaseTextSizeChange = onIncreaseTextSizeChangeMock, onLanguageSettingsClick = onLanguageSettingsClickMock, context = context, viewModel = mockViewModel, @@ -354,6 +436,7 @@ class SettingsScreenInstrumentedTest { setTestContent { SettingsScreen( onDarkModeChange = onDarkModeChangeMock, + onIncreaseTextSizeChange = onIncreaseTextSizeChangeMock, onLanguageSettingsClick = onLanguageSettingsClickMock, context = context, ) diff --git a/app/src/main/java/be/scri/ui/screens/settings/SettingsViewModel.kt b/app/src/main/java/be/scri/ui/screens/settings/SettingsViewModel.kt index 13c40b73..6656c693 100644 --- a/app/src/main/java/be/scri/ui/screens/settings/SettingsViewModel.kt +++ b/app/src/main/java/be/scri/ui/screens/settings/SettingsViewModel.kt @@ -3,12 +3,12 @@ package be.scri.ui.screens.settings import android.content.Context +import androidx.core.content.edit import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.launch -import androidx.core.content.edit /** This files handles the state and business logic for the settings screen. */ class SettingsViewModel( diff --git a/app/src/main/java/be/scri/ui/theme/Typography.kt b/app/src/main/java/be/scri/ui/theme/Typography.kt index 52475497..558e8a48 100644 --- a/app/src/main/java/be/scri/ui/theme/Typography.kt +++ b/app/src/main/java/be/scri/ui/theme/Typography.kt @@ -1,6 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later - package be.scri.ui.theme import androidx.compose.material3.Typography @@ -10,26 +9,48 @@ import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.TextUnit import androidx.compose.ui.unit.sp -private fun TextUnit.scaled(scale: Float): TextUnit = if (isSp) (value * scale).sp else this +/** + * Text styles for the application. + */ +private fun TextUnit.scaled(scale: Float): TextUnit = + if (isSp) { + (value * scale).sp + } else { + this + } -fun createTypography(scale: Float): Typography { - return Typography( +fun createTypography(scale: Float): Typography = + Typography( + headlineMedium = + TextStyle( + fontFamily = FontFamily.SansSerif, + fontWeight = FontWeight.Bold, + fontSize = 20.sp.scaled(scale), + ), + titleMedium = + TextStyle( + fontFamily = FontFamily.SansSerif, + fontWeight = FontWeight.Bold, + fontSize = 18.sp.scaled(scale), + ), bodyMedium = TextStyle( fontFamily = FontFamily.SansSerif, fontWeight = FontWeight.Normal, fontSize = 16.sp.scaled(scale), ), - headlineMedium = + bodySmall = + TextStyle( + fontFamily = FontFamily.SansSerif, + fontWeight = FontWeight.Normal, + fontSize = 12.sp.scaled(scale), + ), + labelLarge = TextStyle( fontFamily = FontFamily.SansSerif, fontWeight = FontWeight.Bold, - fontSize = 20.sp.scaled(scale), + fontSize = 24.sp.scaled(scale), ), ) -} -/** - * Text styles for the application. - */ val ScribeTypography = createTypography(1f) From 43441175e5568c62e3176cd30098eaa24fabe6af Mon Sep 17 00:00:00 2001 From: Femi Ogundipe Date: Thu, 19 Mar 2026 08:38:55 +0100 Subject: [PATCH 6/7] test: fix ambiguous node selection in SettingsScreenInstrumentedTest --- .../SettingsScreenInstrumentedTest.kt | 21 +++---------------- .../common/components/SwitchableItemComp.kt | 11 +++++++--- 2 files changed, 11 insertions(+), 21 deletions(-) diff --git a/app/src/androidTestKeyboards/kotlin/be/scri/ui/screens/settings/SettingsScreenInstrumentedTest.kt b/app/src/androidTestKeyboards/kotlin/be/scri/ui/screens/settings/SettingsScreenInstrumentedTest.kt index 1069a8bd..c984cadb 100644 --- a/app/src/androidTestKeyboards/kotlin/be/scri/ui/screens/settings/SettingsScreenInstrumentedTest.kt +++ b/app/src/androidTestKeyboards/kotlin/be/scri/ui/screens/settings/SettingsScreenInstrumentedTest.kt @@ -7,9 +7,6 @@ import androidx.activity.ComponentActivity import androidx.compose.runtime.Composable import androidx.compose.ui.test.assertHasClickAction import androidx.compose.ui.test.assertIsDisplayed -import androidx.compose.ui.test.filterToOne -import androidx.compose.ui.test.hasClickAction -import androidx.compose.ui.test.hasText import androidx.compose.ui.test.junit4.createAndroidComposeRule import androidx.compose.ui.test.onNodeWithText import androidx.compose.ui.test.performClick @@ -137,7 +134,7 @@ class SettingsScreenInstrumentedTest { } @Test - fun settingsScreen_displaysIncreaseTextSizeSwitch() { + fun settingsScreen_increaseTextSizeSwitch_isDisplayed() { setTestContent { SettingsScreen( onDarkModeChange = onDarkModeChangeMock, @@ -255,13 +252,7 @@ class SettingsScreenInstrumentedTest { composeTestRule .onNodeWithText(darkModeText) - .assertIsDisplayed() - - composeTestRule - .onAllNodes(hasClickAction() and !hasText(darkModeText)) - .filterToOne( - !hasText("App language") and !hasText("Install keyboards") and !hasText("Increase app text size"), - ).performClick() + .performClick() composeTestRule.waitForIdle() @@ -297,13 +288,7 @@ class SettingsScreenInstrumentedTest { composeTestRule .onNodeWithText(increaseTextSizeText) - .assertIsDisplayed() - - composeTestRule - .onAllNodes(hasClickAction() and !hasText(increaseTextSizeText)) - .filterToOne( - !hasText("App language") and !hasText("Install keyboards") and !hasText("Dark mode"), - ).performClick() + .performClick() composeTestRule.waitForIdle() diff --git a/app/src/main/java/be/scri/ui/common/components/SwitchableItemComp.kt b/app/src/main/java/be/scri/ui/common/components/SwitchableItemComp.kt index adf3179c..e01f7785 100644 --- a/app/src/main/java/be/scri/ui/common/components/SwitchableItemComp.kt +++ b/app/src/main/java/be/scri/ui/common/components/SwitchableItemComp.kt @@ -10,6 +10,7 @@ import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width +import androidx.compose.foundation.selection.toggleable import androidx.compose.foundation.shape.CircleShape import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Switch @@ -19,6 +20,7 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color +import androidx.compose.ui.semantics.Role import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp @@ -41,7 +43,11 @@ fun SwitchableItemComp( Column( modifier = modifier - .padding(horizontal = 12.dp, vertical = 10.dp), + .toggleable( + value = isChecked, + onValueChange = onCheckedChange, + role = Role.Switch, + ).padding(horizontal = 12.dp, vertical = 10.dp), ) { Row( verticalAlignment = Alignment.CenterVertically, @@ -53,9 +59,8 @@ fun SwitchableItemComp( style = MaterialTheme.typography.bodyMedium, ) Switch( - interactionSource = null, checked = isChecked, - onCheckedChange = onCheckedChange, + onCheckedChange = null, modifier = Modifier .width(51.dp) From 239e498d7ed24f3217dd6f1e6c9b99496f7c49ab Mon Sep 17 00:00:00 2001 From: Femi Ogundipe Date: Thu, 19 Mar 2026 09:50:58 +0100 Subject: [PATCH 7/7] fix(test): resolve ClassCastException in SettingsScreen tests --- .../screens/settings/SettingsScreenInstallKeyboardButtonTest.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/androidTestKeyboards/kotlin/be/scri/ui/screens/settings/SettingsScreenInstallKeyboardButtonTest.kt b/app/src/androidTestKeyboards/kotlin/be/scri/ui/screens/settings/SettingsScreenInstallKeyboardButtonTest.kt index f29f859d..d377f0c6 100644 --- a/app/src/androidTestKeyboards/kotlin/be/scri/ui/screens/settings/SettingsScreenInstallKeyboardButtonTest.kt +++ b/app/src/androidTestKeyboards/kotlin/be/scri/ui/screens/settings/SettingsScreenInstallKeyboardButtonTest.kt @@ -29,6 +29,7 @@ class SettingsScreenInstallKeyboardButtonTest { every { mockViewModel.vibrateOnKeypress } returns MutableStateFlow(false) every { mockViewModel.popupOnKeypress } returns MutableStateFlow(false) every { mockViewModel.isUserDarkMode } returns MutableStateFlow(false) + every { mockViewModel.isIncreaseTextSize } returns MutableStateFlow(false) return mockViewModel }