import 'package:fluent_reader_lite/components/badge.dart'; import 'package:fluent_reader_lite/components/dismissible_background.dart'; import 'package:fluent_reader_lite/components/list_tile_group.dart'; import 'package:fluent_reader_lite/components/mark_all_action_sheet.dart'; import 'package:fluent_reader_lite/components/my_list_tile.dart'; import 'package:fluent_reader_lite/generated/l10n.dart'; import 'package:fluent_reader_lite/models/groups_model.dart'; import 'package:fluent_reader_lite/models/source.dart'; import 'package:fluent_reader_lite/models/sources_model.dart'; import 'package:fluent_reader_lite/utils/colors.dart'; import 'package:fluent_reader_lite/utils/global.dart'; import 'package:fluent_reader_lite/utils/utils.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/services.dart'; import 'package:provider/provider.dart'; import 'package:tuple/tuple.dart'; class GroupListPage extends StatefulWidget { @override _GroupListPageState createState() => _GroupListPageState(); } class _GroupListPageState extends State { static const List _uncategorizedIndicator = ["_", "_"]; int _unreadCount(Iterable sources) { return sources.fold(0, (c, s) => c + (s != null ? s.unreadCount : 0)); } void _showGroupSettings(BuildContext context, String groupName) { HapticFeedback.mediumImpact(); Navigator.of(context).push(CupertinoPageRoute( builder: (context) => _GroupSettingsPage(groupName: groupName), )); } static const _dismissThresholds = { DismissDirection.startToEnd: 0.25, }; @override Widget build(BuildContext context) { final navigationBar = CupertinoSliverNavigationBar( largeTitle: Text(S.of(context).groups), automaticallyImplyLeading: false, backgroundColor: Global.isTablet ? CupertinoColors.systemBackground : null, leading: CupertinoButton( minSize: 36, padding: EdgeInsets.zero, child: Text(S.of(context).cancel), onPressed: () { Navigator.of(context).pop(); }, ), ); final allSources = Consumer( builder: (context, sourcesModel, child) { var count = _unreadCount(sourcesModel.getSources()); return SliverToBoxAdapter(child: MyListTile( title: Text(S.of(context).allSubscriptions), trailing: count > 0 ? Badge(count) : null, onTap: () { Navigator.of(context).pop(List.empty()); }, background: CupertinoColors.systemBackground, )); }, ); final dismissBg = DismissibleBackground(CupertinoIcons.checkmark_circle, true); final groupList = Consumer2( builder: (context, groupsModel, sourcesModel, child) { final sortedKeys = groupsModel.groups.keys.toList(); sortedKeys.sort(Utils.localStringCompare); final hasUncategorized = groupsModel.uncategorized != null; final totalCount = sortedKeys.length + (hasUncategorized ? 1 : 0); return SliverList( delegate: SliverChildBuilderDelegate((context, index) { String groupName; List group; final isUncategorized = groupsModel.showUncategorized && hasUncategorized && index == 0; if (isUncategorized) { groupName = S.of(context).uncategorized; group = groupsModel.uncategorized!; } else { final adjustedIndex = hasUncategorized ? index - 1 : index; groupName = sortedKeys[adjustedIndex]; group = groupsModel.groups[groupName]!; } final count = _unreadCount( group.map((sid) => sourcesModel.getSource(sid)) ); final tile = GestureDetector( onLongPress: isUncategorized ? null : () { _showGroupSettings(context, groupName); }, child: MyListTile( title: Flexible(child: Text(groupName, overflow: TextOverflow.ellipsis)), trailing: count > 0 ? Badge(count) : null, onTap: () { Navigator.of(context).pop( isUncategorized ? _uncategorizedIndicator : [groupName] ); }, background: CupertinoColors.systemBackground, ), ); return Dismissible( key: Key("$groupName$index"), child: tile, background: dismissBg, direction: DismissDirection.startToEnd, dismissThresholds: _dismissThresholds, confirmDismiss: (_) async { HapticFeedback.mediumImpact(); Set sids = Set.from(group); showCupertinoModalPopup( context: context, builder: (context) => MarkAllActionSheet(sids), ); return false; }, ); }, childCount: totalCount), ); }, ); final padding = SliverToBoxAdapter(child: Padding( padding: EdgeInsets.only(bottom: 80), ),); return CupertinoPageScaffold( backgroundColor: CupertinoColors.systemBackground, child: CupertinoScrollbar(child: CustomScrollView( slivers: [ navigationBar, allSources, groupList, padding, ], )) ); } } class _GroupSettingsPage extends StatelessWidget { final String groupName; const _GroupSettingsPage({required this.groupName}); @override Widget build(BuildContext context) { return Consumer( builder: (context, groupsModel, child) { final openTarget = ListTileGroup.fromOptions( [ Tuple2(S.of(context).inheritDefault, SourceOpenTarget.Inherit), Tuple2(S.of(context).rssText, SourceOpenTarget.Local), Tuple2(S.of(context).loadFull, SourceOpenTarget.FullContent), Tuple2(S.of(context).loadWebpage, SourceOpenTarget.Webpage), Tuple2(S.of(context).openExternal, SourceOpenTarget.External), ], groupsModel.getGroupOpenTarget(groupName), (v) { groupsModel.setGroupOpenTarget(groupName, v); }, title: S.of(context).openTarget, ); return CupertinoPageScaffold( backgroundColor: MyColors.background, navigationBar: CupertinoNavigationBar( middle: Text(groupName, overflow: TextOverflow.ellipsis), ), child: ListView(children: [ openTarget, ]), ); }, ); } }