8.2 KiB
8.2 KiB
ActivityPub UI Implementation
Overview
Complete UI implementation for ActivityPub features in Solian client, including search, following, and followers screens.
Created Files
1. Widgets (lib/widgets/activitypub/)
activitypub.dart
- Purpose: Export file for ActivityPub widgets
- Exports:
ActivityPubUserListItem
user_list_item.dart
- Purpose: Reusable list item widget for displaying ActivityPub users
- Features:
- Avatar with remote instance indicator (public icon)
- Display name with instance badge (e.g., "mastodon.social")
- Bio with truncation (max 2 lines)
- Followed at timestamp (relative time)
- Follow/Unfollow buttons with loading states
- Tap callback for navigation to profile
2. Screens (lib/screens/activitypub/)
activitypub.dart
- Purpose: Export file for ActivityPub screens
- Exports:
ActivityPubSearchScreen,ActivityPubListScreen
search.dart
- Purpose: Search and follow ActivityPub users from other instances
- Features:
- Search bar with 500ms debounce
- Real-time search results
- Instant follow/unfollow actions
- Local tracking of followed users
- Empty states for no search and no results
- Refresh support via pull-to-refresh
- User feedback via snack bars
- User Flow:
- User enters search query (e.g.,
@alice@mastodon.social) - Results appear after debounce
- User taps "Follow" → Follow request sent
- Success message shown
- Button updates to "Unfollow"
- User enters search query (e.g.,
list.dart
- Purpose: Display following/followers lists
- Features:
- Reusable for both Following and Followers
- Local state management
- Per-user loading states during actions
- Empty states with helpful hints
- Refresh support
- Auto-update lists when actions occur
- Types:
ActivityPubListType.following: Shows users you followActivityPubListType.followers: Shows users who follow you
- User Flow:
- User opens Following/Followers screen
- List loads from API
- User can unfollow (Following tab) or follow (Followers tab)
- List updates automatically
- Success/error messages shown
Design Patterns
Follows Project Conventions
- Material 3 Design: All widgets use Material 3 components
- Styled Widget Package: Used for
.padding(),.textColor(), etc. - Riverpod State Management: Hooks for local state, providers for global state
- Error Handling:
showErrorAlert()fromalert.dartfor user feedback - Success Feedback:
showSnackBar()for quick notifications - Localization: All strings use
.tr()with placeholder args
Color Scheme & Theming
- Remote Badge: Uses
Theme.colorScheme.primaryfor indicator - Instance Tag: Uses
Theme.colorScheme.secondaryContainer - Text Colors: Adaptive based on theme (dark/light)
- States: Loading indicators with standard
CircularProgressIndicator
Spacing & Layout
- List Item Padding:
EdgeInsets.only(left: 16, right: 12) - Avatar Size: 24px radius (48px diameter)
- Badge Size: Small (10px font) with 6px horizontal padding
- Button Size: Minimum 88px width, 36px height
Translations Added
New Keys in assets/i18n/en-US.json
{
"searchFediverse": "Search Fediverse",
"searchFediverseHint": "Search by address, e.g. {}",
"searchFediverseEmpty": "Search for users on other ActivityPub instances",
"searchFediverseNoResults": "No users found for this search",
"following": "Following",
"followers": "Followers",
"follow": "Follow",
"unfollow": "Unfollow",
"followedUser": "Followed @{}",
"unfollowedUser": "Unfollowed @{}",
"followingEmpty": "You're not following anyone yet",
"followersEmpty": "No followers yet",
"followingEmptyHint": "Start by searching for users or explore other instances"
}
Usage Examples
Using Search Screen
import 'package:go_router/go_router.dart';
import 'package:island/screens/activitypub/activitypub.dart';
// In navigation or route
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const ActivityPubSearchScreen(),
),
);
// Or using go_router
context.push('/activitypub/search');
Using List Screen
// Following
ActivityPubListScreen(
type: ActivityPubListType.following,
);
// Followers
ActivityPubListScreen(
type: ActivityPubListType.followers,
);
Using User List Item Widget
ActivityPubUserListItem(
user: user,
isFollowing: isFollowing,
isLoading: isLoading,
onFollow: () => handleFollow(user),
onUnfollow: () => handleUnfollow(user),
onTap: () => navigateToProfile(user),
);
Integration Points
Navigation Integration
To add ActivityPub screens to navigation:
- Option A: Add to existing tab/navigation structure
- Option B: Add as standalone routes in
go_router - Option C: Add to profile menu overflow menu
Service Integration
All screens use activityPubServiceProvider:
import 'package:island/services/activitypub_service.dart';
final service = ref.read(activityPubServiceProvider);
Error Handling
All errors are caught and displayed using:
try {
// API call
} catch (err) {
showErrorAlert(err);
}
Testing Checklist
- Search for existing Mastodon user
- Search for Pleroma user
- Follow a user
- Unfollow a user
- View following list
- View followers list
- Test empty states
- Test loading states
- Test error handling
- Test dark mode
- Test RTL languages (if supported)
Technical Details
Dependencies
Already in project:
- ✅
cached_network_image- For avatar images - ✅
easy_localization- For translations - ✅
hooks_riverpod- For state management - ✅
flutter_hooks- For hooks (useState, useEffect, etc.) - ✅
material_symbols_icons- For icons - ✅
relative_time- For timestamp formatting - ✅
island/services/activitypub_service.dart- API service (created earlier) - ✅
island/widgets/alert.dart- Error/success dialogs - ✅
island/models/activitypub.dart- Data models (created earlier)
Performance Considerations
- Debounced Search: 500ms delay prevents excessive API calls
- Local State Tracking:
followingUrisSet prevents duplicate API calls - Conditional Rebuilds: Widget only rebuilds when necessary
- Image Caching: Uses
CachedNetworkImageProviderfor avatars
Accessibility
- Semantic Labels: All ListTile widgets have proper content
- Touch Targets: Minimum 44px touch targets for buttons
- Color Contrast: Follows Material 3 color guidelines
- Loading Indicators: Visual feedback during async operations
Future Enhancements
Potential Additions
- Profile Integration: Show ActivityPub profile details
- Post Timeline: Show federated posts from followed users
- Instance Blocking: Block entire ActivityPub instances
- Advanced Search: Filter by instance, user type, etc.
- Batch Actions: Follow/unfollow multiple users at once
- Suggested Users: Show recommended users to follow
- Recent Activity: Show recent interactions
- Notifications: Follow/unfollow notifications
Localization
Need to add same keys to other language files:
es-ES.jsonja-JP.jsonko-KR.json- etc.
Browser Testing
Test with real ActivityPub instances:
- mastodon.social
- pixelfed.social
- lemmy.world
- pleroma.site
- fosstodon.org
Troubleshooting
Common Issues
-
Search returns no results
- Check if user exists on remote instance
- Verify instance is accessible
- Try full URL instead of handle
-
Follow button not working
- Check if user is already following
- Verify server is online
- Check API logs
-
Avatar not loading
- Check remote avatar URL
- Verify network connection
- Check image cache
Summary
✅ Fully functional ActivityPub UI with:
- Search screen for discovering fediverse users
- Following/Followers list screens
- Reusable user list item component
- Proper error handling and user feedback
- Material 3 design
- Responsive layout
- Local state management
- Debounced search
- Empty states and loading indicators
Ready for integration into main app navigation! 🎉