loris/lib/partials/interaction_button.dart

246 lines
7.0 KiB
Dart

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<InteractionButton> createState() => _InteractionButtonState();
}
class _InteractionButtonState extends State<InteractionButton> {
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<void> 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<void> 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<Map<String, PostModel?>> updateIdentities() async {
Map<String, PostModel?> idList = {};
for (int i = 0; i < global.settings!.identities.length; i++) {
final Map<int, PostModel?> 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<void> 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) {
List<Widget> c = [
SelectableText(
widget.type.name,
style: Theme.of(context).textTheme.displayLarge,
)
];
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),
),
);
}
},
);
return SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: c,
),
);
}));
}
},
icon: Icon(icon));
}
}