mirror of
https://gitlab.com/mysocialportal/relatica
synced 2024-10-18 21:43:31 +00:00
c7df3ff1ba
Finishes implementation of Issue #93
222 lines
6.3 KiB
Dart
222 lines
6.3 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:go_router/go_router.dart';
|
|
import 'package:logging/logging.dart';
|
|
import 'package:result_monad/result_monad.dart';
|
|
|
|
import '../../globals.dart';
|
|
import '../../models/exec_error.dart';
|
|
import '../../models/timeline_entry.dart';
|
|
import '../../services/feature_version_checker.dart';
|
|
import '../../services/fediverse_server_validator.dart';
|
|
import '../../services/timeline_manager.dart';
|
|
import '../../utils/active_profile_selector.dart';
|
|
import '../../utils/interaction_availability_util.dart';
|
|
import '../../utils/snackbar_builder.dart';
|
|
|
|
class InteractionsBarControl extends StatefulWidget {
|
|
final TimelineEntry entry;
|
|
final bool showOpenControl;
|
|
final bool isMine;
|
|
|
|
const InteractionsBarControl({
|
|
super.key,
|
|
required this.entry,
|
|
required this.isMine,
|
|
required this.showOpenControl,
|
|
});
|
|
|
|
@override
|
|
State<InteractionsBarControl> createState() => _InteractionsBarControlState();
|
|
}
|
|
|
|
class _InteractionsBarControlState extends State<InteractionsBarControl> {
|
|
static final _logger = Logger('$InteractionsBarControl');
|
|
|
|
var isProcessing = false;
|
|
|
|
bool get isPost => widget.entry.parentId.isEmpty;
|
|
|
|
bool get isFavorited => widget.entry.isFavorited;
|
|
|
|
bool get youReshared => widget.entry.youReshared;
|
|
|
|
int get reshares => widget.entry.engagementSummary.rebloggedCount;
|
|
|
|
int get comments => widget.entry.engagementSummary.repliesCount;
|
|
|
|
int get likes => widget.entry.engagementSummary.favoritesCount;
|
|
|
|
Future<void> toggleFavorited() async {
|
|
setState(() {
|
|
isProcessing = true;
|
|
});
|
|
final newState = !isFavorited;
|
|
_logger.fine('Trying to toggle favorite from $isFavorited to $newState');
|
|
final result = await getIt<ActiveProfileSelector<TimelineManager>>()
|
|
.activeEntry
|
|
.andThenAsync(
|
|
(tm) async => await tm.toggleFavorited(widget.entry.id, newState));
|
|
result.match(onSuccess: (update) {
|
|
setState(() {
|
|
_logger.fine(
|
|
'Success toggling! $isFavorited -> ${update.entry.isFavorited}');
|
|
});
|
|
}, onError: (error) {
|
|
buildSnackbar(context, 'Error toggling like status: $error');
|
|
});
|
|
setState(() {
|
|
isProcessing = false;
|
|
});
|
|
}
|
|
|
|
Future<void> resharePost() async {
|
|
setState(() {
|
|
isProcessing = true;
|
|
});
|
|
|
|
// TODO Add can reshare check
|
|
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;
|
|
});
|
|
}
|
|
}
|
|
|
|
final id = widget.entry.id;
|
|
_logger.fine('Trying to reshare $id');
|
|
final result = await getIt<ActiveProfileSelector<TimelineManager>>()
|
|
.activeEntry
|
|
.andThenAsync((tm) async => await tm.resharePost(id));
|
|
|
|
result.match(onSuccess: (update) {
|
|
setState(() {
|
|
_logger.fine('Success resharing post by ${widget.entry.author}');
|
|
});
|
|
}, onError: (error) {
|
|
buildSnackbar(context, 'Error resharing post by ${widget.entry.author}');
|
|
logError(error, _logger);
|
|
});
|
|
setState(() {
|
|
isProcessing = false;
|
|
});
|
|
}
|
|
|
|
Future<void> addComment() async {
|
|
if (mounted) {
|
|
context.push('/comment/new?parent_id=${widget.entry.id}');
|
|
}
|
|
}
|
|
|
|
Future<void> unResharePost() async {
|
|
setState(() {
|
|
isProcessing = true;
|
|
});
|
|
final id = widget.entry.id;
|
|
_logger.fine('Trying to un-reshare $id');
|
|
final result = await getIt<ActiveProfileSelector<TimelineManager>>()
|
|
.activeEntry
|
|
.andThenAsync((tm) async => await tm.unResharePost(id));
|
|
result.match(onSuccess: (update) {
|
|
setState(() {
|
|
_logger.fine('Success un-resharing post by ${widget.entry.author}');
|
|
});
|
|
}, onError: (error) {
|
|
buildSnackbar(
|
|
context, 'Error un-resharing post by ${widget.entry.author}');
|
|
logError(error, _logger);
|
|
});
|
|
setState(() {
|
|
isProcessing = false;
|
|
});
|
|
}
|
|
|
|
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() {
|
|
final canReact = widget.entry.getCanReact();
|
|
final tooltip =
|
|
canReact.canDo ? 'Press to toggle like/unlike' : canReact.reason;
|
|
return buildButton(
|
|
isFavorited ? Icons.thumb_up : Icons.thumb_up_outlined,
|
|
likes,
|
|
true,
|
|
tooltip,
|
|
canReact.canDo ? () async => await toggleFavorited() : null,
|
|
);
|
|
}
|
|
|
|
Widget buildCommentButton() {
|
|
final canComment = widget.entry.getCanComment();
|
|
final tooltip =
|
|
canComment.canDo ? 'Press to add a comment' : canComment.reason;
|
|
return buildButton(
|
|
Icons.comment,
|
|
comments,
|
|
true,
|
|
tooltip,
|
|
canComment.canDo ? () async => await addComment() : null,
|
|
);
|
|
}
|
|
|
|
Widget buildReshareButton() {
|
|
final reshareable = widget.entry.getIsReshareable(widget.isMine);
|
|
final canReshare = reshareable.canDo;
|
|
late final String tooltip;
|
|
if (canReshare) {
|
|
tooltip = youReshared ? 'Press to undo reshare' : 'Press to reshare';
|
|
} else {
|
|
tooltip = reshareable.reason;
|
|
}
|
|
return buildButton(
|
|
youReshared ? Icons.repeat_on_outlined : Icons.repeat,
|
|
reshares,
|
|
true,
|
|
tooltip,
|
|
canReshare && !isProcessing
|
|
? () async =>
|
|
youReshared ? await unResharePost() : await resharePost()
|
|
: null,
|
|
);
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
_logger.finest('Building: ${widget.entry.toShortString()}');
|
|
return Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
|
children: [
|
|
buildLikeButton(),
|
|
buildCommentButton(),
|
|
if (widget.entry.parentId.isEmpty) buildReshareButton(),
|
|
],
|
|
);
|
|
}
|
|
}
|