7a18011b0f
Add a dev-only Vite UI mode with Tauri API mocks, in-memory fixture scenarios, reusable media source handling, and documentation for browser-based visual testing.
181 lines
4.9 KiB
Markdown
181 lines
4.9 KiB
Markdown
# Phokus UI Lab
|
|
|
|
Phokus UI Lab is a browser-only development mode for visual work on the real
|
|
Phokus frontend. It runs the same `App.tsx`, Zustand store, components, and CSS
|
|
as the Tauri app, but installs Tauri JavaScript mocks before the app imports.
|
|
|
|
This gives UI agents and contributors a stable browser target without launching
|
|
the Rust backend or a Tauri window.
|
|
|
|
## Run It
|
|
|
|
```bash
|
|
pnpm dev:ui
|
|
```
|
|
|
|
Then open:
|
|
|
|
```text
|
|
http://127.0.0.1:1422
|
|
```
|
|
|
|
The script runs Vite in the custom `ui` mode:
|
|
|
|
```bash
|
|
vite --mode ui --host 127.0.0.1 --port 1422 --strictPort --open
|
|
```
|
|
|
|
The normal app development commands are unchanged:
|
|
|
|
```bash
|
|
pnpm dev:app # Tauri app + Rust backend
|
|
pnpm dev:vite # frontend dev server for Tauri dev
|
|
```
|
|
|
|
## Scenarios
|
|
|
|
UI Lab reads `?scenario=` from the URL. If no scenario is provided, it uses
|
|
`rich`.
|
|
|
|
| URL | Purpose |
|
|
| --- | --- |
|
|
| `/?scenario=rich` | Default realistic library with folders, albums, ratings, favorites, tags, images, and videos |
|
|
| `/?scenario=empty` | First-run state with no folders or media |
|
|
| `/?scenario=busy` | Background workers with pending thumbnail, metadata, embedding, caption, and tagging jobs |
|
|
| `/?scenario=duplicates` | Duplicate Finder opened with duplicate groups already available |
|
|
| `/?scenario=album` | Gallery opened directly into an album |
|
|
| `/?scenario=errors` | Broken thumbnails, folder scan errors, failed embeddings, failed tagging, and metadata issues |
|
|
| `/?scenario=huge` | Large mock library for virtualization and layout checks |
|
|
|
|
Examples:
|
|
|
|
```text
|
|
http://127.0.0.1:1422/?scenario=duplicates
|
|
http://127.0.0.1:1422/?scenario=errors
|
|
http://127.0.0.1:1422/?scenario=huge
|
|
```
|
|
|
|
## How It Works
|
|
|
|
`src/main.tsx` bootstraps the app asynchronously. In `ui` mode it imports
|
|
`src/dev/setupMockTauri.ts` first, then imports the real `App`.
|
|
|
|
That order matters because static imports are hoisted. The Tauri mocks must be
|
|
installed before `App`, the store, the title bar, or visual components import
|
|
Tauri APIs.
|
|
|
|
The mock setup installs:
|
|
|
|
- `mockWindows("main")` for window APIs used by the title bar
|
|
- `mockConvertFileSrc("windows")` as a baseline Tauri file URL mock
|
|
- `mockIPC(..., { shouldMockEvents: true })` for `invoke`, `listen`, and `emit`
|
|
|
|
The in-memory backend lives in:
|
|
|
|
```text
|
|
src/dev/mockBackend.ts
|
|
src/dev/mockFixtures.ts
|
|
src/dev/mockScenarios.ts
|
|
src/dev/applyMockScenario.ts
|
|
```
|
|
|
|
Happy-path fixture media is imported from the existing onboarding assets in:
|
|
|
|
```text
|
|
src/assets/onboarding/
|
|
```
|
|
|
|
Synthetic or deliberately broken fixture paths can still use the `mock://`
|
|
scheme described below.
|
|
|
|
## Mock Media
|
|
|
|
Visual components should use `mediaSrc(...)` instead of calling
|
|
`convertFileSrc(...)` directly:
|
|
|
|
```ts
|
|
import { mediaSrc } from "../lib/mediaSrc";
|
|
|
|
const src = mediaSrc(image.thumbnail_path);
|
|
```
|
|
|
|
In normal Tauri modes, `mediaSrc` delegates to `convertFileSrc`. In UI Lab,
|
|
already-resolved Vite asset URLs are returned as-is, so fixtures can reuse
|
|
existing imported assets. Paths beginning with `mock://` are served from
|
|
`public/dev-media`:
|
|
|
|
```text
|
|
mock://thumb-1.svg -> /dev-media/thumb-1.svg
|
|
```
|
|
|
|
Use `mediaSrc` when adding components that render thumbnails, album covers,
|
|
preview images, or video posters.
|
|
|
|
## Adding A Mock Command
|
|
|
|
If the browser console logs an unmocked command, add it to
|
|
`src/dev/mockBackend.ts`.
|
|
|
|
Prefer returning realistic data for commands that affect visible UI. For actions
|
|
that would touch the machine, return a safe no-op:
|
|
|
|
```ts
|
|
case "open_app_data_folder":
|
|
return null;
|
|
```
|
|
|
|
When adding fixture data, keep it shaped like the real store/Rust contracts.
|
|
Most frontend-facing types are exported from `src/store.ts`, so the mocks can
|
|
stay type-checked against the real UI.
|
|
|
|
## Adding A Scenario
|
|
|
|
1. Add the scenario name to `MockScenario` and `SCENARIOS` in
|
|
`src/dev/mockScenarios.ts`.
|
|
2. Adjust fixture creation in `src/dev/mockFixtures.ts`.
|
|
3. If the scenario should open a specific view, add that behavior in
|
|
`src/dev/applyMockScenario.ts`.
|
|
4. Visit `http://127.0.0.1:1422/?scenario=your-scenario` and check for console
|
|
errors.
|
|
|
|
## What UI Lab Is For
|
|
|
|
UI Lab is intended for:
|
|
|
|
- visual iteration on the real app shell
|
|
- layout and responsive checks
|
|
- state-heavy views like Explore, Timeline, Duplicates, albums, and Settings
|
|
- AI-agent screenshot/browser inspection
|
|
- safe UI work without filesystem or Rust-side effects
|
|
|
|
It is not a replacement for Tauri app testing. Validate native behavior with
|
|
`pnpm dev:app` when touching:
|
|
|
|
- file or folder pickers
|
|
- filesystem permissions
|
|
- real thumbnail/video loading
|
|
- window drag, minimize, maximize, or close behavior
|
|
- Rust backend performance
|
|
- updater installation
|
|
- WebView2-specific behavior
|
|
|
|
## Verification
|
|
|
|
Useful checks after changing UI Lab:
|
|
|
|
```bash
|
|
pnpm exec tsc --noEmit
|
|
pnpm build:vite
|
|
pnpm dev:ui
|
|
```
|
|
|
|
Then smoke-test at least:
|
|
|
|
```text
|
|
http://127.0.0.1:1422/?scenario=rich
|
|
http://127.0.0.1:1422/?scenario=empty
|
|
http://127.0.0.1:1422/?scenario=duplicates
|
|
http://127.0.0.1:1422/?scenario=errors
|
|
http://127.0.0.1:1422/?scenario=huge
|
|
```
|