2024-07-09 16:44:10 +00:00
|
|
|
import 'package:flutter/material.dart';
|
|
|
|
import 'package:get/get.dart';
|
|
|
|
import 'package:solian/exts.dart';
|
|
|
|
import 'package:solian/models/articles.dart';
|
|
|
|
import 'package:solian/models/reaction.dart';
|
|
|
|
import 'package:solian/providers/auth.dart';
|
|
|
|
import 'package:solian/widgets/posts/post_reaction.dart';
|
|
|
|
|
|
|
|
class ArticleQuickAction extends StatefulWidget {
|
|
|
|
final Article item;
|
|
|
|
final bool isReactable;
|
|
|
|
final void Function(String symbol, int num) onReact;
|
|
|
|
|
|
|
|
const ArticleQuickAction({
|
|
|
|
super.key,
|
|
|
|
required this.item,
|
|
|
|
this.isReactable = true,
|
|
|
|
required this.onReact,
|
|
|
|
});
|
|
|
|
|
|
|
|
@override
|
|
|
|
State<ArticleQuickAction> createState() => _ArticleQuickActionState();
|
|
|
|
}
|
|
|
|
|
|
|
|
class _ArticleQuickActionState extends State<ArticleQuickAction> {
|
|
|
|
bool _isSubmitting = false;
|
|
|
|
|
|
|
|
void showReactMenu() {
|
|
|
|
showModalBottomSheet(
|
|
|
|
useRootNavigator: true,
|
|
|
|
context: context,
|
|
|
|
builder: (context) => PostReactionPopup(
|
|
|
|
reactionList: widget.item.reactionList,
|
|
|
|
onReact: (key, value) {
|
|
|
|
doWidgetReact(key, value.attitude);
|
|
|
|
},
|
|
|
|
),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
Future<void> doWidgetReact(String symbol, int attitude) async {
|
|
|
|
if (!widget.isReactable) return;
|
|
|
|
|
|
|
|
final AuthProvider auth = Get.find();
|
|
|
|
|
|
|
|
if (_isSubmitting) return;
|
|
|
|
if (!await auth.isAuthorized) return;
|
|
|
|
|
|
|
|
final client = auth.configureClient('interactive');
|
|
|
|
|
|
|
|
setState(() => _isSubmitting = true);
|
|
|
|
|
2024-07-10 02:50:10 +00:00
|
|
|
final resp = await client.post('/api/articles/${widget.item.alias}/react', {
|
2024-07-09 16:44:10 +00:00
|
|
|
'symbol': symbol,
|
|
|
|
'attitude': attitude,
|
|
|
|
});
|
|
|
|
if (resp.statusCode == 201) {
|
|
|
|
widget.onReact(symbol, 1);
|
|
|
|
context.showSnackbar('reactCompleted'.tr);
|
|
|
|
} else if (resp.statusCode == 204) {
|
|
|
|
widget.onReact(symbol, -1);
|
|
|
|
context.showSnackbar('reactUncompleted'.tr);
|
|
|
|
} else {
|
|
|
|
context.showErrorDialog(resp.bodyString);
|
|
|
|
}
|
|
|
|
|
|
|
|
setState(() => _isSubmitting = false);
|
|
|
|
}
|
|
|
|
|
|
|
|
@override
|
|
|
|
void initState() {
|
|
|
|
super.initState();
|
|
|
|
|
|
|
|
if (!widget.isReactable && widget.item.reactionList.isEmpty) {
|
|
|
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
|
|
|
widget.onReact('thumb_up', 0);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@override
|
|
|
|
Widget build(BuildContext context) {
|
|
|
|
const density = VisualDensity(horizontal: -4, vertical: -3);
|
|
|
|
|
|
|
|
return SizedBox(
|
|
|
|
height: 32,
|
|
|
|
width: double.infinity,
|
|
|
|
child: Row(
|
|
|
|
mainAxisAlignment: MainAxisAlignment.start,
|
|
|
|
crossAxisAlignment: CrossAxisAlignment.center,
|
|
|
|
children: [
|
|
|
|
Expanded(
|
|
|
|
child: ListView(
|
|
|
|
shrinkWrap: true,
|
|
|
|
scrollDirection: Axis.horizontal,
|
|
|
|
children: [
|
|
|
|
...widget.item.reactionList.entries.map((x) {
|
|
|
|
final info = reactions[x.key];
|
|
|
|
return Padding(
|
|
|
|
padding: const EdgeInsets.only(right: 8),
|
|
|
|
child: ActionChip(
|
|
|
|
avatar: Text(info!.icon),
|
|
|
|
label: Text(x.value.toString()),
|
|
|
|
tooltip: ':${x.key}:',
|
|
|
|
visualDensity: density,
|
|
|
|
onPressed: _isSubmitting
|
|
|
|
? null
|
|
|
|
: () => doWidgetReact(x.key, info.attitude),
|
|
|
|
),
|
|
|
|
);
|
|
|
|
}),
|
|
|
|
if (widget.isReactable)
|
|
|
|
ActionChip(
|
|
|
|
avatar: const Icon(Icons.add_reaction, color: Colors.teal),
|
|
|
|
label: Text('reactAdd'.tr),
|
|
|
|
visualDensity: density,
|
|
|
|
onPressed: () => showReactMenu(),
|
|
|
|
),
|
|
|
|
],
|
|
|
|
),
|
|
|
|
)
|
|
|
|
],
|
|
|
|
),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|