import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:logging/logging.dart'; import 'package:scrollable_positioned_list/scrollable_positioned_list.dart'; import '../../globals.dart'; import '../../models/auth/profile.dart'; import '../../models/timeline_identifiers.dart'; import '../../riverpod_controllers/account_services.dart'; import '../../riverpod_controllers/networking/network_status_services.dart'; import '../../riverpod_controllers/timeline_services.dart'; import '../padding.dart'; import 'post_control.dart'; class TimelinePanel extends ConsumerWidget { static final _logger = Logger('$TimelinePanel'); final TimelineIdentifiers timeline; final controller = ItemScrollController(); TimelinePanel({super.key, required this.timeline}); Future update( BuildContext context, Profile profile, WidgetRef ref) async { final confirm = await showYesNoDialog(context, 'Reload timeline from scratch?'); if (confirm == true) { await ref .read(timelineManagerProvider(profile, timeline).notifier) .updateTimeline(TimelineRefreshType.refresh); } } void scrollToTop() { controller.jumpTo(index: 0); } @override Widget build(BuildContext context, WidgetRef ref) { _logger.finer('Build'); final profile = ref.watch(activeProfileProvider); final postIds = ref.watch(timelineManagerProvider(profile, timeline)).posts; final loading = ref.watch(timelineLoadingStatusProvider(profile, timeline)); if (postIds.isEmpty && loading) { return const Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Text('Loading Posts'), ], ), ); } if (postIds.isEmpty) { return Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ const Text('No posts loaded'), const VerticalPadding(), ElevatedButton( onPressed: () => ref .read(timelineManagerProvider(profile, timeline).notifier) .updateTimeline(TimelineRefreshType.refresh), child: const Text('Load Posts')) ], ), ); } return RefreshIndicator( onRefresh: () async { update(context, profile, ref); return; }, child: ScrollablePositionedList.separated( itemScrollController: controller, physics: const AlwaysScrollableScrollPhysics(), separatorBuilder: (context, index) => index == 0 || index == postIds.length ? const SizedBox() : const Divider(), itemBuilder: (context, index) { if (index == 0) { return TextButton( onPressed: () async => await ref .read(timelineManagerProvider(profile, timeline).notifier) .updateTimeline(TimelineRefreshType.loadNewer), child: const Text('Load newer posts')); } if (index == postIds.length + 1) { return TextButton( onPressed: () async => await ref .read(timelineManagerProvider(profile, timeline).notifier) .updateTimeline(TimelineRefreshType.loadOlder), child: const Text('Load older posts')); } final itemIndex = index - 1; final id = postIds[itemIndex]; TimelinePanel._logger.finest('Building item: $itemIndex: $id'); return PostControl( id: id, scrollToId: id, openRemote: false, showStatusOpenButton: true, isRoot: false, ); }, itemCount: postIds.length + 2, ), ); } }