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

480 lines
15 KiB
Dart
Raw Normal View History

2019-01-29 06:34:52 +01:00
import 'dart:core';
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
2019-11-08 11:29:08 +01:00
import 'package:git_touch/models/theme.dart';
2020-01-12 08:44:07 +01:00
import 'package:git_touch/widgets/label.dart';
2019-11-08 11:29:08 +01:00
import 'package:provider/provider.dart';
2019-01-31 07:37:25 +01:00
import '../utils/utils.dart';
2019-02-07 07:35:19 +01:00
import 'comment_item.dart';
2020-11-08 12:54:18 +01:00
TextSpan createUserSpan(BuildContext context, String login) {
return createLinkSpan(context, login, '/github/$login');
}
2019-09-07 11:48:59 +02:00
class TimelineEventItem extends StatelessWidget {
final String actor;
final IconData iconData;
final Color iconColor;
final TextSpan textSpan;
2020-01-12 09:03:11 +01:00
final p;
2019-09-07 11:48:59 +02:00
TimelineEventItem({
this.actor,
this.iconData = Octicons.octoface,
2020-01-12 08:44:07 +01:00
this.iconColor = Colors.grey,
2019-09-07 11:48:59 +02:00
this.textSpan,
2020-01-12 09:03:11 +01:00
this.p,
2019-09-07 11:48:59 +02:00
});
2019-09-07 11:48:59 +02:00
@override
Widget build(BuildContext context) {
2019-11-08 11:29:08 +01:00
final theme = Provider.of<ThemeModel>(context);
return Row(
children: <Widget>[
2019-09-07 11:48:59 +02:00
SizedBox(width: 6),
Icon(iconData, color: iconColor, size: 20),
2019-09-07 11:48:59 +02:00
SizedBox(width: 12),
Expanded(
2020-01-26 16:44:45 +01:00
child: Text.rich(
TextSpan(
2020-01-27 08:11:51 +01:00
style: TextStyle(color: theme.palette.text, fontSize: 16),
2019-11-08 11:29:08 +01:00
children: [
// TODO: actor is null
createUserSpan(context, actor),
textSpan,
// TextSpan(text: ' ' + TimeAgo.formatFromString(item['createdAt']))
],
),
),
),
],
);
}
2019-09-07 11:48:59 +02:00
}
class TimelineItem extends StatelessWidget {
2020-01-12 09:03:11 +01:00
final Map<String, dynamic> p;
2020-01-30 10:20:36 +01:00
TimelineItem(this.p);
2019-09-07 11:48:59 +02:00
TextSpan _buildReviewText(BuildContext context, item) {
switch (item['state']) {
case 'APPROVED':
return TextSpan(text: ' approved these changes');
case 'COMMENTED':
2019-11-30 17:22:19 +01:00
return TextSpan(text: ' reviewed ');
2019-09-07 11:48:59 +02:00
default:
return warningSpan;
}
}
2020-01-12 08:44:07 +01:00
InlineSpan _buildLabel(p) {
return WidgetSpan(
2020-01-14 06:51:53 +01:00
child: MyLabel(
2020-01-12 08:44:07 +01:00
name: p['label']['name'],
cssColor: p['label']['color'],
2019-02-04 11:32:39 +01:00
),
2019-01-29 06:34:52 +01:00
);
}
2019-11-30 17:22:19 +01:00
Widget _buildByType(BuildContext context, String type) {
2019-11-30 16:49:05 +01:00
final theme = Provider.of<ThemeModel>(context);
2019-09-07 11:48:59 +02:00
var defaultItem = TimelineEventItem(
2019-02-08 07:30:22 +01:00
actor: '',
iconData: Octicons.octoface,
textSpan: TextSpan(children: [
TextSpan(text: 'Woops, $type type not implemented yet'),
]),
2020-01-12 09:03:11 +01:00
p: p,
2019-02-08 07:30:22 +01:00
);
switch (type) {
// common types
2020-01-12 09:03:11 +01:00
case 'PullRequestCommit':
2019-09-07 11:48:59 +02:00
return TimelineEventItem(
2020-01-12 09:03:11 +01:00
actor: p['prCommit']['author']['user'] == null
2019-02-18 11:54:06 +01:00
? null
2020-01-12 09:03:11 +01:00
: p['prCommit']['author']['user']['login'],
2019-02-08 07:30:22 +01:00
iconData: Octicons.git_commit,
textSpan: TextSpan(children: [
2019-02-08 07:30:22 +01:00
TextSpan(text: ' added commit '),
2020-01-12 09:03:11 +01:00
TextSpan(text: p['prCommit']['oid'].substring(0, 8))
]),
2020-01-12 09:03:11 +01:00
p: p,
);
2019-02-08 07:30:22 +01:00
case 'IssueComment':
2020-01-30 10:20:36 +01:00
return CommentItem.gh(p);
2019-02-08 07:30:22 +01:00
case 'CrossReferencedEvent':
2020-10-08 08:30:13 +02:00
final number = p['source']['number'] as int;
final owner = p['source']['repository']['owner']['login'] as String;
final name = p['source']['repository']['name'] as String;
final prefix = p['source']['__typename'] == 'Issue' ? 'issues' : 'pull';
2019-09-07 11:48:59 +02:00
return TimelineEventItem(
2020-01-12 09:03:11 +01:00
actor: p['actor']['login'],
2019-02-08 07:30:22 +01:00
iconData: Octicons.primitive_dot,
2019-11-08 13:23:09 +01:00
iconColor: GithubPalette.open,
2020-10-08 08:30:13 +02:00
textSpan: TextSpan(children: [
TextSpan(text: ' referenced this on '),
createLinkSpan(context, '$owner/$name#$number',
'/github/$owner/$name/$prefix/$number'),
]),
2020-01-12 09:03:11 +01:00
p: p,
);
case 'ClosedEvent':
2019-09-07 11:48:59 +02:00
return TimelineEventItem(
2020-01-12 09:03:11 +01:00
actor: p['actor']['login'],
iconData: Octicons.circle_slash,
2019-11-08 13:23:09 +01:00
iconColor: GithubPalette.closed,
textSpan: TextSpan(text: ' closed this '),
2020-01-12 09:03:11 +01:00
p: p,
);
2019-02-08 07:30:22 +01:00
case 'ReopenedEvent':
2019-09-07 11:48:59 +02:00
return TimelineEventItem(
2020-01-12 09:03:11 +01:00
actor: p['actor']['login'],
iconData: Octicons.primitive_dot,
2019-11-08 13:23:09 +01:00
iconColor: GithubPalette.open,
textSpan: TextSpan(text: ' reopened this '),
2020-01-12 09:03:11 +01:00
p: p,
);
2019-02-08 07:30:22 +01:00
case 'SubscribedEvent':
2020-02-09 14:16:26 +01:00
return TimelineEventItem(
actor: p['actor']['login'],
textSpan: TextSpan(text: ' subscribed to this issue '),
p: p,
);
2019-02-08 07:30:22 +01:00
case 'UnsubscribedEvent':
2020-04-16 05:36:48 +02:00
return TimelineEventItem(
2020-04-08 14:39:29 +02:00
actor: p['actor']['login'],
textSpan: TextSpan(text: ' unsubscribed from this issue '),
p: p,
);
2019-02-08 07:30:22 +01:00
case 'ReferencedEvent':
// TODO: isCrossRepository
2020-01-12 09:03:11 +01:00
if (p['commit'] == null) {
2019-02-08 07:30:22 +01:00
return Container();
}
2020-04-16 05:36:48 +02:00
if (p['isCrossRepository']) {
2020-04-08 14:39:29 +02:00
return TimelineEventItem(
actor: p['actor']['login'],
iconData: Octicons.bookmark,
textSpan: TextSpan(children: [
TextSpan(text: ' referenced this pull request from commit '),
TextSpan(text: p['commit']['oid'].substring(0, 8)),
TextSpan(text: ' from ' + p['commitRepository']['name']),
]),
p: p,
);
}
2019-09-07 11:48:59 +02:00
return TimelineEventItem(
2020-01-12 09:03:11 +01:00
actor: p['actor']['login'],
2019-02-08 07:30:22 +01:00
iconData: Octicons.bookmark,
textSpan: TextSpan(children: [
TextSpan(text: ' referenced this pull request from commit '),
2020-01-12 09:03:11 +01:00
TextSpan(text: p['commit']['oid'].substring(0, 8)),
2019-02-08 07:30:22 +01:00
]),
2020-01-12 09:03:11 +01:00
p: p,
2019-02-08 07:30:22 +01:00
);
case 'AssignedEvent':
2019-09-07 11:48:59 +02:00
return TimelineEventItem(
2020-01-12 09:03:11 +01:00
actor: p['actor']['login'],
2019-02-08 07:30:22 +01:00
iconData: Octicons.key,
textSpan: TextSpan(children: [
TextSpan(text: ' assigned this to '),
createLinkSpan(context, p['assignee']['login'],
'/github/' + p['assignee']['login']),
2019-02-08 07:30:22 +01:00
]),
2020-01-12 09:03:11 +01:00
p: p,
);
2019-02-08 07:30:22 +01:00
case 'UnassignedEvent':
2020-04-08 14:39:29 +02:00
return TimelineEventItem(
actor: p['actor']['login'],
iconData: Octicons.key,
textSpan: TextSpan(children: [
TextSpan(text: ' unassigned this from '),
createLinkSpan(context, p['assignee']['login'],
'/github/' + p['assignee']['login']),
2020-04-08 14:39:29 +02:00
]),
p: p,
);
2019-01-29 06:34:52 +01:00
case 'LabeledEvent':
2019-09-07 11:48:59 +02:00
return TimelineEventItem(
2020-01-12 09:03:11 +01:00
actor: p['actor']['login'],
2019-01-29 06:34:52 +01:00
iconData: Octicons.tag,
textSpan: TextSpan(children: [
TextSpan(text: ' added '),
2020-01-12 09:03:11 +01:00
_buildLabel(p),
2019-01-29 06:34:52 +01:00
TextSpan(text: ' label'),
]),
2020-01-12 09:03:11 +01:00
p: p,
2019-01-29 06:34:52 +01:00
);
case 'UnlabeledEvent':
2019-09-07 11:48:59 +02:00
return TimelineEventItem(
2020-01-12 09:03:11 +01:00
actor: p['actor']['login'],
2019-01-29 06:34:52 +01:00
iconData: Octicons.tag,
textSpan: TextSpan(children: [
TextSpan(text: ' removed '),
2020-01-12 09:03:11 +01:00
_buildLabel(p),
2019-01-29 06:34:52 +01:00
TextSpan(text: ' label'),
]),
2020-01-12 09:03:11 +01:00
p: p,
2019-01-29 06:34:52 +01:00
);
2019-02-08 07:30:22 +01:00
2019-01-29 06:34:52 +01:00
case 'MilestonedEvent':
2019-09-07 11:48:59 +02:00
return TimelineEventItem(
2020-01-12 09:03:11 +01:00
actor: p['actor']['login'],
2019-01-29 06:34:52 +01:00
iconData: Octicons.milestone,
textSpan: TextSpan(children: [
TextSpan(text: ' added this to '),
2020-01-12 09:03:11 +01:00
TextSpan(text: p['milestoneTitle']),
2019-01-29 06:34:52 +01:00
TextSpan(text: ' milestone'),
]),
2020-01-12 09:03:11 +01:00
p: p,
2019-01-29 06:34:52 +01:00
);
2019-02-08 07:30:22 +01:00
case 'DemilestonedEvent':
2020-04-08 14:39:29 +02:00
return TimelineEventItem(
actor: p['actor']['login'],
iconData: Octicons.milestone,
textSpan: TextSpan(children: [
TextSpan(text: ' removed this from '),
TextSpan(text: p['milestoneTitle']),
TextSpan(text: ' milestone'),
]),
p: p,
);
2019-02-08 07:30:22 +01:00
case 'RenamedTitleEvent':
2019-09-07 11:48:59 +02:00
return TimelineEventItem(
2020-01-12 09:03:11 +01:00
actor: p['actor']['login'],
2019-02-08 07:30:22 +01:00
iconData: Octicons.pencil,
2019-01-29 06:34:52 +01:00
textSpan: TextSpan(children: [
2019-02-08 07:30:22 +01:00
TextSpan(text: ' changed the title '),
TextSpan(
2020-01-12 09:03:11 +01:00
text: p['previousTitle'],
2019-02-08 07:30:22 +01:00
style: TextStyle(decoration: TextDecoration.lineThrough),
),
TextSpan(text: ' to '),
2020-01-12 09:03:11 +01:00
TextSpan(text: p['currentTitle'])
2019-01-29 06:34:52 +01:00
]),
2020-01-12 09:03:11 +01:00
p: p,
2019-01-29 06:34:52 +01:00
);
2019-02-08 07:30:22 +01:00
case 'LockedEvent':
2019-09-07 11:48:59 +02:00
return TimelineEventItem(
2020-01-12 09:03:11 +01:00
actor: p['actor']['login'],
2019-02-08 07:30:22 +01:00
iconData: Octicons.lock,
2019-01-29 06:34:52 +01:00
textSpan: TextSpan(children: [
2019-02-08 07:30:22 +01:00
TextSpan(text: ' locked this conversation '),
2019-01-29 06:34:52 +01:00
]),
2020-01-12 09:03:11 +01:00
p: p,
2019-01-29 06:34:52 +01:00
);
2019-02-08 07:30:22 +01:00
case 'UnlockedEvent':
2019-09-07 11:48:59 +02:00
return TimelineEventItem(
2020-01-12 09:03:11 +01:00
actor: p['actor']['login'],
2019-01-29 06:34:52 +01:00
iconData: Octicons.key,
textSpan: TextSpan(children: [
2019-02-08 07:30:22 +01:00
TextSpan(text: ' unlocked this conversation '),
2019-01-29 06:34:52 +01:00
]),
2020-01-12 09:03:11 +01:00
p: p,
2019-01-29 06:34:52 +01:00
);
2019-02-08 07:30:22 +01:00
// issue only types
case 'TransferredEvent':
2020-04-16 05:36:48 +02:00
return TimelineEventItem(
2020-04-08 14:39:29 +02:00
actor: p['actor']['login'],
2020-04-16 05:36:48 +02:00
textSpan: TextSpan(
2020-04-08 14:39:29 +02:00
children: [
2020-04-16 05:36:48 +02:00
TextSpan(
text: ' transferred this issue from ' +
p['fromRepository']['name'])
2020-04-08 14:39:29 +02:00
],
),
);
2019-02-08 07:30:22 +01:00
// pull request only types
case 'CommitCommentThread':
return defaultItem; // TODO:
case 'PullRequestReview':
2019-09-07 11:48:59 +02:00
return TimelineEventItem(
2020-01-12 09:03:11 +01:00
actor: p['author']['login'],
2019-11-08 13:23:09 +01:00
iconColor: GithubPalette.open,
iconData: Octicons.check,
2020-01-12 09:03:11 +01:00
textSpan: _buildReviewText(context, p),
p: p,
);
2019-02-08 07:30:22 +01:00
case 'PullRequestReviewThread':
case 'PullRequestReviewComment':
return defaultItem; // TODO:
case 'MergedEvent':
2019-09-07 11:48:59 +02:00
return TimelineEventItem(
2020-01-12 09:03:11 +01:00
actor: p['actor']['login'],
iconData: Octicons.git_merge,
2019-11-08 13:23:09 +01:00
iconColor: GithubPalette.merged,
textSpan: TextSpan(children: [
TextSpan(text: ' merged commit '),
2020-01-12 09:03:11 +01:00
TextSpan(text: p['commit']['oid'].substring(0, 8)),
TextSpan(text: ' into '),
2020-01-12 09:03:11 +01:00
TextSpan(text: p['mergeRefName']),
]),
2020-01-12 09:03:11 +01:00
p: p,
);
2020-02-09 14:16:26 +01:00
case 'MentionedEvent':
return TimelineEventItem(
actor: p['actor']['login'],
iconData: Octicons.bookmark,
2020-02-09 14:25:51 +01:00
textSpan: TextSpan(text: ' was mentioned '),
2020-02-09 14:16:26 +01:00
);
case 'PinnedEvent':
return TimelineEventItem(
actor: p['actor']['login'],
iconData: Octicons.pin,
textSpan: TextSpan(text: ' pinned this issue '),
);
2019-02-08 07:30:22 +01:00
case 'DeployedEvent':
2020-04-16 05:36:48 +02:00
return TimelineEventItem(
2020-04-08 14:39:29 +02:00
actor: p['actor']['login'],
2020-04-16 05:36:48 +02:00
textSpan: TextSpan(
text: ' deployed the pull request ' + p['pullRequest']['name']),
2020-04-08 14:39:29 +02:00
);
2019-02-08 07:30:22 +01:00
case 'DeploymentEnvironmentChangedEvent':
2020-04-16 05:36:48 +02:00
return TimelineEventItem(
2020-04-08 14:39:29 +02:00
actor: p['actor']['login'],
2020-04-16 05:36:48 +02:00
textSpan: TextSpan(
text: ' changed the deployment environment to ' +
p['deploymentStatus']['deployment']['environment']),
2020-04-08 14:39:29 +02:00
);
case 'HeadRefDeletedEvent':
2019-09-07 11:48:59 +02:00
return TimelineEventItem(
2020-01-12 09:03:11 +01:00
actor: p['actor']['login'],
iconData: Octicons.git_branch,
textSpan: TextSpan(children: [
TextSpan(text: ' deleted the '),
2020-01-12 09:03:11 +01:00
TextSpan(text: p['headRefName']),
TextSpan(text: ' branch'),
]),
2020-01-12 09:03:11 +01:00
p: p,
);
2019-02-08 07:30:22 +01:00
case 'HeadRefRestoredEvent':
2020-04-16 05:36:48 +02:00
return TimelineEventItem(
2020-04-08 14:39:29 +02:00
actor: p['actor']['login'],
2020-04-16 05:36:48 +02:00
textSpan: TextSpan(children: [
TextSpan(text: ' restored the '),
WidgetSpan(
2020-10-11 16:12:53 +02:00
child: PrimerBranchName(p['pullRequest']['headRefName'])),
2020-04-16 05:36:48 +02:00
TextSpan(text: ' branch')
]),
2020-04-08 14:39:29 +02:00
);
2019-02-08 07:30:22 +01:00
case 'HeadRefForcePushedEvent':
2019-11-30 16:49:05 +01:00
return TimelineEventItem(
iconData: Octicons.repo_force_push,
2020-01-12 09:03:11 +01:00
actor: p['actor']['login'],
2019-11-30 16:49:05 +01:00
textSpan: TextSpan(
children: [
TextSpan(text: ' force-pushed the '),
WidgetSpan(
2020-10-11 16:12:53 +02:00
child: PrimerBranchName(p['pullRequest']['headRefName'])),
2019-11-30 16:49:05 +01:00
TextSpan(text: ' branch from '),
TextSpan(
2020-01-12 09:03:11 +01:00
text: (p['beforeCommit']['oid'] as String).substring(0, 7),
2020-01-27 08:11:51 +01:00
style: TextStyle(color: theme.palette.primary),
2019-11-30 16:49:05 +01:00
),
TextSpan(text: ' to '),
TextSpan(
2020-01-12 09:03:11 +01:00
text: (p['afterCommit']['oid'] as String).substring(0, 7),
2020-01-27 08:11:51 +01:00
style: TextStyle(color: theme.palette.primary),
2019-11-30 16:49:05 +01:00
),
],
),
2020-01-12 09:03:11 +01:00
p: p,
2019-11-30 16:49:05 +01:00
);
2019-02-08 07:30:22 +01:00
case 'BaseRefForcePushedEvent':
2020-04-08 14:39:29 +02:00
return TimelineEventItem(
iconData: Octicons.repo_force_push,
actor: p['actor']['login'],
textSpan: TextSpan(
children: [
TextSpan(text: ' force-pushed the '),
WidgetSpan(
child: PrimerBranchName(p['pullRequest']['baseRef']['name'])),
TextSpan(text: ' branch from '),
TextSpan(
text: (p['beforeCommit']['oid'] as String).substring(0, 7),
style: TextStyle(color: theme.palette.primary),
),
TextSpan(text: ' to '),
TextSpan(
text: (p['afterCommit']['oid'] as String).substring(0, 7),
style: TextStyle(color: theme.palette.primary),
),
],
),
p: p,
);
2019-02-08 07:30:22 +01:00
case 'ReviewRequestedEvent':
2019-09-07 11:48:59 +02:00
return TimelineEventItem(
2019-02-08 07:30:22 +01:00
iconData: Octicons.eye,
2020-01-12 09:03:11 +01:00
actor: p['actor']['login'],
textSpan: TextSpan(children: [
2019-02-08 07:30:22 +01:00
TextSpan(text: ' requested a review from '),
2020-01-12 09:03:11 +01:00
createUserSpan(context, p['requestedReviewer']['login']),
]),
2020-01-12 09:03:11 +01:00
p: p,
);
2019-02-08 07:30:22 +01:00
case 'ReviewRequestRemovedEvent':
2020-04-08 14:39:29 +02:00
return TimelineEventItem(
iconData: Octicons.eye,
actor: p['actor']['login'],
textSpan: TextSpan(children: [
TextSpan(text: ' removed '),
createUserSpan(context, p['requestedReviewer']['login']),
TextSpan(text: ' from the review request '),
]),
p: p,
);
2019-02-08 07:30:22 +01:00
case 'ReviewDismissedEvent':
2020-04-16 05:36:48 +02:00
return TimelineEventItem(
2020-04-08 14:39:29 +02:00
iconData: Octicons.eye,
actor: p['actor']['login'],
textSpan: TextSpan(children: [
TextSpan(text: ' dismissed the pull request review requested by '),
createUserSpan(context, p['pullRequest']['author']['login'])
]),
);
default:
2019-02-08 07:30:22 +01:00
return defaultItem;
}
}
@override
Widget build(BuildContext context) {
2020-01-12 09:03:11 +01:00
final type = p['__typename'] as String;
2019-11-30 17:22:19 +01:00
Widget widget = Container(
2019-10-02 10:09:54 +02:00
padding: CommonStyle.padding,
2019-11-30 17:22:19 +01:00
child: _buildByType(context, type),
);
2019-11-30 17:22:19 +01:00
if (type == 'PullRequestReview') {
2020-01-12 09:03:11 +01:00
final comments = p['comments']['nodes'] as List;
2019-11-30 17:22:19 +01:00
if (comments.isNotEmpty) {
widget = Column(
children: <Widget>[
widget,
Container(
padding: CommonStyle.padding.copyWith(left: 50),
child: Column(
2020-01-30 10:20:36 +01:00
children: <Widget>[
for (var v in comments) CommentItem.gh(v),
],
),
2019-11-30 17:22:19 +01:00
),
],
);
}
}
return widget;
}
}