Dev Build / cleanup (push) Waiting to run
Dev Build / typecheck (push) Waiting to run
Publish MCP to npm / Build, test, and publish MCP (push) Waiting to run
Publish SDK to npm / Build, test, and publish SDK (push) Waiting to run
Sync action catalog to docs / sync (push) Waiting to run
Publish UI to npm / Build and publish UI (push) Waiting to run
Build and Release / preflight (push) Waiting to run
131 lines
6.9 KiB
Markdown
131 lines
6.9 KiB
Markdown
# SnowLuma WebUI
|
||
|
||
SnowLuma's browser console is a Vite + React application for managing runtime
|
||
status, OneBot configuration, logs, storage, and server settings.
|
||
|
||
## Default appearance
|
||
|
||
New installations and appearance resets use the mascot's lavender accent.
|
||
The light variant uses a deeper purple for readable button labels; dark mode
|
||
uses a softer lavender. Existing saved accents and custom colors are preserved.
|
||
The original sky-blue accent remains available in Settings.
|
||
|
||
With the default palette, page, card, input, popover and sidebar surfaces mix a
|
||
small amount of the active accent into neutral light/dark backgrounds. Text stays
|
||
neutral for readability. Sidebar-only accents tint only the sidebar; OLED keeps a
|
||
true-black canvas. Named palettes, custom CSS variables and host appearance
|
||
overlays retain control of their own surfaces.
|
||
|
||
Keep the server defaults in `packages/core/src/webui/ui-config.ts`, the frontend
|
||
defaults and preset in `src/contexts/ThemeContext.tsx`, and the pre-mount tokens
|
||
in `src/index.css` aligned when changing the default accent.
|
||
|
||
The browser favicon, home-screen icon and in-app logo share the mascot avatar
|
||
in [`assets/brand/mascot-avatar.png`](../../assets/brand/mascot-avatar.png).
|
||
Its exported sizes live in `public/`: `logo.png` (512 px), `favicon.png` (64 px),
|
||
and `apple-touch-icon.png` (180 px). Export from the master without redrawing
|
||
individual sizes.
|
||
|
||
## Host appearance integration
|
||
|
||
`SNOWLUMA_WEBUI_TARGET=maibot` opts a deployment into a reversible millennium
|
||
appearance overlay. Standalone defaults are unchanged. Hosts drive live light/dark
|
||
updates without saving over personal preferences or adding another selector.
|
||
See [the integration contract and extension guide](INTEGRATIONS.md) before changing
|
||
target startup, theme ownership, host messaging or scoped styles.
|
||
|
||
## Interaction conventions
|
||
|
||
- Destructive actions and second confirmations stay in modal dialogs.
|
||
- Operations that may take time show a bottom-right running state.
|
||
- Completed and failed operations use bottom-right result notices that close
|
||
automatically after a visible countdown.
|
||
- Routine, high-frequency adjustments should not generate a notice for every
|
||
intermediate edit.
|
||
- Foreground polling pauses in hidden tabs and waits for each request to finish
|
||
before scheduling the next. Connection-state polling runs only while SSE clients
|
||
are subscribed.
|
||
- Data-backed surfaces use the Interior Skeleton Swap defaults (120 ms delay,
|
||
380 ms minimum visibility) so fast local responses do not flash a placeholder.
|
||
Submission, upload, and other explicit operation progress keeps its spinner.
|
||
- Variable-height content must release the skeleton's reserved box after it is
|
||
ready; do not introduce a second scrolling region inside the page.
|
||
- The mobile navigation menu uses a controlled Icon Morph whose visual state
|
||
follows the actual drawer state.
|
||
- Failures must remain visible in the affected control and in the operation
|
||
result; do not convert failed responses into successful feedback.
|
||
- JSON endpoints must return an object. Malformed or non-object responses are
|
||
reported as errors rather than displayed as empty lists or default settings.
|
||
- Configuration responses include `config`; saves also report `saved`, `applied`,
|
||
`online`, `errors`, and `message`. The UI uses these fields without legacy aliases
|
||
or a second request after saving.
|
||
- Password change flows use floating labels and inline validation consistently.
|
||
- Password strength details appear only while the new-password field has focus
|
||
and leave with the same motion language when focus moves away.
|
||
- The first-run wizard keeps agreement text as the primary reading surface and
|
||
aligns each step's actions inside one responsive footer. Settings includes a
|
||
visible developer page for safely replaying this wizard and exercising the
|
||
page-level crash screen; replayed consent and passwords are never persisted.
|
||
|
||
## Authentication behind a reverse proxy
|
||
|
||
Authenticated WebUI requests send the session token in `X-SnowLuma-Token`, leaving
|
||
`Authorization` available for the reverse proxy's HTTP authentication (such as
|
||
Nginx Basic Auth). Forward `X-SnowLuma-Token` unchanged if the proxy filters
|
||
request headers. The backend still accepts `Authorization: Bearer <token>` for
|
||
existing clients when the dedicated header is absent. Both layers still require
|
||
their own valid credentials.
|
||
|
||
Late authentication failures from an old session do not sign out a newer session.
|
||
Live streams release subscriptions on disconnect and pause with the page.
|
||
Malformed stream data is reported; a debug stream invocation fails instead of silently succeeding.
|
||
|
||
## Process account detection
|
||
|
||
Process cards use QQ's local account data before injection and the hook's confirmed
|
||
identity after login. Missing local data means the account is unknown. It does not
|
||
prove that QQ is signed out, and local detection alone never marks a bridge online.
|
||
The manual login probe and `/api/processes/:pid/probe-login` endpoint are removed.
|
||
|
||
Linux resolves data roots from each QQ process's `XDG_CONFIG_HOME` or `HOME`.
|
||
Windows uses the bundled addon’s `getFileHoldersAsync` to find the process holding
|
||
each account database. Query failures are reported instead of treated as no login.
|
||
|
||
## Account notification templates
|
||
|
||
Webhook bodies and email subjects/bodies support `{uin}`, `{nickname}`, `{event}`
|
||
(`offline` or `online`), `{time}`, `{status}` (Hook process state), `{pid}`, and
|
||
`{error}` (Hook process error). New webhook and email channels include process
|
||
status in their default body; existing saved templates are preserved.
|
||
JSON templates escape substituted strings, including quotes, line breaks and control characters.
|
||
|
||
Process facts are resolved when the notification is dispatched, after any offline
|
||
debounce. Each transition carries its process PID, including the final PID detached
|
||
when an account goes offline. Facts are looked up for that PID and UIN without
|
||
substituting another process. Missing facts render empty and mean unknown, not
|
||
proof that QQ exited. Hook status alone does not identify the cause of a QQ login
|
||
failure. Notifications for one account are delivered in transition order; a slow
|
||
account does not delay other accounts.
|
||
|
||
## Local development
|
||
|
||
Packaged installations offer download and restart controls in Settings → About.
|
||
Downloads are verified and staged; files are applied before the application starts.
|
||
Restart confirmation uses the shared modal, and download results use action feedback.
|
||
|
||
On Windows, the native API logs the process token and EXE integrity label once
|
||
at startup. A Low (or lower) token triggers a WebUI warning; file labels and
|
||
query failures alone do not. “临时关闭” lasts for the tab session, including
|
||
reloads; “永久关闭” persists in this browser's site storage. Neither suppresses
|
||
startup logs. Failed queries and preference writes remain visible.
|
||
|
||
From the repository root:
|
||
|
||
```bash
|
||
pnpm --filter webui dev
|
||
pnpm --filter webui typecheck
|
||
pnpm --filter webui lint
|
||
pnpm --filter webui test
|
||
pnpm --filter webui build
|
||
```
|