Commit Graph

333 Commits

Author SHA1 Message Date
talksik 30fbca2188 config for mobile 2026-04-29 17:38:43 -07:00
talksik 5acb29e6e3 update bundle id for mobile 2026-04-29 17:09:05 -07:00
talksik 41cde9ce5d ux improvements 2026-04-29 17:00:21 -07:00
talksik 10ac433834 infra: bump memory limits as insurance 2026-04-29 16:07:54 -07:00
talksik d2a453e381 cap video resolution to save on memory 2026-04-29 16:07:40 -07:00
talksik 6b4a51125c tweak padding 2026-04-29 15:57:05 -07:00
talksik 45d661d955 view on desktop placeholder 2026-04-29 15:52:49 -07:00
talksik 8e807d8187 log transcode work 2026-04-29 15:52:31 -07:00
talksik 271b0d9892 tweaks to mobile 2026-04-29 15:47:27 -07:00
talksik 743310e18b infra: increase particle processor worker resources
Was dealing with OOM errors
2026-04-29 15:13:37 -07:00
talksik 7397dc45e8 build: rename skaffold module for particle processor worker 2026-04-29 15:04:04 -07:00
talksik 2b37979a76 build: reproducible go generate 2026-04-29 15:02:16 -07:00
talksik 0c38866251 transcode media particles to mp4 2026-04-29 14:39:48 -07:00
talksik b54ac4aa15 fix: broken record 2026-04-29 14:35:53 -07:00
talksik a974fa50b0 step 5-6: compose experience 2026-04-29 13:29:02 -07:00
talksik ddfcf1ee12 step 4: stream playback experience 2026-04-29 12:01:34 -07:00
talksik 73cc65c5d1 step 2.5: streams list 2026-04-29 11:24:29 -07:00
talksik cd1837c5f1 stage 2: skeleton with navigation 2026-04-29 11:05:21 -07:00
talksik 06918f033d stage 1: project init 2026-04-29 10:42:20 -07:00
Arjun Patel 3a11a82cd3 refactor: organize desktop vs. mobile into separate folders 2026-04-29 08:42:56 -07:00
Arjun Patel 3d9fe67936 chore: bump version 2026-04-29 07:55:38 -07:00
Arjun Patel aacea01c1f feat: text reactions
Closes #180
2026-04-29 07:44:26 -07:00
Arjun Patel eb1e77b4c1 fix: allow next / prev particle during pause 2026-04-29 07:16:39 -07:00
Arjun Patel 1f2ab9b752 show keyboard hints for space pause 2026-04-29 07:16:16 -07:00
Arjun Patel a216b0722f fix: go to new local particle after creation
If human is on the last particle of the stream and creates a new one, this would navigate them there, as it makes sense to consider them caught up.
2026-04-29 06:49:13 -07:00
Arjun Patel f642d13ba1 feat: allow toggle stream-view play/pause 2026-04-29 06:16:24 -07:00
Arjun Patel 70087cf4e5 refactor: precondition for record toggle 2026-04-29 06:11:57 -07:00
Arjun Patel 0f73d685c2 refactor: narrow auth service to smaller units
Easier for testing, and omits need for full dep injection for pusher service, where we passed in nil for deps dangerously.
2026-04-27 16:14:37 -07:00
Arjun Patel 48d6d5cb07 refactor: unit testable units and cleaner dep injection 2026-04-27 16:07:28 -07:00
talksik 013c453dd3 chore: bump version 2026-04-25 14:25:42 -07:00
talksik 6b755a426b feat: add sound effects for hud actions
Closes #174
2026-04-25 14:25:24 -07:00
talksik 13c6bbd0fb refactor: re-structure stream playback control 2026-04-25 13:48:37 -07:00
talksik cf143f232d fix: prevent exit countdown during editing text 2026-04-25 13:10:32 -07:00
talksik a686d85e96 fix: papercuts around last particle in stream
Pause when holding space during close countdown. Prevent arrow keys
starting exit countdown when on last particle
2026-04-25 13:06:26 -07:00
talksik 03ced6d180 fix: pause playback during delete particle overlay 2026-04-25 12:49:01 -07:00
talksik 1c3b4447cf infra: hook up sentry 2026-04-25 12:43:30 -07:00
talksik 1e7a14d703 fix: set proper cluster name 2026-04-24 16:14:57 -07:00
talksik 0ac395ceb6 refactor: unused imports 2026-04-22 09:13:49 -07:00
talksik 110f4594be refactor: use shared mocks for tests 2026-04-22 09:06:10 -07:00
talksik 2e9ff742a0 send admin alert when new network created 2026-04-22 08:50:03 -07:00
Arjun Patel 64a21198b3 Add comprehensive error handling and recovery UI (#173)
* feat(electron): error handling foundation

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.

* refactor(errors): defer mutation errors to global handler

Now that MutationCache toasts via toUserMessage by default, the per-hook
onError duplicates drop away. Also normalizes inline query-error UI and
surfaces a previously-silent failure.

Mutations — removed redundant onError toasts:
- network-selector: useAcceptInvitation, createNetwork (inline)
- network-settings: useInviteMembers, useRevokeInvitation, useRemoveMember
- network-billing: useCreateCheckoutSession, useCreatePortalSession
  (onSuccess toasts stay — they carry domain context like network name)

Queries — consistent inline error UX via toUserMessage:
- network-selector: failed-to-load state gets a "Try again" button
- network-billing: "Couldn't load billing" includes friendly reason
- network-settings: useNetworkInvitations failure now surfaces a hint
  (previously rendered as "0 pending" — silently wrong)

Trimmed noisy JSDoc from PR 1 files (errors.ts, query-client.ts,
app-error-boundary.tsx, error-fallback.tsx, ipc-utils.ts).

* refactor(errors): route silent catches through logError/reportError

Every catch now either surfaces, re-throws, or calls logError with a scope
tag. No more empty catches or bare console.error:

- auth-store: signInToFirebase / restoreSession / signOut paths gain
  logError context. Behavior is unchanged (best-effort local sign-out,
  fall back to login on restore failure).
- use-stream-autoplay: Audio.play() and download-URL fetches log their
  failures instead of dropping silently (both are nice-to-haves so UX
  stays silent — but we can now trace "why didn't autoplay trigger?").
- pusher-client: ws errors / parse failures / server errors / listener
  crashes all routed through logError, and listener bugs (which silently
  break user flows) now go through reportError so they're actually
  surfaced in observability.
- settings-page: email-notifications toggle now toasts on failure
  instead of silently reverting with no explanation.
- huddle-app: screen-share failures use logError.

* feat(errors): add Sentry observability behind a sinks facade

logError / reportError now route through a pair of sinks installed at
bootstrap by each process (main + every renderer entry). No call site
knows about Sentry — if sentryDsn is empty, the sinks simply aren't
installed and logError/reportError stay console-only.

- appConfig.sentryDsn: per-env string (empty for now — populate when
  ops creates the DSNs). Empty is the no-op mode for dev.
- lib/errors.ts: installErrorSinks({ capture, breadcrumb }) gates
  Sentry.captureException / Sentry.addBreadcrumb. Everything flows
  through toUserMessage and the two existing call types.
- lib/sentry.ts: initSentryRenderer() for the main window + autoplay,
  huddle, and screen-record renderers.
- main/sentry.ts: initSentryMain() runs before anything else in
  main.ts to catch bootstrap failures. Captures uncaught exceptions
  and the crash reporter automatically.
- main/ipc-utils.ts::safeHandle now routes through reportError.
- main.ts::fetchLinkMetadata logs via logError.

* chore: cleanup reexports

* fix(errors): use relative import so main-process bundle resolves

Rollup in vite.main.config.ts doesn't know about the `@/` alias (only the
renderer configs do). After PR 4 made `lib/errors.ts` reachable from main,
its `@/config/env` import broke the main build with:

  [vite]: Rollup failed to resolve import "@/config/env" from "lib/errors.ts"

Swap to a relative import — the module is now genuinely isomorphic.

* build(vite): resolve @/ alias in main + preload configs

The four renderer vite configs all resolve "@" to ./src; main and preload
didn't, so any main-reachable file using @/ imports would break the
bundle. Mirror the same alias block in both configs and revert
lib/errors.ts + src/main/* to the project's @/ convention.

* fix invalid tsconfig field

* comment

* feat(errors): fallback handlers for unhandled rejections and errors

Sentry's global integrations natively capture window.onerror /
unhandledrejection (renderer) and uncaughtException / unhandledRejection
(main). When a DSN is configured we let Sentry own those paths to avoid
double-capturing. When it isn't (dev, unconfigured prod), we attach
minimal listeners that route through reportError so stray promise
rejections and uncaught errors at least hit the console and the facade.

This closes the one gap where a bare click-handler promise rejection
(no try/catch, not a useMutation) would otherwise be invisible.

* Revert "feat(errors): fallback handlers for unhandled rejections and errors"

This reverts commit ed84b29c6b.

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Arjun from Flowy Labs <arjun@flowy.live>
2026-04-20 19:22:02 -07:00
Arjun Patel bd7a0c4fb8 ci: remove unnecessary env variables 2026-04-20 17:41:02 -07:00
Arjun Patel 7bc06d1dc5 ci: add deployment workflows for different services 2026-04-20 17:29:33 -07:00
talksik 2deef1fe37 fix: prevent email notifications to removed members
Content will retain an older member in visible_to, even if that member
was removed from the network.
2026-04-18 07:37:07 -07:00
talksik 30469fda66 revert "fix: prevent writing to nonexistent firestore docs"
This reverts commit 46170eb5d3.
2026-04-16 18:00:51 -07:00
talksik 5e930d3c2e chore: bump version 2026-04-16 15:38:48 -07:00
Arjun Patel 98fdc98c76 feat: surface privacy policy and terms in sign-in and settings (#171)
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 <noreply@anthropic.com>
2026-04-16 15:37:28 -07:00
Arjun Patel ef899ee5cd security: access control for particles (#169)
* 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
2026-04-16 15:14:34 -07:00
talksik 28b1ff542b feat: add support email
This will help humans whether they have billing questions or otherwise.
2026-04-16 09:15:31 -07:00
talksik 61a6904cc2 add nav bar to sign in flow 2026-04-16 09:14:50 -07:00