Skip to content

Mobile#1506

Merged
ringringlin merged 33 commits intoiOfficeAI:mainfrom
xavierliang:feature/mobile-app
Mar 24, 2026
Merged

Mobile#1506
ringringlin merged 33 commits intoiOfficeAI:mainfrom
xavierliang:feature/mobile-app

Conversation

@xavierliang
Copy link
Copy Markdown
Collaborator

@xavierliang xavierliang commented Mar 19, 2026

very basic RN

Expo Router app with WebSocket bridge to AionUi desktop backend.

Includes:
- Connection screen with JWT auth
- Conversation list with create/delete support
- Chat screen with streaming responses and markdown rendering
- File browser via REST API
- Settings screen with connection management
- i18n support (en-US, zh-CN)
- Bridge service for WS request-response protocol
- Message adapter ported from desktop chatLib
Wire file tap in the browser to navigate to a new preview screen that
supports markdown, code, HTML, diff, and image files via the existing
bridge WebSocket protocol. Includes size guard (>1 MB), unsupported
type message, loading/error states with retry, and i18n for en/zh.
Set up Jest + jest-expo testing with 71 tests covering utils and services
(uuid, messageAdapter, api, websocket, bridge). Add EAS Build profiles
for development/preview/production and integrate expo-dev-client.
- Add versions/version.json for centralized version tracking
- Add scripts/build.js with auto buildNumber bump and rollback on failure
- Configure eas.json with local version source, real device support, and Apple credentials
- Wire up build/prebuild/device scripts in package.json
- Add .easignore to reduce cloud build upload size
- Add placeholder app icon (1024x1024)
- Update app.config.ts with dynamic version, EAS project ID, and iOS compliance flags
Add index.tsx as the root route gateway that redirects based on
connection state. Refactor _layout.tsx to declare all routes statically
instead of conditionally rendering Stack.Screen (which breaks production
builds). Add isRestoring state to ConnectionContext to keep splash
screen visible during SecureStore restoration. Add auth guard in tabs
layout to redirect back when disconnected.
Use expo-camera to scan QR codes from AionUi desktop for one-tap
server authentication, replacing the manual host/port/token form.
The mobile BridgeService was sending raw event names but the server
expects the @office-ai/platform subscribe protocol (subscribe-{key}
with unique request IDs). This caused all requests to silently fail
and time out, leaving the app stuck in loading state.

- Update request() to send subscribe-{name} and listen for
  subscribe.callback-{name}{id} responses
- Update emit() to wrap fire-and-forget calls in subscribe protocol
- Add proper loading state tracking in NewConversationModal
- Apply formatting fixes across mobile components
Replace the conversations list tab + push navigation with a drawer sidebar
for quick session switching. Fix all hardcoded light-mode colors across chat
components (MarkdownContent, ToolCallBlock, ConfirmationCard, MessageBubble,
ChatInputBar, ChatScreen, ThemedText) by using dynamic theme tokens.
…r and files tab

Associate Files with Chat sessions through a shared WorkspaceContext so
switching sessions automatically shows the relevant project files. Chat
sidebar now groups conversations by workspace and timeline (pinned,
today, yesterday, etc.). Files tab is rebuilt as a drawer-based layout
with multi-file tabs, tree sidebar, and inline file preview.

New contexts: WorkspaceContext (derives workspace from active session),
FilesTabContext (multi-tab state with AsyncStorage persistence).
New utils: workspace, timeline, groupingHelpers (ported from desktop).
New components: WorkspaceGroup, WorkspaceFilesSidebar, MobileFileTabHeader,
FileContentView. Chat header shows workspace name with tap-to-navigate.
The WorkspaceFilesSidebar was using REST API (/api/directory/browse) for
directory listing, which caused path mismatches with workspace paths stored
in conversations. Switch to bridge protocol (conversation.get-workspace)
to align with the desktop data flow.

- Replace REST API with bridge.request for workspace tree fetching
- Adapt data types from flat DirEntry to nested IDirOrFile
- Simplify tree logic: full tree is pre-loaded, no lazy folder expansion
- Add client-side sorting (dirs first, then alphabetical)
- Fix unnecessary refetch on language change
Settings page, ToolCallBlock confirming status, and theme.ts updated
to use semantic color tokens instead of hardcoded hex values.
…on and listing

- Map agentBackend to correct conversation type ('acp' for most agents)
  instead of passing raw backend name, matching WebUI's useGuidSend behavior
- Fix 0-based pagination offset (page: 0) to avoid skipping all conversations
- Switch chat.send.message from emit to request for proper error handling
…ersation creation

- Switch chat.stop.stream and confirmation.confirm from emit (fire-and-forget)
  to request (request-response) to match WebUI provider protocol
- Add workspace and model fields to CreateConversationParams, auto-infer
  workspace from most recent conversation so new chats get file tree access
@sentry
Copy link
Copy Markdown

sentry bot commented Mar 19, 2026

Codecov Report

❌ Patch coverage is 0% with 2 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
...tings/SettingsModal/contents/WebuiModalContent.tsx 0.00% 2 Missing ⚠️

📢 Thoughts on this report? Let us know!

The fetchAgents call was treating the full bridge response as the agent
array directly. Now correctly checks response.success and reads
response.data, matching the IBridgeResponse protocol used by the backend.
The mobile/ directory is an independent Expo project with its own
tsconfig. Root ESLint cannot parse its files, causing 55 errors in CI.
…itle

Move workspace indicator from a right header button to a subtitle below
the conversation title, reducing header overlap on small screens.
…reation until first message

Instead of creating an empty conversation immediately when selecting an agent,
introduce a pendingAgent state that waits for the user's first message. On send,
the conversation is created atomically with the message as its name, matching
the desktop behavior.
…gChatScreen

Align PendingChatScreen with desktop Guid page by adding option pills for
workspace selection, server-side file attachment, model switching, and session
mode selection. Workspace and files are mutually exclusive. Mode/model pills
conditionally render based on backend capabilities.
…& diff display

- Add search bar to chat sidebar for filtering conversations by name/agent
- Add rename option to conversation long-press menu (iOS Alert.prompt, Android inline input)
- Add copy button to code blocks in markdown with expo-clipboard
- Add web search display for codex_tool_call web_search_begin/end subtypes
- Add diff display for codex_tool_call turn_diff subtype with expandable colored diff
- Add i18n keys for all new features in en-US and zh-CN
…token refresh, dead connection detection

- Support thought messages: transform, merge by msg_id, collapsible ThoughtBlock UI
- Fix confirmation system: populate confirmation.add handler, add update/remove listeners, restore on reconnect, use confirmation.id for confirm requests
- Handle acp_context_usage metadata in stream listener
- Add files parameter to sendMessage for future file attachment support
- Add client-side dead connection detection (50s ping timeout, 15s check interval)
- Reconnect WebSocket when app returns to foreground
- Add token refresh: decode JWT exp, schedule refresh 1hr before expiry
- Auto-refresh conversation list on foreground, 30s polling, and chat finish events
@xavierliang xavierliang changed the title fix(mobile): align bridge protocol with WebUI for chat operations Mobile Mar 20, 2026
… block

Group consecutive tool call messages into a single ToolCallSummary that
auto-expands during streaming and collapses to a one-line summary when
complete. Also refactor thought messages to ephemeral state instead of
injecting into the message list.
…tion banner, and data retention

Add auth challenge callback to WebSocketService so ConnectionContext can
attempt token refresh before falling back to auth_failed. Preserve
conversation data during transient disconnects (only clear on explicit
server change). Delay auth_failed redirect by 5s to allow auto-recovery.
Add ConnectionBanner component showing connection status with tap-to-retry.
…request

The server destructures `msg_id` but mobile was sending `id`, causing the
value to be silently ignored. No functional bug (matching uses `callId`),
but aligning the field name prevents future issues.
…settings reconnect

- Wrap TabLayout in SafeAreaView with top edge and zero out top inset
  for child navigators to prevent double safe area padding
- Add headerStatusBarHeight: 0 to chat Drawer for consistent header
- Replace wrapping TouchableOpacity in ToolStepRow with dedicated
  StepRowHeader to prevent touch event bubbling from ToolCallBlock
- Add reconnect button in Settings connection card when disconnected
Remove redundant paddingTop: 60 from sidebar drawers (parent SafeAreaView
already handles safe area) and extract DrawerMenuButton so useNavigation()
runs inside the drawer navigator context.
…echanism

setTimeout-based token refresh fails when the app is backgrounded because
the OS kills timers. Use WebSocket heartbeat (ping/pong) to check token
expiry on every heartbeat and refresh proactively when < 1 hour remains.
Also pre-check token expiry before connect to avoid useless reconnects.
kaizhou-lab
kaizhou-lab previously approved these changes Mar 23, 2026
- Accept deletion of .eslintignore (main migrated to oxc toolchain)
- Add mobile/ to .oxlintrc.json ignorePatterns to exclude standalone RN project
zk added 4 commits March 23, 2026 21:08
- Create .prettierignore to exclude mobile/ from oxfmt checks
- Auto-fix formatting in fix-sentry SKILL.md
Remove non-existent src/types from metro watchFolders and extraNodeModules.
Add paste-link mode to connect screen for simulator debugging without camera.
@ringringlin ringringlin merged commit f297be8 into iOfficeAI:main Mar 24, 2026
8 of 14 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants