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

377 lines
13 KiB
Dart
Raw Normal View History

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-11-02 16:36:49 +01:00
import 'package:git_touch/widgets/action_button.dart';
2019-12-20 13:52:49 +01:00
import 'package:primer/primer.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-08 07:21:14 +01:00
final GithubEvent event;
2018-07-05 16:08:19 +02:00
EventItem(this.event);
2019-11-05 14:22:41 +01:00
TextSpan _buildLinkSpan(ThemeModel theme, String text) {
return TextSpan(
text: text,
style: TextStyle(
color: theme.palette.primary,
),
);
}
2018-07-05 16:08:19 +02:00
2019-11-05 14:22:41 +01:00
TextSpan _buildRepo(ThemeModel theme) =>
2019-12-08 07:21:14 +01:00
_buildLinkSpan(theme, event.repo.name);
2019-11-03 16:23:05 +01:00
Iterable<ActionItem> _getUserActions(List<String> users) {
// Remove duplicates
return users.toSet().map((user) {
return ActionItem.user(user);
});
}
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-02-07 10:19:08 +01:00
String detail,
Widget detailWidget,
2019-02-07 10:19:08 +01:00
IconData iconData = Octicons.octoface,
2019-09-08 14:33:04 +02:00
String url,
2019-11-02 16:36:49 +01:00
List<ActionItem> actionItems,
2019-02-07 10:19:08 +01:00
}) {
2019-11-05 14:22:41 +01:00
final theme = Provider.of<ThemeModel>(context);
2019-09-07 11:08:24 +02:00
if (detailWidget == null && detail != null) {
detailWidget =
Text(detail.trim(), overflow: TextOverflow.ellipsis, maxLines: 5);
2019-08-31 15:37:29 +02:00
}
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>[
Link(
url: '/' + event.actor.login,
child: Avatar.small(url: event.actor.avatarUrl),
),
SizedBox(width: 10),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: join(SizedBox(height: 8), [
RichText(
text: TextSpan(
style: TextStyle(
fontSize: 16,
color: theme.palette.text,
2019-08-31 15:37:29 +02:00
),
2019-12-20 13:52:49 +01:00
children: [
_buildLinkSpan(theme, event.actor.login),
...spans,
],
2019-09-07 11:08:24 +02:00
),
2019-12-20 13:52:49 +01:00
),
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Icon(iconData,
color: theme.palette.tertiaryText, size: 14),
SizedBox(width: 4),
Text(timeago.format(event.createdAt),
style: TextStyle(
fontSize: 13,
color: theme.palette.tertiaryText,
)),
// Expanded(child: Container()),
// GestureDetector(
// child: Icon(Icons.more_horiz),
// onTap: () {
// theme.showActions(context, actionItems);
// },
// ),
],
),
if (detailWidget != null)
Container(
padding: EdgeInsets.all(12),
decoration: BoxDecoration(
color: PrimerColors.gray100,
borderRadius: BorderRadius.all(Radius.circular(4))),
child: DefaultTextStyle(
2019-09-12 10:30:35 +02:00
style: TextStyle(
2019-11-05 14:22:41 +01:00
color: theme.palette.text, fontSize: 14),
2019-09-12 10:30:35 +02:00
child: detailWidget,
),
2019-09-07 11:08:24 +02:00
),
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(
text: ' ' + event.type,
2019-11-05 14:22:41 +01:00
style: TextStyle(color: theme.palette.primary),
2019-02-10 05:54:48 +01:00
)
],
iconData: Octicons.octoface,
detail: 'Woops, ${event.type} not implemented yet',
);
2019-12-12 07:02:48 +01:00
}
2019-12-20 13:52:49 +01:00
Widget _buildIssueCard(GithubEventIssue issue, String body) {
return Column(
children: <Widget>[
Row(
children: <Widget>[
Icon(Octicons.issue_opened),
Text('#' + issue.number.toString()),
Text(issue.title),
],
),
SizedBox(height: 4),
if (body != null) Text(body),
],
);
}
2019-12-12 07:02:48 +01:00
@override
build(BuildContext context) {
final theme = Provider.of<ThemeModel>(context);
// all events types here:
// https://developer.github.com/v3/activity/events/types/#event-types--payloads
2019-02-07 10:19:08 +01:00
switch (event.type) {
case 'CheckRunEvent':
case 'CheckSuiteEvent':
case 'CommitCommentEvent':
case 'ContentReferenceEvent':
case 'CreateEvent':
case 'DeleteEvent':
case 'DeploymentEvent':
case 'DeploymentStatusEvent':
case 'DownloadEvent':
case 'FollowEvent':
// TODO:
2019-12-12 07:02:48 +01:00
return _buildDefaultItem(context);
case 'ForkEvent':
2019-12-20 13:52:49 +01:00
final forkeeOwner = event.payload.forkee['owner']['login'] as String;
final forkeeName = event.payload.forkee['name'] as String;
2019-02-07 10:19:08 +01:00
return _buildItem(
context: context,
spans: [
TextSpan(text: ' forked '),
2019-11-05 14:22:41 +01:00
_buildLinkSpan(theme, '$forkeeOwner/$forkeeName'),
TextSpan(text: ' from '),
2019-11-05 14:22:41 +01:00
_buildRepo(theme),
],
iconData: Octicons.repo_forked,
2019-12-12 13:29:56 +01:00
url: '/$forkeeOwner/$forkeeName',
2019-11-02 16:36:49 +01:00
actionItems: [
2019-12-08 07:21:14 +01:00
..._getUserActions([event.actor.login, forkeeOwner]),
2019-11-02 16:36:49 +01:00
ActionItem.repository(forkeeOwner, forkeeName),
2019-11-03 16:23:05 +01:00
ActionItem.repository(event.repoOwner, event.repoName),
2019-11-02 16:36:49 +01:00
],
);
case 'ForkApplyEvent':
case 'GitHubAppAuthorizationEvent':
case 'GistEvent':
case 'GollumEvent':
case 'InstallationEvent':
case 'InstallationRepositoriesEvent':
// TODO:
2019-12-12 07:02:48 +01:00
return _buildDefaultItem(context);
case 'IssueCommentEvent':
2019-12-20 13:52:49 +01:00
final isPullRequest = event.payload.issue.pullRequest != null;
return _buildItem(
context: context,
spans: [
2019-12-20 13:52:49 +01:00
TextSpan(
text:
' commented on ${isPullRequest ? 'pull request' : 'issue'} '),
_buildLinkSpan(theme, '#${event.payload.issue.number}'),
2019-02-07 10:19:08 +01:00
TextSpan(text: ' at '),
2019-11-05 14:22:41 +01:00
_buildRepo(theme),
2019-02-07 10:19:08 +01:00
],
2019-12-20 13:52:49 +01:00
detailWidget:
_buildIssueCard(event.payload.issue, event.payload.comment.body),
iconData: Octicons.comment_discussion,
2019-12-12 13:29:56 +01:00
url:
2019-12-20 13:52:49 +01:00
'/${event.repoOwner}/${event.repoName}/${isPullRequest ? 'pulls' : 'issues'}/${event.payload.issue.number}',
2019-11-02 16:36:49 +01:00
actionItems: [
2019-12-08 07:21:14 +01:00
..._getUserActions([event.actor.login, event.repoOwner]),
2019-12-20 13:52:49 +01:00
ActionItem.pullRequest(
event.repoOwner, event.repoName, event.payload.issue.number),
2019-11-02 16:36:49 +01:00
],
2019-02-07 10:19:08 +01:00
);
case 'IssuesEvent':
2019-12-20 13:52:49 +01:00
final issue = event.payload.issue;
2019-02-07 10:19:08 +01:00
return _buildItem(
context: context,
spans: [
2019-12-20 13:52:49 +01:00
TextSpan(text: ' ${event.payload.action} issue '),
_buildLinkSpan(theme, '#${issue.number}'),
2019-02-07 10:19:08 +01:00
TextSpan(text: ' at '),
2019-11-05 14:22:41 +01:00
_buildRepo(theme),
2019-02-07 10:19:08 +01:00
],
iconData: Octicons.issue_opened,
2019-12-20 13:52:49 +01:00
detailWidget: _buildIssueCard(issue, issue.body),
url: '/${event.repoOwner}/${event.repoName}/issues/${issue.number}',
2019-11-02 16:36:49 +01:00
actionItems: [
2019-12-08 07:21:14 +01:00
..._getUserActions([event.actor.login, event.repoOwner]),
2019-11-02 16:56:10 +01:00
ActionItem.repository(event.repoOwner, event.repoName),
2019-12-20 13:52:49 +01:00
ActionItem.issue(event.repoOwner, event.repoName, issue.number),
2019-11-02 16:36:49 +01:00
],
2019-02-07 10:19:08 +01:00
);
case 'LabelEvent':
case 'MarketplacePurchaseEvent':
case 'MemberEvent':
case 'MembershipEvent':
case 'MilestoneEvent':
case 'OrganizationEvent':
case 'OrgBlockEvent':
case 'PageBuildEvent':
case 'ProjectCardEvent':
case 'ProjectColumnEvent':
case 'ProjectEvent':
case 'PublicEvent':
// TODO:
2019-12-12 07:02:48 +01:00
return _buildDefaultItem(context);
2019-02-07 10:19:08 +01:00
case 'PullRequestEvent':
2019-12-20 13:52:49 +01:00
final pr = event.payload.pullRequest;
2019-02-07 10:19:08 +01:00
return _buildItem(
context: context,
spans: [
2019-12-20 13:52:49 +01:00
TextSpan(text: ' ${event.payload.action} pull request '),
_buildLinkSpan(theme, '#${pr.number}'),
2019-02-07 10:19:08 +01:00
TextSpan(text: ' at '),
2019-11-05 14:22:41 +01:00
_buildRepo(theme),
2019-02-07 10:19:08 +01:00
],
iconData: Octicons.git_pull_request,
2019-12-20 13:52:49 +01:00
detailWidget: _buildIssueCard(pr, pr.body),
url: '/${event.repoOwner}/${event.repoName}/pulls/${pr.number}',
2019-11-02 16:36:49 +01:00
actionItems: [
2019-12-08 07:21:14 +01:00
..._getUserActions([event.actor.login, event.repoOwner]),
2019-11-02 16:56:10 +01:00
ActionItem.repository(event.repoOwner, event.repoName),
2019-12-20 13:52:49 +01:00
ActionItem.pullRequest(event.repoOwner, event.repoName, pr.number),
2019-11-02 16:36:49 +01:00
],
2019-02-07 10:19:08 +01:00
);
case 'PullRequestReviewEvent':
// TODO:
2019-12-12 07:02:48 +01:00
return _buildDefaultItem(context);
2019-02-07 10:19:08 +01:00
case 'PullRequestReviewCommentEvent':
2019-12-20 13:52:49 +01:00
final pr = event.payload.pullRequest;
2019-02-07 10:19:08 +01:00
return _buildItem(
context: context,
spans: [
TextSpan(text: ' reviewed pull request '),
2019-12-20 13:52:49 +01:00
_buildLinkSpan(theme, '#${pr.number}'),
2019-02-07 10:19:08 +01:00
TextSpan(text: ' at '),
2019-11-05 14:22:41 +01:00
_buildRepo(theme),
2019-02-07 10:19:08 +01:00
],
2019-12-20 13:52:49 +01:00
detailWidget: _buildIssueCard(pr, pr.body),
url: '/${event.repoOwner}/${event.repoName}/pulls/${pr.number}',
2019-11-02 16:36:49 +01:00
actionItems: [
2019-12-08 07:21:14 +01:00
..._getUserActions([event.actor.login, event.repoOwner]),
2019-11-02 16:56:10 +01:00
ActionItem.repository(event.repoOwner, event.repoName),
2019-12-20 13:52:49 +01:00
ActionItem.pullRequest(event.repoOwner, event.repoName, pr.number),
2019-11-02 16:36:49 +01:00
],
2019-02-07 10:19:08 +01:00
);
case 'PushEvent':
2019-02-07 10:19:08 +01:00
return _buildItem(
context: context,
2019-12-20 13:52:49 +01:00
spans: [TextSpan(text: ' pushed to '), _buildRepo(theme)],
iconData: Octicons.repo_push,
2019-09-08 14:33:04 +02:00
detailWidget: Column(
2019-12-20 13:52:49 +01:00
crossAxisAlignment: CrossAxisAlignment.start,
children: [
RichText(
text: TextSpan(
style: TextStyle(color: theme.palette.primary),
children: [
TextSpan(
text: event.payload.commits.length.toString() +
' commits to '),
WidgetSpan(
child: PrimerBranchName(
event.payload.ref.replaceFirst('refs/heads/', '')),
2019-09-13 09:55:58 +02:00
),
2019-12-20 13:52:49 +01:00
],
),
),
...event.payload.commits.map((commit) {
return Row(
children: <Widget>[
Text(
commit.sha.substring(0, 7),
style: TextStyle(
color: theme.palette.primary,
fontSize: 13,
fontFamily: CommonStyle.monospace,
),
2019-09-13 09:55:58 +02:00
),
2019-12-20 13:52:49 +01:00
SizedBox(width: 6),
Expanded(
child: Text(
commit.message,
overflow: TextOverflow.ellipsis,
maxLines: 1,
),
)
],
);
}).toList()
],
),
2019-11-02 16:56:10 +01:00
url:
2019-12-20 13:52:49 +01:00
'https://github.com/${event.repoOwner}/${event.repoName}/compare/${event.payload.before}...${event.payload.after}',
2019-11-02 16:36:49 +01:00
actionItems: [
2019-12-08 07:21:14 +01:00
..._getUserActions([event.actor.login, event.repoOwner]),
2019-11-02 16:56:10 +01:00
ActionItem.repository(event.repoOwner, event.repoName),
2019-11-02 16:36:49 +01:00
],
2019-02-07 10:19:08 +01:00
);
case 'ReleaseEvent':
case 'RepositoryEvent':
case 'RepositoryImportEvent':
case 'RepositoryVulnerabilityAlertEvent':
case 'SecurityAdvisoryEvent':
case 'StatusEvent':
case 'TeamEvent':
case 'TeamAddEvent':
// TODO:
2019-12-12 07:02:48 +01:00
return _buildDefaultItem(context);
case 'WatchEvent':
2019-02-07 10:19:08 +01:00
return _buildItem(
context: context,
2019-11-05 14:22:41 +01:00
spans: [TextSpan(text: ' starred '), _buildRepo(theme)],
iconData: Octicons.star,
2019-12-12 13:29:56 +01:00
url: '/${event.repoOwner}/${event.repoName}',
2019-11-02 16:36:49 +01:00
actionItems: [
2019-12-08 07:21:14 +01:00
..._getUserActions([event.actor.login, event.repoOwner]),
2019-11-02 16:56:10 +01:00
ActionItem.repository(event.repoOwner, event.repoName),
2019-11-02 16:36:49 +01:00
],
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
}