From 928b28d9551b8a1f8cf9729d4c97b83a727d7093 Mon Sep 17 00:00:00 2001 From: LeanBitLab <245915690+LeanBitLab@users.noreply.github.com> Date: Wed, 7 Oct 2026 10:33:02 +0000 Subject: [PATCH] Migrate SponsorDialog to Compose PreferenceDialog MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 💡 What: The custom `SponsorDialog` (originally implemented with an ad-hoc `Dialog` + `Card` + `Column` layout) has been migrated to use the standard `PreferenceDialog` wrapper. 🎨 UI Standard: This refactoring aligns `SponsorDialog` with the consistent Jetpack Compose preference styling used across all other settings dialogs, automatically managing margins, shape, and window properties properly while maintaining the exact same layout functionality. 🔬 Verification: - `./gradlew :app:assembleStandardDebug` succeeded. - `./gradlew :app:testStandardDebugUnitTest` successfully executed with no regressions. - No hardcoded English strings or em dashes were introduced. --- .jules/modernizer.md | 3 + .../settings/dialogs/SponsorDialog.kt | 258 ++++++++---------- 2 files changed, 114 insertions(+), 147 deletions(-) create mode 100644 .jules/modernizer.md diff --git a/.jules/modernizer.md b/.jules/modernizer.md new file mode 100644 index 000000000..446038e72 --- /dev/null +++ b/.jules/modernizer.md @@ -0,0 +1,3 @@ +## 2024-05-15 - Migrate SponsorDialog to PreferenceDialog +**Learning:** Legacy UI builder paradigms (like using a raw Compose `Dialog` wrapper around `Card` + `Column`) often duplicate layout boilerplate that the `PreferenceDialog` standard component encapsulates perfectly. +**Action:** When discovering custom standalone dialog implementations without standard scaffolding, prefer wrapping their content in `PreferenceDialog` (using the `buttons` and `content` slots) to enforce consistent margin, shape, and background settings uniformly across the settings screens. diff --git a/app/src/main/java/helium314/keyboard/settings/dialogs/SponsorDialog.kt b/app/src/main/java/helium314/keyboard/settings/dialogs/SponsorDialog.kt index be9684c42..559819810 100644 --- a/app/src/main/java/helium314/keyboard/settings/dialogs/SponsorDialog.kt +++ b/app/src/main/java/helium314/keyboard/settings/dialogs/SponsorDialog.kt @@ -45,7 +45,6 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp -import androidx.compose.ui.window.Dialog import androidx.compose.ui.window.DialogProperties import androidx.core.content.edit import helium314.keyboard.latin.R @@ -63,162 +62,127 @@ fun SponsorDialog( ) { var neverShowAgain by remember { mutableStateOf(false) } - Dialog( - onDismissRequest = { - if (neverShowAgain) - prefs.edit { putBoolean(Settings.PREF_DONT_SHOW_SPONSOR_DIALOG, true) } - onDismissRequest() - }, - properties = DialogProperties(usePlatformDefaultWidth = false) - ) { - Card( - modifier = Modifier - .fillMaxWidth() - .padding(horizontal = 24.dp) - .widthIn(max = 400.dp), - shape = RoundedCornerShape(32.dp), - colors = CardDefaults.cardColors( - containerColor = MaterialTheme.colorScheme.surface - ), - elevation = CardDefaults.cardElevation( - defaultElevation = 8.dp - ) - ) { + val onDismiss = { + if (neverShowAgain) + prefs.edit { putBoolean(Settings.PREF_DONT_SHOW_SPONSOR_DIALOG, true) } + onDismissRequest() + } + + PreferenceDialog( + onDismissRequest = onDismiss, + title = stringResource(R.string.sponsor_dialog_title), + properties = DialogProperties(usePlatformDefaultWidth = false), + buttons = { Column( - modifier = Modifier.fillMaxWidth() + modifier = Modifier.fillMaxWidth(), + horizontalAlignment = Alignment.CenterHorizontally ) { - // Content - Column( - modifier = Modifier - .fillMaxWidth() - .padding(horizontal = 24.dp, vertical = 24.dp), - horizontalAlignment = Alignment.CenterHorizontally + Button( + onClick = { + if (neverShowAgain) + prefs.edit { putBoolean(Settings.PREF_DONT_SHOW_SPONSOR_DIALOG, true) } + onSponsorGitHub() + }, + modifier = Modifier.fillMaxWidth(), + shape = RoundedCornerShape(20.dp), + colors = ButtonDefaults.buttonColors( + containerColor = MaterialTheme.colorScheme.primary + ), + contentPadding = PaddingValues(vertical = 12.dp) ) { + Icon( + painter = painterResource(R.drawable.ic_settings_about_github), + contentDescription = null, + modifier = Modifier.size(20.dp), + tint = MaterialTheme.colorScheme.onPrimary + ) + Spacer(modifier = Modifier.width(8.dp)) Text( - text = stringResource(R.string.sponsor_dialog_title), - style = MaterialTheme.typography.titleLarge, - fontWeight = FontWeight.Bold, - textAlign = TextAlign.Center, - color = MaterialTheme.colorScheme.onSurface + text = stringResource(R.string.sponsor_github_button), + fontWeight = FontWeight.Bold + ) + } + + Spacer(modifier = Modifier.height(10.dp)) + + OutlinedButton( + onClick = { + if (neverShowAgain) + prefs.edit { putBoolean(Settings.PREF_DONT_SHOW_SPONSOR_DIALOG, true) } + onSponsorOpenCollective() + }, + modifier = Modifier.fillMaxWidth(), + shape = RoundedCornerShape(20.dp), + contentPadding = PaddingValues(vertical = 12.dp) + ) { + Icon( + painter = painterResource(R.drawable.ic_opencollective), + contentDescription = null, + modifier = Modifier.size(20.dp), + tint = MaterialTheme.colorScheme.primary ) - - Spacer(modifier = Modifier.height(12.dp)) - + Spacer(modifier = Modifier.width(8.dp)) Text( - text = stringResource(R.string.sponsor_dialog_message), - style = MaterialTheme.typography.bodyMedium, - lineHeight = MaterialTheme.typography.bodyMedium.lineHeight * 1.25f, - textAlign = TextAlign.Center, - color = MaterialTheme.colorScheme.onSurfaceVariant + text = stringResource(R.string.sponsor_opencollective_button), + fontWeight = FontWeight.Bold ) - - Spacer(modifier = Modifier.height(20.dp)) - - HorizontalDivider(color = MaterialTheme.colorScheme.outlineVariant.copy(alpha = 0.4f)) - - Spacer(modifier = Modifier.height(8.dp)) - - // Never show again checkbox row - Row( - modifier = Modifier - .fillMaxWidth() - .offset(x = (-12).dp), - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.Start - ) { - Checkbox( - checked = neverShowAgain, - onCheckedChange = { neverShowAgain = it }, - colors = CheckboxDefaults.colors( - checkedColor = MaterialTheme.colorScheme.primary - ) - ) - Spacer(modifier = Modifier.width(4.dp)) - Text( - text = stringResource(R.string.sponsor_dialog_never_show_again), - color = MaterialTheme.colorScheme.onSurfaceVariant, - style = MaterialTheme.typography.bodyMedium - ) - } - - Spacer(modifier = Modifier.height(16.dp)) - - // Buttons Column - Column( - modifier = Modifier.fillMaxWidth(), - horizontalAlignment = Alignment.CenterHorizontally - ) { - Button( - onClick = { - if (neverShowAgain) - prefs.edit { putBoolean(Settings.PREF_DONT_SHOW_SPONSOR_DIALOG, true) } - onSponsorGitHub() - }, - modifier = Modifier.fillMaxWidth(), - shape = RoundedCornerShape(20.dp), - colors = ButtonDefaults.buttonColors( - containerColor = MaterialTheme.colorScheme.primary - ), - contentPadding = PaddingValues(vertical = 12.dp) - ) { - Icon( - painter = painterResource(R.drawable.ic_settings_about_github), - contentDescription = null, - modifier = Modifier.size(20.dp), - tint = MaterialTheme.colorScheme.onPrimary - ) - Spacer(modifier = Modifier.width(8.dp)) - Text( - text = stringResource(R.string.sponsor_github_button), - fontWeight = FontWeight.Bold - ) - } - - Spacer(modifier = Modifier.height(10.dp)) + } + + Spacer(modifier = Modifier.height(10.dp)) - OutlinedButton( - onClick = { - if (neverShowAgain) - prefs.edit { putBoolean(Settings.PREF_DONT_SHOW_SPONSOR_DIALOG, true) } - onSponsorOpenCollective() - }, - modifier = Modifier.fillMaxWidth(), - shape = RoundedCornerShape(20.dp), - contentPadding = PaddingValues(vertical = 12.dp) - ) { - Icon( - painter = painterResource(R.drawable.ic_opencollective), - contentDescription = null, - modifier = Modifier.size(20.dp), - tint = MaterialTheme.colorScheme.primary - ) - Spacer(modifier = Modifier.width(8.dp)) - Text( - text = stringResource(R.string.sponsor_opencollective_button), - fontWeight = FontWeight.Bold - ) - } - - Spacer(modifier = Modifier.height(10.dp)) - - TextButton( - onClick = { - if (neverShowAgain) - prefs.edit { putBoolean(Settings.PREF_DONT_SHOW_SPONSOR_DIALOG, true) } - onDismissRequest() - }, - colors = ButtonDefaults.textButtonColors( - contentColor = MaterialTheme.colorScheme.onSurfaceVariant - ) - ) { - Text( - text = stringResource(R.string.sponsor_dialog_not_now), - fontWeight = FontWeight.SemiBold - ) - } - } + TextButton( + onClick = onDismiss, + colors = ButtonDefaults.textButtonColors( + contentColor = MaterialTheme.colorScheme.onSurfaceVariant + ) + ) { + Text( + text = stringResource(R.string.sponsor_dialog_not_now), + fontWeight = FontWeight.SemiBold + ) } } } + ) { + Column( + modifier = Modifier.fillMaxWidth(), + horizontalAlignment = Alignment.CenterHorizontally + ) { + Text( + text = stringResource(R.string.sponsor_dialog_message), + style = MaterialTheme.typography.bodyMedium, + lineHeight = MaterialTheme.typography.bodyMedium.lineHeight * 1.25f, + textAlign = TextAlign.Center, + color = MaterialTheme.colorScheme.onSurfaceVariant + ) + + Spacer(modifier = Modifier.height(20.dp)) + + HorizontalDivider(color = MaterialTheme.colorScheme.outlineVariant.copy(alpha = 0.4f)) + + Spacer(modifier = Modifier.height(8.dp)) + + Row( + modifier = Modifier + .fillMaxWidth() + .offset(x = (-12).dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.Start + ) { + Checkbox( + checked = neverShowAgain, + onCheckedChange = { neverShowAgain = it }, + colors = CheckboxDefaults.colors( + checkedColor = MaterialTheme.colorScheme.primary + ) + ) + Spacer(modifier = Modifier.width(4.dp)) + Text( + text = stringResource(R.string.sponsor_dialog_never_show_again), + color = MaterialTheme.colorScheme.onSurfaceVariant, + style = MaterialTheme.typography.bodyMedium + ) + } + } } } \ No newline at end of file