Skip to content

Commit f0ce116

Browse files
committed
feat(account): add source to follow page
- Implemented source selection - Added follow/unfollow logic - Displays available sources
1 parent c265e7f commit f0ce116

File tree

1 file changed

+95
-0
lines changed

1 file changed

+95
-0
lines changed
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
import 'package:flutter/material.dart';
2+
import 'package:flutter_bloc/flutter_bloc.dart';
3+
import 'package:ht_main/account/bloc/account_bloc.dart';
4+
import 'package:ht_main/headlines-feed/bloc/sources_filter_bloc.dart';
5+
import 'package:ht_main/l10n/l10n.dart';
6+
import 'package:ht_main/shared/constants/app_spacing.dart';
7+
import 'package:ht_main/shared/widgets/widgets.dart';
8+
import 'package:ht_shared/ht_shared.dart';
9+
import 'package:ht_data_repository/ht_data_repository.dart';
10+
11+
/// {@template add_source_to_follow_page}
12+
/// A page that allows users to browse and select sources to follow.
13+
/// {@endtemplate}
14+
class AddSourceToFollowPage extends StatelessWidget {
15+
/// {@macro add_source_to_follow_page}
16+
const AddSourceToFollowPage({super.key});
17+
18+
@override
19+
Widget build(BuildContext context) {
20+
final l10n = context.l10n;
21+
return BlocProvider(
22+
create: (context) => SourcesFilterBloc(
23+
sourcesRepository: context.read<HtDataRepository<Source>>(),
24+
countriesRepository: context.read<HtDataRepository<Country>>(),
25+
)..add(const LoadSourceFilterData()), // Use correct event
26+
child: Scaffold(
27+
appBar: AppBar(
28+
title: Text(l10n.addSourcesPageTitle),
29+
),
30+
body: BlocBuilder<SourcesFilterBloc, SourcesFilterState>(
31+
builder: (context, sourcesState) {
32+
if (sourcesState.dataLoadingStatus == SourceFilterDataLoadingStatus.loading || sourcesState.dataLoadingStatus == SourceFilterDataLoadingStatus.initial) {
33+
return const Center(child: CircularProgressIndicator());
34+
}
35+
if (sourcesState.dataLoadingStatus == SourceFilterDataLoadingStatus.failure) {
36+
return FailureStateWidget(
37+
message: sourcesState.errorMessage ?? l10n.sourceFilterError,
38+
onRetry: () => context
39+
.read<SourcesFilterBloc>()
40+
.add(const LoadSourceFilterData()), // Use correct event
41+
);
42+
}
43+
// Use allAvailableSources to display all sources for selection
44+
if (sourcesState.allAvailableSources.isEmpty) {
45+
return FailureStateWidget(
46+
message: l10n.sourceFilterEmptyHeadline, // Re-use
47+
);
48+
}
49+
50+
return BlocBuilder<AccountBloc, AccountState>(
51+
builder: (context, accountState) {
52+
final followedSources =
53+
accountState.preferences?.followedSources ?? [];
54+
55+
return ListView.builder(
56+
padding: const EdgeInsets.all(AppSpacing.md),
57+
itemCount: sourcesState.allAvailableSources.length, // Use allAvailableSources
58+
itemBuilder: (context, index) {
59+
final source = sourcesState.allAvailableSources[index]; // Use allAvailableSources
60+
final isFollowed =
61+
followedSources.any((fs) => fs.id == source.id);
62+
63+
return Card(
64+
margin: const EdgeInsets.only(bottom: AppSpacing.sm),
65+
child: ListTile(
66+
// Consider adding source.iconUrl if available
67+
title: Text(source.name),
68+
trailing: IconButton(
69+
icon: isFollowed
70+
? Icon(
71+
Icons.check_circle,
72+
color: Theme.of(context).colorScheme.primary,
73+
)
74+
: const Icon(Icons.add_circle_outline),
75+
tooltip: isFollowed
76+
? l10n.unfollowSourceTooltip(source.name)
77+
: l10n.followSourceTooltip(source.name), // New
78+
onPressed: () {
79+
context.read<AccountBloc>().add(
80+
AccountFollowSourceToggled(source: source),
81+
);
82+
},
83+
),
84+
),
85+
);
86+
},
87+
);
88+
},
89+
);
90+
},
91+
),
92+
),
93+
);
94+
}
95+
}

0 commit comments

Comments
 (0)