feat: increase feature parity between mobile and desktop #298

Merged
talksik merged 10 commits from claude/mobile-app-audit-x1ax88 into main 2026-06-21 17:38:17 +00:00
talksik commented 2026-06-21 15:36:51 +00:00 (Migrated from github.com)

Summary

Implements task, paper, and file particle views for the mobile app, along with network settings and member management screens. Mirrors desktop functionality while adapting to mobile constraints.

Key Changes

New Particle Views

  • TaskParticleView: Editable task cards with title, notes, checklist items, and assignee picker. Auto-advances after 8s dwell; suspends playback when editing to prevent interruption
  • PaperParticleView: Read-only document view with markdown rendering and length-based dwell timer (4-30s)
  • FileParticleView: File download card with name, size, and signed URL resolution

Network Settings & Member Management

  • NetworkSettingsScreen: Admin-gated member list, pending invitations, and removal controls
  • AddMembersSheet: Email-based invitation UI with email validation and batch submission
  • BillingSection: Plan display and admin-only upgrade/manage controls (mirrors desktop)
  • CreateNetworkSheet: Network creation dialog for the network list screen

Shared Components & Utilities

  • MarkdownBody: Extracted markdown rendering logic from TextParticleView for reuse across text, paper, and task particles. Includes task-list checkbox rendering and Crepe palette styling
  • Avatar: Enhanced with image display support and avatar URL resolution
  • useAvatarUrl: New hook for resolving avatar object IDs to signed URLs
  • useInvitations: Hooks for listing/accepting invitations and creating networks
  • useMemberManagement: Hooks for member operations (add, remove, list invitations)
  • useBilling: Hooks for usage and billing queries

Compose & Upload

  • TaskComposeSheet: Quick task creator (title + optional notes)
  • ComposeDock: Added task compose button with allowTask prop to disable in new-stream flow
  • createTaskParticle: Upload utility for task creation

Settings & Account

  • AccountScreen: Avatar picker with image library integration and upload
  • SettingsScreen: Email notification toggle and sign-out
  • AuthStore: Added refreshUser method for post-upload user refresh

Type & API Updates

  • Extended Human type with optional avatar_object_id
  • Added task/paper/file particle type definitions
  • Extended apiClient with avatar upload, billing, member management, and invitation endpoints
  • Updated particle type handling (renamed 'quest' to 'task')

Implementation Details

  • Task checklist uses ref-based composition to handle concurrent edits gracefully (last-write-wins, same as desktop)
  • Markdown rendering unified across particles via MarkdownBody component with task-list checkbox substitution
  • Dwell timers follow consistent pattern: track elapsed time in ref, tick at 100ms intervals, suspend on user interaction
  • Avatar upload streams file directly via expo-file-system rather than multipart form
  • Network creation/settings flows use bottom sheets for mobile UX
  • Billing section gates admin controls behind useIsNetworkAdmin check

https://claude.ai/code/session_01LqGPzXQ1AA9CqYHgCgmbtV

Summary by CodeRabbit

Release Notes

  • New Features

    • Profile photos: upload, remove, and display signed avatars in Account and headers.
    • Task particles in streams: create and edit (done, notes, checklist, assignees), plus task compose from the dock.
    • Improved stream rendering: markdown body for text, plus new paper and file views (with auto-advance and file download).
    • Network settings: create networks, invite/manage members and pending invites, and view plan/billing.
    • Settings: email notification toggle.
  • Other Improvements

    • Updated stream UI to use shared avatars and task-based preview labeling.
## Summary Implements task, paper, and file particle views for the mobile app, along with network settings and member management screens. Mirrors desktop functionality while adapting to mobile constraints. ## Key Changes ### New Particle Views - **TaskParticleView**: Editable task cards with title, notes, checklist items, and assignee picker. Auto-advances after 8s dwell; suspends playback when editing to prevent interruption - **PaperParticleView**: Read-only document view with markdown rendering and length-based dwell timer (4-30s) - **FileParticleView**: File download card with name, size, and signed URL resolution ### Network Settings & Member Management - **NetworkSettingsScreen**: Admin-gated member list, pending invitations, and removal controls - **AddMembersSheet**: Email-based invitation UI with email validation and batch submission - **BillingSection**: Plan display and admin-only upgrade/manage controls (mirrors desktop) - **CreateNetworkSheet**: Network creation dialog for the network list screen ### Shared Components & Utilities - **MarkdownBody**: Extracted markdown rendering logic from TextParticleView for reuse across text, paper, and task particles. Includes task-list checkbox rendering and Crepe palette styling - **Avatar**: Enhanced with image display support and avatar URL resolution - **useAvatarUrl**: New hook for resolving avatar object IDs to signed URLs - **useInvitations**: Hooks for listing/accepting invitations and creating networks - **useMemberManagement**: Hooks for member operations (add, remove, list invitations) - **useBilling**: Hooks for usage and billing queries ### Compose & Upload - **TaskComposeSheet**: Quick task creator (title + optional notes) - **ComposeDock**: Added task compose button with `allowTask` prop to disable in new-stream flow - **createTaskParticle**: Upload utility for task creation ### Settings & Account - **AccountScreen**: Avatar picker with image library integration and upload - **SettingsScreen**: Email notification toggle and sign-out - **AuthStore**: Added `refreshUser` method for post-upload user refresh ### Type & API Updates - Extended `Human` type with optional `avatar_object_id` - Added task/paper/file particle type definitions - Extended `apiClient` with avatar upload, billing, member management, and invitation endpoints - Updated particle type handling (renamed 'quest' to 'task') ## Implementation Details - Task checklist uses ref-based composition to handle concurrent edits gracefully (last-write-wins, same as desktop) - Markdown rendering unified across particles via MarkdownBody component with task-list checkbox substitution - Dwell timers follow consistent pattern: track elapsed time in ref, tick at 100ms intervals, suspend on user interaction - Avatar upload streams file directly via expo-file-system rather than multipart form - Network creation/settings flows use bottom sheets for mobile UX - Billing section gates admin controls behind `useIsNetworkAdmin` check https://claude.ai/code/session_01LqGPzXQ1AA9CqYHgCgmbtV <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit ## Release Notes * **New Features** * Profile photos: upload, remove, and display signed avatars in Account and headers. * Task particles in streams: create and edit (done, notes, checklist, assignees), plus task compose from the dock. * Improved stream rendering: markdown body for text, plus new paper and file views (with auto-advance and file download). * Network settings: create networks, invite/manage members and pending invites, and view plan/billing. * Settings: email notification toggle. * **Other Improvements** * Updated stream UI to use shared avatars and task-based preview labeling. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
coderabbitai[bot] commented 2026-06-21 15:36:59 +00:00 (Migrated from github.com)

Review Change Stack

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Free

Run ID: ef160727-8a7c-44b7-9539-db2c2ca1d7ca

📥 Commits

Reviewing files that changed from the base of the PR and between 4a73ccad0b and 9ed1c949fd.

📒 Files selected for processing (9)
  • js/mobile/src/components/Avatar.tsx
  • js/mobile/src/features/huddle/HuddleScreen.tsx
  • js/mobile/src/features/networks/Drawer.tsx
  • js/mobile/src/features/networks/NetworkListScreen.tsx
  • js/mobile/src/features/settings/AccountScreen.tsx
  • js/mobile/src/features/stream-view/ReactionStack.tsx
  • js/mobile/src/features/stream-view/StreamStatusPills.tsx
  • js/mobile/src/features/stream-view/StreamView.tsx
  • js/mobile/src/features/streams/StreamCard.tsx
🚧 Files skipped from review as they are similar to previous changes (2)
  • js/mobile/src/features/settings/AccountScreen.tsx
  • js/mobile/src/features/networks/NetworkListScreen.tsx

📝 Walkthrough

Walkthrough

This PR adds task particle support (replacing quest), avatar upload/removal with image picker, a shared MarkdownBody component extracted from TextParticleView, three new stream particle views (TaskParticleView, PaperParticleView, FileParticleView), a NetworkSettingsScreen with member management and Stripe billing, network creation and invitation acceptance flows, an expanded SettingsScreen with email notification preferences, and consolidates avatar display across Huddle, Drawer, and ReactionStack components.

Changes

Task Particle Support

Layer / File(s) Summary
Task type schemas and Firestore parsing
js/mobile/src/api/types.ts, js/mobile/src/lib/firestore-particles.ts
Adds ChecklistItemSchema/TaskPropertiesSchema, replaces quest with task in ParticleSchema discriminated union and ParticlePropertiesMap, and updates Firestore fromFirestore switch to parse task on the paper logic path.
Task creation: upload helper and ComposeDock wiring
js/mobile/src/lib/upload.ts, js/mobile/src/features/compose/ComposeDock.tsx, js/mobile/src/features/compose/TaskComposeSheet.tsx, js/mobile/src/features/streams/NewStreamScreen.tsx, js/mobile/src/features/streams/StreamCard.tsx
Adds createTaskParticle to Firestore upload helpers; extends ComposeDock with allowTask prop, taskOpen state, submitTask handler, and TaskComposeSheet sheet component; disables task button in NewStreamScreen; updates StreamCard preview label from quest to task.
TaskParticleView: dwell, editing, and Firestore writes
js/mobile/src/features/stream-view/TaskParticleView.tsx
Full TaskParticleView with 8-second dwell timer, focus-suspended playback, inline Firestore writes for done/title/notes/checklist/assignee, and ChecklistItemRow/AddChecklistItemRow/AssigneeChip sub-components.

MarkdownBody and New Particle Views

Layer / File(s) Summary
Shared MarkdownBody component
js/mobile/src/components/MarkdownBody.tsx, js/mobile/src/features/stream-view/TextParticleView.tsx
New MarkdownBody with Flowy palette theme, GFM task-list glyph preprocessing, and custom Renderer for inline code; TextParticleView removes ~159 lines of local markdown setup and delegates to MarkdownBody.
PaperParticleView, FileParticleView, and FallbackParticleView
js/mobile/src/features/stream-view/PaperParticleView.tsx, js/mobile/src/features/stream-view/FileParticleView.tsx, js/mobile/src/features/stream-view/FallbackParticleView.tsx
PaperParticleView renders title + MarkdownBody with length-based dwell timer; FileParticleView displays filename/size with a signed-URL download flow and dwell pause while downloading; FallbackParticleView simplified to HelpCircle icon and raw particle.type label.
StreamStatusPills component and StreamView wiring
js/mobile/src/features/stream-view/StreamStatusPills.tsx, js/mobile/src/features/stream-view/StreamView.tsx
New StreamStatusPills component renders conditional paused/closing-in badges; StreamView adds renderParticle switch cases for task, paper, and file wiring the three new view components and relocates status-pill rendering from inline to dedicated component.

Avatar Upload and Account/Settings Screens

Layer / File(s) Summary
Avatar API methods, hook, and data shape
js/mobile/app.config.ts, js/mobile/package.json, js/mobile/src/api/client.ts, js/mobile/src/api/types.ts, js/mobile/src/hooks/use-avatar-url.ts, js/mobile/src/stores/auth-store.ts
Adds expo-image-picker dependency and photosPermission config; adds uploadAvatar/deleteAvatar/getAvatarDownloadUrl to ApiClient; adds avatar_object_id to HumanSchema; adds useAvatarUrl hook with 1-hour stale time; adds refreshUser to AuthState and its Zustand implementation.
Avatar component image rendering and account/display consolidation
js/mobile/src/components/Avatar.tsx, js/mobile/src/features/settings/AccountScreen.tsx, js/mobile/src/features/huddle/HuddleScreen.tsx, js/mobile/src/features/networks/Drawer.tsx, js/mobile/src/features/stream-view/ReactionStack.tsx
Avatar component resolves signed URL via useAvatarUrl and renders Image vs initials with overflow-hidden and expanded sizes; AccountScreen adds pickAndUpload/removeAvatar handlers with busy state and camera-overlay pressable; HuddleScreen/Drawer/ReactionStack consolidate avatar display using shared Avatar component.
SettingsScreen: email notifications, version, and sign out
js/mobile/src/features/settings/SettingsScreen.tsx
Adds email notifications Switch with optimistic update/rollback via apiClient.updateSettings, version display from Expo config, sign-out button with pending state, and local SettingsGroup layout component.

Network Settings, Billing, Members, and Invitations

Layer / File(s) Summary
Navigation route and React Query hooks
js/mobile/src/navigation/types.ts, js/mobile/src/navigation/RootNavigator.tsx, js/mobile/src/hooks/use-invitations.ts, js/mobile/src/hooks/use-member-management.ts, js/mobile/src/hooks/use-billing.ts
Registers NetworkSettings in navigation stack; adds useMyInvitations/useAcceptInvitation/useCreateNetwork, useNetworkInvitations/useAddMembers/useRemoveMember/useRevokeInvitation, and billing hooks with appropriate cache invalidations.
NetworkListScreen: create network and invitations
js/mobile/src/features/networks/CreateNetworkSheet.tsx, js/mobile/src/features/networks/NetworkListScreen.tsx
CreateNetworkSheet bottom sheet for new network naming; NetworkListScreen adds Plus header action, concurrent network+invitation refresh, InvitationsSection with accept-invitation cards, and updated EmptyState with create button.
NetworkSettingsScreen, AddMembersSheet, BillingSection, and Drawer/StreamList entry points
js/mobile/src/features/network-settings/NetworkSettingsScreen.tsx, js/mobile/src/features/network-settings/AddMembersSheet.tsx, js/mobile/src/features/network-settings/BillingSection.tsx, js/mobile/src/features/networks/Drawer.tsx, js/mobile/src/features/streams/StreamListScreen.tsx
NetworkSettingsScreen renders members with admin remove, pending invitations with revoke, billing, and AddMembersSheet; BillingSection with FreeBilling Stripe checkout and ProBilling portal management; Drawer adds Settings row; StreamListScreen adds settings icon navigating to NetworkSettings.

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~120 minutes

Poem

🐇 Hop hop, the quest is done—
A task takes its place under the sun!
Avatars bloom, Stripe portals gleam,
MarkdownBody flows like a lazy stream.
New particle views join the parade—
Paper, file, task in the arcade!
The warren grows with every merge made. 🥕


Note

🎁 Summarized by CodeRabbit Free

Your organization is on the Free plan. CodeRabbit will generate a high-level summary and a walkthrough for each pull request. For a comprehensive line-by-line review, please upgrade your subscription to CodeRabbit Pro by visiting https://app.coderabbit.ai/login.

Comment @coderabbitai help to get the list of available commands and usage tips.

<!-- This is an auto-generated comment: summarize by coderabbit.ai --> <!-- review_stack_entry_start --> [![Review Change Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/flowy-live/llink/pull/298?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack) <!-- review_stack_entry_end --> <details> <summary>ℹ️ Recent review info</summary> <details> <summary>⚙️ Run configuration</summary> **Configuration used**: defaults **Review profile**: CHILL **Plan**: Free **Run ID**: `ef160727-8a7c-44b7-9539-db2c2ca1d7ca` </details> <details> <summary>📥 Commits</summary> Reviewing files that changed from the base of the PR and between 4a73ccad0ba82f95ec84be6ee132f1688346f3ed and 9ed1c949fd446f57e49425a107b28bfbdaad34c3. </details> <details> <summary>📒 Files selected for processing (9)</summary> * `js/mobile/src/components/Avatar.tsx` * `js/mobile/src/features/huddle/HuddleScreen.tsx` * `js/mobile/src/features/networks/Drawer.tsx` * `js/mobile/src/features/networks/NetworkListScreen.tsx` * `js/mobile/src/features/settings/AccountScreen.tsx` * `js/mobile/src/features/stream-view/ReactionStack.tsx` * `js/mobile/src/features/stream-view/StreamStatusPills.tsx` * `js/mobile/src/features/stream-view/StreamView.tsx` * `js/mobile/src/features/streams/StreamCard.tsx` </details> <details> <summary>🚧 Files skipped from review as they are similar to previous changes (2)</summary> * js/mobile/src/features/settings/AccountScreen.tsx * js/mobile/src/features/networks/NetworkListScreen.tsx </details> </details> --- <!-- walkthrough_start --> <details> <summary>📝 Walkthrough</summary> ## Walkthrough This PR adds task particle support (replacing quest), avatar upload/removal with image picker, a shared `MarkdownBody` component extracted from `TextParticleView`, three new stream particle views (`TaskParticleView`, `PaperParticleView`, `FileParticleView`), a `NetworkSettingsScreen` with member management and Stripe billing, network creation and invitation acceptance flows, an expanded `SettingsScreen` with email notification preferences, and consolidates avatar display across Huddle, Drawer, and ReactionStack components. ## Changes **Task Particle Support** |Layer / File(s)|Summary| |---|---| |**Task type schemas and Firestore parsing** <br> `js/mobile/src/api/types.ts`, `js/mobile/src/lib/firestore-particles.ts` | Adds `ChecklistItemSchema`/`TaskPropertiesSchema`, replaces `quest` with `task` in `ParticleSchema` discriminated union and `ParticlePropertiesMap`, and updates Firestore `fromFirestore` switch to parse `task` on the `paper` logic path. | |**Task creation: upload helper and ComposeDock wiring** <br> `js/mobile/src/lib/upload.ts`, `js/mobile/src/features/compose/ComposeDock.tsx`, `js/mobile/src/features/compose/TaskComposeSheet.tsx`, `js/mobile/src/features/streams/NewStreamScreen.tsx`, `js/mobile/src/features/streams/StreamCard.tsx` | Adds `createTaskParticle` to Firestore upload helpers; extends `ComposeDock` with `allowTask` prop, `taskOpen` state, `submitTask` handler, and `TaskComposeSheet` sheet component; disables task button in `NewStreamScreen`; updates `StreamCard` preview label from `quest` to `task`. | |**TaskParticleView: dwell, editing, and Firestore writes** <br> `js/mobile/src/features/stream-view/TaskParticleView.tsx` | Full `TaskParticleView` with 8-second dwell timer, focus-suspended playback, inline Firestore writes for done/title/notes/checklist/assignee, and `ChecklistItemRow`/`AddChecklistItemRow`/`AssigneeChip` sub-components. | **MarkdownBody and New Particle Views** |Layer / File(s)|Summary| |---|---| |**Shared MarkdownBody component** <br> `js/mobile/src/components/MarkdownBody.tsx`, `js/mobile/src/features/stream-view/TextParticleView.tsx` | New `MarkdownBody` with Flowy palette theme, GFM task-list glyph preprocessing, and custom `Renderer` for inline code; `TextParticleView` removes ~159 lines of local markdown setup and delegates to `MarkdownBody`. | |**PaperParticleView, FileParticleView, and FallbackParticleView** <br> `js/mobile/src/features/stream-view/PaperParticleView.tsx`, `js/mobile/src/features/stream-view/FileParticleView.tsx`, `js/mobile/src/features/stream-view/FallbackParticleView.tsx` | `PaperParticleView` renders title + `MarkdownBody` with length-based dwell timer; `FileParticleView` displays filename/size with a signed-URL download flow and dwell pause while downloading; `FallbackParticleView` simplified to `HelpCircle` icon and raw `particle.type` label. | |**StreamStatusPills component and StreamView wiring** <br> `js/mobile/src/features/stream-view/StreamStatusPills.tsx`, `js/mobile/src/features/stream-view/StreamView.tsx` | New `StreamStatusPills` component renders conditional paused/closing-in badges; `StreamView` adds `renderParticle` switch cases for `task`, `paper`, and `file` wiring the three new view components and relocates status-pill rendering from inline to dedicated component. | **Avatar Upload and Account/Settings Screens** |Layer / File(s)|Summary| |---|---| |**Avatar API methods, hook, and data shape** <br> `js/mobile/app.config.ts`, `js/mobile/package.json`, `js/mobile/src/api/client.ts`, `js/mobile/src/api/types.ts`, `js/mobile/src/hooks/use-avatar-url.ts`, `js/mobile/src/stores/auth-store.ts` | Adds `expo-image-picker` dependency and `photosPermission` config; adds `uploadAvatar`/`deleteAvatar`/`getAvatarDownloadUrl` to `ApiClient`; adds `avatar_object_id` to `HumanSchema`; adds `useAvatarUrl` hook with 1-hour stale time; adds `refreshUser` to `AuthState` and its Zustand implementation. | |**Avatar component image rendering and account/display consolidation** <br> `js/mobile/src/components/Avatar.tsx`, `js/mobile/src/features/settings/AccountScreen.tsx`, `js/mobile/src/features/huddle/HuddleScreen.tsx`, `js/mobile/src/features/networks/Drawer.tsx`, `js/mobile/src/features/stream-view/ReactionStack.tsx` | `Avatar` component resolves signed URL via `useAvatarUrl` and renders `Image` vs initials with overflow-hidden and expanded sizes; `AccountScreen` adds `pickAndUpload`/`removeAvatar` handlers with busy state and camera-overlay pressable; HuddleScreen/Drawer/ReactionStack consolidate avatar display using shared `Avatar` component. | |**SettingsScreen: email notifications, version, and sign out** <br> `js/mobile/src/features/settings/SettingsScreen.tsx` | Adds email notifications `Switch` with optimistic update/rollback via `apiClient.updateSettings`, version display from Expo config, sign-out button with pending state, and local `SettingsGroup` layout component. | **Network Settings, Billing, Members, and Invitations** |Layer / File(s)|Summary| |---|---| |**Navigation route and React Query hooks** <br> `js/mobile/src/navigation/types.ts`, `js/mobile/src/navigation/RootNavigator.tsx`, `js/mobile/src/hooks/use-invitations.ts`, `js/mobile/src/hooks/use-member-management.ts`, `js/mobile/src/hooks/use-billing.ts` | Registers `NetworkSettings` in navigation stack; adds `useMyInvitations`/`useAcceptInvitation`/`useCreateNetwork`, `useNetworkInvitations`/`useAddMembers`/`useRemoveMember`/`useRevokeInvitation`, and billing hooks with appropriate cache invalidations. | |**NetworkListScreen: create network and invitations** <br> `js/mobile/src/features/networks/CreateNetworkSheet.tsx`, `js/mobile/src/features/networks/NetworkListScreen.tsx` | `CreateNetworkSheet` bottom sheet for new network naming; `NetworkListScreen` adds `Plus` header action, concurrent network+invitation refresh, `InvitationsSection` with accept-invitation cards, and updated `EmptyState` with create button. | |**NetworkSettingsScreen, AddMembersSheet, BillingSection, and Drawer/StreamList entry points** <br> `js/mobile/src/features/network-settings/NetworkSettingsScreen.tsx`, `js/mobile/src/features/network-settings/AddMembersSheet.tsx`, `js/mobile/src/features/network-settings/BillingSection.tsx`, `js/mobile/src/features/networks/Drawer.tsx`, `js/mobile/src/features/streams/StreamListScreen.tsx` | `NetworkSettingsScreen` renders members with admin remove, pending invitations with revoke, billing, and `AddMembersSheet`; `BillingSection` with `FreeBilling` Stripe checkout and `ProBilling` portal management; `Drawer` adds Settings row; `StreamListScreen` adds settings icon navigating to `NetworkSettings`. | ## Estimated code review effort 🎯 5 (Critical) | ⏱️ ~120 minutes ## Poem > 🐇 Hop hop, the quest is done— > A `task` takes its place under the sun! > Avatars bloom, Stripe portals gleam, > MarkdownBody flows like a lazy stream. > New particle views join the parade— > Paper, file, task in the arcade! > The warren grows with every merge made. 🥕 </details> <!-- walkthrough_end --> <!-- tips_start --> --- > [!NOTE] > <details> > <summary>🎁 Summarized by CodeRabbit Free</summary> > > Your organization is on the Free plan. CodeRabbit will generate a high-level summary and a walkthrough for each pull request. For a comprehensive line-by-line review, please upgrade your subscription to CodeRabbit Pro by visiting <https://app.coderabbit.ai/login>. > > </details> <sub>Comment `@coderabbitai help` to get the list of available commands and usage tips.</sub> <!-- tips_end -->
Sign in to join this conversation.