Fix compilation errors in followers/following and privacy screens

- Fix FollowersFollowingScreen: correct imports, AppTheme references, SignedMediaImage param
- Fix profile_screen.dart: move _navigateToConnections to _ProfileScreenState, pass callback to _ProfileHeader
- Fix profile_settings_screen.dart: update property names (isPrivate, defaultVisibility)
This commit is contained in:
Patrick Britton 2026-02-04 17:21:08 -06:00
parent adeffe691e
commit 69358b016f
3 changed files with 35 additions and 31 deletions

View file

@ -3,7 +3,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../../theme/app_theme.dart'; import '../../theme/app_theme.dart';
import '../../widgets/app_scaffold.dart'; import '../../widgets/app_scaffold.dart';
import '../../widgets/media/signed_media_image.dart'; import '../../widgets/media/signed_media_image.dart';
import '../../services/api_service.dart'; import '../../providers/api_provider.dart';
import 'viewable_profile_screen.dart'; import 'viewable_profile_screen.dart';
/// Screen to manage followers and following with tabbed interface /// Screen to manage followers and following with tabbed interface
@ -156,17 +156,16 @@ class _FollowersFollowingScreenState
Widget build(BuildContext context) { Widget build(BuildContext context) {
return AppScaffold( return AppScaffold(
title: 'Connections', title: 'Connections',
showBackButton: true,
body: Column( body: Column(
children: [ children: [
// Tab Bar // Tab Bar
Container( Container(
color: AppTheme.surfaceColor, color: AppTheme.cardSurface,
child: TabBar( child: TabBar(
controller: _tabController, controller: _tabController,
indicatorColor: AppTheme.primaryColor, indicatorColor: AppTheme.ksuPurple,
labelColor: AppTheme.textPrimary, labelColor: AppTheme.navyText,
unselectedLabelColor: AppTheme.textSecondary, unselectedLabelColor: AppTheme.navyText.withOpacity(0.5),
tabs: [ tabs: [
Tab(text: 'Followers (${_followers.length})'), Tab(text: 'Followers (${_followers.length})'),
Tab(text: 'Following (${_following.length})'), Tab(text: 'Following (${_following.length})'),
@ -217,7 +216,7 @@ class _FollowersFollowingScreenState
child: Column( child: Column(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
Icon(Icons.error_outline, size: 48, color: AppTheme.textSecondary), Icon(Icons.error_outline, size: 48, color: AppTheme.navyText.withOpacity(0.5)),
const SizedBox(height: 16), const SizedBox(height: 16),
Text('Failed to load', style: AppTheme.bodyLarge), Text('Failed to load', style: AppTheme.bodyLarge),
const SizedBox(height: 8), const SizedBox(height: 8),
@ -238,12 +237,12 @@ class _FollowersFollowingScreenState
Icon( Icon(
isFollowersList ? Icons.people_outline : Icons.person_add_outlined, isFollowersList ? Icons.people_outline : Icons.person_add_outlined,
size: 64, size: 64,
color: AppTheme.textSecondary.withOpacity(0.5), color: AppTheme.navyText.withOpacity(0.3),
), ),
const SizedBox(height: 16), const SizedBox(height: 16),
Text( Text(
isFollowersList ? 'No followers yet' : 'Not following anyone yet', isFollowersList ? 'No followers yet' : 'Not following anyone yet',
style: AppTheme.bodyLarge.copyWith(color: AppTheme.textSecondary), style: AppTheme.bodyLarge.copyWith(color: AppTheme.navyText.withOpacity(0.6)),
), ),
], ],
), ),
@ -343,7 +342,7 @@ class _UserListTile extends StatelessWidget {
case 'bronze': case 'bronze':
return const Color(0xFFCD7F32); return const Color(0xFFCD7F32);
default: default:
return AppTheme.textSecondary; return AppTheme.navyText.withOpacity(0.5);
} }
} }
@ -354,11 +353,11 @@ class _UserListTile extends StatelessWidget {
contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 4), contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 4),
leading: CircleAvatar( leading: CircleAvatar(
radius: 24, radius: 24,
backgroundColor: AppTheme.surfaceColor, backgroundColor: AppTheme.cardSurface,
child: user.avatarUrl != null child: user.avatarUrl != null
? ClipOval( ? ClipOval(
child: SignedMediaImage( child: SignedMediaImage(
imageUrl: user.avatarUrl!, url: user.avatarUrl!,
width: 48, width: 48,
height: 48, height: 48,
fit: BoxFit.cover, fit: BoxFit.cover,
@ -400,14 +399,14 @@ class _UserListTile extends StatelessWidget {
), ),
subtitle: Text( subtitle: Text(
'@${user.handle}', '@${user.handle}',
style: AppTheme.bodySmall.copyWith(color: AppTheme.textSecondary), style: AppTheme.labelSmall.copyWith(color: AppTheme.navyText.withOpacity(0.6)),
), ),
trailing: isFollowersList trailing: isFollowersList
? null // Followers don't have action button for now ? null // Followers don't have action button for now
: TextButton( : TextButton(
onPressed: onAction, onPressed: onAction,
style: TextButton.styleFrom( style: TextButton.styleFrom(
foregroundColor: AppTheme.textSecondary, foregroundColor: AppTheme.navyText.withOpacity(0.7),
padding: const EdgeInsets.symmetric(horizontal: 12), padding: const EdgeInsets.symmetric(horizontal: 12),
), ),
child: const Text('Unfollow'), child: const Text('Unfollow'),

View file

@ -807,6 +807,18 @@ class _ProfileScreenState extends ConsumerState<ProfileScreen>
); );
} }
void _navigateToConnections(int tabIndex) {
if (_profile == null) return;
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => FollowersFollowingScreen(
userId: _profile!.id,
initialTabIndex: tabIndex,
),
),
);
}
Widget _buildSliverAppBar(Profile profile) { Widget _buildSliverAppBar(Profile profile) {
return SliverAppBar( return SliverAppBar(
expandedHeight: 255, expandedHeight: 255,
@ -823,6 +835,7 @@ class _ProfileScreenState extends ConsumerState<ProfileScreen>
onSettingsTap: _openSettings, onSettingsTap: _openSettings,
onPrivacyTap: _openPrivacyMenu, onPrivacyTap: _openPrivacyMenu,
onAvatarTap: _showAvatarActions, onAvatarTap: _showAvatarActions,
onConnectionsTap: _navigateToConnections,
), ),
), ),
); );
@ -951,6 +964,7 @@ class _ProfileHeader extends StatelessWidget {
final VoidCallback onSettingsTap; final VoidCallback onSettingsTap;
final VoidCallback onPrivacyTap; final VoidCallback onPrivacyTap;
final VoidCallback onAvatarTap; final VoidCallback onAvatarTap;
final void Function(int tabIndex) onConnectionsTap;
const _ProfileHeader({ const _ProfileHeader({
required this.profile, required this.profile,
@ -958,6 +972,7 @@ class _ProfileHeader extends StatelessWidget {
required this.onSettingsTap, required this.onSettingsTap,
required this.onPrivacyTap, required this.onPrivacyTap,
required this.onAvatarTap, required this.onAvatarTap,
required this.onConnectionsTap,
}); });
@override @override
@ -1090,13 +1105,13 @@ class _ProfileHeader extends StatelessWidget {
_StatItem( _StatItem(
label: 'Followers', label: 'Followers',
value: stats.followers.toString(), value: stats.followers.toString(),
onTap: () => _navigateToConnections(0), onTap: () => onConnectionsTap(0),
), ),
const SizedBox(width: AppTheme.spacingMd), const SizedBox(width: AppTheme.spacingMd),
_StatItem( _StatItem(
label: 'Following', label: 'Following',
value: stats.following.toString(), value: stats.following.toString(),
onTap: () => _navigateToConnections(1), onTap: () => onConnectionsTap(1),
), ),
], ],
), ),
@ -1104,17 +1119,7 @@ class _ProfileHeader extends StatelessWidget {
); );
} }
void _navigateToConnections(int tabIndex) {
if (_profile == null) return;
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => FollowersFollowingScreen(
userId: _profile!.id,
initialTabIndex: tabIndex,
),
),
);
}
LinearGradient _generateGradient(String seed) { LinearGradient _generateGradient(String seed) {
final hash = seed.hashCode.abs(); final hash = seed.hashCode.abs();

View file

@ -423,8 +423,8 @@ class _ProfileSettingsScreenState extends ConsumerState<ProfileSettingsScreen> {
SwitchListTile( SwitchListTile(
title: const Text('Private Profile'), title: const Text('Private Profile'),
subtitle: const Text('Only followers can see your posts and activity'), subtitle: const Text('Only followers can see your posts and activity'),
value: privacy.isPrivateProfile, value: privacy.isPrivate,
onChanged: (v) => ref.read(settingsProvider.notifier).updatePrivacy(privacy.copyWith(isPrivateProfile: v)), onChanged: (v) => ref.read(settingsProvider.notifier).updatePrivacy(privacy.copyWith(isPrivate: v)),
), ),
const SizedBox(height: 32), const SizedBox(height: 32),
const Text('Default Post Visibility', style: TextStyle(fontWeight: FontWeight.bold)), const Text('Default Post Visibility', style: TextStyle(fontWeight: FontWeight.bold)),
@ -435,8 +435,8 @@ class _ProfileSettingsScreenState extends ConsumerState<ProfileSettingsScreen> {
ButtonSegment(value: 'followers', label: Text('Circle')), ButtonSegment(value: 'followers', label: Text('Circle')),
ButtonSegment(value: 'private', label: Text('Self')), ButtonSegment(value: 'private', label: Text('Self')),
], ],
selected: {privacy.defaultPostVisibility}, selected: {privacy.defaultVisibility},
onSelectionChanged: (set) => ref.read(settingsProvider.notifier).updatePrivacy(privacy.copyWith(defaultPostVisibility: set.first)), onSelectionChanged: (set) => ref.read(settingsProvider.notifier).updatePrivacy(privacy.copyWith(defaultVisibility: set.first)),
), ),
const SizedBox(height: 48), const SizedBox(height: 48),
], ],