From 0b505742a41885317160351b15a8df86784fac89 Mon Sep 17 00:00:00 2001 From: "Luis Guzman (AppDevForAll)" Date: Fri, 4 Sep 2026 17:08:03 -0600 Subject: [PATCH 1/5] K2GO-385 refactor(ui): migrate the confirm dialogs the follow-up (#540) missed to BrandDialog #540 swept the raw MaterialAlertDialogBuilder confirms, but matched only the short form -- these four used the FULLY-QUALIFIED name or android/androidx AlertDialog.Builder, so the grep passed over them and they still rendered as plain platform dialogs (buttons in a row, no card). They are all simple destructive confirms; route them through the shared BrandDialog like the rest. - BackupRestoreFragment "Reinstall from scratch?" (fully-qualified MADB) -> BrandDialog destructive ("Erase and reinstall"). - LibraryActivity "Cancel the download?" (fully-qualified MADB) -> destructive. - SetupProgressActivity "Cancel the module install?" (fully-qualified MADB) -> destructive. - SettingsFragment "Turn off K2Go?" (AlertDialog.Builder) -> destructive, matching the clay "Turn off" button that opens it. Left as-is on purpose: the theme picker (SettingsFragment) and the language pickers are setItems LIST dialogs, which BrandDialog does not model; LibraryActivity's "damaged" dialog is a special three-button, non-cancelable dialog with a neutral that must not dismiss (it captures a screenshot of itself); FqrController's dialogs are its own themed subsystem. After this, no MaterialAlertDialogBuilder confirm remains outside FqrController. --- .../k2go/redesign/BackupRestoreFragment.java | 7 ++++--- .../appdevforall/k2go/redesign/LibraryActivity.java | 7 ++++--- .../appdevforall/k2go/redesign/SettingsFragment.java | 11 ++++++----- .../k2go/redesign/SetupProgressActivity.java | 7 ++++--- 4 files changed, 18 insertions(+), 14 deletions(-) diff --git a/controller/app/src/main/java/org/appdevforall/k2go/redesign/BackupRestoreFragment.java b/controller/app/src/main/java/org/appdevforall/k2go/redesign/BackupRestoreFragment.java index 6e8240566..01430bbcb 100644 --- a/controller/app/src/main/java/org/appdevforall/k2go/redesign/BackupRestoreFragment.java +++ b/controller/app/src/main/java/org/appdevforall/k2go/redesign/BackupRestoreFragment.java @@ -207,15 +207,16 @@ private View hairline() { /** ADFA-5023: strong confirm before a from-scratch reinstall (wipes everything), then the wizard. */ private void confirmReinstall() { - new com.google.android.material.dialog.MaterialAlertDialogBuilder(requireContext()) + // K2GO-385: destructive from-scratch reinstall confirm -> the shared BrandDialog (clay destructive). + new org.appdevforall.k2go.ui.dialog.BrandDialog(requireContext()) .setTitle(R.string.k2go_reinstall_confirm_title) .setMessage(R.string.k2go_reinstall_confirm_msg) - .setNegativeButton(android.R.string.cancel, null) - .setPositiveButton(R.string.k2go_reinstall_confirm_yes, (d, w) -> { + .setDestructive(R.string.k2go_reinstall_confirm_yes, () -> { if (getActivity() instanceof SetupLibraryActivity) { ((SetupLibraryActivity) getActivity()).openReinstallWizard(); } }) + .setNegative(android.R.string.cancel, null) .show(); } diff --git a/controller/app/src/main/java/org/appdevforall/k2go/redesign/LibraryActivity.java b/controller/app/src/main/java/org/appdevforall/k2go/redesign/LibraryActivity.java index af6e431d0..712da16a6 100644 --- a/controller/app/src/main/java/org/appdevforall/k2go/redesign/LibraryActivity.java +++ b/controller/app/src/main/java/org/appdevforall/k2go/redesign/LibraryActivity.java @@ -726,13 +726,14 @@ private void onDownloadToggle() { * second copy of it here would be a second place formatting the same fact. */ private void confirmCancelDownload() { - new com.google.android.material.dialog.MaterialAlertDialogBuilder(this) + // K2GO-385: cancel-the-download confirm -> the shared BrandDialog (destructive: it stops + starts over). + new org.appdevforall.k2go.ui.dialog.BrandDialog(this) .setTitle(R.string.k2go_dl_cancel_title) .setMessage(R.string.k2go_dl_cancel_body) - .setNegativeButton(R.string.k2go_dl_cancel_keep, null) - .setPositiveButton(R.string.k2go_dl_cancel_confirm, (d, w) -> + .setDestructive(R.string.k2go_dl_cancel_confirm, () -> sendToInstallService( org.appdevforall.k2go.install.presentation.InstallService.ACTION_CANCEL)) + .setNegative(R.string.k2go_dl_cancel_keep, null) .show(); } diff --git a/controller/app/src/main/java/org/appdevforall/k2go/redesign/SettingsFragment.java b/controller/app/src/main/java/org/appdevforall/k2go/redesign/SettingsFragment.java index df74be000..73a8132a4 100644 --- a/controller/app/src/main/java/org/appdevforall/k2go/redesign/SettingsFragment.java +++ b/controller/app/src/main/java/org/appdevforall/k2go/redesign/SettingsFragment.java @@ -143,15 +143,16 @@ private void buildFooter(Context ctx, LinearLayout footer) { } private void confirmTurnOff() { - new AlertDialog.Builder(requireContext()) - .setTitle(getString(R.string.k2go_settings_turnoff_title)) - .setMessage(getString(R.string.k2go_settings_turnoff_msg)) - .setNegativeButton(getString(R.string.k2go_cancel), null) - .setPositiveButton(getString(R.string.k2go_settings_turnoff_confirm), (d, w) -> { + // K2GO-385: turn-off confirm -> the shared BrandDialog (destructive, matching the clay "Turn off" button). + new org.appdevforall.k2go.ui.dialog.BrandDialog(requireContext()) + .setTitle(R.string.k2go_settings_turnoff_title) + .setMessage(R.string.k2go_settings_turnoff_msg) + .setDestructive(R.string.k2go_settings_turnoff_confirm, () -> { if (getActivity() instanceof LibraryActivity) { ((LibraryActivity) getActivity()).turnOffK2Go(); } }) + .setNegative(R.string.k2go_cancel, null) .show(); } diff --git a/controller/app/src/main/java/org/appdevforall/k2go/redesign/SetupProgressActivity.java b/controller/app/src/main/java/org/appdevforall/k2go/redesign/SetupProgressActivity.java index 3984f5e82..c4ebde5ec 100644 --- a/controller/app/src/main/java/org/appdevforall/k2go/redesign/SetupProgressActivity.java +++ b/controller/app/src/main/java/org/appdevforall/k2go/redesign/SetupProgressActivity.java @@ -1389,13 +1389,14 @@ private void configureDetailBar() { * flag and marks the module failed; the base system is untouched and the server restarts. */ private void confirmCancelModule() { - new com.google.android.material.dialog.MaterialAlertDialogBuilder(this) + // K2GO-385: cancel-running-install confirm -> the shared BrandDialog (destructive). + new org.appdevforall.k2go.ui.dialog.BrandDialog(this) .setTitle(R.string.k2go_mod_cancel_title) .setMessage(R.string.k2go_mod_cancel_body) - .setNegativeButton(R.string.k2go_mod_cancel_dismiss, null) - .setPositiveButton(R.string.k2go_mod_cancel_confirm, (d, w) -> + .setDestructive(R.string.k2go_mod_cancel_confirm, () -> startService(new android.content.Intent(this, org.appdevforall.k2go.install.presentation.InstallService.class) .setAction(org.appdevforall.k2go.install.presentation.InstallService.ACTION_CANCEL))) + .setNegative(R.string.k2go_mod_cancel_dismiss, null) .show(); } From 82540f9e097dc492fa3be94aa11267239a50bf3a Mon Sep 17 00:00:00 2001 From: "Luis Guzman (AppDevForAll)" Date: Sat, 5 Sep 2026 12:04:25 -0600 Subject: [PATCH 2/5] K2GO-385 refactor(ui): theme picker becomes a themed single-choice dialog Pill-roles Q3: a list picker is a themed M3 single-choice dialog with a leading filled radio on the current row, not a bare list. chooseTheme moves from AlertDialog.Builder.setItems to MaterialAlertDialogBuilder.setSingleChoiceItems wrapped in Theme_K2Go, pre-checking the active theme (Light / System / Dark). Tap still applies and closes, so behavior is unchanged; the dialog now shows which theme is active. Drops the now-unused AlertDialog import. --- .../appdevforall/k2go/redesign/SettingsFragment.java | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/controller/app/src/main/java/org/appdevforall/k2go/redesign/SettingsFragment.java b/controller/app/src/main/java/org/appdevforall/k2go/redesign/SettingsFragment.java index 73a8132a4..1c269e5bc 100644 --- a/controller/app/src/main/java/org/appdevforall/k2go/redesign/SettingsFragment.java +++ b/controller/app/src/main/java/org/appdevforall/k2go/redesign/SettingsFragment.java @@ -11,7 +11,6 @@ import android.widget.TextView; import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AppCompatDelegate; import androidx.core.content.ContextCompat; import androidx.fragment.app.Fragment; @@ -107,11 +106,17 @@ private void chooseTheme() { AppCompatDelegate.MODE_NIGHT_NO, AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM, AppCompatDelegate.MODE_NIGHT_YES}; - new AlertDialog.Builder(requireContext()) + int cur = prefs().getInt("k2go_theme", AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM); + int checked = cur == AppCompatDelegate.MODE_NIGHT_NO ? 0 : (cur == AppCompatDelegate.MODE_NIGHT_YES ? 2 : 1); + // K2GO-385 (pill roles Q3): a single-choice list picker -- a themed M3 dialog with a leading + // filled radio on the current theme, not a bare setItems list. Tap applies and closes, as before. + new com.google.android.material.dialog.MaterialAlertDialogBuilder( + new android.view.ContextThemeWrapper(requireContext(), R.style.Theme_K2Go)) .setTitle(getString(R.string.k2go_settings_theme)) - .setItems(labels, (d, w) -> { + .setSingleChoiceItems(labels, checked, (d, w) -> { prefs().edit().putInt("k2go_theme", modes[w]).apply(); AppCompatDelegate.setDefaultNightMode(modes[w]); + d.dismiss(); }) .show(); } From 9966a3145798dd7de550a0aac401af7f67aa3b1a Mon Sep 17 00:00:00 2001 From: "Luis Guzman (AppDevForAll)" Date: Sat, 5 Sep 2026 12:07:07 -0600 Subject: [PATCH 3/5] K2GO-385 refactor(ui): Books language selector reads as a dropdown, not a chip Pill-roles Q3B: the language selector sits next to the filter chips but is a different control -- it opens the single-choice language picker rather than toggling a filter. It now carries a trailing caret (ic_expand_more, teal) so it reads as a menu button that shows the current value ("English"), distinct from the chips (which toggle and show a check). No behavior change; the tap still opens the shared ZimLanguageDialog. The optional leading globe glyph is deferred until there is a size-matched icon -- the caret is the essential "this opens a menu" cue. --- .../src/main/res/layout/fragment_k2go_books_landing.xml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/controller/app/src/main/res/layout/fragment_k2go_books_landing.xml b/controller/app/src/main/res/layout/fragment_k2go_books_landing.xml index 54341fcb4..d0963be0c 100644 --- a/controller/app/src/main/res/layout/fragment_k2go_books_landing.xml +++ b/controller/app/src/main/res/layout/fragment_k2go_books_landing.xml @@ -46,6 +46,9 @@ android:textColor="@color/k2go_ink" android:textColorHint="@color/k2go_muted" /> + From 7c0e1312b92f97300ca7d6cc963529efbf63c381 Mon Sep 17 00:00:00 2001 From: "Luis Guzman (AppDevForAll)" Date: Sat, 5 Sep 2026 12:20:04 -0600 Subject: [PATCH 4/5] K2GO-385 refactor(ui): add the leading globe to the Books language dropdown Completes Q3B: the language selector now carries a leading globe (new ic_language) as well as the trailing caret, so it reads unmistakably as a language picker. Both glyphs take the teal drawableTint already on the view. --- controller/app/src/main/res/drawable/ic_language.xml | 7 +++++++ .../src/main/res/layout/fragment_k2go_books_landing.xml | 5 +++-- 2 files changed, 10 insertions(+), 2 deletions(-) create mode 100644 controller/app/src/main/res/drawable/ic_language.xml diff --git a/controller/app/src/main/res/drawable/ic_language.xml b/controller/app/src/main/res/drawable/ic_language.xml new file mode 100644 index 000000000..8d572675a --- /dev/null +++ b/controller/app/src/main/res/drawable/ic_language.xml @@ -0,0 +1,7 @@ + + + + diff --git a/controller/app/src/main/res/layout/fragment_k2go_books_landing.xml b/controller/app/src/main/res/layout/fragment_k2go_books_landing.xml index d0963be0c..3c6425f93 100644 --- a/controller/app/src/main/res/layout/fragment_k2go_books_landing.xml +++ b/controller/app/src/main/res/layout/fragment_k2go_books_landing.xml @@ -47,8 +47,8 @@ android:textColorHint="@color/k2go_muted" /> + chip. A leading globe and a trailing caret frame the current value, and a tap opens the + single-choice picker; no check or selected-fill (that is the chip language). --> Date: Sat, 5 Sep 2026 17:23:25 -0600 Subject: [PATCH 5/5] K2GO-385 fix(ui): themed M3 dialogs take a K2Go surface and teal control, not the M3 lilac default The theme picker (a MaterialAlertDialog wrapped in Theme_K2Go) rendered with the Material3 baseline lilac card and a purple radio: Theme.K2Go set colorSurface / colorSurfaceContainer but left the rest of the surface-container ladder and the control-activated colour undefined, so an M3 dialog fell back to the baseline defaults. Define the full ladder -- colorSurfaceContainerLowest / Low -> k2go_paper, High / Highest -> k2go_surface (an M3 dialog reads colorSurfaceContainerHigh for its card) -- and set colorControlActivated + android:colorControlActivated to k2go_teal (the single-choice radio uses the android-namespace attr). Root fix: every themed M3 dialog, menu and control now takes a K2Go surface and teal, not lilac / purple. The tokens carry their -night twins, so DayNight is handled. --- controller/app/src/main/res/values/themes_k2go.xml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/controller/app/src/main/res/values/themes_k2go.xml b/controller/app/src/main/res/values/themes_k2go.xml index a1b91341f..537e81bb0 100644 --- a/controller/app/src/main/res/values/themes_k2go.xml +++ b/controller/app/src/main/res/values/themes_k2go.xml @@ -10,6 +10,19 @@ @color/k2go_paper @color/k2go_paper @color/k2go_surface + + @color/k2go_paper + @color/k2go_paper + @color/k2go_surface + @color/k2go_surface + + @color/k2go_teal + @color/k2go_teal @color/k2go_ink @color/k2go_ink @color/k2go_muted