home_screen.dart 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. import 'package:flutter/material.dart';
  2. import 'package:flutter_riverpod/flutter_riverpod.dart';
  3. import 'package:veloe_kemono_party_flutter/app_layout.dart';
  4. import 'package:veloe_kemono_party_flutter/main.dart';
  5. import 'package:veloe_kemono_party_flutter/models/creator.dart';
  6. import 'package:veloe_kemono_party_flutter/pages/widgets/creator_card.dart';
  7. class HomeScreen extends ConsumerStatefulWidget {
  8. const HomeScreen({super.key});
  9. @override
  10. ConsumerState<HomeScreen> createState() => _HomeScreenState();
  11. }
  12. class _HomeScreenState extends ConsumerState<HomeScreen> {
  13. final TextEditingController _searchController = TextEditingController();
  14. final _searchQuery = StateProvider<String>((ref) => '');
  15. final filteredCreatorsProvider = FutureProvider.autoDispose.family<List<Creator>, String>(
  16. (ref, query) async {
  17. final originalList = await ref.watch(creatorsProvider.future);
  18. return originalList.where(
  19. (creator) => creator.name.toLowerCase().contains(query.toLowerCase())
  20. ).toList();
  21. },
  22. );
  23. @override
  24. void initState() {
  25. super.initState();
  26. ref.listenManual(sourceChangeProvider, (_, __) {
  27. ref.invalidate(creatorsProvider);
  28. ref.invalidate(_searchQuery);
  29. _searchController.clear();
  30. });
  31. }
  32. @override
  33. Widget build(BuildContext context) {
  34. ref.watch(sourceChangeProvider);
  35. final filteredCreators = ref.watch(filteredCreatorsProvider(ref.watch(_searchQuery)));
  36. return DefaultTabController(
  37. length: 2,
  38. child: Scaffold(
  39. appBar: AppBar(
  40. title: _buildSearchField(ref),
  41. leading: Builder(
  42. builder: (context) => IconButton(
  43. icon: const Icon(Icons.menu),
  44. onPressed: () => AppLayout.openDrawer(context),
  45. ),
  46. ),
  47. actions: [
  48. IconButton(
  49. icon: const Icon(Icons.refresh),
  50. onPressed: () => ref.invalidate(creatorsProvider),
  51. ),
  52. ],
  53. ),
  54. body: _buildCreatorsList(filteredCreators),
  55. ),
  56. );
  57. }
  58. Widget _buildSearchField(WidgetRef ref) {
  59. return TextField(
  60. controller: _searchController,
  61. decoration: InputDecoration(
  62. hintText: 'Search creators...',
  63. border: InputBorder.none,
  64. suffixIcon: IconButton(
  65. icon: const Icon(Icons.clear),
  66. onPressed: () {
  67. _searchController.clear();
  68. ref.read(_searchQuery.notifier).state = '';
  69. },
  70. ),
  71. ),
  72. onChanged: (value) => ref.read(_searchQuery.notifier).state = value,
  73. );
  74. }
  75. Widget _buildCreatorsList(AsyncValue<List<Creator>> creatorsAsync) {
  76. return RefreshIndicator(
  77. onRefresh: () => ref.refresh(filteredCreatorsProvider(ref.read(_searchQuery)).future),
  78. child: creatorsAsync.when(
  79. loading: () => const Center(child: CircularProgressIndicator()),
  80. error: (error, _) => Center(child: Text(error.toString())),
  81. data: (creators) => creators.isEmpty
  82. ? const Center(child: Text('No matching creators found'))
  83. : ListView.separated(
  84. padding: const EdgeInsets.all(16),
  85. itemCount: creators.length,
  86. separatorBuilder: (_, __) => const SizedBox(height: 8),
  87. itemBuilder: (context, index) => CreatorCard(creator: creators[index]),
  88. ),
  89. ),
  90. );
  91. }
  92. /*
  93. Widget _buildGlobalPostsGrid() {
  94. final postsAsync = ref.watch(postsProvider(('82522', 'patreon','')));
  95. return postsAsync.when(
  96. loading: () => const Center(child: CircularProgressIndicator()),
  97. error: (error, _) => Center(child: Text(error.toString())),
  98. data: (posts) => CustomScrollView(
  99. slivers: [
  100. SliverAppBar(),
  101. SliverList(
  102. delegate: SliverChildBuilderDelegate(
  103. (context, index) => PostContainer(post: posts[index]),
  104. childCount: posts.length,
  105. ),
  106. ),
  107. ],
  108. ),
  109. );
  110. }
  111. */
  112. }