Adds the infrastructure for a coherent client-side error story:
- `lib/errors.ts`: canonical ApiError + QuotaExceededError, `toUserMessage`
(friendly strings for ApiError/ZodError/network errors, strips Electron
IPC message prefixes), `logError` (expected), `reportError` (unexpected).
- `lib/query-client.ts`: QueryClient factory with sane retry defaults (no
retry on 4xx except 408/429, 2 retries otherwise; 0 mutation retries),
`QueryCache` onError logs + opts in via `meta.toastOnError`, and
`MutationCache` onError toasts `toUserMessage(err)` by default with
`meta.suppressToast` as the opt-out.
- `components/app-error-boundary.tsx` + `error-fallback.tsx`: two boundaries
(top-level outside the router, route-level inside) with a Card-based
fallback offering 'Go home' + 'Try again'. Route boundary resets on
pathname change and clears React Query error cache on retry.
- `main/ipc-utils.ts` + main.ts migration: `safeHandle` wraps ipcMain.handle
so main-process failures log with full stack and surface a sanitized
message to the renderer. `link:fetch-metadata` keeps its null contract
but now logs.
- `useCreateParticle` opts out of the global toast (compose-overlay renders
its own quota UX) so nothing double-toasts.
Render crashes now have a recovery UI, every mutation gets a free error
toast, and silent-catch cleanup + Sentry land in follow-up PRs.
Adds an implicit-consent disclaimer under the sign-in "Continue" button
and a new "Legal" section in the settings page. Both link out to the
policies hosted on flowylabs.ai via the existing openExternal bridge.
https://claude.ai/code/session_01U6gT7XFQ8Rtm3FStsHG63j
Co-authored-by: Claude <[email protected]>
* setup firebase custom token
* docs
* docs
* feat: allow admin removing members from a network
* fix: properly handle fallback avatar and names
This is especially helpful in the case of members who were removed from
a network
Hardcoded ⌘ glyphs in compose hints were misleading on non-mac
platforms. Add a tiny platform helper sourced from the existing
window.electronWindow.platform bridge and substitute "Ctrl" off mac.
Closes#167.
https://claude.ai/code/session_01YZY4wUqACT7mgibHr2Yncx
Co-authored-by: Claude <[email protected]>
Closes#154
The sender of the message wouldn't see the children particle since we
only fetch the children once. And perhaps the firestore local cache
doesn't have the children particles or some other race condition. But
now, we fetch the live children.
This should anyways use the same number of reads as before since
attachments do not change.
Lets a particle's creator delete their own message from the TopBar
dropdown. Other viewers see a "This particle was deleted" tombstone in
place and playback auto-advances after ~2s, keeping indices stable for
concurrent watchers.
- Add optional deleted_at / deleted_by_human_id to non-container
particle variants and isParticleDeleted helper.
- Add softDeleteParticle Firestore helper.
- New DeleteParticleOverlay confirmation and DeletedParticleView
tombstone.
- Hide reactions (bar + 1-7 keybinding) on tombstoned particles.
- Show "Deleted particle" + Trash2 icon in the stream list preview.
Closes#146https://claude.ai/code/session_01M2ShnZPvWfQzzvuu3Xm8b9
Co-authored-by: Claude <[email protected]>
Closed streams grow unbounded as teams age and can reach 1000s of items,
while open streams stay bounded by active work. Switch the streams list
to subscribe per-status so each tab only pulls what it renders, and cap
the closed tab to a 50-item window that grows via a Load more action.
The open tab remains unbounded so per-row realtime features — autoplay,
huddle indicators — keep full coverage of the streams that matter.
Closed streams are archived and don't need push behavior, which side-
steps the autoplay baseline-reset and huddle-on-page-2 risks that made
pagination complicated for the open tab.
Refs flowy-live/llink#138.
Co-authored-by: Claude <[email protected]>
* increases timeout
* refactor: reuse constants for redis db
* avoid closing connection on pong error
* fix: prevent electron from pausing timer executions
Our pings could be paused when our app is backgrounded.
* refactor: remove unnecessary refs
* fix: presence unreliable within same pod
It was broadcasting presence changes to other pods, but not notifying
clients connected to the same pod