mirror of
https://gitlab.com/mysocialportal/fediverse-archiving-tools.git
synced 2024-10-18 08:53:31 +00:00
Add comments only filter and make comments hiearchy a different color
This commit is contained in:
parent
1f5a312c0e
commit
33dfb509f0
4 changed files with 115 additions and 68 deletions
|
@ -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),
|
||||
|
|
|
@ -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(),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue