Mobile duplicated useLiveQuery, useQuery, useMutation, and buildQueryClient
from packages/ui with the only difference being the executor mechanism
(appService.mediator vs window.colanode). This consolidates them by:
- Adding a DOM-free core-api module to packages/ui with getColanode() and
getEventBus() helpers that access globalThis, avoiding Window/DOM types
- Updating shared hooks and buildQueryClient to use these helpers instead
of window.colanode/window.eventBus directly
- Installing a globalThis.colanode bridge in mobile's _layout.tsx that
delegates to appService.mediator (matching the web/desktop pattern)
- Migrating all 41 mobile files to import hooks from @colanode/ui
- Deleting 4 duplicate mobile files (3 hooks + query-client)
- Adding Metro resolver override to force react/react-native resolution
from the mobile app's node_modules (packages/ui ships a separate
web-only React 19.2.4 that conflicts with mobile's RN-compatible 19.1.0)
Also standardizes useQuery to use buildQueryKey instead of inline sha256.
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Extract duplicated CRDT lifecycle, node views, record layout, and database
layout from the mobile WebView editor into shared primitives in packages/ui.
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Extract duplicated database view business logic from
apps/mobile/webviews/editor/src/database-runtime.tsx (734→188 lines)
into shared packages/ui components and hooks:
- Add NavigationContext for platform-agnostic node navigation
(desktop uses TanStack Router, mobile uses WebView bridge)
- Extract useDatabaseViewValue hook with all DatabaseViewContext
computation (fields, filters, sorts, record creation)
- Make DatabaseViews accept renderLayout prop for custom view rendering
- Refactor ViewFullscreenButton and TableViewNameCell to use
NavigationContext instead of hardcoded TanStack Router Link
- Fix TableViewNameCell canEdit to use useRecord().canEdit (was
hardcoded true on desktop)
- Add readOnly={database.isLocked} to shared TableViewRow
- Merge mobile's view-delete logic into shared TableViewSettings
- Keep open-record button always visible on mobile (no hover)
- Add database node type support to mobile rename-node-sheet
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add database table view and record detail screens rendered inside the
WebView using shared @colanode/ui components. Extend the bridge protocol
with query subscriptions, event forwarding, and global focus tracking for
keyboard avoidance. Fix flush on navigation/background to cover all
debounced mutations. Update README to reflect current feature set and
document the intentional database-runtime duplication.
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Align password validation with shared schema, harden workspace/member role
invariants on both client and server, fix page editor CRDT reconciliation
for incremental updates, and replace file download polling with reactive
local-file state tracking.
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Fix lint errors (import ordering), resolve FileReadStream type mismatch
for mobile's Blob-based readStream, move tests from src/__tests__ to
top-level test/ directory matching web/server conventions, and add tests
for emoji, message, node, radar utils plus an in-memory error log for
debugging experimental builds.
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Allow users to change icons for spaces, channels, pages, and folders
from the rename sheet. Supports both emoji and built-in icon selection
with a tabbed picker UI. Node lists now display custom avatars.
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add a Space Settings screen accessible via a gear icon in the space
header (admin-only). The screen allows managing collaborators (add,
change role, remove with last-admin protection) and deleting a space.
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Consolidate duplicated utility functions into shared format-utils module.
Replace unsafe static ref pattern in PageWebView with forwardRef/useImperativeHandle.
Stabilize useNodeListQuery memoization by replacing JSON.stringify deps.
Add React.memo to FlatList item components (MessageItem, ChatListItem,
SpaceListItem, FileItem). Wrap all tab route layouts with ErrorBoundary.
Set up jest-expo test infrastructure with initial format utility tests.
Add empty states for message list and home screen. Add accessibility
labels to buttons, inputs, list items, and navigation elements. Create
animated skeleton loading components for node lists. Fix pre-existing
lint errors in import ordering.
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add Mermaid diagrams showing how mobile relates to other clients, the
local-first data flow, and the embedded page editor bridge. Expand
feature list, project structure, and dependency documentation.
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add keyboard tracking, automatic content scrolling, and a native toolbar with block type selection for the page editor. The toolbar appears above the keyboard with "+" button for block types and a dismiss button. Keyboard height is tracked via native events and communicated to the WebView for cursor scroll-into-view. Block type selection is inline (not modal) to prevent keyboard dismissal during interaction.
- Track keyboard height in page screen with iOS/Android event listeners
- Use KeyboardAvoidingView for proper layout when keyboard is visible
- Add toolbar component with "+" (block types) and dismiss buttons
- Implement inline block type selector (no modal to preserve keyboard)
- Extend bridge protocol: keyboard.show/hide, editor.blur, block.command, editor.focus
- Handle block command execution in WebView with correct TipTap node commands
- Expose editor instance on window.__editorInstance for command execution
- Add focus/blur callbacks to notify native of editor state
- Send cursor position to scroll-into-view when keyboard shows
- Increase ProseMirror padding-bottom from 40vh to 60vh for comfortable scrolling
- Remove focus-restoration script that prevented cursor following
Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>
* Mobile: add prebuild hook and submit config for EAS builds
Add prebuildCommand to run copy-editor.js during EAS builds so the
editor.html asset is available for Metro bundling. Also restore the
App Store Connect submit credentials (appleId, appleTeamId, ascAppId)
so builds auto-submit to TestFlight.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Mobile: use eas-build-post-install hook for editor asset
prebuildCommand replaces expo prebuild entirely, causing build failures.
Use eas-build-post-install lifecycle hook instead to run copy-editor.js
after npm install but before the native build.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Mobile: fix page editor keyboard and interaction issues
- Disable native WebView scrolling and use CSS overflow to prevent
scroll-to-top when keyboard opens
- Fix slash command click-through by preventing ProseMirror from
processing mousedown events immediately after command selection
- Remove keyboard from auto-opening on page load and auto-focusing
cursor; keyboard now only appears on user tap
- Add eas-build-post-install hook to build editor HTML asset during
EAS builds
- Improve editor.html iframe sandbox and CSP settings
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Mobile: replace inline page editor with WebView-based TipTap editor
Replaces the plain-text block-by-block page editor with a Vite-built
WebView that runs the full TipTap rich text editor. The editor HTML is
bundled as a single self-contained asset, loaded via expo-asset and
rendered in react-native-webview. Communication between RN and the
WebView uses postMessage/onMessage bridge for init, mutations, queries,
theme changes, and navigation.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Mobile: reorganize WebView editor as standalone package
Moves the editor WebView app from apps/mobile/src/editor-webview/ to
apps/mobile/webviews/editor/ as a first-class build target with its own
package.json, tsconfig.json, and vite.config.ts. This fixes TypeScript
compilation (editor code no longer typechecked as React Native) and
makes the build story clearer.
- WebView editor is now at apps/mobile/webviews/editor/
- Built artifact copied to apps/mobile/assets/editor-dist/ on prestart
- Vite dev server support for fast iteration
- Tailwind CSS @source path fixed (../../../../packages/ui)
- Page title editing restored via RenameNodeSheet
- File preview now converts file:// to base64 data URLs for WebView
- WebView hidden until ready to avoid white flash
- Keyboard accessory bar hidden on iOS
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Mobile: set up EAS Build and TestFlight distribution for iOS team testing
- Add eas.json with production build profile (Node 22.16.0)
- Configure iOS app signing and provisioning via EAS
- Add Metro mocking for Kysely FileMigrationProvider (Hermes compilation error)
- Pin react-dom@19.1.0 to match react version (package.json overrides)
- Store EAS projectId in app.json for Expo CLI integration
The app now builds on EAS cloud and distributes to TestFlight. Team members can be added as internal testers for easy installation on their iPhones.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
* Mobile: set up EAS Build and TestFlight distribution for iOS team testing
- Add eas.json with production build profile (Node 22.16.0)
- Configure iOS app signing and provisioning via EAS
- Add Metro mocking for Kysely FileMigrationProvider (Hermes compilation error)
- Pin react-dom@19.1.0 to match react version (package.json overrides)
- Store EAS projectId in app.json for Expo CLI integration
The app now builds on EAS cloud and distributes to TestFlight. Team members can be added as internal testers for easy installation on their iPhones.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>
Replace workspace-role checks with node-role checks derived from the
root space's collaborators map. This aligns mobile with the shared
permission model used by web/desktop: rename requires editor, delete
requires admin, create children requires editor, and message deletion
is allowed for the author or any admin.
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* Mobile: add inline page editing with CRDT persistence
- Inline Notion-style editing: tap and type directly on pages (no separate edit mode)
- Permission-gated via useNodeRole hook (editor access required)
- CRDT save pipeline: debounced YDoc updates via document.update mutation
- Title saved separately via node.update on blur and navigation
- Block type changes via long-press (paragraph, headings, lists, tasks, quotes, dividers)
- Unsupported blocks (tables, code, files, embeds) preserved unchanged and rendered read-only
- Auto-flush on app background, navigation away, and unmount
- Remote reconciliation when no pending local edits
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Mobile: restore full BlockRenderer for non-editable page blocks
Revert to using BlockRenderer for non-editable blocks in the page
editor (files, pages, folders render with rich previews). Revert
hacky kysely-service transaction retry — the SQLite transaction
error is a pre-existing infrastructure issue.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Mobile: add keyboard toolbar for page editor
Toolbar with + (block type) and dismiss keyboard buttons appears
above the keyboard when editing. Uses Keyboard events instead of
InputAccessoryView for Expo compatibility.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Mobile: update README with page editing and current feature set
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Remove unnecessary conditional check that prevented navigation to home when app first loads. Expo Router defaults to the first alphabetically-ordered tab group (chats) before the navigation effect fires. Since the effect is guarded by hasNavigated, we can unconditionally navigate to home when the user has workspaces.
Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>
Add comprehensive documentation covering overview, implemented features, setup instructions, and architecture details. Includes routing structure, local-first data flow, key layers, and Metro bundler mocking configuration.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
- Remove committed ios/android prebuild dirs (CNG generates these on demand)
- Add root-level /ios/ and /android/ to .gitignore to prevent stray prebuilds
- Extract message text utils to shared module (message-utils.ts)
- Fix sync-service bind targets (nodeInteractions/nodeReactions were bound to wrong service)
- Fix node-counters-service lock key (use parent_id instead of node id)
- Replace `any` casts with proper types (TextStyle, error handling, file info)
- Propagate SQLite query errors instead of silently swallowing them
- Skip re-copying assets that already exist on disk
- Memoize message list grouping to avoid unnecessary recomputation
- Show spinner instead of "Loading..." in emoji picker empty state
- Fix cross-tab chat navigation from Home using Link withAnchor + unstable_settings
so back button goes to chat list instead of home screen
- Fix unread count not clearing: add clearCountersForNode for chat/channel nodes
in both mutation handler and sync paths
- Fix unread counts persisting after re-login by checking parent interaction
seen state during message counter increment
- Fix logout crash: await database.destroy() and stop services before closing DB
- Fix login error on re-login by cleaning up stale account data in handleLoginSuccess
- Switch ChatListItem to useNodeListQuery for reactive message preview updates
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Migrate from Vite/web-based setup to native React Native with Expo Router.
Includes auth flows, chat/spaces/settings screens, CRDT sync, file upload,
workspace switching, emoji picker, message reactions, and iOS/Android projects.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>