654 lines
23 KiB
Dart
654 lines
23 KiB
Dart
import 'package:antd_mobile/antd_mobile.dart';
|
|
import 'package:flutter/cupertino.dart';
|
|
import 'package:flutter/gestures.dart';
|
|
import 'package:flutter/widgets.dart';
|
|
import 'package:flutter_gen/gen_l10n/S.dart';
|
|
import 'package:flutter_vector_icons/flutter_vector_icons.dart';
|
|
import 'package:git_touch/models/github.dart';
|
|
import 'package:git_touch/utils/utils.dart';
|
|
import 'package:git_touch/widgets/avatar.dart';
|
|
import 'package:git_touch/widgets/branch_name.dart';
|
|
import 'package:git_touch/widgets/issue_icon.dart';
|
|
import 'package:git_touch/widgets/link.dart';
|
|
import 'package:timeago/timeago.dart' as timeago;
|
|
|
|
class EventItem extends StatelessWidget {
|
|
const EventItem(this.e);
|
|
final GithubEvent e;
|
|
|
|
InlineSpan _buildLinkSpan(BuildContext context, String? text, String? url) {
|
|
return TextSpan(
|
|
text: text,
|
|
style: TextStyle(color: AntTheme.of(context).colorPrimary),
|
|
recognizer: TapGestureRecognizer()
|
|
..onTap = () {
|
|
context.pushUrl(url!);
|
|
},
|
|
);
|
|
}
|
|
|
|
InlineSpan _buildRepo(BuildContext context, [String? fullName]) {
|
|
final name = fullName ?? e.repo!.name;
|
|
return _buildLinkSpan(context, name, '/github/$name');
|
|
}
|
|
|
|
InlineSpan _buildIssue(BuildContext context, int? number,
|
|
{bool isPullRequest = false}) {
|
|
return _buildLinkSpan(context, '#$number',
|
|
'/github/${e.repoOwner}/${e.repoName}/${isPullRequest ? 'pull' : 'issues'}/$number');
|
|
}
|
|
|
|
Widget _buildItem({
|
|
required BuildContext context,
|
|
required List<InlineSpan> spans,
|
|
Widget? card,
|
|
}) {
|
|
return AntListItem(
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: <Widget>[
|
|
Row(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: <Widget>[
|
|
Avatar(
|
|
url: e.actor!.avatarUrl,
|
|
linkUrl: '/github/${e.actor!.login!}'),
|
|
const SizedBox(width: 10),
|
|
Expanded(
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text.rich(
|
|
TextSpan(
|
|
style: TextStyle(
|
|
fontSize: 17,
|
|
color: AntTheme.of(context).colorText,
|
|
),
|
|
children: [
|
|
_buildLinkSpan(context, e.actor!.login,
|
|
'/github/${e.actor!.login}'),
|
|
...spans,
|
|
],
|
|
),
|
|
),
|
|
Row(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: <Widget>[
|
|
Text(timeago.format(e.createdAt!),
|
|
style: TextStyle(
|
|
fontSize: 14,
|
|
color: AntTheme.of(context).colorWeak,
|
|
)),
|
|
],
|
|
),
|
|
if (card != null) card
|
|
].withSeparator(const SizedBox(height: 6)),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildDefaultItem(BuildContext context) {
|
|
return _buildItem(
|
|
context: context,
|
|
spans: [
|
|
TextSpan(
|
|
text: ' ${e.type!}',
|
|
style: TextStyle(color: AntTheme.of(context).colorPrimary),
|
|
)
|
|
],
|
|
card: Text(
|
|
'${e.type} ${AppLocalizations.of(context)!.timelineTypeNotImplemented}'),
|
|
);
|
|
}
|
|
|
|
Widget _buildCommitsCard(BuildContext context) {
|
|
return LinkWidget(
|
|
url:
|
|
'/github/${e.repoOwner}/${e.repoName}/compare/${e.payload!.before}/${e.payload!.head}',
|
|
child: Container(
|
|
padding: const EdgeInsets.all(12),
|
|
decoration: const BoxDecoration(
|
|
color: Color(0xffcccccc),
|
|
borderRadius: BorderRadius.all(Radius.circular(4))),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text.rich(
|
|
TextSpan(
|
|
style: TextStyle(
|
|
color: AntTheme.of(context).colorText, fontSize: 15),
|
|
children: [
|
|
TextSpan(
|
|
text:
|
|
'${AppLocalizations.of(context)!.nCommitsTo(e.payload!.commits!.length)} '),
|
|
WidgetSpan(
|
|
child: BranchName(
|
|
e.payload!.ref!.replaceFirst('refs/heads/', '')),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
const SizedBox(height: 8),
|
|
...e.payload!.commits!.map((commit) {
|
|
return Row(
|
|
children: <Widget>[
|
|
Text(
|
|
commit.sha!.substring(0, 7),
|
|
style: TextStyle(
|
|
color: AntTheme.of(context).colorPrimary,
|
|
fontSize: 15,
|
|
fontFamily: CommonStyle.monospace,
|
|
),
|
|
),
|
|
const SizedBox(width: 6),
|
|
Expanded(
|
|
child: Text(
|
|
commit.message!,
|
|
overflow: TextOverflow.ellipsis,
|
|
maxLines: 1,
|
|
style: TextStyle(
|
|
color: AntTheme.of(context).colorText, fontSize: 15),
|
|
),
|
|
)
|
|
],
|
|
);
|
|
}).toList()
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
// Todo: Add a screen for the url
|
|
Widget _buildCommitCommentCard(BuildContext context) {
|
|
return LinkWidget(
|
|
url: e.payload!.comment!.htmlUrl,
|
|
child: Container(
|
|
padding: const EdgeInsets.all(12),
|
|
decoration: BoxDecoration(
|
|
color: AntTheme.of(context).colorBox,
|
|
borderRadius: const BorderRadius.all(Radius.circular(4))),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Row(
|
|
children: <Widget>[
|
|
Text(
|
|
e.payload!.comment!.commitId!.substring(0, 7),
|
|
style: TextStyle(
|
|
color: AntTheme.of(context).colorPrimary,
|
|
fontSize: 15,
|
|
fontFamily: CommonStyle.monospace,
|
|
),
|
|
),
|
|
const SizedBox(width: 6),
|
|
Expanded(
|
|
child: Text(
|
|
e.payload!.comment!.body!,
|
|
overflow: TextOverflow.ellipsis,
|
|
maxLines: 1,
|
|
style: TextStyle(
|
|
color: AntTheme.of(context).colorText, fontSize: 15),
|
|
),
|
|
)
|
|
],
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildIssueCard(
|
|
BuildContext context, GithubEventIssue issue, String? body,
|
|
{isPullRequest = false}) {
|
|
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 LinkWidget(
|
|
url:
|
|
'/github/${e.repoOwner}/${e.repoName}/${isPullRequest ? 'pull' : 'issues'}/${issue.number}',
|
|
child: Container(
|
|
padding: const EdgeInsets.all(12),
|
|
decoration: BoxDecoration(
|
|
color: AntTheme.of(context).colorBox,
|
|
borderRadius: const BorderRadius.all(Radius.circular(4))),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Row(
|
|
children: <Widget>[
|
|
IssueIcon(state, size: 20),
|
|
const SizedBox(width: 4),
|
|
Expanded(
|
|
child: Text(
|
|
'#${issue.number} ${issue.title!}',
|
|
style: TextStyle(
|
|
fontWeight: FontWeight.w500,
|
|
fontSize: 17,
|
|
color: AntTheme.of(context).colorText,
|
|
),
|
|
overflow: TextOverflow.ellipsis,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
if (body != null && body.isNotEmpty)
|
|
Text(
|
|
body,
|
|
overflow: TextOverflow.ellipsis,
|
|
maxLines: 3,
|
|
style: TextStyle(
|
|
color: AntTheme.of(context).colorTextSecondary,
|
|
fontSize: 15),
|
|
),
|
|
Row(
|
|
children: <Widget>[
|
|
Avatar(url: issue.user!.avatarUrl, size: AvatarSize.extraSmall),
|
|
const SizedBox(width: 8),
|
|
Text(issue.user!.login!,
|
|
style: TextStyle(
|
|
fontSize: 14,
|
|
color: AntTheme.of(context).colorWeak,
|
|
)),
|
|
Expanded(child: Container()),
|
|
if (issue.comments != null) ...[
|
|
Icon(
|
|
Octicons.comment,
|
|
size: 14,
|
|
color: AntTheme.of(context).colorWeak,
|
|
),
|
|
const SizedBox(width: 4),
|
|
Text(issue.comments.toString(),
|
|
style: TextStyle(
|
|
fontSize: 14,
|
|
color: AntTheme.of(context).colorWeak,
|
|
)),
|
|
]
|
|
],
|
|
)
|
|
].withSeparator(const SizedBox(height: 6)),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
@override
|
|
build(BuildContext context) {
|
|
// all events types here:
|
|
// https://developer.github.com/v3/activity/events/types/#event-types--payloads
|
|
switch (e.type) {
|
|
case 'CheckRunEvent':
|
|
return _buildItem(context: context, spans: [
|
|
TextSpan(
|
|
text:
|
|
'${AppLocalizations.of(context)!.checkRunEventMessage(e.payload!.action!, e.payload!.checkRun!.name!)} '),
|
|
]);
|
|
case 'CheckSuiteEvent':
|
|
// Needs checks permission
|
|
var conclusion = '';
|
|
switch (e.payload!.checkSuite!.conclusion) {
|
|
case 'success':
|
|
case 'failure':
|
|
conclusion =
|
|
'${AppLocalizations.of(context)!.checkSuiteEventConclusionMessage(e.payload!.checkSuite!.conclusion!)} ';
|
|
break;
|
|
case 'neutral':
|
|
case 'cancelled':
|
|
case 'timed_out':
|
|
case 'stale':
|
|
conclusion =
|
|
'${AppLocalizations.of(context)!.checkSuiteEventConclusionMessage(e.payload!.checkSuite!.conclusion!)} ';
|
|
break;
|
|
case 'action_required':
|
|
conclusion =
|
|
' ${AppLocalizations.of(context)!.actionRequiredConclusion}';
|
|
break;
|
|
}
|
|
return _buildItem(
|
|
context: context,
|
|
spans: [
|
|
TextSpan(
|
|
text:
|
|
' ${AppLocalizations.of(context)!.checkSuiteEventMessage(e.payload!.action!)} $conclusion'),
|
|
],
|
|
);
|
|
case 'CommitCommentEvent':
|
|
return _buildItem(
|
|
context: context,
|
|
spans: [
|
|
TextSpan(
|
|
text:
|
|
' ${AppLocalizations.of(context)!.commitCommentEventMessage} '),
|
|
_buildRepo(context),
|
|
],
|
|
card: _buildCommitCommentCard(context),
|
|
);
|
|
case 'ContentReferenceEvent':
|
|
return _buildItem(context: context, spans: [
|
|
TextSpan(
|
|
text:
|
|
' ${AppLocalizations.of(context)!.contentReferenceEventMessage(e.payload!.action!)} '),
|
|
_buildLinkSpan(context, e.payload!.contentReference!.reference,
|
|
e.payload!.contentReference!.reference),
|
|
]);
|
|
case 'CreateEvent':
|
|
return _buildItem(
|
|
context: context,
|
|
spans: <InlineSpan>[
|
|
TextSpan(
|
|
text:
|
|
' ${AppLocalizations.of(context)!.createdEventMessage(e.payload!.refType!, e.payload!.ref ?? '')}'),
|
|
_buildRepo(context),
|
|
],
|
|
);
|
|
case 'DeleteEvent':
|
|
return _buildItem(
|
|
context: context,
|
|
spans: <InlineSpan>[
|
|
TextSpan(
|
|
text:
|
|
' ${AppLocalizations.of(context)!.deletedEventMessage(e.payload!.refType!, e.payload!.ref ?? '')}'),
|
|
_buildRepo(context),
|
|
],
|
|
);
|
|
case 'ForkEvent':
|
|
final forkeeOwner = e.payload!.forkee!['owner']['login'] as String?;
|
|
final forkeeName = e.payload!.forkee!['name'] as String?;
|
|
return _buildItem(
|
|
context: context,
|
|
spans: [
|
|
TextSpan(text: ' ${AppLocalizations.of(context)!.forked} '),
|
|
_buildRepo(context, '$forkeeOwner/$forkeeName'),
|
|
TextSpan(text: ' ${AppLocalizations.of(context)!.from} '),
|
|
_buildRepo(context),
|
|
],
|
|
);
|
|
case 'GollumEvent':
|
|
var pageNamesCreated = '';
|
|
var pageNamesEdited = '';
|
|
for (final page in e.payload!.pages!) {
|
|
if (page.action == 'edited') {
|
|
pageNamesEdited += ', ${page.pageName!}';
|
|
} else {
|
|
pageNamesCreated += ', ${page.pageName!}';
|
|
}
|
|
}
|
|
if (pageNamesCreated.isNotEmpty) {
|
|
pageNamesCreated =
|
|
' ${AppLocalizations.of(context)!.createdPages(pageNamesCreated)}';
|
|
}
|
|
if (pageNamesEdited.isNotEmpty) {
|
|
pageNamesEdited =
|
|
' ${AppLocalizations.of(context)!.editedPages(pageNamesEdited)}';
|
|
}
|
|
|
|
return _buildItem(
|
|
context: context,
|
|
spans: [TextSpan(text: ' $pageNamesCreated\n$pageNamesEdited ')]);
|
|
case 'InstallationEvent':
|
|
var action = e.payload!.action;
|
|
if (action == 'new_permissions_accepted') {
|
|
action = AppLocalizations.of(context)!.newPermissionsAccepted;
|
|
}
|
|
return _buildItem(
|
|
context: context,
|
|
spans: [
|
|
TextSpan(
|
|
text:
|
|
' $action ${AppLocalizations.of(context)!.forGithubAppWithId(e.payload!.installation!.id.toString())}'),
|
|
],
|
|
);
|
|
case 'InstallationRepositoriesEvent':
|
|
final repositoriesAdded = e.payload!.installation!.repositoriesAdded!;
|
|
final repositoriesRemoved =
|
|
e.payload!.installation!.repositoriesRemoved!;
|
|
var addedRepos = '';
|
|
var removedRepos = '';
|
|
for (final repo in repositoriesAdded) {
|
|
addedRepos += '${repo.fullName!}, ';
|
|
}
|
|
for (final repo in repositoriesRemoved) {
|
|
removedRepos += '${repo.fullName!}, ';
|
|
}
|
|
var finalListOfRepos = '';
|
|
if (addedRepos != '') {
|
|
finalListOfRepos +=
|
|
'${AppLocalizations.of(context)!.wereAddedTo(addedRepos, e.payload!.installation!.id.toString())}\n ';
|
|
}
|
|
if (removedRepos != '') {
|
|
finalListOfRepos +=
|
|
'$removedRepos ${AppLocalizations.of(context)!.wereRemovedFrom(removedRepos, e.payload!.installation!.id.toString())}';
|
|
}
|
|
return _buildItem(
|
|
context: context,
|
|
spans: [
|
|
TextSpan(text: finalListOfRepos),
|
|
],
|
|
);
|
|
case 'IssueCommentEvent':
|
|
return _buildItem(
|
|
context: context,
|
|
spans: [
|
|
TextSpan(
|
|
text:
|
|
' ${AppLocalizations.of(context)!.commentedOn} ${e.payload!.issue!.isPullRequestComment ? 'pull request' : 'issue'} '),
|
|
_buildIssue(
|
|
context,
|
|
e.payload!.issue!.number,
|
|
isPullRequest: e.payload!.issue!.isPullRequestComment,
|
|
),
|
|
TextSpan(text: ' ${AppLocalizations.of(context)!.at} '),
|
|
_buildRepo(context),
|
|
],
|
|
card: _buildIssueCard(
|
|
context,
|
|
e.payload!.issue!,
|
|
e.payload!.comment!.body,
|
|
isPullRequest: e.payload!.issue!.isPullRequestComment,
|
|
),
|
|
);
|
|
case 'IssuesEvent':
|
|
final issue = e.payload!.issue!;
|
|
return _buildItem(
|
|
context: context,
|
|
spans: [
|
|
TextSpan(
|
|
text:
|
|
' ${e.payload!.action} ${AppLocalizations.of(context)!.issue} '),
|
|
_buildIssue(context, issue.number),
|
|
TextSpan(text: ' ${AppLocalizations.of(context)!.at} '),
|
|
_buildRepo(context),
|
|
],
|
|
card: _buildIssueCard(context, issue, issue.body),
|
|
);
|
|
case 'MarketplacePurchaseEvent':
|
|
final action = e.payload!.action;
|
|
String? messageToDisplay;
|
|
switch (action) {
|
|
case 'purchased':
|
|
messageToDisplay =
|
|
AppLocalizations.of(context)!.purchasedMarketplacePlan;
|
|
break;
|
|
case 'cancelled':
|
|
messageToDisplay =
|
|
AppLocalizations.of(context)!.cancelledMarketplacePlan;
|
|
break;
|
|
case 'pending_change':
|
|
messageToDisplay =
|
|
AppLocalizations.of(context)!.pendingMarketplacePlan;
|
|
break;
|
|
case 'pending_change_cancelled':
|
|
messageToDisplay =
|
|
AppLocalizations.of(context)!.pendingChangeCancelled;
|
|
break;
|
|
case 'changed':
|
|
messageToDisplay =
|
|
AppLocalizations.of(context)!.changedMarketplacePlan;
|
|
break;
|
|
}
|
|
return _buildItem(
|
|
context: context,
|
|
spans: [
|
|
TextSpan(
|
|
text: ' $messageToDisplay ',
|
|
),
|
|
_buildRepo(context),
|
|
],
|
|
);
|
|
case 'MemberEvent':
|
|
final action = e.payload!.action;
|
|
return _buildItem(
|
|
context: context,
|
|
spans: [
|
|
TextSpan(
|
|
text:
|
|
' ${AppLocalizations.of(context)!.was} ${e.payload!.action} ${action == 'added' ? AppLocalizations.of(context)!.to : AppLocalizations.of(context)!.from} '),
|
|
_buildRepo(context),
|
|
],
|
|
);
|
|
case 'ProjectCardEvent':
|
|
var action = e.payload!.action;
|
|
if (action == 'converted') {
|
|
action = ' ${AppLocalizations.of(context)!.convertProjectCard} ';
|
|
} else {
|
|
action =
|
|
'${action!} ${AppLocalizations.of(context)!.theProjectCard} ';
|
|
}
|
|
return _buildItem(
|
|
context: context,
|
|
spans: [
|
|
TextSpan(text: ' $action ${AppLocalizations.of(context)!.at} '),
|
|
_buildRepo(context),
|
|
],
|
|
);
|
|
case 'ProjectColumnEvent':
|
|
return _buildItem(context: context, spans: [
|
|
TextSpan(
|
|
text:
|
|
' ${AppLocalizations.of(context)!.projectColumnEventMessage(e.payload!.action!, e.payload!.projectColumn!.name!)} '),
|
|
_buildRepo(context),
|
|
]);
|
|
case 'ProjectEvent':
|
|
return _buildItem(context: context, spans: [
|
|
TextSpan(
|
|
text:
|
|
' ${AppLocalizations.of(context)!.projectEventMessage(e.payload!.action!, e.payload!.project!.name!)}} '),
|
|
]);
|
|
case 'PublicEvent':
|
|
return _buildItem(
|
|
context: context,
|
|
spans: [
|
|
TextSpan(text: ' ${AppLocalizations.of(context)!.made} '),
|
|
_buildRepo(context),
|
|
TextSpan(text: ' ${AppLocalizations.of(context)!.public}'),
|
|
],
|
|
);
|
|
case 'PullRequestEvent':
|
|
final pr = e.payload!.pullRequest!;
|
|
return _buildItem(
|
|
context: context,
|
|
spans: [
|
|
TextSpan(
|
|
text:
|
|
' ${AppLocalizations.of(context)!.pullRequestEventMessage(e.payload!.action!)} '),
|
|
_buildIssue(context, pr.number, isPullRequest: true),
|
|
TextSpan(text: ' ${AppLocalizations.of(context)!.at} '),
|
|
_buildRepo(context),
|
|
],
|
|
card: _buildIssueCard(context, pr, pr.body, isPullRequest: true),
|
|
);
|
|
case 'PullRequestReviewEvent':
|
|
final pr = e.payload!.pullRequest!;
|
|
return _buildItem(context: context, spans: [
|
|
TextSpan(
|
|
text:
|
|
' ${AppLocalizations.of(context)!.pullRequestReviewEventMessage(e.payload!.action!)} '),
|
|
_buildIssue(context, pr.number, isPullRequest: true),
|
|
TextSpan(text: ' ${AppLocalizations.of(context)!.at} '),
|
|
_buildRepo(context),
|
|
]);
|
|
case 'PullRequestReviewCommentEvent':
|
|
final pr = e.payload!.pullRequest!;
|
|
return _buildItem(
|
|
context: context,
|
|
spans: [
|
|
TextSpan(
|
|
text:
|
|
' ${AppLocalizations.of(context)!.pullRequestReviewCommentEventMessage} '),
|
|
_buildIssue(context, pr.number, isPullRequest: true),
|
|
TextSpan(text: ' ${AppLocalizations.of(context)!.at} '),
|
|
_buildRepo(context),
|
|
],
|
|
card: _buildIssueCard(context, pr, e.payload!.comment!.body,
|
|
isPullRequest: true),
|
|
);
|
|
case 'PushEvent':
|
|
return _buildItem(
|
|
context: context,
|
|
spans: [
|
|
TextSpan(text: ' ${AppLocalizations.of(context)!.pushedTo} '),
|
|
_buildRepo(context)
|
|
],
|
|
card: _buildCommitsCard(context),
|
|
);
|
|
case 'ReleaseEvent':
|
|
return _buildItem(
|
|
context: context,
|
|
spans: [
|
|
TextSpan(text: '${AppLocalizations.of(context)!.released} '),
|
|
_buildLinkSpan(context, e.payload!.release!.tagName,
|
|
e.payload!.release!.htmlUrl),
|
|
const TextSpan(text: ' at '),
|
|
_buildRepo(context)
|
|
],
|
|
);
|
|
// case 'RepositoryImportEvent':
|
|
// // Uses Source Imports API
|
|
case 'RepositoryVulnerabilityAlertEvent':
|
|
return _buildItem(context: context, spans: [
|
|
TextSpan(
|
|
text:
|
|
' ${AppLocalizations.of(context)!.securityAlertInvolvingPackage(e.payload!.alert!.affectedPackageName!, e.payload!.alert!.affectedRange!, e.payload!.action!)}',
|
|
)
|
|
]);
|
|
case 'SecurityAdvisoryEvent':
|
|
return _buildItem(context: context, spans: [
|
|
TextSpan(
|
|
text:
|
|
' ${AppLocalizations.of(context)!.securityAdvisory(e.payload!.securityAdvisory!.summary!, e.payload!.action!)} ',
|
|
)
|
|
]);
|
|
case 'WatchEvent':
|
|
return _buildItem(
|
|
context: context,
|
|
spans: [
|
|
TextSpan(text: ' ${AppLocalizations.of(context)!.starred} '),
|
|
_buildRepo(context)
|
|
],
|
|
);
|
|
default:
|
|
return _buildDefaultItem(context);
|
|
}
|
|
}
|
|
}
|