b4fcddee2f feat(android): offer web-parity color theme presets in appearance settings (#2228)
* feat(android): offer web-parity color theme presets in appearance settings

Bring the web client's color-theme catalog (Default plus 16 named
palettes) to Android as an appearance choice. Each preset carries five
seed colors per scheme and derives every other tone with the web
client's exact math — per-channel elevation mixes, the WCAG-luminance
dark/light call, and tie-up rounding — so a preset renders the same on
both clients. A selected preset overrides the dynamic and OLED schemes
(OLED renders the preset's dark seeds, like the web layering), while
Default keeps Material You and the built-in light/dark/OLED schemes.

The picker reuses the expressive choice dialog: every card shows the
preset's light/dark canvas split plus its accent strip, and longer
catalogs scroll inside the dialog so they stay usable on small screens.
Material You switches off with an explanatory note while a preset is
active, since presets pin their own palettes.

Persistence is one DataStore key over the existing theme prefs, with
unknown ids degrading to Default. Strings land in en/ru/zh in matching
order; the proper-noun preset names stay untranslated, matching the web
locales.

Co-Authored-By: Claude Code <noreply@anthropic.com>
via [HAPI](https://hapi.run)
Co-Authored-By: HAPI <noreply@hapi.run>

* test(android): pin the HapiTheme scheme resolution order with a matrix

The preset > oled > dynamic > static ordering and the OLED-yields-to-dark-
seeds rule (preset.palette(dark = darkTheme || oled)) lived inline in the
HapiTheme composable where no JVM test could reach them -- reordering the
when (a stack-conflict surgery hazard) would pass every gate silently.

Extract the order into a pure resolver (resolveThemeSchemeSource returns a
descriptor; the composable maps it to schemes, with a local SDK guard lint
can see) and pin it with an exhaustive matrix: all 16 named presets x every
darkTheme/oled/dynamicColor/sdk combination resolve to the preset palette,
DEFAULT+oled beats dynamic color, dynamic color only fires on S+ when
enabled, and Nord-under-OLED-with-light-system asserts concrete dark-seed
hexes. Verified discriminating by mutation: dropping `|| oled` fails 2
tests, hoisting dynamic above oled fails 1.

Co-Authored-By: Claude Code <noreply@anthropic.com>

---------

Co-authored-by: Claude Code <noreply@anthropic.com>
Co-authored-by: HAPI <noreply@hapi.run>
2026-11-02 18:24:46 +08:00
2026-11-01 20:30:00 +08:00
2026-08-25 13:31:59 +08:00
2026-01-04 20:45:15 +08:00
2026-03-29 09:47:17 +08:00
2025-12-16 15:03:50 +08:00

HAPI

Run official Claude Code / Codex / Cursor Agent / Grok Build / OpenCode / Kimi / Copilot / Antigravity / Pi / DeepSeek Harness sessions and control them remotely through native iOS / Android apps, Web / PWA, or Telegram Mini App.

Why HAPI? HAPI is a local-first alternative to Happy. See Why Not Happy? for the key differences.

Features

  • Seamless Handoff - Work locally, switch to remote when needed, switch back anytime. No context loss, no session restart.
  • Shared Codex Sessions - Use Codex from your terminal and phone at the same time. Requires Codex 0.154.0+. Usage and limits.
  • Native First - HAPI wraps your AI agent instead of replacing it. Same terminal, same experience, same muscle memory.
  • AFK Without Stopping - Step away from your desk? Approve AI requests from your phone with one tap.
  • Your AI, Your Choice - Claude Code, Codex, Cursor Agent, Grok Build, OpenCode, Kimi, Copilot, Antigravity, Pi, DeepSeek Harness—different agents, one unified workflow.
  • Terminal Anywhere - Run commands from your phone's browser or desktop web app, directly connected to the working machine.
  • Voice Control - Use dictation in native apps, or talk to your AI agent hands-free with the web voice assistant.
  • Workspace Browser - Opt-in via one or more hapi runner start --workspace-root <path> flags: browse scoped file trees from the web and start sessions in allowed subdirectories.

Demo

https://github.com/user-attachments/assets/38230353-94c6-4dbe-9c29-b2a2cc457546

Getting Started

npx @twsxtd/hapi hub --relay     # start hub with E2E encrypted relay
npx @twsxtd/hapi                 # choose an agent and start a session

hapi server remains supported as an alias.

Use hapi <agent> [options] to start an agent directly, for example hapi claude or hapi codex. Scripts must specify the agent explicitly. hapi --help shows HAPI's commands and supported agents.

The hub displays a URL and two QR codes. Then connect a client:

  • Web / PWA (free): open the web URL in a browser, or scan the web QR code. Install it as a PWA for a home-screen app and push notifications.
  • Native apps (paid): install HAPI from the App Store or Google Play, then scan the companion QR. See Native apps for pairing.

The relay uses WireGuard + TLS for end-to-end encryption. Your data is encrypted from your device to your machine.

For self-hosted options (Cloudflare Tunnel, Tailscale), see Installation

Docs

Clients

  • Web / PWA (free) - The full-featured web app, including the remote terminal and voice assistant. Works in any browser and installs as a PWA. See Web / PWA.
  • Native iOS / Android apps (paid) - SwiftUI/UIKit and Kotlin Compose clients with chat, approvals, session creation, files, dictation, and native push notifications. See the native app guide for capabilities and pairing.

Download on the App Store Get it on Google Play

Developers can build the apps from source: iOS, Android. Protocol: client contract.

Build from source

Requires Bun 1.4.4.

bun install
bun run build:single-exe

Credits

HAPI means "哈皮" a Chinese transliteration of Happy. Great credit to the original project.

S
Description
GitHub 镜像: wu736139669/hapi(每日自动同步)
Readme AGPL-3.0
140 MiB
Languages
TypeScript 99.5%
CSS 0.2%
JavaScript 0.2%