import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; import 'package:logging/logging.dart'; import 'package:relatica/models/exec_error.dart'; import 'package:result_monad/result_monad.dart'; import '../../globals.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/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 createState() => _InteractionsBarControlState(); } class _InteractionsBarControlState extends State { 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 toggleFavorited() async { setState(() { isProcessing = true; }); final newState = !isFavorited; _logger.finest('Trying to toggle favorite from $isFavorited to $newState'); final result = await getIt>() .activeEntry .andThenAsync( (tm) async => await tm.toggleFavorited(widget.entry.id, newState)); result.match(onSuccess: (update) { setState(() { _logger.finest( 'Success toggling! $isFavorited -> ${update.entry.isFavorited}'); }); }, onError: (error) { buildSnackbar(context, 'Error toggling like status: $error'); }); setState(() { isProcessing = false; }); } Future resharePost() async { setState(() { isProcessing = true; }); final fvc = getIt(); if (!fvc.canUseFeature(RelaticaFeatures.diasporaReshare)) { final serverTypeEstimate = await getIt() .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.finest('Trying to reshare $id'); final result = await getIt>() .activeEntry .andThenAsync((tm) async => await tm.resharePost(id)); 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}'); logError(error, _logger); }); setState(() { isProcessing = false; }); } Future addComment() async { if (mounted) { context.push('/comment/new?parent_id=${widget.entry.id}'); } } Future unResharePost() async { setState(() { isProcessing = true; }); final id = widget.entry.id; _logger.finest('Trying to un-reshare $id'); final result = await getIt>() .activeEntry .andThenAsync((tm) async => await tm.unResharePost(id)); 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}'); logError(error, _logger); }); setState(() { isProcessing = false; }); } @override Widget build(BuildContext context) { _logger.finest('Building: ${widget.entry.toShortString()}'); return Column( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ TextButton( onPressed: likes == 0 ? null : () { context.push('/likes/${widget.entry.id}'); }, child: Text('$likes Likes'), ), TextButton( onPressed: reshares == 0 ? null : () { context.push('/reshares/${widget.entry.id}'); }, child: Text('$reshares Reshares'), ), widget.showOpenControl ? TextButton( onPressed: comments == 0 ? null : () { context.push( '/post/view/${widget.entry.id}/${widget.entry.id}'); }, child: Text('$comments Comments'), ) : Text('$comments Comments'), ], ), Row(children: [ IconButton( onPressed: isProcessing ? null : () async => await toggleFavorited(), icon: isFavorited ? const Icon( Icons.thumb_up, semanticLabel: 'Like', ) : const Icon(Icons.thumb_up_outlined)), if (isPost) IconButton( onPressed: widget.isMine && !widget.entry.youReshared ? null : isProcessing ? null : () async => youReshared ? await unResharePost() : await resharePost(), icon: Icon( youReshared ? Icons.repeat_on_outlined : Icons.repeat)), IconButton( onPressed: isProcessing ? null : addComment, icon: const Icon(Icons.add_comment)), ]), ], ); } }