relatica/lib/screens/home.dart

226 wiersze
7.0 KiB
Dart

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<HomeScreen> createState() => _HomeScreenState();
}
class _HomeScreenState extends ConsumerState<HomeScreen> {
final _logger = Logger('$HomeScreen');
final _seenTimelines = <TimelineIdentifiers>{};
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<TimelineIdentifiers?>(
value: currentTimeline,
items: items,
isExpanded: true,
onChanged: (value) {
setState(() {
if (value == null) {
return;
}
currentTimeline = value;
if (!_seenTimelines.contains(value)) {
updateTimeline(profile);
}
});
});
}
}
List<DropdownMenuItem<TimelineIdentifiers>>
_timelineGroupingListDataCollectionToDropdown(
List<TimelineGroupingListData> 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();