commits
Add create post functionality with community picker:
Features:
- Community models for API responses
- listCommunities and createPost API endpoints
- Community picker screen with search and pagination
- Create post screen with URL validation and input limits
- Optimistic post navigation support
Tests:
- 76 tests covering models, API, and widget behavior
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Comprehensive test coverage for community features:
Unit tests:
- CommunitiesResponse, CommunityView JSON parsing
- CreatePostResponse, ExternalEmbedInput serialization
- SelfLabels, SelfLabel const construction and serialization
- CovesApiService.listCommunities with pagination/errors
- CovesApiService.createPost with validation/errors
Widget tests:
- CreatePostScreen UI elements and form validation
- Character limits enforcement (title: 300, content: 10000)
- NSFW toggle, URL field show/hide behavior
Logic tests:
- Community search filtering (name, displayName, description)
- Member count formatting (K/M suffixes)
- Description line building with separators
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Add isOptimistic flag to PostDetailScreen to skip initial comment
loading for newly created posts that haven't been indexed yet.
Also adds AlwaysScrollableScrollPhysics for consistent pull-to-refresh.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Create post screen improvements:
- Community picker integration
- URL validation (http/https only)
- Input length limits from backend lexicon (title: 300, content: 10000)
- NSFW toggle with self-labels
- Language selection dropdown
- Navigate to feed after successful post creation
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Full-screen community selection interface for post creation:
- Search with debounced client-side filtering
- Infinite scroll pagination
- Cached avatar images with error fallback
- Proper authenticated API service with disposal
- Member/subscriber count formatting (K/M suffixes)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Add CovesApiService methods for community operations:
- listCommunities(): Fetch communities with pagination and sorting
- createPost(): Create posts with title, content, embeds, and labels
Both methods include proper error handling and debug logging.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Add data models for community-related API operations:
- CommunitiesResponse and CommunityView for listing communities
- CommunityViewerState for subscription/membership status
- CreatePostRequest and CreatePostResponse for post creation
- ExternalEmbedInput for link embeds
- SelfLabels and SelfLabel for content labels (NSFW, etc.)
All models support const constructors for better performance.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Add per-post CommentsProvider caching with LRU eviction for instant
back-navigation, scroll position restoration, and draft text preservation.
Updates feed tests to reflect the new feed type tab behavior:
- Default feed is now Discover (not timeline)
- Authenticated users see both Discover and For You tabs
- Unauthenticated users see only Discover tab
- Updated test descriptions for clarity
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Updates tests to work with the new CommentsProvider constructor that
requires postUri and postCid parameters.
Changes:
- CommentsProvider tests: pass postUri/postCid in constructor, remove
parameters from loadComments calls
- Add MockCommentsProvider helper for widget tests
- Update FocusedThreadScreen tests to provide commentsProvider parameter
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Updates PostDetailScreen, ReplyScreen, and FocusedThreadScreen to use
the new CommentsProviderCache for instant back-navigation and state preservation.
PostDetailScreen:
- Acquires provider from cache with reference counting
- Restores scroll position when returning to cached comments
- Background refresh if data is stale (>5 min)
- Handles sign-out by navigating back to feed
ReplyScreen:
- Requires CommentsProvider parameter for draft access
- Saves draft text on cancel, restores on reopen
- Per-parent-URI drafts (separate drafts for different reply contexts)
- Auto-closes on sign-out
FocusedThreadScreen:
- Passes CommentsProvider to children for consistent draft/vote state
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Introduces a caching layer for CommentsProvider instances to enable instant
back-navigation when returning to previously viewed posts.
Key changes:
- Add CommentsProviderCache with LRU eviction (15 posts max)
- Refactor CommentsProvider to be immutable per post (postUri/postCid in constructor)
- Add reference counting to prevent evicting in-use providers
- Add scroll position and draft text preservation to CommentsProvider
- Add staleness tracking for background refresh of cached data
- Wire up cache in main.dart with sign-out cleanup
The cache automatically disposes providers when evicted and clears all
providers on sign-out for privacy.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
New features:
- FocusedThreadScreen for viewing deep comment threads
- "Read X more replies" link at maxDepth navigates to focused view
- Ancestors shown flat above anchor, replies threaded below
- Auto-scroll to anchor comment on open
Performance & code quality:
- Fix O(n²) descendant counting - only compute when needed at maxDepth
- Extract threading colors to shared kThreadingColors constant
- Remove unused Consumer<VoteProvider> wrapper
- Extract StatusBarOverlay reusable widget
Tests:
- Add unit tests for countDescendants
- Add widget tests for CommentThread max-depth behavior
- Add widget tests for FocusedThreadScreen rendering
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add support for --dart-define=ENV=dev as a convenience shorthand
alongside the existing ENVIRONMENT override. Maps 'dev'/'local' to
local environment and 'prod'/'production' to production.
Also remove macos Flutter config files from tracking (already in gitignore).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Animation improvements:
- Increase collapse duration to 350ms expand / 280ms collapse
- Add combined fade + size + slide transitions
- Content slides down from parent on expand, up on collapse
- Add ClipRect to prevent overflow on nested threads
- Badge now uses scale + opacity animation with easeOutBack bounce
Compact collapsed state:
- Hide comment content when collapsed (only show avatar + username)
- Move "+X hidden" badge to right side, simplified to "+X"
- Reduce padding in collapsed state
PR review fixes:
- Return unmodifiable Set from collapsedComments getter
- Add accessibility Semantics with collapse/expand hints
- Add 6 unit tests for collapse state management
Also includes dart format fixes across touched files.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add Podfile.lock for reproducible CocoaPods builds
- Update Xcode project and workspace settings
- Update AppFrameworkInfo.plist
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add Podfile for iOS native dependencies
- Update xcconfig files to include CocoaPods integration
- Ignore macOS directory (not targeting this platform)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add collapsed comment tracking to CommentsProvider with toggleCollapsed()
- Add long-press gesture on CommentCard with haptic feedback
- Show "+N hidden" badge when thread is collapsed (depth-aware positioning)
- Animate collapse/expand with AnimatedSwitcher + SizeTransition (200ms)
- Only build replies widget when not collapsed (optimization)
- Wire up collapse state in PostDetailScreen
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add FeedType enum (discover/forYou) with feed switching in FeedProvider
- Replace AppBar with transparent gradient header overlay
- Add Discover/For You tabs with underline indicator (auth-gated)
- Rename Search tab to Communities with Workspaces icon
- Use IndexedStack to preserve screen state on tab switch
- Add accessibility labels and extract magic numbers to constants
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Comment creation feature with backend integration:
- CommentService for API calls
- Shared auth interceptor (401 retry)
- Input validation (10k chars, emoji-aware)
- Tap-to-reply UI for nested comments
- 22 new tests
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
CommentService tests (10 tests):
- Successful comment creation
- Auth failure when no session
- Network error handling
- 401 response handling
- Invalid responses (null data, missing uri, empty uri)
- Server error handling
- Nested reply request format
CommentsProvider.createComment tests (12 tests):
- Validation: empty content, whitespace-only, exceeds limit
- Emoji counting with grapheme clusters
- Error states: no post loaded, no CommentService
- Top-level comment (reply to post)
- Nested comment (reply to comment)
- Content trimming
- Refresh after success
- Exception propagation
- Boundary testing at max length
All 52 tests pass.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Pass postCid to loadComments for reply reference support
- Add onReplyTap callback to CommentThread and CommentCard
- Tapping reply icon on a comment navigates to ReplyScreen
- ReplyScreen receives parent comment for nested replies
- Show "Replying to @handle" context in reply screen
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add CommentService dependency to CommentsProvider
- Add createComment() method supporting both post and comment replies
- Store postCid alongside postUri for proper reply references
- Add input validation: 10k char limit using grapheme clusters
- Proper emoji counting (🎉 = 1 char, not 2)
- Wire up CommentService in main.dart
Reply reference logic:
- Reply to post: root=post, parent=post
- Reply to comment: root=post, parent=comment
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Create auth_interceptor.dart with reusable createAuthInterceptor()
- Handles 401 responses by refreshing token and retrying once
- Sign out user if refresh fails to prevent infinite loops
- Refactor VoteService to use shared interceptor
- CommentService already uses it (from previous commit)
Eliminates ~130 lines of duplicated interceptor code.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add CommentService with createComment() method that calls backend API
- Backend handles PDS writes via OAuth/DPoP (sealed token architecture)
- Add ValidationException to api_exceptions for client-side validation
- Add characters package for proper Unicode grapheme cluster counting
The comment creation flow:
Mobile → Coves Backend (sealed token) → User's PDS (DPoP)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Update mock providers to remove VoteService dependency
- Add ViewerState to test fixtures for feed and comments
- Update FeedProvider tests for vote state initialization
- Update CommentsProvider tests for recursive vote state init
- Update VoteProvider tests for extractRkeyFromUri utility
- Remove obsolete vote service test methods (deleteVote, getUserVotes)
- Add generated mock files for auth service tests
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
main.dart:
- Remove voteService parameter from FeedProvider and CommentsProvider
CommentsProvider:
- Remove VoteService dependency - vote state from response viewer data
- Add _initializeCommentVoteState helper for recursive vote initialization
- On refresh: initialize all comments (server data is truth)
- On pagination: only initialize new comments (preserve optimistic state)
This completes the migration from VoteService.getUserVotes() to using
viewer state from API responses for both feed posts and comments.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Remove VoteService dependency - vote state comes from feed response
- Replace getUserVotes + loadInitialVotes with per-post setInitialVoteState
- Use viewer.vote and viewer.voteUri from backend response
- Call setInitialVoteState for ALL posts to handle cross-device vote removal
This fixes the bug where votes would disappear on feed refresh:
1. Backend now populates viewer state from PDS cache
2. Feed provider initializes VoteProvider state from viewer data
3. Score adjustments are cleared to prevent double-counting
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Vote Service:
- Remove deleteVote method - backend handles toggle logic
- Remove getUserVotes - vote state now comes from feed viewer data
- Remove unused ExistingVote and VoteInfo classes
- Handle empty uri/cid response as successful toggle-off
- Use shared extractRkeyFromUri utility
Vote Provider:
- Remove existingVoteRkey/Direction params from createVote call
- Remove loadInitialVotes - replaced by setInitialVoteState per-post
- Add extractRkeyFromUri static utility to VoteState
- Clear score adjustments in setInitialVoteState to prevent double-counting
This aligns with the backend's vote cache approach where viewer state
is populated from PDS on each request rather than relying on the
eventually-consistent AppView index.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Add ViewerState class to represent the viewer's relationship with posts:
- vote: direction ("up", "down", or null)
- voteUri: AT-URI of the vote record
- saved: bookmark status
- tags: user-applied tags
This enables the feed to include viewer-specific state from the backend,
allowing proper initialization of vote UI state on feed refresh.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Major OAuth architecture rework - delegate complexity to backend.
Key changes:
- Add CovesSession model for simplified sealed tokens
- Add CovesAuthService for backend-delegated OAuth
- Update OAuth config for private-use URI scheme (RFC 8252)
- Add automatic token refresh on 401 responses
- Remove atproto_oauth_flutter package (~14K lines)
The backend now handles all OAuth complexity (DPoP, PKCE, token exchange)
and returns opaque sealed tokens that the client simply stores and sends.
- Remove unused imports in test files
- Add assertion on unused variable in singleton test
- Clean up redaction test file (remove unused mocks)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Auto-format all Dart files per CODE_QUALITY_GUIDE.md standards.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Update feed_screen_test.dart for the new OAuth patterns.
iOS changes:
- Add Runner.entitlements for associated domains
- Enable Universal Links (applinks:coves.social)
- Reference entitlements in Xcode project
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Remove the client-side OAuth implementation now that auth is delegated
to the Coves backend. This eliminates ~14,000 lines of complex OAuth
code that handled:
Removed oauth_service.dart:
- Complex OAuthSession management
- Client-side token refresh
- DPoP key generation and proof signing
- PKCE code verifier/challenge generation
Removed atproto_oauth_flutter package:
- DPoP implementation (fetch_dpop.dart)
- Identity resolution (did/handle resolvers)
- OAuth server discovery and metadata
- Token exchange and refresh logic
- Cryptographic key management
- Session state persistence
The backend now handles all of this complexity, returning opaque
sealed tokens that the client simply stores and sends.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Wire up VoteService with the new session getter and auth callbacks
for the backend-delegated OAuth architecture.
Key changes:
- VoteService now uses sessionGetter instead of direct OAuthSession
- Add tokenRefresher callback for automatic 401 recovery
- Add signOutHandler callback for failed refresh cleanup
- Remove OAuthService initialization (deleted)
The new flow ensures votes go through the Coves backend which
has the DPoP keys needed to write to user PDSs.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Update FeedProvider and CommentsProvider to work with the simplified
session model and backend-proxied auth flow.
Key changes:
- Use VoteService callback pattern instead of OAuthSession
- Remove direct PDS URL handling
- Simplify test mocks to match new API
Provider updates:
- FeedProvider: Use token getter instead of session getter
- CommentsProvider: Same simplification
Test updates:
- Update mocks to use CovesSession instead of OAuthSession
- Remove PDS URL getter mocks
- Simplify vote service setup in tests
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Update CovesApiService and VoteService with automatic 401 handling
and token refresh. With sealed tokens, the backend must proxy all
authenticated requests to user PDSs.
CovesApiService changes:
- Add tokenGetter, tokenRefresher, signOutHandler callbacks
- Dio interceptor for fresh token on each request
- Automatic retry on 401 with token refresh
- Prevent infinite loops with retried flag
- Sign out user if refresh fails
VoteService changes:
- Switch from direct PDS writes to backend-proxied votes
- Backend unseals token and uses stored DPoP keys
- Same 401 retry pattern as CovesApiService
- Remove OAuthSession dependency (was for DPoP)
New tests:
- Token refresh on 401 scenarios
- Retry prevention for refresh endpoint
- Sign out on failed refresh
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Simplify AuthProvider by delegating OAuth operations to the new
CovesAuthService. The provider now focuses on state management while
the service handles authentication logic.
Key changes:
- Use CovesSession instead of OAuthSession
- Simplified token access (sealed tokens are opaque)
- Dependency injection support for testing
- Token refresh delegated to CovesAuthService
Removed:
- Complex session getter with DPoP key management
- Direct PDS URL handling (backend proxies requests)
- Manual OAuth state machine management
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Switch from development callback URL to proper atproto-compliant
private-use URI scheme (RFC 8252):
- Scheme: social.coves:/callback (single slash per spec)
- Works on both Android and iOS without Universal Links complexity
Platform changes:
- Android: Update CallbackActivity intent filter scheme
- iOS: Update CFBundleURLSchemes in Info.plist
- Remove taskAffinity from MainActivity (not needed)
Dependencies:
- Add flutter_web_auth_2 for browser-based OAuth
- Remove atproto_oauth_flutter path dependency (to be deleted)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
New authentication service that delegates OAuth complexity to the Coves
backend. Instead of managing DPoP keys, PKCE, and token exchange client-side,
the backend handles everything and returns sealed tokens.
Key features:
- Browser-based OAuth via flutter_web_auth_2
- Secure token storage per environment (prevents cross-env token reuse)
- Mutex pattern for concurrent token refresh handling
- Handle/DID validation with Bluesky profile URL extraction
- Singleton pattern with test instance creation
The backend's /oauth/mobile/login endpoint handles:
- Handle → DID resolution
- PDS discovery
- PKCE/DPoP key generation
- Token exchange and sealing (AES-256-GCM)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Simplified session model that works with the Coves backend's sealed token
architecture. The backend handles all OAuth complexity (DPoP, PKCE, token
refresh) and gives us an opaque AES-256-GCM encrypted token.
Key features:
- Parse session from OAuth callback URI (RFC 8252 private-use scheme)
- JSON serialization for secure storage persistence
- Immutable with copyWithToken for refresh operations
- Proper redaction of sensitive data in toString()
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add Android productFlavors (dev: social.coves.dev, prod: social.coves)
- Create iOS flavor xcconfig files for future scheme setup
- Update EnvironmentConfig to support flavor-based environment detection
- Add VSCode launch configurations for easy flavor switching
- Update app icon to lil_dude mascot with proper adaptive icon padding
Dev flavor points to local server, prod flavor points to coves.social.
Both apps can be installed side-by-side on the same device.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Store timeout timer reference and cancel it in finally block to prevent
stale timer from firing after operation completes
- Check if stream controller is closed before adding cancellation event
to prevent "Cannot add event after closing" error
Add author information to reply screen for consistency with detail view:
- Enable showAuthorFooter in PostCard configuration
- Shows author handle and timestamp above post title
- Provides context about who created the original post
- Maintains same enhanced typography as detail view
This ensures users see clear attribution when composing replies,
matching the enhanced information hierarchy of the detail view.
Changes:
- Set showAuthorFooter: true in PostCard configuration
- Matches detail view settings: 20px title, 16px text, 280px embeds
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Enhance post detail screen with better organization and interaction:
Comment Navigation:
- Wire up dual comment button behavior:
- Input field opens reply composer
- Comment count button scrolls to comments section
- Add _scrollToComments() method with smooth animation
- Uses GlobalKey on CommentsHeader for precise scrolling
Visual Improvements:
- Add 1px border divider before comments section
- Replace blank spacing with clear visual separator
- Matches feed/comment divider styling for consistency
- 16px vertical margins for breathing room
Content Organization:
- Enable author footer in detail view (showAuthorFooter: true)
- Shows author info and timestamp above post title
- Enhanced typography: 20px title, 16px text, 1.6 line height
- Larger embeds (280px) for better content visibility
Changes:
- Add _commentsHeaderKey GlobalKey for scroll targeting
- Add _scrollToComments() method with Scrollable.ensureVisible
- Use onCommentInputTap and onCommentCountTap callbacks
- Add Container divider with AppColors.border
- Enable showAuthorFooter parameter
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Improve post card typography and information hierarchy:
Feed View:
- Increase text opacity from 70% to 85% for better readability
- Maintains visual hierarchy while improving scannability
Detail View:
- Add author info above title (avatar + handle + timestamp)
- Show when post was created (e.g., "2h ago")
- Layout: [Avatar] @username • 2h ago
- Provides clear context about post author and recency
Typography Enhancements:
- Add configurable title font size and weight parameters
- Add configurable text font size, line height, and embed height
- Enable full customization for different view contexts
Changes:
- Add showAuthorFooter parameter to PostCard
- Add _buildAuthorFooter() method with avatar, handle, timestamp
- Add _buildAuthorFallbackAvatar() for missing avatars
- Move author info to appear before title in detail views
- Update text opacity: alpha: 0.7 → 0.85 in feed view
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Split comment button functionality into two separate actions:
- Left button (comment input field): Opens reply composer
- Right button (comment count): Scrolls to comments section
This provides contextual behavior - users can either write a new
comment or quickly navigate to view existing comments.
Changes:
- Add onCommentInputTap and onCommentCountTap callbacks
- Maintain backward compatibility with deprecated onCommentTap
- Update documentation to clarify each button's purpose
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
PostCard enhancements:
- Add showBorder prop to control border independently from showHeader
- Fix duplicate border in post detail by passing showBorder: false
Post detail screen integration:
- Connect comment button to new reply screen
- Add authentication check before opening composer
- Implement comment submission handler (TODO: atProto integration)
- Navigate to reply screen with full post context
Fixes duplicate border issue where post detail showed extra divider
between post content and comments when showHeader: false was used.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Implements full-screen comment/reply composition UI with:
- ReplyScreen: Full-screen interface with Thunder-style keyboard handling
- CommentComposer: Reusable inline comment widget
- Post/comment context preview while composing
- Mention and image upload buttons (coming soon)
- Proper keyboard handling and auto-scroll
- Loading states and error handling
Features:
- Natural scrolling without fixed split ratios
- Manual keyboard margin for smooth transitions
- Text selection and copy/paste enabled
- Haptic feedback on submission
- Auto-dismiss banners for coming soon features
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Resolved all 96 flutter analyze issues by applying automated fixes and
manual corrections to meet Flutter/Dart best practices.
Changes:
- Auto-formatted 15 files with dart format
- Applied 82 automated fixes with dart fix --apply
- Fixed BuildContext async gap in post_detail_screen
- Resolved 18 line length violations (80 char limit)
- Escaped HTML angle brackets in doc comments
- Removed unused imports
- Added const constructors where applicable
- Fixed test issues: unawaited futures, cascade invocations, bool params
Result: flutter analyze now reports 0 issues found.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Auto-generated files updated after adding share_plus dependency
and running flutter pub get.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Major redesign of the post detail view with better visual hierarchy,
community branding, and interactive elements. Introduces a new action
bar component for post interactions.
New PostActionBar widget:
- Dedicated action bar for upvote, downvote, share, and comment actions
- Consistent with feed card actions but optimized for detail view
- Haptic feedback on all interactions
- Proper vote state management
Post detail improvements:
- Custom app bar showing community avatar and styled handle
- Better community branding with fallback avatars
- Removed redundant post card display in detail view
- Cleaner layout with post content displayed directly
- Fixed bottom navigation bar spacing issues
- Integrated share functionality with native share sheet
Visual enhancements:
- Styled community handles with color-coded parts (!community@instance)
- Circular community avatars with fallback to first letter
- Improved spacing and padding throughout
- Better error and loading states
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Improve the comments sort UI with intuitive icons and better visual
feedback. Each sort option now has a matching icon for easier recognition.
Changes:
- Added icons for each sort type (🔥 hot, ✨ top, 🆕 new)
- Show checkmark next to currently selected sort option
- Improved popup menu styling with rounded corners
- Better spacing and alignment in sort dropdown
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Add optional parameters to control visibility of header and actions in
PostCard widget. This allows the same component to be reused in different
contexts (feed vs detail view) with appropriate customization.
Changes:
- Added showActions parameter (default: true) to toggle action buttons
- Added showHeader parameter (default: true) to toggle community/author info
- Adjusted margins and padding based on header visibility
- Maintained backward compatibility with default values
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Replace placeholder share button with actual share functionality using
the share_plus package. Users can now share posts with the post title
and URI through their device's native share sheet.
Changes:
- Added haptic feedback on share button tap for better UX
- Share includes post title (or fallback text) and post URI
- Uses native share sheet for platform-appropriate sharing
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Replace hardcoded seedColor with AppColors.primary to ensure Material
widgets and custom components use the same accent color. This creates
a single source of truth for the app's primary color.
Benefits:
- Material widgets (AppBar, Dialogs, etc.) now match custom components
- Changing AppColors.primary updates the entire color scheme
- Eliminates visual inconsistencies between theme and custom colors
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Add create post functionality with community picker:
Features:
- Community models for API responses
- listCommunities and createPost API endpoints
- Community picker screen with search and pagination
- Create post screen with URL validation and input limits
- Optimistic post navigation support
Tests:
- 76 tests covering models, API, and widget behavior
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Comprehensive test coverage for community features:
Unit tests:
- CommunitiesResponse, CommunityView JSON parsing
- CreatePostResponse, ExternalEmbedInput serialization
- SelfLabels, SelfLabel const construction and serialization
- CovesApiService.listCommunities with pagination/errors
- CovesApiService.createPost with validation/errors
Widget tests:
- CreatePostScreen UI elements and form validation
- Character limits enforcement (title: 300, content: 10000)
- NSFW toggle, URL field show/hide behavior
Logic tests:
- Community search filtering (name, displayName, description)
- Member count formatting (K/M suffixes)
- Description line building with separators
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Add isOptimistic flag to PostDetailScreen to skip initial comment
loading for newly created posts that haven't been indexed yet.
Also adds AlwaysScrollableScrollPhysics for consistent pull-to-refresh.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Create post screen improvements:
- Community picker integration
- URL validation (http/https only)
- Input length limits from backend lexicon (title: 300, content: 10000)
- NSFW toggle with self-labels
- Language selection dropdown
- Navigate to feed after successful post creation
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Full-screen community selection interface for post creation:
- Search with debounced client-side filtering
- Infinite scroll pagination
- Cached avatar images with error fallback
- Proper authenticated API service with disposal
- Member/subscriber count formatting (K/M suffixes)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Add CovesApiService methods for community operations:
- listCommunities(): Fetch communities with pagination and sorting
- createPost(): Create posts with title, content, embeds, and labels
Both methods include proper error handling and debug logging.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Add data models for community-related API operations:
- CommunitiesResponse and CommunityView for listing communities
- CommunityViewerState for subscription/membership status
- CreatePostRequest and CreatePostResponse for post creation
- ExternalEmbedInput for link embeds
- SelfLabels and SelfLabel for content labels (NSFW, etc.)
All models support const constructors for better performance.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Updates feed tests to reflect the new feed type tab behavior:
- Default feed is now Discover (not timeline)
- Authenticated users see both Discover and For You tabs
- Unauthenticated users see only Discover tab
- Updated test descriptions for clarity
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Updates tests to work with the new CommentsProvider constructor that
requires postUri and postCid parameters.
Changes:
- CommentsProvider tests: pass postUri/postCid in constructor, remove
parameters from loadComments calls
- Add MockCommentsProvider helper for widget tests
- Update FocusedThreadScreen tests to provide commentsProvider parameter
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Updates PostDetailScreen, ReplyScreen, and FocusedThreadScreen to use
the new CommentsProviderCache for instant back-navigation and state preservation.
PostDetailScreen:
- Acquires provider from cache with reference counting
- Restores scroll position when returning to cached comments
- Background refresh if data is stale (>5 min)
- Handles sign-out by navigating back to feed
ReplyScreen:
- Requires CommentsProvider parameter for draft access
- Saves draft text on cancel, restores on reopen
- Per-parent-URI drafts (separate drafts for different reply contexts)
- Auto-closes on sign-out
FocusedThreadScreen:
- Passes CommentsProvider to children for consistent draft/vote state
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Introduces a caching layer for CommentsProvider instances to enable instant
back-navigation when returning to previously viewed posts.
Key changes:
- Add CommentsProviderCache with LRU eviction (15 posts max)
- Refactor CommentsProvider to be immutable per post (postUri/postCid in constructor)
- Add reference counting to prevent evicting in-use providers
- Add scroll position and draft text preservation to CommentsProvider
- Add staleness tracking for background refresh of cached data
- Wire up cache in main.dart with sign-out cleanup
The cache automatically disposes providers when evicted and clears all
providers on sign-out for privacy.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
New features:
- FocusedThreadScreen for viewing deep comment threads
- "Read X more replies" link at maxDepth navigates to focused view
- Ancestors shown flat above anchor, replies threaded below
- Auto-scroll to anchor comment on open
Performance & code quality:
- Fix O(n²) descendant counting - only compute when needed at maxDepth
- Extract threading colors to shared kThreadingColors constant
- Remove unused Consumer<VoteProvider> wrapper
- Extract StatusBarOverlay reusable widget
Tests:
- Add unit tests for countDescendants
- Add widget tests for CommentThread max-depth behavior
- Add widget tests for FocusedThreadScreen rendering
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add support for --dart-define=ENV=dev as a convenience shorthand
alongside the existing ENVIRONMENT override. Maps 'dev'/'local' to
local environment and 'prod'/'production' to production.
Also remove macos Flutter config files from tracking (already in gitignore).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Animation improvements:
- Increase collapse duration to 350ms expand / 280ms collapse
- Add combined fade + size + slide transitions
- Content slides down from parent on expand, up on collapse
- Add ClipRect to prevent overflow on nested threads
- Badge now uses scale + opacity animation with easeOutBack bounce
Compact collapsed state:
- Hide comment content when collapsed (only show avatar + username)
- Move "+X hidden" badge to right side, simplified to "+X"
- Reduce padding in collapsed state
PR review fixes:
- Return unmodifiable Set from collapsedComments getter
- Add accessibility Semantics with collapse/expand hints
- Add 6 unit tests for collapse state management
Also includes dart format fixes across touched files.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add collapsed comment tracking to CommentsProvider with toggleCollapsed()
- Add long-press gesture on CommentCard with haptic feedback
- Show "+N hidden" badge when thread is collapsed (depth-aware positioning)
- Animate collapse/expand with AnimatedSwitcher + SizeTransition (200ms)
- Only build replies widget when not collapsed (optimization)
- Wire up collapse state in PostDetailScreen
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add FeedType enum (discover/forYou) with feed switching in FeedProvider
- Replace AppBar with transparent gradient header overlay
- Add Discover/For You tabs with underline indicator (auth-gated)
- Rename Search tab to Communities with Workspaces icon
- Use IndexedStack to preserve screen state on tab switch
- Add accessibility labels and extract magic numbers to constants
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Comment creation feature with backend integration:
- CommentService for API calls
- Shared auth interceptor (401 retry)
- Input validation (10k chars, emoji-aware)
- Tap-to-reply UI for nested comments
- 22 new tests
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
CommentService tests (10 tests):
- Successful comment creation
- Auth failure when no session
- Network error handling
- 401 response handling
- Invalid responses (null data, missing uri, empty uri)
- Server error handling
- Nested reply request format
CommentsProvider.createComment tests (12 tests):
- Validation: empty content, whitespace-only, exceeds limit
- Emoji counting with grapheme clusters
- Error states: no post loaded, no CommentService
- Top-level comment (reply to post)
- Nested comment (reply to comment)
- Content trimming
- Refresh after success
- Exception propagation
- Boundary testing at max length
All 52 tests pass.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Pass postCid to loadComments for reply reference support
- Add onReplyTap callback to CommentThread and CommentCard
- Tapping reply icon on a comment navigates to ReplyScreen
- ReplyScreen receives parent comment for nested replies
- Show "Replying to @handle" context in reply screen
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add CommentService dependency to CommentsProvider
- Add createComment() method supporting both post and comment replies
- Store postCid alongside postUri for proper reply references
- Add input validation: 10k char limit using grapheme clusters
- Proper emoji counting (🎉 = 1 char, not 2)
- Wire up CommentService in main.dart
Reply reference logic:
- Reply to post: root=post, parent=post
- Reply to comment: root=post, parent=comment
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Create auth_interceptor.dart with reusable createAuthInterceptor()
- Handles 401 responses by refreshing token and retrying once
- Sign out user if refresh fails to prevent infinite loops
- Refactor VoteService to use shared interceptor
- CommentService already uses it (from previous commit)
Eliminates ~130 lines of duplicated interceptor code.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add CommentService with createComment() method that calls backend API
- Backend handles PDS writes via OAuth/DPoP (sealed token architecture)
- Add ValidationException to api_exceptions for client-side validation
- Add characters package for proper Unicode grapheme cluster counting
The comment creation flow:
Mobile → Coves Backend (sealed token) → User's PDS (DPoP)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Update mock providers to remove VoteService dependency
- Add ViewerState to test fixtures for feed and comments
- Update FeedProvider tests for vote state initialization
- Update CommentsProvider tests for recursive vote state init
- Update VoteProvider tests for extractRkeyFromUri utility
- Remove obsolete vote service test methods (deleteVote, getUserVotes)
- Add generated mock files for auth service tests
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
main.dart:
- Remove voteService parameter from FeedProvider and CommentsProvider
CommentsProvider:
- Remove VoteService dependency - vote state from response viewer data
- Add _initializeCommentVoteState helper for recursive vote initialization
- On refresh: initialize all comments (server data is truth)
- On pagination: only initialize new comments (preserve optimistic state)
This completes the migration from VoteService.getUserVotes() to using
viewer state from API responses for both feed posts and comments.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Remove VoteService dependency - vote state comes from feed response
- Replace getUserVotes + loadInitialVotes with per-post setInitialVoteState
- Use viewer.vote and viewer.voteUri from backend response
- Call setInitialVoteState for ALL posts to handle cross-device vote removal
This fixes the bug where votes would disappear on feed refresh:
1. Backend now populates viewer state from PDS cache
2. Feed provider initializes VoteProvider state from viewer data
3. Score adjustments are cleared to prevent double-counting
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Vote Service:
- Remove deleteVote method - backend handles toggle logic
- Remove getUserVotes - vote state now comes from feed viewer data
- Remove unused ExistingVote and VoteInfo classes
- Handle empty uri/cid response as successful toggle-off
- Use shared extractRkeyFromUri utility
Vote Provider:
- Remove existingVoteRkey/Direction params from createVote call
- Remove loadInitialVotes - replaced by setInitialVoteState per-post
- Add extractRkeyFromUri static utility to VoteState
- Clear score adjustments in setInitialVoteState to prevent double-counting
This aligns with the backend's vote cache approach where viewer state
is populated from PDS on each request rather than relying on the
eventually-consistent AppView index.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Add ViewerState class to represent the viewer's relationship with posts:
- vote: direction ("up", "down", or null)
- voteUri: AT-URI of the vote record
- saved: bookmark status
- tags: user-applied tags
This enables the feed to include viewer-specific state from the backend,
allowing proper initialization of vote UI state on feed refresh.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Major OAuth architecture rework - delegate complexity to backend.
Key changes:
- Add CovesSession model for simplified sealed tokens
- Add CovesAuthService for backend-delegated OAuth
- Update OAuth config for private-use URI scheme (RFC 8252)
- Add automatic token refresh on 401 responses
- Remove atproto_oauth_flutter package (~14K lines)
The backend now handles all OAuth complexity (DPoP, PKCE, token exchange)
and returns opaque sealed tokens that the client simply stores and sends.
Update feed_screen_test.dart for the new OAuth patterns.
iOS changes:
- Add Runner.entitlements for associated domains
- Enable Universal Links (applinks:coves.social)
- Reference entitlements in Xcode project
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Remove the client-side OAuth implementation now that auth is delegated
to the Coves backend. This eliminates ~14,000 lines of complex OAuth
code that handled:
Removed oauth_service.dart:
- Complex OAuthSession management
- Client-side token refresh
- DPoP key generation and proof signing
- PKCE code verifier/challenge generation
Removed atproto_oauth_flutter package:
- DPoP implementation (fetch_dpop.dart)
- Identity resolution (did/handle resolvers)
- OAuth server discovery and metadata
- Token exchange and refresh logic
- Cryptographic key management
- Session state persistence
The backend now handles all of this complexity, returning opaque
sealed tokens that the client simply stores and sends.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Wire up VoteService with the new session getter and auth callbacks
for the backend-delegated OAuth architecture.
Key changes:
- VoteService now uses sessionGetter instead of direct OAuthSession
- Add tokenRefresher callback for automatic 401 recovery
- Add signOutHandler callback for failed refresh cleanup
- Remove OAuthService initialization (deleted)
The new flow ensures votes go through the Coves backend which
has the DPoP keys needed to write to user PDSs.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Update FeedProvider and CommentsProvider to work with the simplified
session model and backend-proxied auth flow.
Key changes:
- Use VoteService callback pattern instead of OAuthSession
- Remove direct PDS URL handling
- Simplify test mocks to match new API
Provider updates:
- FeedProvider: Use token getter instead of session getter
- CommentsProvider: Same simplification
Test updates:
- Update mocks to use CovesSession instead of OAuthSession
- Remove PDS URL getter mocks
- Simplify vote service setup in tests
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Update CovesApiService and VoteService with automatic 401 handling
and token refresh. With sealed tokens, the backend must proxy all
authenticated requests to user PDSs.
CovesApiService changes:
- Add tokenGetter, tokenRefresher, signOutHandler callbacks
- Dio interceptor for fresh token on each request
- Automatic retry on 401 with token refresh
- Prevent infinite loops with retried flag
- Sign out user if refresh fails
VoteService changes:
- Switch from direct PDS writes to backend-proxied votes
- Backend unseals token and uses stored DPoP keys
- Same 401 retry pattern as CovesApiService
- Remove OAuthSession dependency (was for DPoP)
New tests:
- Token refresh on 401 scenarios
- Retry prevention for refresh endpoint
- Sign out on failed refresh
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Simplify AuthProvider by delegating OAuth operations to the new
CovesAuthService. The provider now focuses on state management while
the service handles authentication logic.
Key changes:
- Use CovesSession instead of OAuthSession
- Simplified token access (sealed tokens are opaque)
- Dependency injection support for testing
- Token refresh delegated to CovesAuthService
Removed:
- Complex session getter with DPoP key management
- Direct PDS URL handling (backend proxies requests)
- Manual OAuth state machine management
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Switch from development callback URL to proper atproto-compliant
private-use URI scheme (RFC 8252):
- Scheme: social.coves:/callback (single slash per spec)
- Works on both Android and iOS without Universal Links complexity
Platform changes:
- Android: Update CallbackActivity intent filter scheme
- iOS: Update CFBundleURLSchemes in Info.plist
- Remove taskAffinity from MainActivity (not needed)
Dependencies:
- Add flutter_web_auth_2 for browser-based OAuth
- Remove atproto_oauth_flutter path dependency (to be deleted)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
New authentication service that delegates OAuth complexity to the Coves
backend. Instead of managing DPoP keys, PKCE, and token exchange client-side,
the backend handles everything and returns sealed tokens.
Key features:
- Browser-based OAuth via flutter_web_auth_2
- Secure token storage per environment (prevents cross-env token reuse)
- Mutex pattern for concurrent token refresh handling
- Handle/DID validation with Bluesky profile URL extraction
- Singleton pattern with test instance creation
The backend's /oauth/mobile/login endpoint handles:
- Handle → DID resolution
- PDS discovery
- PKCE/DPoP key generation
- Token exchange and sealing (AES-256-GCM)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Simplified session model that works with the Coves backend's sealed token
architecture. The backend handles all OAuth complexity (DPoP, PKCE, token
refresh) and gives us an opaque AES-256-GCM encrypted token.
Key features:
- Parse session from OAuth callback URI (RFC 8252 private-use scheme)
- JSON serialization for secure storage persistence
- Immutable with copyWithToken for refresh operations
- Proper redaction of sensitive data in toString()
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add Android productFlavors (dev: social.coves.dev, prod: social.coves)
- Create iOS flavor xcconfig files for future scheme setup
- Update EnvironmentConfig to support flavor-based environment detection
- Add VSCode launch configurations for easy flavor switching
- Update app icon to lil_dude mascot with proper adaptive icon padding
Dev flavor points to local server, prod flavor points to coves.social.
Both apps can be installed side-by-side on the same device.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Add author information to reply screen for consistency with detail view:
- Enable showAuthorFooter in PostCard configuration
- Shows author handle and timestamp above post title
- Provides context about who created the original post
- Maintains same enhanced typography as detail view
This ensures users see clear attribution when composing replies,
matching the enhanced information hierarchy of the detail view.
Changes:
- Set showAuthorFooter: true in PostCard configuration
- Matches detail view settings: 20px title, 16px text, 280px embeds
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Enhance post detail screen with better organization and interaction:
Comment Navigation:
- Wire up dual comment button behavior:
- Input field opens reply composer
- Comment count button scrolls to comments section
- Add _scrollToComments() method with smooth animation
- Uses GlobalKey on CommentsHeader for precise scrolling
Visual Improvements:
- Add 1px border divider before comments section
- Replace blank spacing with clear visual separator
- Matches feed/comment divider styling for consistency
- 16px vertical margins for breathing room
Content Organization:
- Enable author footer in detail view (showAuthorFooter: true)
- Shows author info and timestamp above post title
- Enhanced typography: 20px title, 16px text, 1.6 line height
- Larger embeds (280px) for better content visibility
Changes:
- Add _commentsHeaderKey GlobalKey for scroll targeting
- Add _scrollToComments() method with Scrollable.ensureVisible
- Use onCommentInputTap and onCommentCountTap callbacks
- Add Container divider with AppColors.border
- Enable showAuthorFooter parameter
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Improve post card typography and information hierarchy:
Feed View:
- Increase text opacity from 70% to 85% for better readability
- Maintains visual hierarchy while improving scannability
Detail View:
- Add author info above title (avatar + handle + timestamp)
- Show when post was created (e.g., "2h ago")
- Layout: [Avatar] @username • 2h ago
- Provides clear context about post author and recency
Typography Enhancements:
- Add configurable title font size and weight parameters
- Add configurable text font size, line height, and embed height
- Enable full customization for different view contexts
Changes:
- Add showAuthorFooter parameter to PostCard
- Add _buildAuthorFooter() method with avatar, handle, timestamp
- Add _buildAuthorFallbackAvatar() for missing avatars
- Move author info to appear before title in detail views
- Update text opacity: alpha: 0.7 → 0.85 in feed view
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Split comment button functionality into two separate actions:
- Left button (comment input field): Opens reply composer
- Right button (comment count): Scrolls to comments section
This provides contextual behavior - users can either write a new
comment or quickly navigate to view existing comments.
Changes:
- Add onCommentInputTap and onCommentCountTap callbacks
- Maintain backward compatibility with deprecated onCommentTap
- Update documentation to clarify each button's purpose
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
PostCard enhancements:
- Add showBorder prop to control border independently from showHeader
- Fix duplicate border in post detail by passing showBorder: false
Post detail screen integration:
- Connect comment button to new reply screen
- Add authentication check before opening composer
- Implement comment submission handler (TODO: atProto integration)
- Navigate to reply screen with full post context
Fixes duplicate border issue where post detail showed extra divider
between post content and comments when showHeader: false was used.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Implements full-screen comment/reply composition UI with:
- ReplyScreen: Full-screen interface with Thunder-style keyboard handling
- CommentComposer: Reusable inline comment widget
- Post/comment context preview while composing
- Mention and image upload buttons (coming soon)
- Proper keyboard handling and auto-scroll
- Loading states and error handling
Features:
- Natural scrolling without fixed split ratios
- Manual keyboard margin for smooth transitions
- Text selection and copy/paste enabled
- Haptic feedback on submission
- Auto-dismiss banners for coming soon features
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Resolved all 96 flutter analyze issues by applying automated fixes and
manual corrections to meet Flutter/Dart best practices.
Changes:
- Auto-formatted 15 files with dart format
- Applied 82 automated fixes with dart fix --apply
- Fixed BuildContext async gap in post_detail_screen
- Resolved 18 line length violations (80 char limit)
- Escaped HTML angle brackets in doc comments
- Removed unused imports
- Added const constructors where applicable
- Fixed test issues: unawaited futures, cascade invocations, bool params
Result: flutter analyze now reports 0 issues found.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Major redesign of the post detail view with better visual hierarchy,
community branding, and interactive elements. Introduces a new action
bar component for post interactions.
New PostActionBar widget:
- Dedicated action bar for upvote, downvote, share, and comment actions
- Consistent with feed card actions but optimized for detail view
- Haptic feedback on all interactions
- Proper vote state management
Post detail improvements:
- Custom app bar showing community avatar and styled handle
- Better community branding with fallback avatars
- Removed redundant post card display in detail view
- Cleaner layout with post content displayed directly
- Fixed bottom navigation bar spacing issues
- Integrated share functionality with native share sheet
Visual enhancements:
- Styled community handles with color-coded parts (!community@instance)
- Circular community avatars with fallback to first letter
- Improved spacing and padding throughout
- Better error and loading states
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Improve the comments sort UI with intuitive icons and better visual
feedback. Each sort option now has a matching icon for easier recognition.
Changes:
- Added icons for each sort type (🔥 hot, ✨ top, 🆕 new)
- Show checkmark next to currently selected sort option
- Improved popup menu styling with rounded corners
- Better spacing and alignment in sort dropdown
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Add optional parameters to control visibility of header and actions in
PostCard widget. This allows the same component to be reused in different
contexts (feed vs detail view) with appropriate customization.
Changes:
- Added showActions parameter (default: true) to toggle action buttons
- Added showHeader parameter (default: true) to toggle community/author info
- Adjusted margins and padding based on header visibility
- Maintained backward compatibility with default values
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Replace placeholder share button with actual share functionality using
the share_plus package. Users can now share posts with the post title
and URI through their device's native share sheet.
Changes:
- Added haptic feedback on share button tap for better UX
- Share includes post title (or fallback text) and post URI
- Uses native share sheet for platform-appropriate sharing
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Replace hardcoded seedColor with AppColors.primary to ensure Material
widgets and custom components use the same accent color. This creates
a single source of truth for the app's primary color.
Benefits:
- Material widgets (AppBar, Dialogs, etc.) now match custom components
- Changing AppColors.primary updates the entire color scheme
- Eliminates visual inconsistencies between theme and custom colors
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>