Skip to content

Restore fallback Web UI assets and fix bottom-nav emoji rendering#83

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

Restore fallback Web UI assets and fix bottom-nav emoji rendering#83
aztr0nutzs merged 1 commit into
mainfrom
codex/inspect-and-fix-ui-navigation-issues

Conversation

@aztr0nutzs

Copy link
Copy Markdown
Owner

Motivation

  • The Android app falls back to an asset-hosted UI when the local server is not ready, so missing files under android-app/src/main/assets/web-ui break navigation and UI behavior (MainActivity.kt builds assetDashboardUrl used as fallback).【android-app/src/main/java/com/netninja/MainActivity.kt:L61-L71】
  • The local embedded server copies assets from web-ui into internal storage, so missing fallback assets cause the runtime UI to lack CSS/JS that implement tab switching and visibility rules (AndroidLocalServer.copyDir + installApiRoutes serve /ui).【android-app/src/main/java/com/netninja/AndroidLocalServer.kt:L363-L367】【android-app/src/main/java/com/netninja/ApiRoutes.kt:L535-L536】
  • Missing stylesheet/JS caused: (1) taps not opening screens because js/dashboard.js contains the setTab handler and click listeners, (2) screens overlaying because CSS controls .tab-page visibility, and (3) garbled bottom-nav icons because emoji glyphs may render with a font lacking color/emoji support in WebView. Evidence: ninja_mobile_new.html references the CSS/JS and contains nav buttons, while js/dashboard.js implements setTab and listeners.【android-app/src/main/assets/web-ui/ninja_mobile_new.html:L678-L679】【android-app/src/main/assets/web-ui/ninja_mobile_new.html:L505-L542】【android-app/src/main/assets/web-ui/js/dashboard.js:L474-L493】【android-app/src/main/assets/web-ui/css/dashboard.css:L210-L217】

Description

  • Added the missing fallback UI assets under android-app/src/main/assets/web-ui/: css/dashboard.css, js/api-client.js, js/dashboard.js, and net_ninja_cam.html so the asset fallback is functionally equivalent to the primary UI at runtime.【android-app/src/main/assets/web-ui/css/dashboard.css】【android-app/src/main/assets/web-ui/js/api-client.js】【android-app/src/main/assets/web-ui/js/dashboard.js】【android-app/src/main/assets/web-ui/net_ninja_cam.html】
  • Fixed the top badge media path in the fallback HTML to use an existing asset (openclaw_icon.mp4new_assets/openclaw_icon.mp4) so the badge loads rather than producing missing-resource errors.【android-app/src/main/assets/web-ui/ninja_mobile_new.html:L24-L27】
  • Added an explicit emoji-capable font fallback to the bottom-nav icon rule (.tabbtn .ticon) to avoid tofu/garbled glyphs inside Android WebView (font stack added to css/dashboard.css near the .tabbtn .ticon rule).【android-app/src/main/assets/web-ui/css/dashboard.css:L698-L707】
  • Kept changes minimal and constrained to the asset files listed above to restore expected runtime wiring without touching Gradle, manifests, or native navigation code.【files changed: see commit】

Testing

  • Attempted Gradle verification ./gradlew :app:assembleDebug, ./gradlew test, and ./gradlew lint, but all failed in this environment due to missing Android SDK configuration (local.properties / ANDROID_HOME) and not due to the code edits; build failure message: "SDK location not found" (environment constraint). (Result: failed).【./gradlew :app:assembleDebug output】
  • Static/runtime wiring checks: verified the fallback HTML references the added CSS/JS and that the setTab handler in js/dashboard.js maps bottom-nav data-tab to section#tab-* IDs 1:1, confirming click→handler→destination chain is present (script lines implementing setTab and event wiring exist). (Result: passed).【android-app/src/main/assets/web-ui/js/dashboard.js:L475-L493】【android-app/src/main/assets/web-ui/ninja_mobile_new.html:L505-L542】
  • Verified CSS restores the .tab-page visibility rules so screens will not render simultaneously and added emoji font stack to .tabbtn .ticon to avoid glyph corruption (inspected css/dashboard.css rule). (Result: passed).【android-app/src/main/assets/web-ui/css/dashboard.css:L210-L217】【android-app/src/main/assets/web-ui/css/dashboard.css:L698-L707】
  • Local UI smoke attempt: copied assets into android-app/src/main/assets/web-ui and attempted to serve via a local static server and capture with headless browser; Playwright attempts could not complete in this sandbox for file/port reasons, but the static file server and script copies succeeded and grep-based checks confirmed expected file presence. (Result: partial due to environment).

Notes: commit created with message "Fix fallback WebUI navigation assets and bottom-nav icon rendering" and changes are limited to the asset files listed above to restore correct tab navigation, prevent screens overlaying, and fix bottom-nav icon rendering in the fallback WebView environment.


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 critical issues affecting the Android application's fallback Web UI by restoring essential assets and correcting display problems. The changes ensure that the application's user interface remains functional and visually consistent even when the local server is not ready, improving overall stability and user experience without altering core native or Gradle configurations.

Highlights

  • Restored Missing Web UI Assets: Added critical fallback UI assets including css/dashboard.css, js/api-client.js, js/dashboard.js, and net_ninja_cam.html to ensure the asset-hosted UI functions correctly when the local server is unavailable.
  • Fixed Top Badge Media Path: Corrected the media path for the top badge in ninja_mobile_new.html from openclaw_icon.mp4 to new_assets/openclaw_icon.mp4 to resolve missing resource errors.
  • Improved Bottom Navigation Emoji Rendering: Implemented an explicit emoji-capable font fallback in css/dashboard.css for the .tabbtn .ticon rule, preventing garbled or 'tofu' glyphs in the Android WebView.
Changelog
  • android-app/src/main/assets/web-ui/css/dashboard.css
    • Added new CSS file to define the styling for the web UI, including layout, components, and responsive adjustments.
    • Included font-family fallbacks for emoji rendering in bottom navigation icons.
  • android-app/src/main/assets/web-ui/js/api-client.js
    • Added new JavaScript file to handle API client functionality, including base URL resolution, token management, and JSON fetching/posting.
  • android-app/src/main/assets/web-ui/js/dashboard.js
    • Added new JavaScript file containing the core logic for the dashboard UI, managing state, rendering components, handling user interactions, and integrating with backend APIs.
  • android-app/src/main/assets/web-ui/net_ninja_cam.html
    • Added new HTML file for the camera grid interface, supporting various stream types and providing controls for camera management.
  • android-app/src/main/assets/web-ui/ninja_mobile_new.html
    • Updated the video source path for the brand badge to correctly reference new_assets/openclaw_icon.mp4.
Activity
  • The author attempted Gradle verification (assembleDebug, test, lint) but encountered SDK configuration failures unrelated to the code changes.
  • Static and runtime wiring checks confirmed that the fallback HTML correctly references the new CSS/JS and that the setTab handler functions as expected.
  • CSS verification confirmed the restoration of .tab-page visibility rules and the successful addition of the emoji font stack.
  • A local UI smoke test was partially successful, confirming static file serving and script copies, though Playwright attempts were limited by environment constraints.
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 b6cb298 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 successfully restores missing fallback Web UI assets and addresses emoji rendering issues in the bottom navigation. The added CSS, JavaScript, and HTML files provide a functional UI for the Android app's asset-hosted fallback mode. I have identified a few areas for improvement, primarily concerning the security of attribute rendering in the device list and the frequency of background port scans on the gateway.

tbody.innerHTML = rows.map(d => {
const isSel = d.id === state.selectedDeviceId;
return `
<tr data-id="${d.id}" class="${isSel ? "selected" : ""}">

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.

security-medium medium

The d.id value is used directly within an HTML attribute. If a device ID (which can originate from the backend) contains double quotes or other special characters, it could break the HTML structure or lead to XSS vulnerabilities. It is safer to escape this value.

Suggested change
<tr data-id="${d.id}" class="${isSel ? "selected" : ""}">
<tr data-id="${escapeHtml(d.id)}" class="${isSel ? "selected" : ""}">

<td>${escapeHtml(d.firstSeen || "—")}</td>
<td>${escapeHtml(d.lastSeen || "—")}</td>
<td>${escapeHtml(d.trust)}</td>
<td><button class="kebab" data-menu="${d.id}" title="Actions">⋮</button></td>

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.

security-medium medium

Similar to the row ID, the data-menu attribute should have its value escaped to prevent HTML breakage or potential injection if the ID contains special characters.

Suggested change
<td><button class="kebab" data-menu="${d.id}" title="Actions"></button></td>
<td><button class="kebab" data-menu="${escapeHtml(d.id)}" title="Actions"></button></td>

Comment on lines +205 to +208
fetchJson("/api/v1/actions/portscan", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ ip: gateway, timeoutMs: 250 })

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

A port scan is initiated on the gateway every time the network UI is refreshed, which currently happens every 20 seconds via _dashPollTick. Probing the gateway this frequently might be considered aggressive and could trigger security alerts or rate-limiting on some routers. Consider performing this scan only when the network configuration changes or on manual refresh.

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