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

595 lines
19 KiB
Dart
Raw Normal View History

2019-12-22 06:00:58 +01:00
import 'package:flutter/gestures.dart';
2018-07-05 16:08:19 +02:00
import 'package:flutter/material.dart';
2019-02-02 17:28:51 +01:00
import 'package:flutter/cupertino.dart';
2019-12-12 07:02:48 +01:00
import 'package:git_touch/models/github.dart';
2019-11-03 16:33:24 +01:00
import 'package:git_touch/models/theme.dart';
2019-12-20 15:41:38 +01:00
import 'package:git_touch/widgets/issue_icon.dart';
2019-11-03 16:33:24 +01:00
import 'package:provider/provider.dart';
2019-08-31 15:37:29 +02:00
import 'package:timeago/timeago.dart' as timeago;
2019-02-07 07:35:19 +01:00
import 'avatar.dart';
import '../widgets/link.dart';
import '../utils/utils.dart';
2018-07-05 16:08:19 +02:00
class EventItem extends StatelessWidget {
2019-12-20 15:41:38 +01:00
final GithubEvent e;
2019-12-20 15:41:38 +01:00
EventItem(this.e);
2018-07-05 16:08:19 +02:00
2019-12-22 06:00:58 +01:00
InlineSpan _buildLinkSpan(BuildContext context, String text, String url) {
final theme = Provider.of<ThemeModel>(context);
2019-11-05 14:22:41 +01:00
return TextSpan(
text: text,
2020-01-27 08:11:51 +01:00
style: TextStyle(color: theme.palette.primary),
2019-12-22 06:00:58 +01:00
recognizer: TapGestureRecognizer()
..onTap = () {
theme.push(context, url);
},
2019-11-05 14:22:41 +01:00
);
}
2018-07-05 16:08:19 +02:00
2019-12-22 06:00:58 +01:00
InlineSpan _buildRepo(BuildContext context, [String fullName]) {
final name = fullName ?? e.repo.name;
return _buildLinkSpan(context, name, '/$name');
}
InlineSpan _buildIssue(BuildContext context, int number,
{bool isPullRequest = false}) {
return _buildLinkSpan(context, '#$number',
2020-01-31 06:35:49 +01:00
'/${e.repoOwner}/${e.repoName}/${isPullRequest ? 'pull' : 'issues'}/$number');
2019-12-22 06:00:58 +01:00
}
2019-02-07 10:19:08 +01:00
Widget _buildItem({
@required BuildContext context,
2019-09-25 07:34:13 +02:00
@required List<InlineSpan> spans,
2019-12-20 15:41:38 +01:00
Widget card,
2019-02-07 10:19:08 +01:00
}) {
2019-11-05 14:22:41 +01:00
final theme = Provider.of<ThemeModel>(context);
2019-12-20 13:52:49 +01:00
return Container(
padding: CommonStyle.padding,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
2019-12-27 08:06:45 +01:00
Avatar(url: e.actor.avatarUrl, linkUrl: '/' + e.actor.login),
2019-12-20 13:52:49 +01:00
SizedBox(width: 10),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
2019-12-25 04:05:25 +01:00
children: join(SizedBox(height: 6), [
2020-01-26 16:44:45 +01:00
Text.rich(
TextSpan(
2019-12-20 13:52:49 +01:00
style: TextStyle(
fontSize: 17,
2020-01-27 08:11:51 +01:00
color: theme.palette.text,
2019-08-31 15:37:29 +02:00
),
2019-12-20 13:52:49 +01:00
children: [
2019-12-22 06:00:58 +01:00
_buildLinkSpan(
context, e.actor.login, '/${e.actor.login}'),
2019-12-20 13:52:49 +01:00
...spans,
],
2019-09-07 11:08:24 +02:00
),
2019-12-20 13:52:49 +01:00
),
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
2019-12-20 15:41:38 +01:00
Text(timeago.format(e.createdAt),
2019-12-20 13:52:49 +01:00
style: TextStyle(
fontSize: 14,
2020-01-27 08:11:51 +01:00
color: theme.palette.tertiaryText,
2019-12-20 13:52:49 +01:00
)),
],
),
2019-12-20 15:41:38 +01:00
if (card != null) card
2019-12-20 13:52:49 +01:00
]),
2019-01-31 07:37:25 +01:00
),
2019-12-20 13:52:49 +01:00
),
],
),
],
2018-07-05 16:08:19 +02:00
),
);
}
2019-02-07 10:19:08 +01:00
2019-12-12 07:02:48 +01:00
Widget _buildDefaultItem(BuildContext context) {
2019-11-05 14:22:41 +01:00
final theme = Provider.of<ThemeModel>(context);
2019-12-12 07:02:48 +01:00
return _buildItem(
context: context,
2019-02-10 05:54:48 +01:00
spans: [
TextSpan(
2019-12-20 15:41:38 +01:00
text: ' ' + e.type,
2020-01-27 08:11:51 +01:00
style: TextStyle(color: theme.palette.primary),
2019-02-10 05:54:48 +01:00
)
],
2019-12-22 06:00:58 +01:00
card: Text('Woops, ${e.type} not implemented yet'),
2019-12-20 15:41:38 +01:00
);
}
Widget _buildCommitsCard(BuildContext context) {
final theme = Provider.of<ThemeModel>(context);
return Link(
url:
'https://github.com/${e.repoOwner}/${e.repoName}/compare/${e.payload.before}...${e.payload.head}',
child: Container(
padding: EdgeInsets.all(12),
decoration: BoxDecoration(
2020-01-27 08:11:51 +01:00
color: theme.palette.grayBackground,
2019-12-20 15:41:38 +01:00
borderRadius: BorderRadius.all(Radius.circular(4))),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
2020-01-26 16:44:45 +01:00
Text.rich(
TextSpan(
2020-01-27 08:11:51 +01:00
style: TextStyle(color: theme.palette.text, fontSize: 15),
2019-12-20 15:41:38 +01:00
children: [
TextSpan(
text:
e.payload.commits.length.toString() + ' commits to '),
WidgetSpan(
child: PrimerBranchName(
e.payload.ref.replaceFirst('refs/heads/', '')),
),
],
),
),
SizedBox(height: 8),
2019-12-20 15:41:38 +01:00
...e.payload.commits.map((commit) {
return Row(
children: <Widget>[
Text(
commit.sha.substring(0, 7),
style: TextStyle(
2020-01-27 08:11:51 +01:00
color: theme.palette.primary,
fontSize: 15,
2019-12-20 15:41:38 +01:00
fontFamily: CommonStyle.monospace,
),
),
SizedBox(width: 6),
Expanded(
child: Text(
commit.message,
overflow: TextOverflow.ellipsis,
maxLines: 1,
2020-01-27 08:11:51 +01:00
style: TextStyle(color: theme.palette.text, fontSize: 15),
2019-12-20 15:41:38 +01:00
),
)
],
);
}).toList()
],
),
),
);
2019-12-12 07:02:48 +01:00
}
2019-12-20 15:41:38 +01:00
Widget _buildIssueCard(
BuildContext context, GithubEventIssue issue, String body,
{isPullRequest = false}) {
final theme = Provider.of<ThemeModel>(context);
IssueIconState state;
if (isPullRequest) {
if (issue.merged == true) {
state = IssueIconState.prMerged;
} else if (issue.state == 'open') {
state = IssueIconState.prOpen;
} else {
state = IssueIconState.prClosed;
}
} else {
if (issue.state == 'open') {
state = IssueIconState.open;
} else {
state = IssueIconState.closed;
}
}
return Link(
url:
2020-01-31 06:35:49 +01:00
'/${e.repoOwner}/${e.repoName}/${isPullRequest ? 'pull' : 'issues'}/${issue.number}',
2019-12-20 15:41:38 +01:00
child: Container(
padding: EdgeInsets.all(12),
decoration: BoxDecoration(
2020-01-27 08:11:51 +01:00
color: theme.palette.grayBackground,
2019-12-20 15:41:38 +01:00
borderRadius: BorderRadius.all(Radius.circular(4))),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
2019-12-25 04:05:25 +01:00
children: join(SizedBox(height: 6), [
2019-12-20 15:41:38 +01:00
Row(
children: <Widget>[
IssueIcon(state, size: 20),
SizedBox(width: 4),
Expanded(
child: Text(
'#' + issue.number.toString() + ' ' + issue.title,
style: TextStyle(
fontWeight: FontWeight.w500,
fontSize: 17,
2020-01-27 08:11:51 +01:00
color: theme.palette.text,
2019-12-20 15:41:38 +01:00
),
overflow: TextOverflow.ellipsis,
),
),
],
),
if (body != null && body.isNotEmpty)
2019-12-20 15:41:38 +01:00
Text(
body,
overflow: TextOverflow.ellipsis,
maxLines: 3,
2020-01-27 08:11:51 +01:00
style:
TextStyle(color: theme.palette.secondaryText, fontSize: 15),
2019-12-20 15:41:38 +01:00
),
Row(
children: <Widget>[
2019-12-22 04:11:13 +01:00
Avatar(url: issue.user.avatarUrl, size: AvatarSize.extraSmall),
SizedBox(width: 8),
Text(issue.user.login,
style: TextStyle(
fontSize: 14,
2020-01-27 08:11:51 +01:00
color: theme.palette.tertiaryText,
)),
Expanded(child: Container()),
2019-12-25 04:05:25 +01:00
if (issue.comments != null) ...[
Icon(
Octicons.comment,
size: 14,
2020-01-27 08:11:51 +01:00
color: theme.palette.tertiaryText,
2019-12-25 04:05:25 +01:00
),
SizedBox(width: 4),
Text(issue.comments.toString(),
style: TextStyle(
fontSize: 14,
2020-01-27 08:11:51 +01:00
color: theme.palette.tertiaryText,
2019-12-25 04:05:25 +01:00
)),
]
],
)
]),
2019-12-20 13:52:49 +01:00
),
2019-12-20 15:41:38 +01:00
),
2019-12-20 13:52:49 +01:00
);
}
2019-12-12 07:02:48 +01:00
@override
build(BuildContext context) {
// all events types here:
// https://developer.github.com/v3/activity/events/types/#event-types--payloads
2019-12-20 15:41:38 +01:00
switch (e.type) {
case 'CheckRunEvent':
return _buildItem(
context: context,
spans: [
TextSpan(text: ' ${e.payload.action} a check run for ${e.payload.checkRun.name} '),
]
);
case 'CheckSuiteEvent':
// Needs checks permission
String conclusion = "";
switch(e.payload.checkSuite.conclusion) {
case 'success':
case 'failure':
conclusion = 'it is a ' + e.payload.checkSuite.conclusion;
break;
case 'neutral':
case 'cancelled':
case 'timed_out':
case 'stale':
conclusion = 'it is ' + e.payload.checkSuite.conclusion;
break;
case 'action_required':
conclusion = ' it requires more action';
break;
}
return _buildItem(
context: context,
spans: [
TextSpan(text: ' ${e.payload.action} the check suite and the conclusion is that $conclusion'),
],
);
case 'CommitCommentEvent':
return _buildItem(
context: context,
spans: [
TextSpan(text: ' ${e.payload.action} a comment on the commit at '),
_buildRepo(context),
TextSpan(text: ' ${e.payload.comment.body} '),
],
card: _buildCommitsCard(context),
);
case 'ContentReferenceEvent':
return _buildItem(
context: context,
spans: [
TextSpan(text: ' ${e.payload.action} a content reference at '),
_buildLinkSpan(
context, e.payload.contentReference.reference, e.payload.contentReference.reference),
]
);
case 'CreateEvent':
2019-12-25 03:56:30 +01:00
return _buildItem(
context: context,
spans: <InlineSpan>[
TextSpan(
2020-02-08 16:23:06 +01:00
text: ' created a ${e.payload.refType} '),
2019-12-25 03:56:30 +01:00
_buildRepo(context),
],
);
case 'DeleteEvent':
2020-02-08 16:23:06 +01:00
return _buildItem(
context: context,
spans: <InlineSpan>[
TextSpan(
text: ' deleted ${e.payload.refType} '
),
_buildRepo(context),
],
);
case 'ForkEvent':
2019-12-20 15:41:38 +01:00
final forkeeOwner = e.payload.forkee['owner']['login'] as String;
final forkeeName = e.payload.forkee['name'] as String;
2019-02-07 10:19:08 +01:00
return _buildItem(
context: context,
spans: [
TextSpan(text: ' forked '),
2019-12-22 06:00:58 +01:00
_buildRepo(context, '$forkeeOwner/$forkeeName'),
TextSpan(text: ' from '),
2019-12-22 06:00:58 +01:00
_buildRepo(context),
],
);
case 'GollumEvent':
String pageNamesCreated = "";
String pageNamesEdited = "";
for(GithubPagesItem page in e.payload.pages) {
if(page.action == "edited") {
pageNamesEdited += ", " + page.pageName;
} else {
pageNamesCreated += ", " + page.pageName;
}
}
if(pageNamesCreated.length > 0) {
pageNamesCreated = " created the pages: \n" + pageNamesCreated + "\n";
}
if(pageNamesEdited.length > 0) {
pageNamesEdited = " edited the pages: \n" + pageNamesEdited + "\n";
}
return _buildItem(
context: context,
spans: [
TextSpan(
text: ' $pageNamesCreated\n$pageNamesEdited '
)
]
);
case 'InstallationEvent':
String action = e.payload.action;
if(action == 'new_permissions_accepted') {
action = "new permission were accepted for";
}
return _buildItem(
context: context,
spans: [
TextSpan(text: ' $action for the Github App with id ${e.payload.installation.id}'),
],
);
case 'InstallationRepositoriesEvent':
List<GithubNotificationItemRepo> repositoriesAdded = e.payload.installation.repositoriesAdded;
List<GithubNotificationItemRepo> repositoriesRemoved = e.payload.installation.repositoriesRemoved;
String addedRepos = "";
String removedRepos = "";
for(GithubNotificationItemRepo repo in repositoriesAdded) {
addedRepos += repo.fullName + ", ";
}
for(GithubNotificationItemRepo repo in repositoriesRemoved) {
removedRepos += repo.fullName + ", ";
}
String finalListOfRepos = "";
if(addedRepos != "") {
finalListOfRepos += addedRepos + " were added to\n ";
}
if(removedRepos != "") {
finalListOfRepos += removedRepos + " were removed from";
}
return _buildItem(
context: context,
spans: [
TextSpan(text: ' $finalListOfRepos the installation id ${e.payload.installation.id} '),
],
);
case 'IssueCommentEvent':
return _buildItem(
context: context,
spans: [
2019-12-20 13:52:49 +01:00
TextSpan(
text:
2019-12-20 15:41:38 +01:00
' commented on ${e.payload.issue.isPullRequestComment ? 'pull request' : 'issue'} '),
2020-01-06 05:50:31 +01:00
_buildIssue(
context,
e.payload.issue.number,
isPullRequest: e.payload.issue.isPullRequestComment,
),
2019-02-07 10:19:08 +01:00
TextSpan(text: ' at '),
2019-12-22 06:00:58 +01:00
_buildRepo(context),
2019-02-07 10:19:08 +01:00
],
2019-12-20 15:41:38 +01:00
card: _buildIssueCard(
context,
e.payload.issue,
e.payload.comment.body,
isPullRequest: e.payload.issue.isPullRequestComment,
),
2019-02-07 10:19:08 +01:00
);
case 'IssuesEvent':
2019-12-20 15:41:38 +01:00
final issue = e.payload.issue;
2019-02-07 10:19:08 +01:00
return _buildItem(
context: context,
spans: [
2019-12-20 15:41:38 +01:00
TextSpan(text: ' ${e.payload.action} issue '),
2019-12-22 06:00:58 +01:00
_buildIssue(context, issue.number),
2019-02-07 10:19:08 +01:00
TextSpan(text: ' at '),
2019-12-22 06:00:58 +01:00
_buildRepo(context),
2019-02-07 10:19:08 +01:00
],
2019-12-20 15:41:38 +01:00
card: _buildIssueCard(context, issue, issue.body),
2019-02-07 10:19:08 +01:00
);
case 'MarketplacePurchaseEvent':
2020-02-08 16:23:06 +01:00
final action = e.payload.action;
var messageToDisplay;
switch(action) {
case "purchased":
messageToDisplay = "purchased a Marketplace Plan";
break;
case "cancelled":
messageToDisplay = "cancelled their Marketplace Plan";
break;
case "pending_change":
messageToDisplay = " Marketplace Plan is pending change";
break;
case "pending_change_cancelled":
messageToDisplay = " Pending Marketplace Plan was cancelled";
break;
case "changed":
messageToDisplay = " changed their Marketplace Plan";
break;
}
return _buildItem(
context: context,
spans: [
TextSpan(
text: ' $messageToDisplay ',
),
_buildRepo(context),
],
);
case 'MemberEvent':
2020-02-08 16:23:06 +01:00
final action = e.payload.action;
return _buildItem(
context: context,
spans: [
TextSpan(
text: ' was ${e.payload.action} ${action == 'added' ? 'to' : 'from' } '),
_buildRepo(context),
],
);
case 'ProjectCardEvent':
String action = e.payload.action;
if(action == 'converted') {
action = ' converted the project card into an issue ';
} else {
action = action + ' the project card ';
}
return _buildItem(
context: context,
spans: [
TextSpan(text: ' $action at '),
_buildRepo(context),
],
);
case 'ProjectColumnEvent':
return _buildItem(
context: context,
spans: [
TextSpan(text: ' ${e.payload.action} the project column ${e.payload.projectColumn.name} at '),
_buildRepo(context),
]
);
case 'ProjectEvent':
return _buildItem(
context: context,
spans: [
TextSpan(text: ' ${e.payload.action} the project ${e.payload.project.name} '),
]
);
case 'PublicEvent':
2020-02-08 16:23:06 +01:00
return _buildItem(
context: context,
spans: [
TextSpan(text: ' made '),
_buildRepo(context),
TextSpan(text: ' public'),
],
2020-02-08 16:23:06 +01:00
);
2019-02-07 10:19:08 +01:00
case 'PullRequestEvent':
2019-12-20 15:41:38 +01:00
final pr = e.payload.pullRequest;
2019-02-07 10:19:08 +01:00
return _buildItem(
context: context,
spans: [
2019-12-20 15:41:38 +01:00
TextSpan(text: ' ${e.payload.action} pull request '),
2019-12-22 06:00:58 +01:00
_buildIssue(context, pr.number, isPullRequest: true),
2019-02-07 10:19:08 +01:00
TextSpan(text: ' at '),
2019-12-22 06:00:58 +01:00
_buildRepo(context),
2019-02-07 10:19:08 +01:00
],
2019-12-20 15:41:38 +01:00
card: _buildIssueCard(context, pr, pr.body, isPullRequest: true),
2019-02-07 10:19:08 +01:00
);
case 'PullRequestReviewEvent':
final pr = e.payload.pullRequest;
return _buildItem(
context: context,
spans: [
TextSpan(text: ' ${e.payload.action} the pull request review '),
_buildIssue(context, pr.number, isPullRequest: true),
TextSpan(text: ' at '),
_buildRepo(context),
]
);
2019-02-07 10:19:08 +01:00
case 'PullRequestReviewCommentEvent':
2019-12-20 15:41:38 +01:00
final pr = e.payload.pullRequest;
2019-02-07 10:19:08 +01:00
return _buildItem(
context: context,
spans: [
TextSpan(text: ' reviewed pull request '),
2019-12-22 06:00:58 +01:00
_buildIssue(context, pr.number, isPullRequest: true),
2019-02-07 10:19:08 +01:00
TextSpan(text: ' at '),
2019-12-22 06:00:58 +01:00
_buildRepo(context),
2019-02-07 10:19:08 +01:00
],
2019-12-25 04:05:25 +01:00
card: _buildIssueCard(context, pr, e.payload.comment.body,
isPullRequest: true),
2019-02-07 10:19:08 +01:00
);
case 'PushEvent':
2019-02-07 10:19:08 +01:00
return _buildItem(
context: context,
2019-12-22 06:00:58 +01:00
spans: [TextSpan(text: ' pushed to '), _buildRepo(context)],
2019-12-20 15:41:38 +01:00
card: _buildCommitsCard(context),
2019-02-07 10:19:08 +01:00
);
case 'ReleaseEvent':
2019-12-25 03:46:56 +01:00
return _buildItem(
context: context,
spans: [
TextSpan(text: ' released '),
_buildLinkSpan(
context, e.payload.release.tagName, e.payload.release.htmlUrl),
TextSpan(text: ' at '),
_buildRepo(context)
],
);
// case 'RepositoryImportEvent':
// // Uses Source Imports API
case 'RepositoryVulnerabilityAlertEvent':
return _buildItem(
context: context,
spans: [
TextSpan(
text: ' Security alert involving the package ${e.payload.alert.affectedPackageName} between versions ${e.payload.alert.affectedRange} was {e.payload.action}ed',
)
]
);
case 'SecurityAdvisoryEvent':
return _buildItem(
context: context,
spans: [
TextSpan(
text: ' Security advisory regarding ${e.payload.securityAdvisory.summary} was ${e.payload.action} ',
)
]
);
case 'WatchEvent':
2019-02-07 10:19:08 +01:00
return _buildItem(
context: context,
2019-12-22 06:00:58 +01:00
spans: [TextSpan(text: ' starred '), _buildRepo(context)],
2019-02-07 10:19:08 +01:00
);
default:
2019-12-12 07:02:48 +01:00
return _buildDefaultItem(context);
2019-02-07 10:19:08 +01:00
}
}
2018-07-05 16:08:19 +02:00
}