git-touch-android-ios-app/lib/widgets/comment_item.dart

253 lines
7.7 KiB
Dart
Raw Normal View History

2022-09-24 20:46:37 +02:00
import 'package:antd_mobile/antd_mobile.dart';
2022-09-17 14:35:45 +02:00
import 'package:flutter/widgets.dart';
2020-01-30 10:20:36 +01:00
import 'package:git_touch/models/auth.dart';
import 'package:git_touch/models/theme.dart';
2022-09-23 20:22:17 +02:00
import 'package:git_touch/utils/utils.dart';
2020-02-08 06:02:12 +01:00
import 'package:git_touch/widgets/action_button.dart';
2022-09-23 20:22:17 +02:00
import 'package:git_touch/widgets/avatar.dart';
import 'package:git_touch/widgets/link.dart';
import 'package:git_touch/widgets/markdown_view.dart';
2022-09-23 20:22:17 +02:00
import 'package:git_touch/widgets/user_name.dart';
import 'package:gql_github/issue.data.gql.dart';
import 'package:gql_github/schema.schema.gql.dart';
2022-09-13 19:19:52 +02:00
import 'package:primer/primer.dart';
import 'package:provider/provider.dart';
2019-08-31 14:44:59 +02:00
import 'package:timeago/timeago.dart' as timeago;
2022-09-13 19:19:52 +02:00
2021-01-31 12:27:45 +01:00
class EmojiPayload {
EmojiPayload({
2021-05-16 09:16:35 +02:00
required this.key,
required this.text,
required this.count,
required this.reacted,
2021-01-31 12:27:45 +01:00
});
2022-09-21 18:28:21 +02:00
GReactionContent key;
String text;
int count;
bool reacted;
2021-01-31 12:27:45 +01:00
}
typedef EmojiUpdateCallaback = void Function(GReactionContent data);
2020-01-30 10:20:36 +01:00
class GhEmojiAction extends StatefulWidget {
2021-01-31 12:27:45 +01:00
GhEmojiAction(this.id, GReactableParts r, this.onReaction)
: items = [
EmojiPayload(
key: GReactionContent.THUMBS_UP,
text: '👍',
count: r.THUMBS_UP.totalCount,
reacted: r.THUMBS_UP.viewerHasReacted,
),
EmojiPayload(
key: GReactionContent.THUMBS_DOWN,
text: '👎',
count: r.THUMBS_DOWN.totalCount,
reacted: r.THUMBS_DOWN.viewerHasReacted,
),
EmojiPayload(
key: GReactionContent.LAUGH,
text: '😄',
count: r.LAUGH.totalCount,
reacted: r.LAUGH.viewerHasReacted,
),
EmojiPayload(
key: GReactionContent.HOORAY,
text: '🎉',
count: r.HOORAY.totalCount,
reacted: r.HOORAY.viewerHasReacted,
),
EmojiPayload(
key: GReactionContent.CONFUSED,
text: '😕',
count: r.CONFUSED.totalCount,
reacted: r.CONFUSED.viewerHasReacted,
),
EmojiPayload(
key: GReactionContent.HEART,
text: '❤️',
count: r.HEART.totalCount,
reacted: r.HEART.viewerHasReacted,
),
EmojiPayload(
key: GReactionContent.ROCKET,
text: '🚀',
count: r.ROCKET.totalCount,
reacted: r.ROCKET.viewerHasReacted,
),
EmojiPayload(
key: GReactionContent.EYES,
text: '👀',
count: r.EYES.totalCount,
reacted: r.EYES.viewerHasReacted,
),
];
2022-09-21 18:28:21 +02:00
final String? id;
final Iterable<EmojiPayload> items;
final EmojiUpdateCallaback onReaction;
2020-01-30 10:20:36 +01:00
@override
2022-10-03 19:05:29 +02:00
State<GhEmojiAction> createState() => _GhEmojiActionState();
2020-01-30 10:20:36 +01:00
}
2020-01-30 10:20:36 +01:00
class _GhEmojiActionState extends State<GhEmojiAction> {
2021-01-31 12:27:45 +01:00
_onReaction(EmojiPayload item) async {
final op = item.reacted ? 'remove' : 'add';
2021-01-31 12:27:45 +01:00
await context.read<AuthModel>().query('''
2020-01-30 10:20:36 +01:00
mutation {
2021-01-31 12:27:45 +01:00
${op}Reaction(input: {subjectId: "${widget.id}", content: ${item.key.name}}) {
2020-01-30 10:20:36 +01:00
clientMutationId
}
}
''');
2021-01-31 12:27:45 +01:00
setState(() {
item.reacted = !item.reacted;
if (item.reacted) {
item.count++;
} else {
item.count--;
}
});
// TODO: should set state from parent widgets
// widget.onReaction(item.key);
2019-04-05 15:19:00 +02:00
}
2020-01-30 10:20:36 +01:00
@override
Widget build(BuildContext context) {
final theme = Provider.of<ThemeModel>(context);
return Wrap(
crossAxisAlignment: WrapCrossAlignment.center,
children: [
2021-01-31 12:27:45 +01:00
for (final item in widget.items)
if (item.count > 0)
2021-05-16 09:16:35 +02:00
LinkWidget(
2021-01-31 12:27:45 +01:00
onTap: () {
_onReaction(item);
},
child: Container(
2022-09-06 18:28:12 +02:00
padding: const EdgeInsets.all(4),
2021-01-31 12:27:45 +01:00
decoration: BoxDecoration(
color: item.reacted
? (theme.brightness == Brightness.dark
? PrimerColors.blue900
: PrimerColors.blue000)
: Colors.transparent,
),
child: Wrap(
crossAxisAlignment: WrapCrossAlignment.center,
children: <Widget>[
2022-09-06 18:28:12 +02:00
Text(item.text, style: const TextStyle(fontSize: 18)),
const SizedBox(width: 4),
2021-01-31 12:27:45 +01:00
Text(numberFormat.format(item.count),
style: TextStyle(
2022-09-24 20:46:37 +02:00
color: AntTheme.of(context).colorPrimary,
fontSize: 14))
2021-01-31 12:27:45 +01:00
],
),
2020-01-30 10:20:36 +01:00
),
),
2021-05-16 09:16:35 +02:00
LinkWidget(
2020-01-30 10:20:36 +01:00
onTap: () async {
2021-01-31 12:27:45 +01:00
await theme.showActions(context, [
for (final item in widget.items)
ActionItem(
text: item.text,
2020-02-08 06:02:12 +01:00
onTap: (_) {
2021-01-31 12:27:45 +01:00
_onReaction(item);
2020-02-08 06:02:12 +01:00
},
2021-01-31 12:27:45 +01:00
)
]);
2020-01-30 10:20:36 +01:00
},
child: Container(
2022-09-06 18:28:12 +02:00
padding: const EdgeInsets.all(4),
2020-01-30 10:20:36 +01:00
child: Wrap(
crossAxisAlignment: WrapCrossAlignment.center,
children: <Widget>[
2022-09-24 20:46:37 +02:00
Text('+',
style: TextStyle(color: AntTheme.of(context).colorPrimary)),
Icon(Octicons.smiley,
color: AntTheme.of(context).colorPrimary, size: 18),
2020-01-30 10:20:36 +01:00
],
),
),
),
],
);
2019-04-05 15:19:00 +02:00
}
2020-01-30 10:20:36 +01:00
}
2022-09-23 20:22:17 +02:00
class CommentItem extends StatelessWidget {
// TODO
2022-09-21 18:28:21 +02:00
const CommentItem({
required this.avatar,
required this.login,
required this.createdAt,
required this.body,
required this.prefix,
this.widgets,
this.commentActionItemList,
});
2020-01-30 10:20:36 +01:00
// p.author could be null (deleted user)
2021-01-31 12:27:45 +01:00
CommentItem.gql(
GCommentParts p, GReactableParts r, EmojiUpdateCallaback onReaction)
2021-01-17 15:08:32 +01:00
: avatar = Avatar(
url: p.author?.avatarUrl ??
'https://avatars.githubusercontent.com/u/10137?s=460&u=b1951d34a583cf12ec0d3b0781ba19be97726318&v=4',
2022-09-06 18:28:12 +02:00
linkUrl: '/github/${p.author?.login ?? 'ghost'}',
2021-01-17 15:08:32 +01:00
),
login = p.author?.login ?? 'ghost',
2021-01-17 15:08:32 +01:00
createdAt = p.createdAt,
body = p.body,
2021-01-31 12:27:45 +01:00
widgets = [GhEmojiAction(p.id, r, onReaction)],
2021-01-17 15:08:32 +01:00
prefix = 'github',
2022-09-21 18:28:21 +02:00
commentActionItemList = [];
final Avatar avatar;
final String? login;
final DateTime? createdAt;
final String? body;
final String prefix;
final List<Widget>? widgets;
final List<ActionItem>? commentActionItemList;
@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Row(children: <Widget>[
2020-01-30 10:20:36 +01:00
avatar,
2022-09-06 18:28:12 +02:00
const SizedBox(width: 8),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
UserName(login, prefix),
2022-09-06 18:28:12 +02:00
const SizedBox(height: 2),
Text(
2021-05-16 09:16:35 +02:00
timeago.format(createdAt!),
2019-11-08 11:29:08 +01:00
style: TextStyle(
2022-09-24 20:46:37 +02:00
color: AntTheme.of(context).colorWeak, fontSize: 13),
),
],
),
),
Align(
alignment: Alignment.centerRight,
child: ActionButton(
iconData: Octicons.kebab_horizontal,
title: 'Comment Actions',
items: [
2021-05-16 09:16:35 +02:00
if (commentActionItemList != null) ...commentActionItemList!
],
)),
]),
2022-09-06 18:28:12 +02:00
const SizedBox(height: 12),
2020-11-08 08:00:13 +01:00
MarkdownFlutterView(body, padding: EdgeInsets.zero), // TODO: link
2022-09-06 18:28:12 +02:00
const SizedBox(height: 12),
2021-05-16 09:16:35 +02:00
if (widgets != null) ...widgets!
],
);
}
}