From 8adad9c708ceace0f82b6a158f5b4b1ccb2e23c2 Mon Sep 17 00:00:00 2001 From: Luis Guzman Date: Thu, 18 Jun 2026 21:19:23 +0000 Subject: [PATCH 1/5] feat(controller): semantic colour tokens + migrate Dashboard (theming T0) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Start the light-theme overhaul as a refactor-by-feature slice. The app already had a DayNight setup, but most screens hardcoded dark-tuned hex, so light mode breaks wherever that happens. Foundation (additive — nothing renamed or removed yet): - Add a semantic colour-token palette with full light/dark parity in values/colors.xml + values-night/colors.xml: surfaces (surface_background/ card/section), text (primary/secondary/disabled/on_accent), accent/accent_muted, status (success/warning/danger/info), divider_line, and data-viz (chart_*). QR colours (qr_foreground/qr_background) are intentionally fixed — no -night override — since a QR must stay black/white to scan. - Document the palette and the rule (no hardcoded colours; every token defined in both values and values-night) in CLAUDE.md (new "Theming" section). Pilot — Dashboard (the reference migration to copy): - fragment_dashboard.xml: replace the 7 hardcoded hex (#888888 -> @color/text_secondary; offline badge #555555 -> @color/surface_section). - DashboardFragment.java: replace the Color.parseColor gauge/battery colours with ContextCompat.getColor(R.color.status_warning/danger/success/info). Legacy dash_*/literal tokens are kept for now and retired as other screens migrate. Verify in light AND dark on device. --- CLAUDE.md | 28 +++++++++++++++ .../iiab/controller/DashboardFragment.java | 8 ++--- .../main/res/layout/fragment_dashboard.xml | 14 ++++---- .../app/src/main/res/values-night/colors.xml | 23 ++++++++++++ controller/app/src/main/res/values/colors.xml | 35 +++++++++++++++++++ 5 files changed, 97 insertions(+), 11 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index af7de61..5081c3a 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -169,6 +169,34 @@ live-size data behind the reference slice. --- +## Theming (colors) — mandatory for all UI + +The app supports light and dark via `DayNight` (toggle in `MainActivity`), but most +screens historically hardcoded dark-tuned hex, so the light theme is broken wherever +that happens. We are migrating to one semantic colour-token system, screen by screen +(refactor-by-feature). + +Rules for any new or migrated UI: + +1. **No hardcoded colours.** No `#RRGGBB` in layouts and no `Color.parseColor("#…")` + / `Color.WHITE` etc. in code. Reference a semantic token instead: + `@color/` in XML, `ContextCompat.getColor(ctx, R.color.)` in code. +2. **Every token has a light value in `values/colors.xml` and a dark twin in + `values-night/colors.xml`.** If you add a token, add both. +3. **Use the semantic families**: surfaces (`surface_background`, `surface_card`, + `surface_section`), text (`text_primary`, `text_secondary`, `text_disabled`, + `text_on_accent`), `accent`/`accent_muted`, status + (`status_success/warning/danger/info`), `divider_line`, and data-viz + (`chart_storage/ram/swap/os/maps/wiki/track`). Pick by role, not by look. +4. **Legitimately fixed colours stay fixed:** a QR must be black/white to scan, so + `qr_foreground`/`qr_background` are mode-independent (no `-night` override). +5. **Verify both modes** on a device before merge. + +Legacy tokens (`dash_*`, `white`, `black`, `section_*`, `btn_*`) are retired as screens +migrate. Reference migration: the Dashboard (`fragment_dashboard` + `DashboardFragment`). + +--- + ## Tech-debt watch list (controller) — opportunistic targets Evident debt noticed while building the pilot. Chip away at these **only when diff --git a/controller/app/src/main/java/org/iiab/controller/DashboardFragment.java b/controller/app/src/main/java/org/iiab/controller/DashboardFragment.java index 17fa200..cecabb5 100644 --- a/controller/app/src/main/java/org/iiab/controller/DashboardFragment.java +++ b/controller/app/src/main/java/org/iiab/controller/DashboardFragment.java @@ -283,8 +283,8 @@ private void updateSystemStats() { int baseColorSwap = ContextCompat.getColor(requireContext(), R.color.dash_bar_swap); int baseColorStorage = ContextCompat.getColor(requireContext(), R.color.dash_bar_storage); - int warnColor = Color.parseColor("#FF9800"); // Orange - int dangerColor = Color.parseColor("#F44336"); // Red + int warnColor = ContextCompat.getColor(requireContext(), R.color.status_warning); // Orange + int dangerColor = ContextCompat.getColor(requireContext(), R.color.status_danger); // Red // RAM Gauge (Warning at 90%, Danger at 95%) int finalColorRam = memProgress >= 95 ? dangerColor : (memProgress >= 90 ? warnColor : baseColorRam); @@ -344,9 +344,9 @@ private void updateSystemStats() { if (batLevel <= 33) { colorBattery = warnColor; // Orange (1-33%) } else if (batLevel <= 66) { - colorBattery = Color.parseColor("#4CAF50"); // Green (34-66%) + colorBattery = ContextCompat.getColor(requireContext(), R.color.status_success); // Green (34-66%) } else { - colorBattery = Color.parseColor("#2196F3"); // Blue (67-100%) + colorBattery = ContextCompat.getColor(requireContext(), R.color.status_info); // Blue (67-100%) } // Update the gauge with the newly assigned 4-parameter method diff --git a/controller/app/src/main/res/layout/fragment_dashboard.xml b/controller/app/src/main/res/layout/fragment_dashboard.xml index ba78564..efe991a 100644 --- a/controller/app/src/main/res/layout/fragment_dashboard.xml +++ b/controller/app/src/main/res/layout/fragment_dashboard.xml @@ -117,14 +117,14 @@ android:layout_width="16dp" android:layout_height="16dp" android:src="@drawable/outline_android_wifi_3_bar_24" - app:tint="#888888" + app:tint="@color/text_secondary" android:layout_centerVertical="true" /> + app:tint="@color/text_secondary" /> @@ -339,7 +339,7 @@ android:layout_height="wrap_content" android:text="@string/dash_offline" android:background="@drawable/rounded_button" - android:backgroundTint="#555555" + android:backgroundTint="@color/surface_section" android:textColor="@color/dash_text_primary" android:fontFamily="@font/orbitron" android:textSize="11sp" diff --git a/controller/app/src/main/res/values-night/colors.xml b/controller/app/src/main/res/values-night/colors.xml index 82a7751..049b625 100644 --- a/controller/app/src/main/res/values-night/colors.xml +++ b/controller/app/src/main/res/values-night/colors.xml @@ -18,4 +18,27 @@ #444444 #333333 + + + #121212 + #1E1E1E + #2A2A2A + #FAFAFA + #BDBDBD + #7A7A7A + #FFFFFF + #4CAF50 + #2E5A30 + #66BB6A + #FFB300 + #EF5350 + #42A5F5 + #333333 + #4DB6AC + #FFB300 + #7986CB + #26C6DA + #FF9800 + #66BB6A + #333333 diff --git a/controller/app/src/main/res/values/colors.xml b/controller/app/src/main/res/values/colors.xml index e7f118c..127023e 100644 --- a/controller/app/src/main/res/values/colors.xml +++ b/controller/app/src/main/res/values/colors.xml @@ -44,6 +44,41 @@ #5F6368 + + + + + + #F4F5F7 + #FFFFFF + #E8EAED + + #202124 + #5F6368 + #9AA0A6 + #FFFFFF + + #2E7D32 + #A5D6A7 + + #2E7D32 + #E65100 + #C62828 + #1565C0 + + #E0E0E0 + + #00897B + #FF8F00 + #5C6BC0 + #00838F + #EF6C00 + #2E7D32 + #E0E0E0 + + #000000 + #FFFFFF From f27492628e0d7a2d03dace68f145774d7f13b3ec Mon Sep 17 00:00:00 2001 From: Luis Guzman Date: Thu, 18 Jun 2026 21:49:24 +0000 Subject: [PATCH 2/5] fix(controller): make Dashboard gauge text legible (theming) ResourceGaugeView hardcoded the gauge title (#CCCCCC) and subtitle (#AAAAAA) in a light grey that is unreadable on the light surface, and the track arc in #333333 (a heavy black arc on a light card). Route them through tokens: title/subtitle -> text_secondary, percent -> text_primary, track -> chart_track, default arc -> status_success. Removes the last hardcoded colours from the Dashboard's gauges; verify both modes. --- .../java/org/iiab/controller/ResourceGaugeView.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/controller/app/src/main/java/org/iiab/controller/ResourceGaugeView.java b/controller/app/src/main/java/org/iiab/controller/ResourceGaugeView.java index cc507cc..01c3044 100644 --- a/controller/app/src/main/java/org/iiab/controller/ResourceGaugeView.java +++ b/controller/app/src/main/java/org/iiab/controller/ResourceGaugeView.java @@ -11,7 +11,6 @@ import android.animation.ValueAnimator; import android.content.Context; import android.graphics.Canvas; -import android.graphics.Color; import android.graphics.Paint; import android.graphics.RectF; import android.graphics.Typeface; @@ -30,7 +29,7 @@ public class ResourceGaugeView extends View { private String centerText = "0%"; private String bottomText = "-- / --"; - private int currentColor = Color.parseColor("#4CAF50"); + private int currentColor; public ResourceGaugeView(Context context, AttributeSet attrs) { super(context, attrs); @@ -40,10 +39,11 @@ public ResourceGaugeView(Context context, AttributeSet attrs) { private void init(Context context) { setLayerType(View.LAYER_TYPE_SOFTWARE, null); rectF = new RectF(); + currentColor = androidx.core.content.ContextCompat.getColor(context, R.color.status_success); bgArcPaint = new Paint(Paint.ANTI_ALIAS_FLAG); bgArcPaint.setStyle(Paint.Style.STROKE); - bgArcPaint.setColor(Color.parseColor("#333333")); + bgArcPaint.setColor(androidx.core.content.ContextCompat.getColor(context, R.color.chart_track)); bgArcPaint.setStrokeCap(Paint.Cap.ROUND); bgArcPaint.setPathEffect(null); @@ -57,16 +57,16 @@ private void init(Context context) { percentPaint = new Paint(Paint.ANTI_ALIAS_FLAG); percentPaint.setTextAlign(Paint.Align.CENTER); - percentPaint.setColor(androidx.core.content.ContextCompat.getColor(context, R.color.dash_text_inverted)); + percentPaint.setColor(androidx.core.content.ContextCompat.getColor(context, R.color.text_primary)); percentPaint.setFakeBoldText(true); valuePaint = new Paint(Paint.ANTI_ALIAS_FLAG); valuePaint.setTextAlign(Paint.Align.CENTER); - valuePaint.setColor(Color.parseColor("#AAAAAA")); + valuePaint.setColor(androidx.core.content.ContextCompat.getColor(context, R.color.text_secondary)); titlePaint = new Paint(Paint.ANTI_ALIAS_FLAG); titlePaint.setTextAlign(Paint.Align.CENTER); - titlePaint.setColor(Color.parseColor("#CCCCCC")); + titlePaint.setColor(androidx.core.content.ContextCompat.getColor(context, R.color.text_secondary)); titlePaint.setFakeBoldText(true); // LOAD AND APPLY ORBITRON From ec68f2de561603623d2c83259fb6ab10640fc782 Mon Sep 17 00:00:00 2001 From: Luis Guzman Date: Thu, 18 Jun 2026 22:01:03 +0000 Subject: [PATCH 3/5] fix(controller): darken gauge track in light theme for visibility The light-theme track (#E0E0E0) blended into the card background, so the gauge 'path' was barely distinguishable from the surface. Bump to #C4C7CC so the track reads clearly as the channel the colored arc follows. Dark theme track (#333333) is unchanged. --- controller/app/src/main/res/values/colors.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/controller/app/src/main/res/values/colors.xml b/controller/app/src/main/res/values/colors.xml index 127023e..c5a80ce 100644 --- a/controller/app/src/main/res/values/colors.xml +++ b/controller/app/src/main/res/values/colors.xml @@ -74,7 +74,7 @@ #00838F #EF6C00 #2E7D32 - #E0E0E0 + #C4C7CC #000000 From ab980ae1edd1c4200d5c3bb2f1d9077c9de69323 Mon Sep 17 00:00:00 2001 From: Luis Guzman Date: Thu, 18 Jun 2026 22:25:18 +0000 Subject: [PATCH 4/5] feat(controller): migrate Share/Sync screen to semantic colour tokens Refactor-by-feature theming slice for the SHARE tab (SyncFragment + fragment_sync.xml) plus the QR modal (activity_qr.xml) and the share tutorial overlay (overlay_tutorial_share.xml). Includes the shared round-2 token block (twins in values + values-night). Migration (no behaviour/layout change intended): - fragment_sync.xml (25), activity_qr.xml (7), overlay_tutorial_share.xml (4): card titles -> text_primary, subtitles #AAAAAA -> text_secondary, card surfaces #222222 -> surface_card, badges #1A1A1A -> surface_section, segmented-toggle bg #333333 -> btn_neutral, button fills -> status_success/info/danger, status text #FF9800 -> status_warning, arch badge green -> status_success. - QR image backgrounds (#FFFFFF) -> qr_background (must stay white to scan). - Full-screen scrims (#DD000000 / #D9000000) -> overlay_scrim, and text/icons sitting ON the scrim -> text_on_accent (fixed white) so they stay legible in both themes (text_primary would turn dark in light mode and vanish). - SyncFragment.java: added ContextCompat import; parseColor(...)/Color.BLACK -> ContextCompat.getColor(R.color.*). Active-card tints #173317/#17263A -> surface_active_success/info; bright-green badge #00E676 -> status_success with black text -> text_on_warning. Verify in light AND dark on device. --- .../org/iiab/controller/SyncFragment.java | 33 ++++++------ .../app/src/main/res/layout/activity_qr.xml | 14 +++--- .../app/src/main/res/layout/fragment_sync.xml | 50 +++++++++---------- .../res/layout/overlay_tutorial_share.xml | 8 +-- .../app/src/main/res/values-night/colors.xml | 12 +++++ controller/app/src/main/res/values/colors.xml | 13 +++++ 6 files changed, 78 insertions(+), 52 deletions(-) diff --git a/controller/app/src/main/java/org/iiab/controller/SyncFragment.java b/controller/app/src/main/java/org/iiab/controller/SyncFragment.java index d401967..9fda479 100644 --- a/controller/app/src/main/java/org/iiab/controller/SyncFragment.java +++ b/controller/app/src/main/java/org/iiab/controller/SyncFragment.java @@ -48,6 +48,7 @@ import java.util.List; import android.widget.RadioButton; +import androidx.core.content.ContextCompat; public class SyncFragment extends Fragment { @@ -318,14 +319,14 @@ private void startShareDaemon(File rootfsDir) { qrDisplaySection.setVisibility(View.VISIBLE); qrCardContainer.setVisibility(View.VISIBLE); imgQrCode.setAlpha(1f); - cardShareSystem.setBackgroundTintList(android.content.res.ColorStateList.valueOf(android.graphics.Color.parseColor("#173317"))); + cardShareSystem.setBackgroundTintList(android.content.res.ColorStateList.valueOf(ContextCompat.getColor(requireContext(), R.color.surface_active_success))); rgNetworkSelector.setVisibility((wifiIp != null && hotspotIp != null) ? View.VISIBLE : View.GONE); showingWifi = (wifiIp != null); updateQrDisplayRsync(); btnStartServer.setText(getString(R.string.sync_btn_stop_server)); - btnStartServer.setBackgroundTintList(android.content.res.ColorStateList.valueOf(android.graphics.Color.parseColor("#F44336"))); // Red + btnStartServer.setBackgroundTintList(android.content.res.ColorStateList.valueOf(ContextCompat.getColor(requireContext(), R.color.status_danger))); // Red btnShareApp.setVisibility(View.GONE); } else { Toast.makeText(getContext(), getString(R.string.sync_error_daemon_failed), Toast.LENGTH_SHORT).show(); @@ -341,7 +342,7 @@ private void updateQrDisplayRsync() { String baseText = showingWifi ? getString(R.string.sync_share_status_wifi) : getString(R.string.sync_share_status_hotspot); txtShareStatus.setText(baseText); - txtShareStatus.setTextColor(android.graphics.Color.parseColor("#AAAAAA")); + txtShareStatus.setTextColor(ContextCompat.getColor(requireContext(), R.color.text_secondary)); } private void stopShareDaemon() { @@ -352,13 +353,13 @@ private void stopShareDaemon() { qrDisplaySection.setVisibility(View.GONE); btnStartServer.setText(getString(R.string.sync_btn_start_server)); - cardShareSystem.setBackgroundTintList(android.content.res.ColorStateList.valueOf(android.graphics.Color.parseColor("#222222"))); + cardShareSystem.setBackgroundTintList(android.content.res.ColorStateList.valueOf(ContextCompat.getColor(requireContext(), R.color.surface_card))); btnStartServer.setText(getString(R.string.sync_btn_start_server)); - btnStartServer.setBackgroundTintList(android.content.res.ColorStateList.valueOf(android.graphics.Color.parseColor("#008000"))); // Green + btnStartServer.setBackgroundTintList(android.content.res.ColorStateList.valueOf(ContextCompat.getColor(requireContext(), R.color.status_success))); // Green btnShareApp.setVisibility(View.VISIBLE); txtShareStatus.setText(getString(R.string.sync_share_status_off)); - txtShareStatus.setTextColor(android.graphics.Color.parseColor("#FF9800")); // Orange + txtShareStatus.setTextColor(ContextCompat.getColor(requireContext(), R.color.status_warning)); // Orange } // --- APK SERVER METHODS --- @@ -375,14 +376,14 @@ private void startApkServer() { qrCardContainer.setVisibility(View.VISIBLE); updateCardOrder(true); imgQrCode.setAlpha(1f); - cardShareApk.setBackgroundTintList(android.content.res.ColorStateList.valueOf(android.graphics.Color.parseColor("#17263A"))); + cardShareApk.setBackgroundTintList(android.content.res.ColorStateList.valueOf(ContextCompat.getColor(requireContext(), R.color.surface_active_info))); rgNetworkSelector.setVisibility((wifiIp != null && hotspotIp != null) ? View.VISIBLE : View.GONE); showingWifi = (wifiIp != null); updateQrDisplayApk(); btnShareApp.setText(getString(R.string.sync_btn_stop_app)); - btnShareApp.setBackgroundTintList(android.content.res.ColorStateList.valueOf(android.graphics.Color.parseColor("#F44336"))); // Red + btnShareApp.setBackgroundTintList(android.content.res.ColorStateList.valueOf(ContextCompat.getColor(requireContext(), R.color.status_danger))); // Red btnStartServer.setVisibility(View.GONE); } catch (Exception e) { @@ -400,7 +401,7 @@ private void updateQrDisplayApk() { String baseText = showingWifi ? getString(R.string.sync_app_status_wifi) : getString(R.string.sync_app_status_hotspot); txtShareStatus.setText(baseText); - txtShareStatus.setTextColor(android.graphics.Color.parseColor("#AAAAAA")); + txtShareStatus.setTextColor(ContextCompat.getColor(requireContext(), R.color.text_secondary)); } private void stopApkServer() { @@ -413,13 +414,13 @@ private void stopApkServer() { qrDisplaySection.setVisibility(View.GONE); btnShareApp.setText(getString(R.string.sync_btn_share_app)); - cardShareApk.setBackgroundTintList(android.content.res.ColorStateList.valueOf(android.graphics.Color.parseColor("#222222"))); + cardShareApk.setBackgroundTintList(android.content.res.ColorStateList.valueOf(ContextCompat.getColor(requireContext(), R.color.surface_card))); btnShareApp.setText(getString(R.string.sync_btn_share_app)); - btnShareApp.setBackgroundTintList(android.content.res.ColorStateList.valueOf(android.graphics.Color.parseColor("#0055A4"))); // Blue + btnShareApp.setBackgroundTintList(android.content.res.ColorStateList.valueOf(ContextCompat.getColor(requireContext(), R.color.status_info))); // Blue btnStartServer.setVisibility(View.VISIBLE); txtShareStatus.setText(getString(R.string.sync_share_status_off)); - txtShareStatus.setTextColor(android.graphics.Color.parseColor("#FF9800")); // Orange + txtShareStatus.setTextColor(ContextCompat.getColor(requireContext(), R.color.status_warning)); // Orange } // --- CLIENT (RECEIVER) METHODS --- @@ -776,16 +777,16 @@ private void showArchCompatibilitySuccess(Runnable onComplete) { } if (txtGuestArchLabel != null) { - txtGuestArchLabel.setBackgroundTintList(android.content.res.ColorStateList.valueOf(android.graphics.Color.parseColor("#00E676"))); - txtGuestArchLabel.setTextColor(android.graphics.Color.BLACK); + txtGuestArchLabel.setBackgroundTintList(android.content.res.ColorStateList.valueOf(ContextCompat.getColor(requireContext(), R.color.status_success))); + txtGuestArchLabel.setTextColor(ContextCompat.getColor(requireContext(), R.color.text_on_warning)); } Snackbar.make(requireView(), getString(R.string.sync_msg_arch_compatible), Snackbar.LENGTH_SHORT).show(); new Handler(Looper.getMainLooper()).postDelayed(() -> { if (txtGuestArchLabel != null) { - txtGuestArchLabel.setBackgroundTintList(android.content.res.ColorStateList.valueOf(android.graphics.Color.parseColor("#1A1A1A"))); - txtGuestArchLabel.setTextColor(android.graphics.Color.parseColor("#4CAF50")); + txtGuestArchLabel.setBackgroundTintList(android.content.res.ColorStateList.valueOf(ContextCompat.getColor(requireContext(), R.color.surface_section))); + txtGuestArchLabel.setTextColor(ContextCompat.getColor(requireContext(), R.color.status_success)); } onComplete.run(); }, 1500); diff --git a/controller/app/src/main/res/layout/activity_qr.xml b/controller/app/src/main/res/layout/activity_qr.xml index 96fb324..a6ef567 100644 --- a/controller/app/src/main/res/layout/activity_qr.xml +++ b/controller/app/src/main/res/layout/activity_qr.xml @@ -3,7 +3,7 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" - android:background="#DD000000" + android:background="@color/overlay_scrim" android:padding="24dp"> @@ -35,7 +35,7 @@ android:layout_centerVertical="true" android:layout_toStartOf="@+id/btn_flip_qr" android:text="@string/qr_title_wifi" - android:textColor="#FFFFFF" + android:textColor="@color/text_primary" android:textSize="22sp" android:textStyle="bold" /> @@ -48,7 +48,7 @@ android:background="?android:attr/selectableItemBackgroundBorderless" android:src="@android:drawable/ic_popup_sync" android:contentDescription="@string/qr_flip_network" - android:tint="#FFFFFF" + android:tint="@color/text_primary" android:scaleType="fitCenter" android:padding="8dp" android:visibility="gone" /> @@ -59,7 +59,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:text="http://---" - android:textColor="#AAAAAA" + android:textColor="@color/text_secondary" android:textSize="16sp" android:layout_marginBottom="16dp" /> @@ -69,7 +69,7 @@ android:layout_height="wrap_content" android:adjustViewBounds="true" android:scaleType="fitCenter" - android:background="#FFFFFF" + android:background="@color/qr_background" android:padding="16dp" /> @@ -82,6 +82,6 @@ android:layout_marginTop="24dp" android:text="@string/qr_btn_close" android:backgroundTint="@color/btn_danger" - android:textColor="#FFFFFF" /> + android:textColor="@color/text_on_accent" /> \ No newline at end of file diff --git a/controller/app/src/main/res/layout/fragment_sync.xml b/controller/app/src/main/res/layout/fragment_sync.xml index d58e181..867e4be 100644 --- a/controller/app/src/main/res/layout/fragment_sync.xml +++ b/controller/app/src/main/res/layout/fragment_sync.xml @@ -19,7 +19,7 @@ android:layout_height="48dp" android:orientation="horizontal" android:background="@drawable/rounded_button" - android:backgroundTint="#333333" + android:backgroundTint="@color/btn_neutral" android:layout_marginBottom="24dp"> @@ -122,7 +122,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/sync_share_status_init" - android:textColor="#FF9800" + android:textColor="@color/status_warning" android:textSize="14sp" android:textAlignment="center" android:layout_marginBottom="16dp" /> @@ -133,12 +133,12 @@ android:layout_height="wrap_content" android:layout_marginBottom="24dp" android:background="@drawable/rounded_button" - android:backgroundTint="#1A1A1A" + android:backgroundTint="@color/surface_section" android:paddingStart="16dp" android:paddingTop="6dp" android:paddingEnd="16dp" android:paddingBottom="6dp" - android:textColor="#4CAF50" + android:textColor="@color/status_success" android:textSize="14sp" android:textStyle="bold" android:fontFamily="monospace" @@ -152,7 +152,7 @@ android:layout_height="wrap_content" android:orientation="vertical" android:background="@drawable/rounded_button" - android:backgroundTint="#222222" + android:backgroundTint="@color/surface_card" android:padding="16dp" android:layout_marginBottom="16dp"> @@ -160,7 +160,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/sync_card_title_system" - android:textColor="#FFFFFF" + android:textColor="@color/text_primary" android:textSize="18sp" android:textStyle="bold" android:layout_marginBottom="8dp" /> @@ -169,7 +169,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/sync_card_desc_system" - android:textColor="#AAAAAA" + android:textColor="@color/text_secondary" android:textSize="14sp" android:layout_marginBottom="16dp" /> @@ -180,9 +180,9 @@ android:text="@string/sync_btn_start_server" android:textSize="16sp" android:textStyle="bold" - android:textColor="#FFFFFF" + android:textColor="@color/text_on_accent" android:background="@drawable/rounded_button" - android:backgroundTint="#008000" + android:backgroundTint="@color/status_success" android:textAllCaps="false" /> @@ -192,7 +192,7 @@ android:layout_height="wrap_content" android:orientation="vertical" android:background="@drawable/rounded_button" - android:backgroundTint="#222222" + android:backgroundTint="@color/surface_card" android:padding="16dp" android:layout_marginBottom="16dp"> @@ -200,7 +200,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/sync_card_title_apk" - android:textColor="#FFFFFF" + android:textColor="@color/text_primary" android:textSize="18sp" android:textStyle="bold" android:layout_marginBottom="8dp" /> @@ -209,7 +209,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/sync_card_desc_apk" - android:textColor="#AAAAAA" + android:textColor="@color/text_secondary" android:textSize="14sp" android:layout_marginBottom="16dp" /> @@ -220,9 +220,9 @@ android:text="@string/sync_btn_share_app" android:textSize="16sp" android:textStyle="bold" - android:textColor="#FFFFFF" + android:textColor="@color/text_on_accent" android:background="@drawable/rounded_button" - android:backgroundTint="#0055A4" + android:backgroundTint="@color/status_info" android:textAllCaps="false" /> @@ -241,7 +241,7 @@ android:layout_height="wrap_content" android:orientation="vertical" android:background="@drawable/rounded_button" - android:backgroundTint="#222222" + android:backgroundTint="@color/surface_card" android:padding="16dp" android:layout_marginBottom="16dp"> @@ -249,7 +249,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/sync_card_title_receive" - android:textColor="#FFFFFF" + android:textColor="@color/text_primary" android:textSize="18sp" android:textStyle="bold" android:layout_marginBottom="8dp" /> @@ -258,7 +258,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/sync_card_desc_receive" - android:textColor="#AAAAAA" + android:textColor="@color/text_secondary" android:textSize="14sp" android:layout_marginBottom="16dp" /> @@ -269,9 +269,9 @@ android:text="@string/sync_btn_scan_qr" android:textSize="16sp" android:textStyle="bold" - android:textColor="#FFFFFF" + android:textColor="@color/text_on_accent" android:background="@drawable/rounded_button" - android:backgroundTint="#2196F3" + android:backgroundTint="@color/status_info" android:textAllCaps="false" app:icon="@android:drawable/ic_menu_camera" app:iconGravity="textStart" /> @@ -336,8 +336,8 @@ android:layout_marginTop="16dp" android:text="@string/sync_btn_cancel_transfer" android:background="@drawable/rounded_button" - android:backgroundTint="#F44336" - android:textColor="#FFFFFF" + android:backgroundTint="@color/status_danger" + android:textColor="@color/text_on_accent" android:textStyle="bold" android:textAllCaps="false" /> @@ -351,12 +351,12 @@ android:layout_marginTop="16dp" android:layout_marginBottom="32dp" android:background="@drawable/rounded_button" - android:backgroundTint="#1A1A1A" + android:backgroundTint="@color/surface_section" android:paddingStart="16dp" android:paddingTop="6dp" android:paddingEnd="16dp" android:paddingBottom="6dp" - android:textColor="#4CAF50" + android:textColor="@color/status_success" android:textSize="14sp" android:textStyle="bold" android:fontFamily="monospace" diff --git a/controller/app/src/main/res/layout/overlay_tutorial_share.xml b/controller/app/src/main/res/layout/overlay_tutorial_share.xml index 2c80c16..a090d6d 100644 --- a/controller/app/src/main/res/layout/overlay_tutorial_share.xml +++ b/controller/app/src/main/res/layout/overlay_tutorial_share.xml @@ -4,7 +4,7 @@ android:id="@+id/tutorial_root" android:layout_width="match_parent" android:layout_height="match_parent" - android:background="#D9000000" + android:background="@color/overlay_scrim" android:elevation="10dp" android:alpha="0"> @@ -58,7 +58,7 @@ android:layout_marginTop="16dp" android:backgroundTint="@color/btn_primary" android:text="@string/tutorial_share_got_it" - android:textColor="#FFFFFF" /> + android:textColor="@color/text_on_accent" /> @@ -67,7 +67,7 @@ android:layout_width="48dp" android:layout_height="48dp" android:padding="12dp" - app:tint="#FFFFFF" /> + app:tint="@color/text_on_accent" /> diff --git a/controller/app/src/main/res/values-night/colors.xml b/controller/app/src/main/res/values-night/colors.xml index 049b625..75d047d 100644 --- a/controller/app/src/main/res/values-night/colors.xml +++ b/controller/app/src/main/res/values-night/colors.xml @@ -41,4 +41,16 @@ #FF9800 #66BB6A #333333 + + #173317 + #17263A + #5C1A1A + #3A2A0E + #FFCA28 + #B39DDB + #424242 + #212121 + #0D0D0D + #33FF33 + #CC000000 diff --git a/controller/app/src/main/res/values/colors.xml b/controller/app/src/main/res/values/colors.xml index c5a80ce..d63b89f 100644 --- a/controller/app/src/main/res/values/colors.xml +++ b/controller/app/src/main/res/values/colors.xml @@ -75,6 +75,19 @@ #EF6C00 #2E7D32 #C4C7CC + + #E6F4EA + #E3F0FB + #FDECEA + #FFF3E0 + #F9A825 + #6A3FB5 + #616161 + #212121 + #0D0D0D + #33FF33 + #CC000000 + #000000 From 003aec7c93fe427bc2b9239bb3037213bdad1460 Mon Sep 17 00:00:00 2001 From: Luis Guzman Date: Fri, 19 Jun 2026 02:03:52 +0000 Subject: [PATCH 5/5] fix(controller): restore Share cards + readable toggle in light theme MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Review feedback: in light mode the Share screen lost its cards (text on a white page) and the segmented toggle text was illegible. Root cause: Share's page used ?android:attr/windowBackground (white in light), and the cards were mapped to surface_card (also white) — white on white. The toggle track used btn_neutral (dark-ish) with dark text. Fixes (no dark-mode regression): - Page background -> surface_background (#F4F5F7), matching Status/Install. - The three cards (system / apk / receive) surface_card -> dash_module_bg, so they read as cards on the page (same token as the Dashboard panels and the existing transfer-progress card). Also darken dash_module_bg light #E8EAED -> #DEE1E6 to match the Usage/Install slices. - Segmented toggles (mode + network): track btn_neutral -> surface_section (light track), and the selected-segment drawable #444444 -> new toggle_selected token (#FFFFFF light / #3A3A3A dark) — a raised light thumb so the selected label reads in both themes. New token toggle_selected added to values + values-night. --- .../app/src/main/res/drawable/radio_selector_bg.xml | 2 +- controller/app/src/main/res/layout/fragment_sync.xml | 12 ++++++------ controller/app/src/main/res/values-night/colors.xml | 1 + controller/app/src/main/res/values/colors.xml | 3 ++- 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/controller/app/src/main/res/drawable/radio_selector_bg.xml b/controller/app/src/main/res/drawable/radio_selector_bg.xml index 8e92e5c..90edb64 100644 --- a/controller/app/src/main/res/drawable/radio_selector_bg.xml +++ b/controller/app/src/main/res/drawable/radio_selector_bg.xml @@ -3,7 +3,7 @@ - + diff --git a/controller/app/src/main/res/layout/fragment_sync.xml b/controller/app/src/main/res/layout/fragment_sync.xml index 867e4be..927aace 100644 --- a/controller/app/src/main/res/layout/fragment_sync.xml +++ b/controller/app/src/main/res/layout/fragment_sync.xml @@ -5,7 +5,7 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:fillViewport="true" - android:background="?android:attr/windowBackground"> + android:background="@color/surface_background"> @@ -152,7 +152,7 @@ android:layout_height="wrap_content" android:orientation="vertical" android:background="@drawable/rounded_button" - android:backgroundTint="@color/surface_card" + android:backgroundTint="@color/dash_module_bg" android:padding="16dp" android:layout_marginBottom="16dp"> @@ -192,7 +192,7 @@ android:layout_height="wrap_content" android:orientation="vertical" android:background="@drawable/rounded_button" - android:backgroundTint="@color/surface_card" + android:backgroundTint="@color/dash_module_bg" android:padding="16dp" android:layout_marginBottom="16dp"> @@ -241,7 +241,7 @@ android:layout_height="wrap_content" android:orientation="vertical" android:background="@drawable/rounded_button" - android:backgroundTint="@color/surface_card" + android:backgroundTint="@color/dash_module_bg" android:padding="16dp" android:layout_marginBottom="16dp"> diff --git a/controller/app/src/main/res/values-night/colors.xml b/controller/app/src/main/res/values-night/colors.xml index 75d047d..7b2f5bb 100644 --- a/controller/app/src/main/res/values-night/colors.xml +++ b/controller/app/src/main/res/values-night/colors.xml @@ -53,4 +53,5 @@ #0D0D0D #33FF33 #CC000000 + #3A3A3A diff --git a/controller/app/src/main/res/values/colors.xml b/controller/app/src/main/res/values/colors.xml index d63b89f..00a986c 100644 --- a/controller/app/src/main/res/values/colors.xml +++ b/controller/app/src/main/res/values/colors.xml @@ -36,7 +36,7 @@ #5F6368 #202124 #5F6368 - #E8EAED + #DEE1E6 #202124 #E0E0E0 #E65100 @@ -87,6 +87,7 @@ #0D0D0D #33FF33 #CC000000 + #FFFFFF