2022-11-18 21:50:15 +00:00
|
|
|
import 'package:flutter/material.dart';
|
2022-11-23 02:59:08 +00:00
|
|
|
import 'package:go_router/go_router.dart';
|
2022-11-21 21:21:45 +00:00
|
|
|
import 'package:logging/logging.dart';
|
2023-04-20 20:26:11 +00:00
|
|
|
import 'package:relatica/models/exec_error.dart';
|
2023-03-23 14:14:25 +00:00
|
|
|
import 'package:result_monad/result_monad.dart';
|
2022-11-18 21:50:15 +00:00
|
|
|
|
|
|
|
import '../../globals.dart';
|
|
|
|
import '../../models/timeline_entry.dart';
|
2023-11-18 20:13:42 +00:00
|
|
|
import '../../models/visibility.dart' as v;
|
2023-03-23 14:14:25 +00:00
|
|
|
import '../../services/feature_version_checker.dart';
|
|
|
|
import '../../services/fediverse_server_validator.dart';
|
2022-11-21 21:21:45 +00:00
|
|
|
import '../../services/timeline_manager.dart';
|
2023-03-14 03:47:40 +00:00
|
|
|
import '../../utils/active_profile_selector.dart';
|
2022-11-18 21:50:15 +00:00
|
|
|
import '../../utils/snackbar_builder.dart';
|
|
|
|
|
|
|
|
class InteractionsBarControl extends StatefulWidget {
|
|
|
|
final TimelineEntry entry;
|
2023-01-05 21:32:34 +00:00
|
|
|
final bool showOpenControl;
|
2022-11-22 19:42:26 +00:00
|
|
|
final bool isMine;
|
|
|
|
|
2023-01-05 21:32:34 +00:00
|
|
|
const InteractionsBarControl({
|
|
|
|
super.key,
|
|
|
|
required this.entry,
|
|
|
|
required this.isMine,
|
|
|
|
required this.showOpenControl,
|
|
|
|
});
|
2022-11-18 21:50:15 +00:00
|
|
|
|
|
|
|
@override
|
|
|
|
State<InteractionsBarControl> createState() => _InteractionsBarControlState();
|
|
|
|
}
|
|
|
|
|
|
|
|
class _InteractionsBarControlState extends State<InteractionsBarControl> {
|
2022-11-21 21:21:45 +00:00
|
|
|
static final _logger = Logger('$InteractionsBarControl');
|
2022-11-18 21:50:15 +00:00
|
|
|
|
2022-12-27 04:36:04 +00:00
|
|
|
var isProcessing = false;
|
|
|
|
|
2022-11-22 16:43:16 +00:00
|
|
|
bool get isPost => widget.entry.parentId.isEmpty;
|
|
|
|
|
2022-11-21 21:21:45 +00:00
|
|
|
bool get isFavorited => widget.entry.isFavorited;
|
|
|
|
|
2023-01-12 23:33:21 +00:00
|
|
|
bool get youReshared => widget.entry.youReshared;
|
2022-11-22 16:43:16 +00:00
|
|
|
|
2022-11-21 21:21:45 +00:00
|
|
|
int get reshares => widget.entry.engagementSummary.rebloggedCount;
|
|
|
|
|
|
|
|
int get comments => widget.entry.engagementSummary.repliesCount;
|
|
|
|
|
|
|
|
int get likes => widget.entry.engagementSummary.favoritesCount;
|
2022-11-18 21:50:15 +00:00
|
|
|
|
|
|
|
Future<void> toggleFavorited() async {
|
2022-12-27 04:36:04 +00:00
|
|
|
setState(() {
|
|
|
|
isProcessing = true;
|
|
|
|
});
|
2022-11-18 21:50:15 +00:00
|
|
|
final newState = !isFavorited;
|
2022-11-21 21:21:45 +00:00
|
|
|
_logger.finest('Trying to toggle favorite from $isFavorited to $newState');
|
2023-03-14 03:47:40 +00:00
|
|
|
final result = await getIt<ActiveProfileSelector<TimelineManager>>()
|
|
|
|
.activeEntry
|
|
|
|
.andThenAsync(
|
|
|
|
(tm) async => await tm.toggleFavorited(widget.entry.id, newState));
|
2022-11-18 21:50:15 +00:00
|
|
|
result.match(onSuccess: (update) {
|
|
|
|
setState(() {
|
2022-11-21 21:21:45 +00:00
|
|
|
_logger.finest(
|
|
|
|
'Success toggling! $isFavorited -> ${update.entry.isFavorited}');
|
2022-11-18 21:50:15 +00:00
|
|
|
});
|
|
|
|
}, onError: (error) {
|
|
|
|
buildSnackbar(context, 'Error toggling like status: $error');
|
|
|
|
});
|
2022-12-27 04:36:04 +00:00
|
|
|
setState(() {
|
|
|
|
isProcessing = false;
|
|
|
|
});
|
2022-11-18 21:50:15 +00:00
|
|
|
}
|
|
|
|
|
2022-11-22 16:43:16 +00:00
|
|
|
Future<void> resharePost() async {
|
2022-12-27 04:36:04 +00:00
|
|
|
setState(() {
|
|
|
|
isProcessing = true;
|
|
|
|
});
|
2023-03-23 14:14:25 +00:00
|
|
|
|
|
|
|
final fvc = getIt<FriendicaVersionChecker>();
|
|
|
|
if (!fvc.canUseFeature(RelaticaFeatures.diasporaReshare)) {
|
|
|
|
final serverTypeEstimate = await getIt<FediverseServiceValidator>()
|
|
|
|
.getServerData(widget.entry.externalLink)
|
|
|
|
.fold(onSuccess: (d) => d.softwareName, onError: (_) => '');
|
|
|
|
if (serverTypeEstimate ==
|
|
|
|
FediverseServiceValidator.softwareTypeDiaspora) {
|
|
|
|
if (mounted) {
|
|
|
|
final error =
|
|
|
|
fvc.versionErrorString(RelaticaFeatures.diasporaReshare);
|
|
|
|
await showConfirmDialog(context, error);
|
|
|
|
}
|
|
|
|
setState(() {
|
|
|
|
isProcessing = false;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-11-22 16:43:16 +00:00
|
|
|
final id = widget.entry.id;
|
|
|
|
_logger.finest('Trying to reshare $id');
|
2023-03-14 03:47:40 +00:00
|
|
|
final result = await getIt<ActiveProfileSelector<TimelineManager>>()
|
|
|
|
.activeEntry
|
|
|
|
.andThenAsync((tm) async => await tm.resharePost(id));
|
|
|
|
|
2022-11-22 16:43:16 +00:00
|
|
|
result.match(onSuccess: (update) {
|
|
|
|
setState(() {
|
|
|
|
_logger.finest('Success resharing post by ${widget.entry.author}');
|
|
|
|
});
|
|
|
|
}, onError: (error) {
|
|
|
|
buildSnackbar(context, 'Error resharing post by ${widget.entry.author}');
|
2023-04-20 20:26:11 +00:00
|
|
|
logError(error, _logger);
|
2022-11-22 16:43:16 +00:00
|
|
|
});
|
2022-12-27 04:36:04 +00:00
|
|
|
setState(() {
|
|
|
|
isProcessing = false;
|
|
|
|
});
|
2022-11-22 16:43:16 +00:00
|
|
|
}
|
|
|
|
|
2022-11-23 02:59:08 +00:00
|
|
|
Future<void> addComment() async {
|
2023-04-27 13:13:13 +00:00
|
|
|
if (mounted) {
|
|
|
|
context.push('/comment/new?parent_id=${widget.entry.id}');
|
|
|
|
}
|
2022-11-23 02:59:08 +00:00
|
|
|
}
|
|
|
|
|
2022-11-22 16:43:16 +00:00
|
|
|
Future<void> unResharePost() async {
|
2022-12-27 04:36:04 +00:00
|
|
|
setState(() {
|
|
|
|
isProcessing = true;
|
|
|
|
});
|
2022-11-22 16:43:16 +00:00
|
|
|
final id = widget.entry.id;
|
|
|
|
_logger.finest('Trying to un-reshare $id');
|
2023-03-14 03:47:40 +00:00
|
|
|
final result = await getIt<ActiveProfileSelector<TimelineManager>>()
|
|
|
|
.activeEntry
|
|
|
|
.andThenAsync((tm) async => await tm.unResharePost(id));
|
2022-11-22 16:43:16 +00:00
|
|
|
result.match(onSuccess: (update) {
|
|
|
|
setState(() {
|
|
|
|
_logger.finest('Success un-resharing post by ${widget.entry.author}');
|
|
|
|
});
|
|
|
|
}, onError: (error) {
|
|
|
|
buildSnackbar(
|
|
|
|
context, 'Error un-resharing post by ${widget.entry.author}');
|
2023-04-20 20:26:11 +00:00
|
|
|
logError(error, _logger);
|
2022-11-22 16:43:16 +00:00
|
|
|
});
|
2022-12-27 04:36:04 +00:00
|
|
|
setState(() {
|
|
|
|
isProcessing = false;
|
|
|
|
});
|
2022-11-22 16:43:16 +00:00
|
|
|
}
|
|
|
|
|
2023-11-18 20:13:42 +00:00
|
|
|
Widget buildButton(
|
|
|
|
IconData icon,
|
|
|
|
int count,
|
|
|
|
bool isEnabled,
|
|
|
|
String tooltip,
|
|
|
|
Future Function()? onPressed,
|
|
|
|
) {
|
|
|
|
return Row(
|
|
|
|
children: [
|
|
|
|
IconButton(
|
|
|
|
onPressed: isEnabled && !isProcessing ? onPressed : null,
|
|
|
|
icon: Icon(icon),
|
|
|
|
tooltip: tooltip,
|
|
|
|
),
|
|
|
|
Text('$count'),
|
|
|
|
],
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
Widget buildLikeButton() {
|
|
|
|
return buildButton(
|
|
|
|
isFavorited ? Icons.thumb_up : Icons.thumb_up_outlined,
|
|
|
|
likes,
|
|
|
|
true,
|
|
|
|
'Press to toggle like/unlike',
|
|
|
|
() async => await toggleFavorited(),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
Widget buildCommentButton() {
|
|
|
|
return buildButton(
|
|
|
|
Icons.comment,
|
|
|
|
comments,
|
|
|
|
true,
|
|
|
|
'Press to add a comment',
|
|
|
|
() async => await addComment(),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
Widget buildReshareButton() {
|
|
|
|
final canReshare = !widget.isMine &&
|
|
|
|
widget.entry.visibility.type == v.VisibilityType.public;
|
|
|
|
late final String tooltip;
|
|
|
|
if (canReshare) {
|
|
|
|
tooltip = youReshared ? 'Press to undo reshare' : 'Press to reshare';
|
|
|
|
} else {
|
|
|
|
if (widget.isMine) {
|
|
|
|
tooltip = "Can't reshare your own post";
|
|
|
|
} else if (widget.entry.visibility.type != v.VisibilityType.public) {
|
|
|
|
tooltip = "Can't reshare a private post";
|
|
|
|
} else {
|
|
|
|
tooltip = "Can't reshare at this time";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return buildButton(
|
|
|
|
youReshared ? Icons.repeat_on_outlined : Icons.repeat,
|
|
|
|
reshares,
|
|
|
|
true,
|
|
|
|
tooltip,
|
|
|
|
canReshare && !isProcessing
|
|
|
|
? () async =>
|
|
|
|
youReshared ? await unResharePost() : await resharePost()
|
|
|
|
: null,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2022-11-18 21:50:15 +00:00
|
|
|
@override
|
|
|
|
Widget build(BuildContext context) {
|
2022-11-21 21:21:45 +00:00
|
|
|
_logger.finest('Building: ${widget.entry.toShortString()}');
|
2023-11-18 20:13:42 +00:00
|
|
|
return Row(
|
|
|
|
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
2022-11-18 21:50:15 +00:00
|
|
|
children: [
|
2023-11-18 20:13:42 +00:00
|
|
|
buildLikeButton(),
|
|
|
|
buildCommentButton(),
|
|
|
|
buildReshareButton(),
|
2022-11-18 21:50:15 +00:00
|
|
|
],
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|