import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; import 'package:logging/logging.dart'; import '../controls/app_bottom_nav_bar.dart'; import '../controls/focus_mode_status_headline.dart'; import '../controls/login_aware_cached_network_image.dart'; import '../controls/responsive_max_width.dart'; import '../controls/standard_app_drawer.dart'; import '../controls/timeline/timeline_panel.dart'; import '../models/auth/profile.dart'; import '../models/timeline_grouping_list_data.dart'; import '../models/timeline_identifiers.dart'; import '../riverpod_controllers/account_services.dart'; import '../riverpod_controllers/circles_repo_services.dart'; import '../riverpod_controllers/focus_mode.dart'; import '../riverpod_controllers/networking/network_status_services.dart'; import '../riverpod_controllers/timeline_services.dart'; class HomeScreen extends ConsumerStatefulWidget { const HomeScreen({super.key}); @override ConsumerState createState() => _HomeScreenState(); } class _HomeScreenState extends ConsumerState { final _logger = Logger('$HomeScreen'); final _seenTimelines = {}; TimelineIdentifiers currentTimeline = TimelineIdentifiers.home(); void updateTimeline(Profile profile) { _logger.finer('Updating timeline: $currentTimeline'); _seenTimelines.add(currentTimeline); Future.delayed(const Duration(milliseconds: 100), () async { await ref .read(timelineManagerProvider(profile, currentTimeline).notifier) .updateTimeline(TimelineRefreshType.loadNewer); }); } @override void initState() { super.initState(); final profile = ref.read(activeProfileProvider); updateTimeline(profile); } @override Widget build(BuildContext context) { _logger.finest('Build'); final profile = ref.watch(activeProfileProvider); final focusMode = ref.watch(focusModeProvider); final loading = ref.watch(timelineLoadingStatusProvider(profile, currentTimeline)); final timeline = TimelinePanel( timeline: focusMode.enabled ? TimelineIdentifiers.myPosts() : currentTimeline); return Scaffold( appBar: AppBar( leading: ref.read(activeProfileProvider.notifier).hasActiveProfile ? Builder(builder: (context) { return IconButton( onPressed: () { Scaffold.of(context).openDrawer(); }, icon: LoginAwareCachedNetworkImage( imageUrl: profile.avatar)); }) : null, backgroundColor: Theme.of(context).canvasColor, title: focusMode.enabled ? FocusModeStatusHeadline(disableTime: focusMode.disableTime) : buildTimelineSelector(context, profile), ), body: Center( child: Column( children: [ if (loading) const LinearProgressIndicator(), Expanded( child: ResponsiveMaxWidth(child: timeline), ), ], ), ), drawer: const StandardAppDrawer(), bottomNavigationBar: focusMode.enabled ? null : AppBottomNavBar( currentButton: NavBarButtons.timelines, onHomeButtonReclick: () => timeline.scrollToTop(), ), floatingActionButton: FloatingActionButton.small( onPressed: () { context.push('/post/new'); }, child: const Icon(Icons.add), )); } Widget buildTimelineSelector(BuildContext context, Profile profile) { final standardTypes = [ TimelineType.self, TimelineType.home, TimelineType.global, TimelineType.local, ]; final circles = ref.watch(timelineGroupingListProvider( profile, GroupingType.circle, )); final groups = ref.watch(timelineGroupingListProvider( profile, GroupingType.group, )); final channels = ref.watch(timelineGroupingListProvider( profile, GroupingType.channel, )); final items = [ ...standardTypes .map((t) => TimelineIdentifiers(timeline: t)) .map((e) => DropdownMenuItem(value: e, child: Text(e.toLabel()))), if (circles.isNotEmpty) ...[ const DropdownMenuItem( value: null, enabled: false, child: Divider(), ), const DropdownMenuItem( value: null, enabled: false, child: Text( 'Circles', style: TextStyle( fontWeight: FontWeight.bold, fontStyle: FontStyle.italic, decoration: TextDecoration.underline, ), )), ..._timelineGroupingListDataCollectionToDropdown(circles), ], if (groups.isNotEmpty) ...[ const DropdownMenuItem( value: null, enabled: false, child: Divider(), ), const DropdownMenuItem( value: null, enabled: false, child: Text( 'Groups', style: TextStyle( fontWeight: FontWeight.bold, fontStyle: FontStyle.italic, decoration: TextDecoration.underline, ), )), ..._timelineGroupingListDataCollectionToDropdown(groups), ], if (channels.isNotEmpty) ...[ const DropdownMenuItem( value: null, enabled: false, child: Divider(), ), const DropdownMenuItem( value: null, enabled: false, child: Text( 'Channels', style: TextStyle( fontWeight: FontWeight.bold, fontStyle: FontStyle.italic, decoration: TextDecoration.underline, ), )), ..._timelineGroupingListDataCollectionToDropdown(channels), ], ]; if (items.where((i) => i.value == currentTimeline).isEmpty) { currentTimeline = TimelineIdentifiers.home(); } return DropdownButton( value: currentTimeline, items: items, isExpanded: true, onChanged: (value) { setState(() { if (value == null) { return; } currentTimeline = value; if (!_seenTimelines.contains(value)) { updateTimeline(profile); } }); }); } } List> _timelineGroupingListDataCollectionToDropdown( List circles) => circles .map((c) => TimelineIdentifiers( timeline: TimelineType.circle, auxData: c.id, label: c.name)) .map((e) => DropdownMenuItem( value: e, child: Text( e.toLabel(), overflow: TextOverflow.fade, ))) .toList();