Files
pearcord-ui-flow/README.md
T

128 lines
5.4 KiB
Markdown

# pearcord-ui-flow
Pearcord desktop UI IPC dispatch and automated flow scenarios for Bare smokes. Mirrors `apps/pearcord` pear-pipe message handling.
## Mission
Centralize the `msg.type``platform.*` routing table used by the Pear UI sidecar so smoke tests and tooling can drive the full platform surface without duplicating hundreds of if-branches in the app entrypoint.
## When to use / not
**Use when:**
- Running Bare smokes that send JSON IPC lines to a headless platform instance.
- Adding a new UI IPC type—implement handler here and call from app shell.
**Do not use when:**
- You need platform business logic — implement on `PearcordPlatform` in `pearcord-platform`.
- You build non-Pear UIs — import platform directly.
## Public API
| Export | Role |
|--------|------|
| `dispatchUiMessage(platform, msg, hooks)` | Returns `true` if `msg.type` handled |
| `fromBase64(str)` | Buffer for attachment/emoji bytes |
| `normalizeEmojiImage(image)` | Maps `dataBase64``data` buffer |
### Hooks
```javascript
{
send: (obj) => {}, // reply events to UI pipe
pushState: () => {} // refresh serialized state
}
```
Returns `false` for unknown types (caller may log).
## Coverage (grouped)
| Area | Example `msg.type` values |
|------|-------------------------|
| Onboarding | `register`, `create-guild`, `join-invite`, `select-guild` |
| Automation | `set-automod-config`, `upsert-automation-hook`, `export-automation-manifest`, `dry-run-automation-hook`, schedule/export/dashboard IPC |
| Bots | `create-bot-install-token`, `install-bot-token`, `register-slash-commands` |
| Announcements | `set-announcement-crosspost`, `set-announcement-hub-publish`, `subscribe-remote-announcement-hub`, `follow-announcement` |
| Boosts / stickers | `contribute-guild-boost`, `upsert-guild-sticker`, `upsert-sticker-pack` |
| Profile | `update-profile-cosmetics`, `set-profile-banner-image`, step-up PIN types |
| Voice / screen | `join-voice`, `join-voice-listen`, `join-stage`, `voice-capture-chunk`, `display-capture-frame` |
| Notifications | `mark-all-notifications-read` (emits `mark-all-notifications-read-cleared` + `composer-focus-channel`, v0.8.407), `mark-notification-read` (calls `platform.markNotificationRead`, emits `mark-notification-read-cleared` + `notificationChannelId`, v0.8.407), `open-notification` (marks read via `markNotificationRead`, emits `composer-focus-channel`, v0.8.407), `mark-channel-read` (emits `mark-channel-read-cleared` + `threadChannelId` for threads, v0.8.287), `refresh-notifications` (v0.8.236) |
| Workers | `export-integration-worker-script`, `run-worker-install-trial`, `announce-worker-release` |
| Moderation / channels | `ban-member`, `upsert-channel-overwrite`, forum/thread types |
| Search | `update-search`, `refresh-search`, `remove-search-recent` (v0.8.140) |
Uses `USER_STATUS` from `pearcord-platform` for presence IPC.
## Dependencies
- `pearcord-platform``PearcordPlatform` instance (git dependency in package.json)
- `pearcord-qr` — optional QR SVG for device pair codes
- `b4a` — base64 decode in Bare
## Platform integration
```javascript
// apps/pearcord/index.js pattern:
const { dispatchUiMessage } = require('pearcord-ui-flow')
async function onPipeLine(line) {
const msg = JSON.parse(line)
const handled = await dispatchUiMessage(platform, msg, { send, pushState })
if (!handled) send({ type: 'error', message: `unknown type ${msg.type}` })
}
```
## P2P surface
None directly—all mesh behavior delegated to platform methods invoked by dispatch.
## Tests
Primary consumer: Bare smoke suites under `apps/pearcord` that spawn platform + pipe JSON lines.
Adding handlers here keeps smokes and production UI in sync.
## Code example
```javascript
const { dispatchUiMessage, fromBase64 } = require('pearcord-ui-flow')
const replies = []
await dispatchUiMessage(
platform,
{ type: 'dry-run-automod', content: 'discord.gg/test' },
{
send: (o) => replies.push(o),
pushState: () => {}
}
)
// replies[0].type === 'automod-dry-run'
```
## Related modules
- `pearcord-platform` — implementation target for every branch
- All feature modules — reached indirectly through platform
**v0.8.174:** `update-guild-settings` IPC forwards `nsfwGateEnabled` to `platform.updateGuildSettings`.
## Composer focus channel (v0.8.406+)
After `create-thread`, `create-forum-post`, `mark-all-notifications-read`, or `open-notification`, dispatch emits a sidecar event (not a full IPC round-trip from the UI):
```javascript
send({ type: 'composer-focus-channel', channelId: thread.id })
**v0.8.420 (Phase 457):** `create-channel` selects the new channel and emits `composer-focus-channel` (see [CHANNELS.md](../../docs/CHANNELS.md)).
// mark-all: channelId = platform.activeChannelId
// open-notification: channelId = result.channelId || msg.channelId || platform.activeChannelId
```
The renderer handles `composer-focus-channel` and calls `requestComposerAutofocusForChannel(channelId)` so the message box focuses once the target channel is active. Smokes: `test:composer-autofocus-after-thread-create`, `test:composer-autofocus-after-mark-all-notif`, `test:composer-autofocus-after-notif-navigate`. See [NOTIFICATIONS.md](../../docs/NOTIFICATIONS.md), [MESSAGE_THREADS.md](../../docs/MESSAGE_THREADS.md), and [FORUM_CHANNELS.md](../../docs/FORUM_CHANNELS.md).
## Maintenance
When adding IPC in the Pear app, add the same `msg.type` branch here first (or simultaneously) so `dispatchUiMessage` remains the single routing table.