import 'package:flutter/material.dart'; import 'package:localization/localization.dart'; import 'package:loris/business_logic/network_tools/get_post_from_url.dart'; import 'package:loris/business_logic/timeline/timeline.dart'; import '../business_logic/interactions/interactions.dart' as interactions; import 'package:loris/global.dart' as global; class InteractionButton extends StatefulWidget { const InteractionButton( {required this.model, required this.type, Key? key, this.extended = false}) : super(key: key); final interactions.InteractionType type; final PostModel model; final bool extended; @override State createState() => _InteractionButtonState(); } class _InteractionButtonState extends State { IconData icon = Icons.question_mark; String idkey = global.settings!.activeIdentity; bool active = false; bool busy = false; bool success = false; // user is logged into multiple accounts // decides if the button has been clicked already bool isActive(PostModel post) { switch (widget.type) { case interactions.InteractionType.favorite: return widget.model.favourited; case interactions.InteractionType.reblog: return widget.model.reblogged; } } @override void initState() { active = isActive(widget.model); icon = active ? widget.type.revokeIcon : widget.type.icon; super.initState(); } Future sendRequest({ required String id, bool fromUrl = false, }) async { if (!busy) { setState(() { busy = true; }); int status = fromUrl ? await interactions.makeFullInteraction( id, widget.model.originalId, widget.model.uri, widget.type, revoke: active, ) : await interactions.makeInteractionFromId( id, widget.model.originalId, widget.type, revoke: active, ); if (mounted) { setState(() { busy = false; }); } if (status == 200 && mounted) { setState(() { active = !active; icon = active ? widget.type.revokeIcon : widget.type.icon; }); showSuccess(); } else { await showError(status); } } } Future showError(int status) async { ScaffoldMessenger.of(context) .showSnackBar(SnackBar(content: Text("error: $status"))); if (mounted) { setState(() { icon = Icons.dangerous; }); } if (mounted) { await Future.delayed(const Duration(seconds: 1)); setState(() { icon = active ? widget.type.revokeIcon : widget.type.icon; }); } } Future> updateIdentities() async { Map idList = {}; for (int i = 0; i < global.settings!.identities.length; i++) { final Map post = await getPostFromUrl( global.settings!.identities.keys.toList()[i], widget.model.uri); if (post.keys.first == 200) { idList.addAll({ global.settings!.identities.keys.toList()[i]: post[post.keys.first] }); } } return idList; } Future showSuccess() async { if (mounted) { setState(() { success = true; }); } await Future.delayed(const Duration(seconds: 1)); if (mounted) { setState(() { success = false; }); } } @override Widget build(BuildContext context) { if (!widget.model.visibility.boostable && widget.type == interactions.InteractionType.reblog) { return const Icon(Icons.lock); } if (success) { return const Icon(Icons.check); } if (busy) { return Center( heightFactor: 1, widthFactor: 1, child: SizedBox( height: Theme.of(context).iconTheme.size, width: Theme.of(context).iconTheme.size, child: const CircularProgressIndicator(), ), ); } if (!widget.extended) { return IconButton( tooltip: widget.type.name, onPressed: () async { await sendRequest( id: widget.model.identity, ); }, icon: Icon(icon), ); } return TextButton.icon( label: Text("${widget.type.name} ${"on-remote-instance".i18n()}"), onPressed: () async { if (mounted) { setState(() { busy = true; }); } final idList = await updateIdentities(); if (mounted) { setState(() { busy = false; }); } if (mounted) { await showModalBottomSheet( context: context, builder: ((context) { SizedBox box = const SizedBox( height: 24, ); List c = [ box, SelectableText( widget.type.name, style: Theme.of(context).textTheme.displayLarge, ), box ]; idList.forEach( (key, value) { if (value != null) { c.add( TextButton.icon( onPressed: () async { Navigator.of(context).pop(); if (mounted) { setState(() { busy = true; }); } final result = await interactions.makeInteractionFromId( key, value.id, widget.type, revoke: isActive(value), ); if (mounted) { setState(() { busy = false; }); } if (result != 200) { showError(result); } else { showSuccess(); } }, icon: Icon( isActive(value) ? widget.type.revokeIcon : widget.type.icon, ), label: Text(key), ), ); } }, ); c.add(box); return SingleChildScrollView( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: c, ), ); })); } }, icon: Icon(icon)); } }