Add comments only filter and make comments hiearchy a different color

This commit is contained in:
Hank Grabowski 2022-01-19 14:10:35 -05:00
parent 1f5a312c0e
commit 33dfb509f0
4 changed files with 115 additions and 68 deletions

View file

@ -6,6 +6,7 @@ import 'package:provider/provider.dart';
class FilterControl<T1, T2> extends StatefulWidget {
final List<T1> allItems;
final List<T1> filteredItems = [];
final bool Function(T1)? commentsOnlyFilterFunction;
final bool Function(T1)? imagesOnlyFilterFunction;
final bool Function(T1)? videosOnlyFilterFunction;
final bool Function(T1, String)? textSearchFilterFunction;
@ -24,6 +25,7 @@ class FilterControl<T1, T2> extends StatefulWidget {
FilterControl(
{Key? key,
required this.allItems,
this.commentsOnlyFilterFunction,
this.imagesOnlyFilterFunction,
this.textSearchFilterFunction,
this.videosOnlyFilterFunction,
@ -61,6 +63,7 @@ class FilterControl<T1, T2> extends StatefulWidget {
class _FilterControlState<T1, T2> extends State<FilterControl<T1, T2>> {
static final _logger = Logger('$_FilterControlState');
bool _withCommentsOnly = false;
bool _withImagesOnly = false;
bool _withVideosOnly = false;
bool _withDateFilter = false;
@ -116,6 +119,12 @@ class _FilterControlState<T1, T2> extends State<FilterControl<T1, T2>> {
passes &= widget.videosOnlyFilterFunction!(p);
}
if (passes &&
_withCommentsOnly &&
widget.commentsOnlyFilterFunction != null) {
passes &= widget.commentsOnlyFilterFunction!(p);
}
if (passes && _withDateFilter) {
passes &=
widget.dateRangeFilterFunction(p, _filterStartDate, _filterEndDate);
@ -211,8 +220,17 @@ class _FilterControlState<T1, T2> extends State<FilterControl<T1, T2>> {
return Column(children: [
if (widget.textSearchFilterFunction != null) _buildTextFilter(context),
_buildDateFilter(context),
if (widget.imagesOnlyFilterFunction != null) _buildImagesOnly(context),
if (widget.videosOnlyFilterFunction != null) _buildVideosOnly(context),
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
if (widget.commentsOnlyFilterFunction != null)
_buildCommentsOnly(context),
if (widget.imagesOnlyFilterFunction != null)
_buildImagesOnly(context),
if (widget.videosOnlyFilterFunction != null)
_buildVideosOnly(context),
],
),
_buildStatusLine(),
]);
}
@ -225,6 +243,22 @@ class _FilterControlState<T1, T2> extends State<FilterControl<T1, T2>> {
);
}
Widget _buildCommentsOnly(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Row(children: [
Checkbox(
value: _withCommentsOnly,
onChanged: (value) => setState(() {
_withCommentsOnly = value ?? false;
_updateFilter();
})),
const SizedBox(width: 1),
const Text('Only with comments'),
]),
);
}
Widget _buildVideosOnly(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(8.0),

View file

@ -48,71 +48,80 @@ class TreeEntryCard extends StatelessWidget {
return Padding(
padding: const EdgeInsets.all(20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
Wrap(
direction: Axis.horizontal,
crossAxisAlignment: WrapCrossAlignment.center,
children: [
Text(
title,
style: const TextStyle(
fontWeight: FontWeight.bold,
),
),
Text(dateStamp,
style: const TextStyle(
fontStyle: FontStyle.italic,
)),
Tooltip(
message: 'Copy text version of post to clipboard',
child: IconButton(
onPressed: () async => await copyToClipboard(
context: context,
text: entry.toHumanString(mapper, formatter),
snackbarMessage: 'Copied Post to clipboard'),
icon: const Icon(Icons.copy)),
),
]),
if (entry.post.isNotEmpty) ...[
const SizedBox(height: spacingHeight),
HtmlWidget(
entry.post,
onTapUrl: (url) async {
bool canLaunchResult = await canLaunch(url);
if (!canLaunchResult) {
return false;
}
child: Container(
color: !isTopLevel ? Theme.of(context).dividerColor : null,
child: Padding(
padding: const EdgeInsets.all(5.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
Wrap(
direction: Axis.horizontal,
crossAxisAlignment: WrapCrossAlignment.center,
children: [
Text(
title,
style: const TextStyle(
fontWeight: FontWeight.bold,
),
),
Text(dateStamp,
style: const TextStyle(
fontStyle: FontStyle.italic,
)),
Tooltip(
message: 'Copy text version of post to clipboard',
child: IconButton(
onPressed: () async => await copyToClipboard(
context: context,
text: entry.toHumanString(mapper, formatter),
snackbarMessage: 'Copied Post to clipboard'),
icon: const Icon(Icons.copy)),
),
]),
if (entry.post.isNotEmpty) ...[
const SizedBox(height: spacingHeight),
HtmlWidget(
entry.post,
onTapUrl: (url) async {
bool canLaunchResult = await canLaunch(url);
if (!canLaunchResult) {
return false;
}
bool launched = await launch(url);
if (!launched) {
final message = 'Failed to launch: $url';
_logger.info(message);
SnackBarStatusBuilder.buildSnackbar(context, message);
}
return launched;
},
)
],
if (entry.locationData.hasData())
entry.locationData.toWidget(spacingHeight),
if (entry.links.isNotEmpty) ...[
const SizedBox(height: spacingHeight),
LinkElementsComponent(links: entry.links)
],
if (entry.mediaAttachments.isNotEmpty) ...[
const SizedBox(height: spacingHeight),
MediaTimelineComponent(mediaAttachments: entry.mediaAttachments)
],
if (treeEntry.children.isNotEmpty)
Column(
children: treeEntry.children
.map((e) => TreeEntryCard(treeEntry: e))
.toList(),
)
],
bool launched = await launch(url);
if (!launched) {
final message = 'Failed to launch: $url';
_logger.info(message);
SnackBarStatusBuilder.buildSnackbar(context, message);
}
return launched;
},
)
],
if (entry.locationData.hasData())
entry.locationData.toWidget(spacingHeight),
if (entry.links.isNotEmpty) ...[
const SizedBox(height: spacingHeight),
LinkElementsComponent(links: entry.links)
],
if (entry.mediaAttachments.isNotEmpty) ...[
const SizedBox(height: spacingHeight),
MediaTimelineComponent(mediaAttachments: entry.mediaAttachments)
],
if (treeEntry.children.isNotEmpty)
Column(
children: treeEntry.children
.map((e) => TreeEntryCard(
treeEntry: e,
isTopLevel: false,
))
.toList(),
)
],
),
),
),
);
}

View file

@ -65,6 +65,7 @@ class _FriendicaEntriesScreenWidget extends StatelessWidget {
_logger.fine('Redrawing');
return FilterControl<FriendicaEntryTreeItem, dynamic>(
allItems: posts,
commentsOnlyFilterFunction: (post) => post.children.isNotEmpty,
imagesOnlyFilterFunction: (post) => post.entry.hasImages(),
videosOnlyFilterFunction: (post) => post.entry.hasVideos(),
textSearchFilterFunction: (post, text) =>
@ -89,7 +90,10 @@ class _FriendicaEntriesScreenWidget extends StatelessWidget {
itemCount: items.length,
itemBuilder: (context, index) {
_logger.finer('Rendering Friendica List Item');
return TreeEntryCard(treeEntry: items[index]);
return TreeEntryCard(
treeEntry: items[index],
isTopLevel: true,
);
},
separatorBuilder: (context, index) {
return const Divider(

View file

@ -50,7 +50,7 @@ class _HomeState extends State<Home> {
_pages.add(notInitialiedWidget);
}
if (!Directory(widget.settingsController.rootFolder).existsSync()) {
if (Directory(widget.settingsController.rootFolder).existsSync()) {
_setSelectedIndex(0);
} else {
_setSelectedIndex(_pageData.length - 1);