2022-08-22 18:08:10 +00:00
|
|
|
import 'package:flutter/material.dart';
|
2022-08-28 09:19:25 +00:00
|
|
|
import 'package:localization/localization.dart';
|
2022-08-27 22:29:17 +00:00
|
|
|
import 'package:loris/business_logic/network_tools/get_post_from_url.dart';
|
2022-08-22 18:08:10 +00:00
|
|
|
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 {
|
2022-08-27 22:29:17 +00:00
|
|
|
const InteractionButton(
|
|
|
|
{required this.model,
|
|
|
|
required this.type,
|
|
|
|
Key? key,
|
|
|
|
this.extended = false})
|
2022-08-22 18:08:10 +00:00
|
|
|
: super(key: key);
|
|
|
|
final interactions.InteractionType type;
|
|
|
|
final PostModel model;
|
2022-08-27 22:29:17 +00:00
|
|
|
final bool extended;
|
2022-08-22 18:08:10 +00:00
|
|
|
|
|
|
|
@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;
|
2022-08-27 22:29:17 +00:00
|
|
|
bool success = false;
|
|
|
|
// user is logged into multiple accounts
|
2022-08-22 18:08:10 +00:00
|
|
|
|
2022-08-27 22:29:17 +00:00
|
|
|
// decides if the button has been clicked already
|
|
|
|
bool isActive(PostModel post) {
|
2022-08-22 18:08:10 +00:00
|
|
|
switch (widget.type) {
|
|
|
|
case interactions.InteractionType.favorite:
|
2022-08-27 22:29:17 +00:00
|
|
|
return widget.model.favourited;
|
2022-08-22 18:08:10 +00:00
|
|
|
case interactions.InteractionType.reblog:
|
2022-08-27 22:29:17 +00:00
|
|
|
return widget.model.reblogged;
|
2022-08-22 18:08:10 +00:00
|
|
|
}
|
2022-08-27 22:29:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@override
|
|
|
|
void initState() {
|
|
|
|
active = isActive(widget.model);
|
|
|
|
|
2022-08-22 18:08:10 +00:00
|
|
|
icon = active ? widget.type.revokeIcon : widget.type.icon;
|
|
|
|
super.initState();
|
|
|
|
}
|
|
|
|
|
|
|
|
Future<void> sendRequest({
|
|
|
|
required String id,
|
|
|
|
bool fromUrl = false,
|
|
|
|
}) async {
|
|
|
|
if (!busy) {
|
2022-08-27 22:29:17 +00:00
|
|
|
setState(() {
|
|
|
|
busy = true;
|
|
|
|
});
|
2022-08-22 18:08:10 +00:00
|
|
|
int status = fromUrl
|
|
|
|
? await interactions.makeFullInteraction(
|
|
|
|
id,
|
2022-08-22 21:16:36 +00:00
|
|
|
widget.model.originalId,
|
2022-08-22 18:08:10 +00:00
|
|
|
widget.model.uri,
|
|
|
|
widget.type,
|
|
|
|
revoke: active,
|
|
|
|
)
|
|
|
|
: await interactions.makeInteractionFromId(
|
|
|
|
id,
|
2022-08-22 21:16:36 +00:00
|
|
|
widget.model.originalId,
|
2022-08-22 18:08:10 +00:00
|
|
|
widget.type,
|
|
|
|
revoke: active,
|
|
|
|
);
|
2022-08-28 09:19:25 +00:00
|
|
|
if (mounted) {
|
|
|
|
setState(() {
|
|
|
|
busy = false;
|
|
|
|
});
|
|
|
|
}
|
2022-08-22 18:08:10 +00:00
|
|
|
if (status == 200 && mounted) {
|
|
|
|
setState(() {
|
|
|
|
active = !active;
|
|
|
|
icon = active ? widget.type.revokeIcon : widget.type.icon;
|
|
|
|
});
|
2022-08-27 22:29:17 +00:00
|
|
|
showSuccess();
|
2022-08-22 18:08:10 +00:00
|
|
|
} else {
|
|
|
|
await showError(status);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Future<void> showError(int status) async {
|
|
|
|
ScaffoldMessenger.of(context)
|
|
|
|
.showSnackBar(SnackBar(content: Text("error: $status")));
|
2022-08-28 09:19:25 +00:00
|
|
|
if (mounted) {
|
|
|
|
setState(() {
|
|
|
|
icon = Icons.dangerous;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
if (mounted) {
|
|
|
|
await Future.delayed(const Duration(seconds: 1));
|
|
|
|
setState(() {
|
|
|
|
icon = active ? widget.type.revokeIcon : widget.type.icon;
|
|
|
|
});
|
|
|
|
}
|
2022-08-22 18:08:10 +00:00
|
|
|
}
|
|
|
|
|
2022-08-27 22:29:17 +00:00
|
|
|
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 {
|
2022-08-28 09:19:25 +00:00
|
|
|
if (mounted) {
|
|
|
|
setState(() {
|
|
|
|
success = true;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2022-08-27 22:29:17 +00:00
|
|
|
await Future.delayed(const Duration(seconds: 1));
|
2022-08-28 09:19:25 +00:00
|
|
|
|
|
|
|
if (mounted) {
|
|
|
|
setState(() {
|
|
|
|
success = false;
|
|
|
|
});
|
|
|
|
}
|
2022-08-27 22:29:17 +00:00
|
|
|
}
|
|
|
|
|
2022-08-22 18:08:10 +00:00
|
|
|
@override
|
|
|
|
Widget build(BuildContext context) {
|
2022-08-27 22:29:17 +00:00
|
|
|
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(),
|
|
|
|
),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2022-08-28 10:14:49 +00:00
|
|
|
if (!widget.extended) {
|
2022-08-22 18:08:10 +00:00
|
|
|
return IconButton(
|
2022-08-27 22:29:17 +00:00
|
|
|
tooltip: widget.type.name,
|
2022-08-22 18:08:10 +00:00
|
|
|
onPressed: () async {
|
2022-08-27 22:29:17 +00:00
|
|
|
await sendRequest(
|
|
|
|
id: widget.model.identity,
|
|
|
|
);
|
2022-08-22 18:08:10 +00:00
|
|
|
},
|
|
|
|
icon: Icon(icon),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2022-08-28 09:19:25 +00:00
|
|
|
return TextButton.icon(
|
|
|
|
label: Text("${widget.type.name} ${"on-remote-instance".i18n()}"),
|
2022-08-27 22:29:17 +00:00
|
|
|
onPressed: () async {
|
2022-08-28 09:19:25 +00:00
|
|
|
if (mounted) {
|
|
|
|
setState(() {
|
|
|
|
busy = true;
|
|
|
|
});
|
|
|
|
}
|
2022-08-27 22:29:17 +00:00
|
|
|
final idList = await updateIdentities();
|
2022-08-28 09:19:25 +00:00
|
|
|
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),
|
2022-08-27 22:29:17 +00:00
|
|
|
),
|
2022-08-28 09:19:25 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
);
|
2022-08-28 18:55:23 +00:00
|
|
|
return SingleChildScrollView(
|
|
|
|
child: Column(
|
|
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
|
|
children: c,
|
|
|
|
),
|
2022-08-28 09:19:25 +00:00
|
|
|
);
|
|
|
|
}));
|
|
|
|
}
|
2022-08-27 22:29:17 +00:00
|
|
|
},
|
|
|
|
icon: Icon(icon));
|
2022-08-22 18:08:10 +00:00
|
|
|
}
|
|
|
|
}
|