Skip to content

Fix web UI navigation reliability and bottom-nav label rendering#84

Merged
aztr0nutzs merged 1 commit into
mainfrom
codex/inspect-and-fix-gui-navigation-issues
Feb 20, 2026
Merged

Fix web UI navigation reliability and bottom-nav label rendering#84
aztr0nutzs merged 1 commit into
mainfrom
codex/inspect-and-fix-gui-navigation-issues

Conversation

@aztr0nutzs

Copy link
Copy Markdown
Owner

Motivation

  • Users reported many taps failing to open screens due to runtime JS errors when action-button IDs were missing, which is traced to device-detail wiring in android-app/src/main/assets/web-ui/js/dashboard.js (around the device-detail render block, ~L750-L780).
  • The camera tab was not using the media full-bleed layout, causing it to overlay/run-into the main UI instead of replacing it, visible in media-mode toggles in dashboard.js (navigation/media-mode toggle at ~L463-L491).
  • Bottom navigation labels and icons were using emoji/non-ASCII glyphs causing mojibake on some devices, evident in android-app/src/main/assets/web-ui/ninja_mobile_new.html bottom-nav icon nodes (~L505-L541) and related CSS emoji font fallback in android-app/src/main/assets/web-ui/css/dashboard.css (~L698-L709).

Description

  • Hardened device-detail action wiring by switching to null-safe listener registration for optional controls (#mPause, #mBlock, #mTrust, #mPort) in android-app/src/main/assets/web-ui/js/dashboard.js (changed listener bindings at the device-detail wiring near ~L774-L780).
  • Included the cameras tab in the media layout activation so media-style pages get full-bleed behavior, updating both media-mode checks in android-app/src/main/assets/web-ui/js/dashboard.js (~L463-L471 and ~L489-L491).
  • Replaced emoji/non-ASCII tab glyphs and a few high-visibility non-ASCII labels (Wi‑Fi hyphens/bullets) with ASCII-safe abbreviations/labels in android-app/src/main/assets/web-ui/ninja_mobile_new.html (bottom-nav icons and text replacements around ~L507-L540 and top labels at ~L24-L81).
  • Adjusted tab icon typography to render textual abbreviations reliably by updating .tabbtn .ticon styling in android-app/src/main/assets/web-ui/css/dashboard.css (~L698-L709).

Testing

  • Attempted ./gradlew :app:assembleDebug, ./gradlew test and ./gradlew lint as required by repository rules, but all three fail in this environment due to missing Android SDK location (ANDROID_HOME/local.properties), not code errors.
  • Started a local static server for the web UI and ran a Playwright click-through that programmatically clicked each bottom-nav button and verified the expected tab section became active for every tab, including cameras (local check against http://127.0.0.1:8787/ninja_mobile_new.html succeeded).
  • Committed the minimal changes (3 files) and produced this PR; further verification should be executed in a proper Android build environment by running ./gradlew :app:assembleDebug, ./gradlew test, and ./gradlew lint.

Codex Task

@gemini-code-assist

Copy link
Copy Markdown
Contributor

Summary of Changes

Hello @aztr0nutzs, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request addresses several critical web UI issues to enhance user experience and application stability. It resolves navigation failures caused by missing action button IDs, corrects the display of the cameras tab to use the intended full-bleed media layout, and eliminates mojibake issues by replacing non-ASCII characters and emojis with ASCII-safe alternatives in navigation labels and icons. These changes collectively improve the robustness and visual consistency of the web interface across different devices.

Highlights

  • Improved Device Action Reliability: Implemented null-safe listener registration for device action buttons (#mPause, #mBlock, #mTrust, #mPort) to prevent runtime JavaScript errors and improve navigation reliability.
  • Enhanced Media Layout for Cameras Tab: Included the 'cameras' tab in the media layout activation logic, ensuring it now utilizes the full-bleed display behavior previously missing.
  • Standardized UI Typography: Replaced non-ASCII glyphs and emojis in bottom navigation icons and high-visibility labels (e.g., Wi-Fi related text) with ASCII-safe abbreviations and characters to prevent mojibake on various devices.
  • Adjusted Tab Icon Styling: Modified CSS for tab icons to ensure reliable rendering of the new textual abbreviations, including changes to font size, letter spacing, and font family.
Changelog
  • android-app/src/main/assets/web-ui/css/dashboard.css
    • Updated .tabbtn .ticon styling to reduce font size, add letter spacing, and change font family to "Orbitron" with bold weight for better rendering of textual abbreviations.
  • android-app/src/main/assets/web-ui/js/dashboard.js
    • Modified app?.classList.toggle("media-tab-active", ...) logic to include state.activeTab === "cameras" for both setTab and updateState functions, ensuring the cameras tab activates the media layout.
    • Applied optional chaining (?.) to event listener registrations for device action buttons (#mPause, #mBlock, #mTrust, #mPort) to prevent errors if elements are not found.
  • android-app/src/main/assets/web-ui/ninja_mobile_new.html
    • Replaced non-ASCII hyphens and bullet points with standard ASCII hyphens in "Home Wi-Fi (SSID) - secure" and other related text labels.
    • Replaced emoji icons (📊, 📱, 🌐, 🛠️, 🤖, 📡, ⚡, 📷) in the bottom navigation with two-letter ASCII abbreviations (DB, DV, NW, TL, OC, GW, SP, CM).
Activity
  • The author attempted to run ./gradlew :app:assembleDebug, ./gradlew test, and ./gradlew lint as per repository rules, but these failed due to a missing Android SDK location.
  • A local static server was used to host the web UI, and a Playwright click-through test was executed to verify bottom navigation functionality, including the cameras tab, which succeeded.
  • The author committed minimal changes across three files and requested further verification within a proper Android build environment.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@aztr0nutzs aztr0nutzs merged commit 3518720 into main Feb 20, 2026
2 of 4 checks passed

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

The pull request effectively addresses reported issues with web UI navigation reliability and rendering. By replacing non-ASCII characters and emojis with ASCII-safe alternatives, it resolves potential mojibake issues on various devices. The inclusion of the "cameras" tab in the media layout ensures a consistent full-bleed experience for media-centric pages. Additionally, the hardening of event listener registrations in the device-detail view improves runtime stability. My feedback focuses on improving the maintainability of the tab-switching logic.

document.getElementById("nnDeviceListBtn")?.classList.toggle("active", !state.deviceMapMode);
const app = document.getElementById("app");
app?.classList.toggle("media-tab-active", state.activeTab === "networks" || state.activeTab === "openclaw" || state.activeTab === "speedtest" || (state.activeTab === "devices" && state.deviceMapMode));
app?.classList.toggle("media-tab-active", state.activeTab === "networks" || state.activeTab === "openclaw" || state.activeTab === "speedtest" || state.activeTab === "cameras" || (state.activeTab === "devices" && state.deviceMapMode));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

The list of tabs that trigger the media layout is becoming long and is duplicated in multiple places. Refactoring this to use an array with .includes() would improve maintainability and readability, making it easier to add or remove tabs in the future.

Suggested change
app?.classList.toggle("media-tab-active", state.activeTab === "networks" || state.activeTab === "openclaw" || state.activeTab === "speedtest" || state.activeTab === "cameras" || (state.activeTab === "devices" && state.deviceMapMode));
app?.classList.toggle("media-tab-active", ["networks", "openclaw", "speedtest", "cameras"].includes(state.activeTab) || (state.activeTab === "devices" && state.deviceMapMode));


const app = document.getElementById("app");
app?.classList.toggle("media-tab-active", tab === "networks" || tab === "openclaw" || tab === "speedtest" || (tab === "devices" && state.deviceMapMode));
app?.classList.toggle("media-tab-active", tab === "networks" || tab === "openclaw" || tab === "speedtest" || tab === "cameras" || (tab === "devices" && state.deviceMapMode));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

Similar to the logic in setDeviceMapMode, using an array for the media tab check here would improve consistency and maintainability.

Suggested change
app?.classList.toggle("media-tab-active", tab === "networks" || tab === "openclaw" || tab === "speedtest" || tab === "cameras" || (tab === "devices" && state.deviceMapMode));
app?.classList.toggle("media-tab-active", ["networks", "openclaw", "speedtest", "cameras"].includes(tab) || (tab === "devices" && state.deviceMapMode));

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant