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/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 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..c5a80ce 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 + #C4C7CC + + #000000 + #FFFFFF