feat(mobile): Flutter iOS app with Phase 1 features#2
Open
dnplkndll wants to merge 15 commits into
Open
Conversation
df6d496 to
7084b9b
Compare
Flutter mobile app for self-hosted Huly with: - Auth: OTP, password, OAuth (Google/GitHub/OIDC) via huly:// scheme - 2FA/TOTP support (verify2fa flow with dedicated screen) - Issue tracking: list, detail, create, edit with TxUpdateDoc - Status management: fetch/display/edit issue statuses - Client-side search/filter on issue list - Auto-refresh (45s timer, pauses when backgrounded) - Huly design system (dark theme, shared widgets) - iOS share extension for quick issue creation - Secure token storage (Keychain) - Server-side mobileRedirect in authProviders Architecture: Riverpod state, go_router, freezed models, dio HTTP Signed-off-by: Don Kendall <kendall@donkendall.com> Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Signed-off-by: Don Kendall <kendall@donkendall.com>
Signed-off-by: Don Kendall <kendall@donkendall.com>
- Add Member model (contact:class:Person) with provider - Add ChatMessage model for activity/comments - Resolve assignee names on issue detail and list screens - Show activity feed (comments) on issue detail screen - Add bottom navigation bar (Issues / Settings tabs) - Add Settings screen (server info, workspace, sign out, version) - Move logout from issue list AppBar to Settings screen Signed-off-by: Don Kendall <kendall@donkendall.com> Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Signed-off-by: Don Kendall <kendall@donkendall.com>
- Add Channel model (channels + direct messages) - Add chat provider (channels list, message fetch) - Add channel list screen with DM name resolution - Add message thread screen with real-time 10s polling - Add send message support (TxCreateDoc for ChatMessage) - Add buildCreateChatMessageTx to transaction builder - Add Chat tab to bottom navigation bar Signed-off-by: Don Kendall <kendall@donkendall.com> Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Signed-off-by: Don Kendall <kendall@donkendall.com>
- Add lifecycle-aware polling to channel list (30s, pauses when backgrounded) - Add lifecycle-aware polling to message thread (10s, pauses when backgrounded) - Add lifecycle-aware polling to issue list (45s, existing — no change) - All polling pauses on AppLifecycleState.paused, resumes + immediate refresh on AppLifecycleState.resumed Signed-off-by: Don Kendall <kendall@donkendall.com> Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Signed-off-by: Don Kendall <kendall@donkendall.com>
DRY: - Extract MessageBubble widget (was duplicated in activity feed + chat) - Extract stripHtml() and formatTimestamp() to core/utils/html.dart - Remove duplicated _formatTime methods Fixes: - Pass channel name via query params when navigating to message thread - Remove redundant server-side sort in chat provider (client sort is sufficient) Signed-off-by: Don Kendall <kendall@donkendall.com> Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Signed-off-by: Don Kendall <kendall@donkendall.com>
- Convert IssueDetailScreen to stateful for text input - Add comment input bar at bottom of issue detail (same pattern as chat) - Post comments via buildCreateChatMessageTx - Auto-refresh activity feed after posting Signed-off-by: Don Kendall <kendall@donkendall.com> Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Signed-off-by: Don Kendall <kendall@donkendall.com>
- Add image_picker dependency for gallery/camera access - Add Attachment model (attachment:class:Attachment) - Add uploadBlob() to REST client (PUT /api/v1/blob) - Add buildCreateAttachmentTx() to transaction builder - Add attachmentsProvider to fetch attachments per document - Add attachments section to issue detail with upload button - Display attachment list with file icon, name, and size Signed-off-by: Don Kendall <kendall@donkendall.com> Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Signed-off-by: Don Kendall <kendall@donkendall.com>
- Add local_auth dependency for biometric authentication - Add biometric toggle to Settings screen - Add lock screen with auto-prompt on app restore - Add AuthStatus.locked state with router redirect - Store biometric preference in secure storage - Auto-unlock prompt on lock screen load - Sign out option from lock screen Signed-off-by: Don Kendall <kendall@donkendall.com> Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Signed-off-by: Don Kendall <kendall@donkendall.com>
- Add HulyWebSocketClient implementing Huly protocol: - HelloRequest/HelloResponse handshake - Ping/pong keep-alive (10s interval) - JSON text mode (no compression for simplicity) - Tx event streaming via broadcast StreamController - Auto-reconnect with exponential backoff - Add realtime_provider with dataVersionProvider - Increments on any Tx event, triggering provider rebuilds - Wire WebSocket listener into _MainShell - Update issuesProvider and channelProviders to watch dataVersionProvider for instant refresh on real-time events - Keep polling as fallback for WebSocket connection gaps Signed-off-by: Don Kendall <kendall@donkendall.com> Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Signed-off-by: Don Kendall <kendall@donkendall.com>
- Add firebase_core, firebase_messaging, flutter_local_notifications deps
- Add PushNotificationService:
- Request notification permission
- Get FCM token and handle refresh
- Display foreground notifications via flutter_local_notifications
- Register FCM token as PushSubscription doc in workspace
(FCM endpoints are valid Web Push endpoints — works with existing
Huly notification service without server changes)
- Background message handler
- Initialize Firebase in main.dart (graceful fallback if not configured)
- Register push subscription on workspace connection
- Add pushServiceProvider to realtime_provider
Note: Requires GoogleService-Info.plist (iOS) or google-services.json
(Android) to be added for Firebase to work. Without these files,
push is silently disabled and the app works normally.
Signed-off-by: Don Kendall <kendall@donkendall.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Signed-off-by: Don Kendall <kendall@donkendall.com>
- Test job: flutter analyze + flutter test on every push/PR to mobile/ - iOS build job: build IPA, upload to TestFlight (on tags or manual trigger) - Android build job: build AAB artifact (on tags or manual trigger) - Manual workflow_dispatch with upload_testflight toggle Required repo secrets for iOS signing + TestFlight: IOS_P12_BASE64, IOS_P12_PASSWORD, IOS_PROVISION_PROFILE_BASE64, IOS_KEYCHAIN_PASSWORD, ASC_KEY_ID, ASC_ISSUER_ID, ASC_API_KEY_BASE64 Signed-off-by: Don Kendall <kendall@donkendall.com> Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Signed-off-by: Don Kendall <kendall@donkendall.com>
- Remove ShareHandler.getPendingShare() from main() — platform channel not registered, causes MissingPluginException crash - Remove Firebase init from main() — hangs without GoogleService-Info.plist - Both will be initialized lazily after auth is complete - Update generated plugin registrants for new dependencies Signed-off-by: Don Kendall <kendall@donkendall.com> Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Signed-off-by: Don Kendall <kendall@donkendall.com>
- Fix catchError return type in realtime_provider.dart and websocket_client.dart (catchError handler must return Future's type) - Remove unused issue_status.dart import from edit_issue_screen.dart Signed-off-by: Don Kendall <kendall@donkendall.com> Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Signed-off-by: Don Kendall <kendall@donkendall.com>
7084b9b to
5b9926b
Compare
- Add unit and widget tests for Issues and Chat features - Refactor EditIssueScreen to use shared HTML utilities - Update root .gitignore to correctly track mobile/lib - Enhance README.md with technical and architectural details
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Flutter mobile app for self-hosted Huly — complete implementation across 11 commits.
Commits
Features
Auth & Security
Issue Tracking
Chunter Chat
Real-Time
Navigation & UX
Architecture
Testing