feat(status): built-in and custom status presets

The Status Message field required typing every status from scratch. Add
a one-click preset row:

- Built-in "Quick statuses" spanning gaming, social, life and work
  (Gaming, In a party, Ranked grind, AFK, Watching, In a meeting,
  Working remotely, Lunch, On vacation, Out sick...), each carrying a
  suggested auto-clear so a click sets the message and the timer at once.
- Custom presets: save the current status as a reusable preset, stored
  in io.lotus.status_presets account data (synced across devices via the
  shared account-data list store), de-duped by normalized label, capped
  at 20, deletable inline.

The existing save path is factored into a shared applyStatus() used by
the Save button and by preset apply, so server writes, the status
localStorage keys, and the auto-clear expiry bookkeeping stay identical.
Ordering/de-dupe logic is pure in utils/statusPresets.ts (upsertPreset,
normalizeLabel) with unit tests; no change to the presence wire format,
expiry monitor, or presence-mode selector.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-09 23:30:08 -04:00
co-authored by Claude Opus 4.8
parent 39e75f4eea
commit d0614710b0
5 changed files with 282 additions and 20 deletions
+1
View File
@@ -910,6 +910,7 @@ A presence status selector in the user panel offering five modes:
- Optional auto-clear timer with presets: 30 minutes, 1 hour, 4 hours, 1 day, 3 days, 7 days
- Status is broadcast via `mx.setPresence({ status_msg: ... })`
- Character counter appears at 56/64 characters remaining to warn of the limit
- **Status presets**: a "Quick statuses" row of built-in presets spanning gaming/social/life/work (🎮 Gaming, 🎧 In a party, 🏆 Ranked grind, 😴 AFK, 🍿 Watching, 🗓️ In a meeting, 🏠 Working remotely, 🍽️ Lunch, 🌴 On vacation, 🤒 Out sick…). Clicking a preset applies its message + suggested auto-clear in one click. Users can also save the current status as a reusable custom preset (stored in `io.lotus.status_presets` account data, synced across devices, de-duped by label, capped at 20) and delete presets inline. Built-in list + pure `upsertPreset` de-dupe/cap logic live in `src/app/utils/statusPresets.ts` (unit-tested); persistence in `src/app/hooks/useStatusPresets.ts`.
### Presence Badges