Skip to content

feat: Added theme support for External Display Input#497

Closed
MayRedBeWithYou wants to merge 3 commits intoutkarshdalal:masterfrom
MayRedBeWithYou:feature/external-display-input-themes
Closed

feat: Added theme support for External Display Input#497
MayRedBeWithYou wants to merge 3 commits intoutkarshdalal:masterfrom
MayRedBeWithYou:feature/external-display-input-themes

Conversation

@MayRedBeWithYou
Copy link
Copy Markdown
Contributor

@MayRedBeWithYou MayRedBeWithYou commented Feb 6, 2026

I recently posted a #feature-request regarding adding AMOLED theme for External Display Input mode. I decided to give it a shot - let me know what you think.

  • Settings:
Screenshot_20260206-170601
  • Default theme:
Screenshot_20260206-170624 Screenshot_20260206-170630
  • AMOLED theme:
Screenshot_20260206-170654 Screenshot_20260206-170700

Summary by cubic

Adds theme support to External Display Input with a new Black theme for true blacks and reduced glare. Themes apply across touchpad, keyboard, hybrid modes, and overlays, with consistent key label and icon colors.

  • New Features

    • Theme system with DEFAULT and BLACK variants for External Display Input.
    • New setting: “External Display Input Theme” (Settings → Interface); persisted via PrefManager.
    • Themed backgrounds, key highlights, key label color, and icon tints for presentation and swap overlay; applied on XServer start and updatable at runtime.
  • Bug Fixes

    • Fixed theming inconsistencies across modes and overlays.
    • Adjusted keyboard text and icon colors to match the selected theme, including swap/hybrid toggles.

Written for commit 07a0187. Summary will update on new commits.

Summary by CodeRabbit

  • New Features

    • External display input now supports two themes (Default and Black) with distinct color palettes applied across keyboard, overlay, and icons; theme changes apply live.
  • Settings

    • Added "External Display Input Theme" dropdown in Settings to choose and persist the preferred theme.
  • UI

    • New color and string resources added to support the themes.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Feb 6, 2026

📝 Walkthrough

Walkthrough

Adds a theme system for external display input: new Theme enum with colors, PrefManager.externalDisplayTheme preference, settings UI to select theme, ExternalDisplayInputController.setTheme API, and views/presentation updated to render and propagate theme changes.

Changes

Cohort / File(s) Summary
Core Theme & Prefs
app/src/main/java/app/gamenative/externaldisplay/ExternalDisplayInputController.kt, app/src/main/java/app/gamenative/PrefManager.kt
Add Theme enum (DEFAULT, BLACK) with color fields and fromConfig; add externalDisplayTheme pref property; controller holds theme and exposes setTheme() to apply it.
Presentation & Controller Binding
app/src/main/java/app/gamenative/externaldisplay/ExternalInputPresentation.kt, app/src/main/java/app/gamenative/externaldisplay/ExternalDisplayInputController.kt
Presentation now accepts/stores a Theme, adds updateTheme(); rendering paths use theme color values; controller propagates theme changes to active presentation.
Keyboard & Overlay Views
app/src/main/java/app/gamenative/externaldisplay/ExternalOnScreenKeyboardView.kt, app/src/main/java/app/gamenative/externaldisplay/SwapInputOverlayView.kt, app/src/main/java/app/gamenative/externaldisplay/HybridInputLayout.kt
Constructors accept a theme param; replace hard-coded/resource colors with theme.* values; apply color filters for icons and key text using theme.keyColor.
Settings UI & Screen Wiring
app/src/main/java/app/gamenative/ui/screen/settings/SettingsGroupInterface.kt, app/src/main/java/app/gamenative/ui/screen/xserver/XServerScreen.kt
Add settings dropdown to choose external display theme, persist to PrefManager.externalDisplayTheme; XServerScreen reads pref, passes theme to overlay, and calls controller.setTheme when starting external display.
Resources
app/src/main/res/values/colors.xml, app/src/main/res/values/strings.xml
Add new color resources for black-theme variants and external_display_key_color; add strings for settings label and two theme option names.

Sequence Diagram

sequenceDiagram
    actor User
    participant Settings as "Settings UI"
    participant PrefMgr as "PrefManager"
    participant XScreen as "XServerScreen"
    participant DisplayCtrl as "ExternalDisplayInputController"
    participant Presentation as "ExternalInputPresentation"
    participant Views as "External Views"

    User->>Settings: select theme option
    Settings->>PrefMgr: save externalDisplayTheme
    PrefMgr-->>Settings: confirm persisted
    XScreen->>PrefMgr: read externalDisplayTheme
    PrefMgr-->>XScreen: return theme
    XScreen->>DisplayCtrl: start / setTheme(theme)
    DisplayCtrl->>Presentation: updateTheme(theme)
    Presentation->>Views: re-render using theme colors
    Views-->>User: show themed external UI
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

🐰✨ I hopped through pixels, painting keys bright,
A theme tucked in prefs for day and for night,
Controller whispers, presentations hum,
Colors align — the keyboard’s become,
Hop, render, repeat — a rabbit’s delight!

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: adding theme support for external display input functionality across multiple files and components.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
📝 Coding Plan
  • Generate coding plan for human review comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Tip

CodeRabbit can suggest fixes for GitHub Check annotations.

Configure the reviews.tools.github-checks setting to adjust the time to wait for GitHub Checks to complete.

Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 8 files

Prompt for AI agents (all issues)

Check if these issues are valid — if so, understand the root cause of each and fix them.


<file name="app/src/main/java/app/gamenative/ui/screen/settings/SettingsGroupInterface.kt">

<violation number="1" location="app/src/main/java/app/gamenative/ui/screen/settings/SettingsGroupInterface.kt:419">
P2: User-visible dropdown labels are hardcoded instead of using string resources, preventing localization and inconsistent with the rest of the settings UI.</violation>
</file>

Since this is your first cubic review, here's how it works:

  • cubic automatically reviews your code and comments on bugs and improvements
  • Teach cubic by replying to its comments. cubic learns from your replies and gets better over time
  • Ask questions if you need clarification on any suggestion

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Comment thread app/src/main/java/app/gamenative/ui/screen/settings/SettingsGroupInterface.kt Outdated
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
app/src/main/java/app/gamenative/externaldisplay/SwapInputOverlayView.kt (1)

55-60: ⚠️ Potential issue | 🟠 Major

Bug: keyboardToggleButton background color is not themed.

Line 57 uses hardcoded R.color.external_display_key_background while every other color in this file and the equivalent button in HybridInputLayout (line 291 of ExternalDisplayInputController.kt) uses theme.keyBg. This means the AMOLED theme won't apply to this button's background in SwapInputOverlayView.

🐛 Proposed fix
         background = GradientDrawable().apply {
             shape = GradientDrawable.OVAL
-            setColor(ContextCompat.getColor(context, R.color.external_display_key_background))
+            setColor(ContextCompat.getColor(context, theme.keyBg))
         }
app/src/main/java/app/gamenative/externaldisplay/ExternalDisplayInputController.kt (1)

213-222: ⚠️ Potential issue | 🟡 Minor

Inconsistent icon styling: alpha = 0.35f here vs. no alpha in SwapInputOverlayView.

In the ExternalInputPresentation KEYBOARD mode, the hint icon uses both setColorFilter(theme.iconColor) (line 220) and alpha = 0.35f (line 221). In SwapInputOverlayView (line 30), only setColorFilter(theme.iconColor) is applied—no alpha. This means the hint icon will look different depending on which code path renders it.

If the intent is for the theme's iconColor to fully control opacity, remove the hardcoded alpha here. If the alpha is intentional for the external display, consider documenting why.

🤖 Fix all issues with AI agents
In
`@app/src/main/java/app/gamenative/ui/screen/settings/SettingsGroupInterface.kt`:
- Around line 415-429: The dropdown is comparing localized labels ("Default",
"AMOLED") to a stored enum name (PrefManager.externalDisplayTheme, e.g.,
"DEFAULT"), causing indexOf to return -1 and wrong persistence; change the
dropdown to be enum-backed: build a list of enum values (e.g., Theme.values())
or enum-name strings to use as the internal items for value/indexing and
persistence, and separately map those enum entries to localized display labels
for title/visible text; initialize selectedExternalDisplayTheme from
PrefManager.externalDisplayTheme (the enum name), use the enum-name list for
SettingsListDropdown.value/indexOf, and onItemSelected persist the selected
enum.name back to PrefManager.externalDisplayTheme while showing the
corresponding localized label.
🧹 Nitpick comments (2)
app/src/main/java/app/gamenative/externaldisplay/ExternalOnScreenKeyboardView.kt (1)

160-165: Hardcoded Color.WHITE for key text.

Key text color is Color.WHITE regardless of theme. This works for both current dark themes, but if a light theme is added later, this won't adapt. Consider adding a textColor property to the Theme enum for forward-compatibility.

app/src/main/java/app/gamenative/externaldisplay/ExternalDisplayInputController.kt (1)

47-52: fromConfig relies on raw string matching—consider using enum name.

fromConfig matches "amoled" as a magic string. If a new theme is added, the developer must remember to update this function. Using Theme.valueOf() (with a fallback) or entries.find { it.name.equals(value, ignoreCase = true) } would auto-extend to new enum values.

♻️ Suggested refactor
         companion object {
-            fun fromConfig(value: String?): Theme = when (value?.lowercase()) {
-                "amoled" -> AMOLED
-                else -> DEFAULT
-            }
+            fun fromConfig(value: String?): Theme =
+                entries.find { it.name.equals(value, ignoreCase = true) } ?: DEFAULT
         }

Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 4 files (changes from recent commits).

Prompt for AI agents (all issues)

Check if these issues are valid — if so, understand the root cause of each and fix them.


<file name="app/src/main/java/app/gamenative/ui/screen/settings/SettingsGroupInterface.kt">

<violation number="1" location="app/src/main/java/app/gamenative/ui/screen/settings/SettingsGroupInterface.kt:433">
P2: Dropdown selection state is no longer updated, so the displayed selection can remain stale after the user picks a theme.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 6 files (changes from recent commits).

Prompt for AI agents (all issues)

Check if these issues are valid — if so, understand the root cause of each and fix them.


<file name="app/src/main/java/app/gamenative/externaldisplay/ExternalDisplayInputController.kt">

<violation number="1" location="app/src/main/java/app/gamenative/externaldisplay/ExternalDisplayInputController.kt:49">
P2: Theme.fromConfig no longer recognizes the previously stored "AMOLED" preference value, so existing users with that saved theme will fall back to DEFAULT after the rename.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

@xXJSONDeruloXx
Copy link
Copy Markdown
Contributor

in effort to reduce complexity, could we just revise grey default to be black for amoled instead of adding as a secondary option?

@MayRedBeWithYou MayRedBeWithYou force-pushed the feature/external-display-input-themes branch from d62c7d1 to 07a0187 Compare March 13, 2026 14:56
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
app/src/main/java/app/gamenative/PrefManager.kt (1)

959-961: Persist a canonical theme value in the setter.

Line 961 currently stores raw input; normalizing to a canonical enum name avoids invalid/stale values being persisted and silently mapped back to default later.

♻️ Suggested change
     var externalDisplayTheme: String
         get() = getPref(EXTERNAL_DISPLAY_THEME, ExternalDisplayInputController.Theme.DEFAULT.name)
-        set(value) = setPref(EXTERNAL_DISPLAY_THEME, value)
+        set(value) = setPref(
+            EXTERNAL_DISPLAY_THEME,
+            ExternalDisplayInputController.Theme.fromConfig(value).name,
+        )
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/src/main/java/app/gamenative/PrefManager.kt` around lines 959 - 961, The
setter for externalDisplayTheme currently stores the raw input string which can
persist invalid/stale values; change the setter to normalize the input to a
canonical enum name from ExternalDisplayInputController.Theme (e.g., resolve the
incoming value to the matching Theme entry—using valueOf or a case-insensitive
lookup—and fall back to ExternalDisplayInputController.Theme.DEFAULT.name if it
doesn't match) before calling setPref(EXTERNAL_DISPLAY_THEME, ...).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@app/src/main/java/app/gamenative/PrefManager.kt`:
- Around line 959-961: The setter for externalDisplayTheme currently stores the
raw input string which can persist invalid/stale values; change the setter to
normalize the input to a canonical enum name from
ExternalDisplayInputController.Theme (e.g., resolve the incoming value to the
matching Theme entry—using valueOf or a case-insensitive lookup—and fall back to
ExternalDisplayInputController.Theme.DEFAULT.name if it doesn't match) before
calling setPref(EXTERNAL_DISPLAY_THEME, ...).

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 41efaf38-9770-4531-a903-d8a4034d6920

📥 Commits

Reviewing files that changed from the base of the PR and between d62c7d1 and 07a0187.

📒 Files selected for processing (6)
  • app/src/main/java/app/gamenative/PrefManager.kt
  • app/src/main/java/app/gamenative/externaldisplay/ExternalDisplayInputController.kt
  • app/src/main/java/app/gamenative/externaldisplay/ExternalOnScreenKeyboardView.kt
  • app/src/main/java/app/gamenative/externaldisplay/SwapInputOverlayView.kt
  • app/src/main/java/app/gamenative/ui/screen/settings/SettingsGroupInterface.kt
  • app/src/main/java/app/gamenative/ui/screen/xserver/XServerScreen.kt
🚧 Files skipped from review as they are similar to previous changes (2)
  • app/src/main/java/app/gamenative/externaldisplay/SwapInputOverlayView.kt
  • app/src/main/java/app/gamenative/ui/screen/settings/SettingsGroupInterface.kt

@MayRedBeWithYou
Copy link
Copy Markdown
Contributor Author

Closing this one in favour of #838

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants