relatica/lib/controls/timeline/timeline_panel.dart

116 wiersze
3.8 KiB
Dart

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<void> 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,
),
);
}
}