mirror of
https://github.com/git-touch/git-touch
synced 2025-02-23 06:47:46 +01:00
feat(gitee): issues, issue, pullRequests screens (#144)
* feat: gitee pulls, issue screens * add action button - issue screen * remove unnecessary comment * feat: gitee create issue in repo * feat: commenting in issue screen * fix: prepend '#' to subtitle props
This commit is contained in:
parent
4679ca10ee
commit
1ac27f4853
@ -276,9 +276,25 @@ class AuthModel with ChangeNotifier {
|
||||
);
|
||||
}
|
||||
|
||||
Future fetchGitee(String p) async {
|
||||
final res = await http.get('${activeAccount.domain}/api/v5$p',
|
||||
headers: {'Authorization': 'token $token'});
|
||||
Future fetchGitee(
|
||||
String p, {
|
||||
isPost = false,
|
||||
Map<String, dynamic> body = const {},
|
||||
}) async {
|
||||
http.Response res;
|
||||
if (isPost) {
|
||||
res = await http.post(
|
||||
'${activeAccount.domain}/api/v5$p',
|
||||
headers: {
|
||||
'Authorization': 'token $token',
|
||||
HttpHeaders.contentTypeHeader: 'application/json'
|
||||
},
|
||||
body: jsonEncode(body),
|
||||
);
|
||||
} else {
|
||||
res = await http.get('${activeAccount.domain}/api/v5$p',
|
||||
headers: {'Authorization': 'token $token'});
|
||||
}
|
||||
final info = json.decode(utf8.decode(res.bodyBytes));
|
||||
return info;
|
||||
}
|
||||
|
@ -122,3 +122,49 @@ class GiteeBlob {
|
||||
factory GiteeBlob.fromJson(Map<String, dynamic> json) =>
|
||||
_$GiteeBlobFromJson(json);
|
||||
}
|
||||
|
||||
@JsonSerializable(fieldRename: FieldRename.snake)
|
||||
class GiteeIssue {
|
||||
int comments;
|
||||
String commentsUrl;
|
||||
String createdAt;
|
||||
String htmlUrl;
|
||||
String updatedAt;
|
||||
String body;
|
||||
String bodyHtml;
|
||||
String title;
|
||||
String state;
|
||||
GiteeRepoOwner user;
|
||||
String number;
|
||||
int id;
|
||||
GiteeIssue();
|
||||
factory GiteeIssue.fromJson(Map<String, dynamic> json) =>
|
||||
_$GiteeIssueFromJson(json);
|
||||
}
|
||||
|
||||
@JsonSerializable(fieldRename: FieldRename.snake)
|
||||
class GiteePull {
|
||||
String commentsUrl;
|
||||
String createdAt;
|
||||
String htmlUrl;
|
||||
String updatedAt;
|
||||
String body;
|
||||
String bodyHtml;
|
||||
String title;
|
||||
GiteeRepoOwner user;
|
||||
int number;
|
||||
int id;
|
||||
GiteePull();
|
||||
factory GiteePull.fromJson(Map<String, dynamic> json) =>
|
||||
_$GiteePullFromJson(json);
|
||||
}
|
||||
|
||||
@JsonSerializable(fieldRename: FieldRename.snake)
|
||||
class GiteeComment {
|
||||
String body;
|
||||
String createdAt;
|
||||
GiteeRepoOwner user;
|
||||
GiteeComment();
|
||||
factory GiteeComment.fromJson(Map<String, dynamic> json) =>
|
||||
_$GiteeCommentFromJson(json);
|
||||
}
|
||||
|
@ -199,3 +199,82 @@ GiteeBlob _$GiteeBlobFromJson(Map<String, dynamic> json) {
|
||||
Map<String, dynamic> _$GiteeBlobToJson(GiteeBlob instance) => <String, dynamic>{
|
||||
'content': instance.content,
|
||||
};
|
||||
|
||||
GiteeIssue _$GiteeIssueFromJson(Map<String, dynamic> json) {
|
||||
return GiteeIssue()
|
||||
..comments = json['comments'] as int
|
||||
..commentsUrl = json['comments_url'] as String
|
||||
..createdAt = json['created_at'] as String
|
||||
..htmlUrl = json['html_url'] as String
|
||||
..updatedAt = json['updated_at'] as String
|
||||
..body = json['body'] as String
|
||||
..bodyHtml = json['body_html'] as String
|
||||
..title = json['title'] as String
|
||||
..state = json['state'] as String
|
||||
..user = json['user'] == null
|
||||
? null
|
||||
: GiteeRepoOwner.fromJson(json['user'] as Map<String, dynamic>)
|
||||
..number = json['number'] as String
|
||||
..id = json['id'] as int;
|
||||
}
|
||||
|
||||
Map<String, dynamic> _$GiteeIssueToJson(GiteeIssue instance) =>
|
||||
<String, dynamic>{
|
||||
'comments': instance.comments,
|
||||
'comments_url': instance.commentsUrl,
|
||||
'created_at': instance.createdAt,
|
||||
'html_url': instance.htmlUrl,
|
||||
'updated_at': instance.updatedAt,
|
||||
'body': instance.body,
|
||||
'body_html': instance.bodyHtml,
|
||||
'title': instance.title,
|
||||
'state': instance.state,
|
||||
'user': instance.user,
|
||||
'number': instance.number,
|
||||
'id': instance.id,
|
||||
};
|
||||
|
||||
GiteePull _$GiteePullFromJson(Map<String, dynamic> json) {
|
||||
return GiteePull()
|
||||
..commentsUrl = json['comments_url'] as String
|
||||
..createdAt = json['created_at'] as String
|
||||
..htmlUrl = json['html_url'] as String
|
||||
..updatedAt = json['updated_at'] as String
|
||||
..body = json['body'] as String
|
||||
..bodyHtml = json['body_html'] as String
|
||||
..title = json['title'] as String
|
||||
..user = json['user'] == null
|
||||
? null
|
||||
: GiteeRepoOwner.fromJson(json['user'] as Map<String, dynamic>)
|
||||
..number = json['number'] as int
|
||||
..id = json['id'] as int;
|
||||
}
|
||||
|
||||
Map<String, dynamic> _$GiteePullToJson(GiteePull instance) => <String, dynamic>{
|
||||
'comments_url': instance.commentsUrl,
|
||||
'created_at': instance.createdAt,
|
||||
'html_url': instance.htmlUrl,
|
||||
'updated_at': instance.updatedAt,
|
||||
'body': instance.body,
|
||||
'body_html': instance.bodyHtml,
|
||||
'title': instance.title,
|
||||
'user': instance.user,
|
||||
'number': instance.number,
|
||||
'id': instance.id,
|
||||
};
|
||||
|
||||
GiteeComment _$GiteeCommentFromJson(Map<String, dynamic> json) {
|
||||
return GiteeComment()
|
||||
..body = json['body'] as String
|
||||
..createdAt = json['created_at'] as String
|
||||
..user = json['user'] == null
|
||||
? null
|
||||
: GiteeRepoOwner.fromJson(json['user'] as Map<String, dynamic>);
|
||||
}
|
||||
|
||||
Map<String, dynamic> _$GiteeCommentToJson(GiteeComment instance) =>
|
||||
<String, dynamic>{
|
||||
'body': instance.body,
|
||||
'created_at': instance.createdAt,
|
||||
'user': instance.user,
|
||||
};
|
||||
|
@ -8,6 +8,11 @@ import 'package:git_touch/screens/bb_user.dart';
|
||||
import 'package:git_touch/screens/code_theme.dart';
|
||||
import 'package:git_touch/screens/ge_blob.dart';
|
||||
import 'package:git_touch/screens/ge_commits.dart';
|
||||
import 'package:git_touch/screens/ge_issue.dart';
|
||||
import 'package:git_touch/screens/ge_issue_comment.dart';
|
||||
import 'package:git_touch/screens/ge_issue_form.dart';
|
||||
import 'package:git_touch/screens/ge_issues.dart';
|
||||
import 'package:git_touch/screens/ge_pulls.dart';
|
||||
import 'package:git_touch/screens/ge_repo.dart';
|
||||
import 'package:git_touch/screens/ge_repos.dart';
|
||||
import 'package:git_touch/screens/ge_search.dart';
|
||||
@ -392,6 +397,11 @@ class GiteeRouter {
|
||||
GiteeRouter.commits,
|
||||
GiteeRouter.tree,
|
||||
GiteeRouter.blob,
|
||||
GiteeRouter.issues,
|
||||
GiteeRouter.pulls,
|
||||
GiteeRouter.issueAdd, // issueAdd should be above issue
|
||||
GiteeRouter.issue, // Due to similarity of uris
|
||||
GiteeRouter.issueComment,
|
||||
];
|
||||
static final search = RouterScreen('/search', (context, parameters) {
|
||||
return GeSearchScreen();
|
||||
@ -449,4 +459,34 @@ class GiteeRouter {
|
||||
);
|
||||
},
|
||||
);
|
||||
static final issues = RouterScreen(
|
||||
'/:owner/:name/issues',
|
||||
(context, parameters) {
|
||||
return GeIssuesScreen(parameters['owner'].first, parameters['name'].first,
|
||||
isPr: false);
|
||||
},
|
||||
);
|
||||
static final issue =
|
||||
RouterScreen('/:owner/:name/issues/:number', (context, parameters) {
|
||||
return GeIssueScreen(parameters['owner'].first, parameters['name'].first,
|
||||
parameters['number'].first,
|
||||
isPr: false);
|
||||
});
|
||||
static final pulls = RouterScreen(
|
||||
'/:owner/:name/pulls',
|
||||
(context, parameters) {
|
||||
return GePullsScreen(parameters['owner'].first, parameters['name'].first,
|
||||
isPr: true);
|
||||
},
|
||||
);
|
||||
static final issueAdd =
|
||||
RouterScreen('/:owner/:name/issues/new', (context, parameters) {
|
||||
return GeIssueFormScreen(
|
||||
parameters['owner'].first, parameters['name'].first);
|
||||
});
|
||||
static final issueComment = RouterScreen(
|
||||
'/:owner/:name/issues/:number/comment', (context, parameters) {
|
||||
return GeIssueCommentScreen(parameters['owner'].first,
|
||||
parameters['name'].first, parameters['number'].first);
|
||||
});
|
||||
}
|
||||
|
@ -37,7 +37,7 @@ class BbIssuesScreen extends StatelessWidget {
|
||||
avatarUrl: v.reporter.avatarUrl,
|
||||
author: v.reporter.displayName,
|
||||
title: v.title,
|
||||
number: issueNumber,
|
||||
subtitle: '#' + issueNumber.toString(),
|
||||
commentCount: 0,
|
||||
updatedAt: v.createdOn,
|
||||
url: '${auth.activeAccount.domain}/$owner/$name/issues/$issueNumber',
|
||||
|
@ -36,7 +36,7 @@ class BbPullsScreen extends StatelessWidget {
|
||||
avatarUrl: v.author.avatarUrl,
|
||||
author: v.author.displayName,
|
||||
title: v.title,
|
||||
number: pullNumber,
|
||||
subtitle: '#' + pullNumber.toString(),
|
||||
commentCount: 0,
|
||||
updatedAt: v.createdOn,
|
||||
url: '${auth.activeAccount.domain}/$owner/$name/issues/$pullNumber',
|
||||
|
116
lib/screens/ge_issue.dart
Normal file
116
lib/screens/ge_issue.dart
Normal file
@ -0,0 +1,116 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:git_touch/models/gitee.dart';
|
||||
import 'package:git_touch/scaffolds/refresh_stateful.dart';
|
||||
import 'package:git_touch/utils/utils.dart';
|
||||
import 'package:git_touch/widgets/action_entry.dart';
|
||||
import 'package:git_touch/widgets/avatar.dart';
|
||||
import 'package:git_touch/widgets/link.dart';
|
||||
import 'package:git_touch/widgets/comment_item.dart';
|
||||
import 'package:primer/primer.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:git_touch/models/auth.dart';
|
||||
import 'package:git_touch/models/theme.dart';
|
||||
import 'package:tuple/tuple.dart';
|
||||
|
||||
class GeIssueScreen extends StatelessWidget {
|
||||
final String owner;
|
||||
final String name;
|
||||
final String number;
|
||||
final bool isPr;
|
||||
|
||||
GeIssueScreen(this.owner, this.name, this.number, {this.isPr: false});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return RefreshStatefulScaffold<Tuple2<GiteeIssue, List<GiteeComment>>>(
|
||||
title: Text("Issue: #$number"),
|
||||
fetch: () async {
|
||||
final auth = context.read<AuthModel>();
|
||||
final items = await Future.wait([
|
||||
auth.fetchGitee('/repos/$owner/$name/issues/$number'),
|
||||
auth.fetchGitee('/repos/$owner/$name/issues/$number/comments')
|
||||
]);
|
||||
return Tuple2(GiteeIssue.fromJson(items[0]),
|
||||
[for (var v in items[1]) GiteeComment.fromJson(v)]);
|
||||
},
|
||||
actionBuilder: (data, _) => ActionEntry(
|
||||
iconData: Octicons.plus,
|
||||
url: '/gitee/$owner/$name/issues/$number/comment',
|
||||
),
|
||||
bodyBuilder: (data, _) {
|
||||
final issue = data.item1;
|
||||
final comments = data.item2;
|
||||
final theme = context.read<ThemeModel>();
|
||||
return Column(children: <Widget>[
|
||||
Container(
|
||||
padding: CommonStyle.padding,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
Link(
|
||||
url: '/gitee/$owner/$name',
|
||||
child: Row(
|
||||
children: <Widget>[
|
||||
Avatar(
|
||||
url: issue.user.avatarUrl,
|
||||
size: AvatarSize.extraSmall,
|
||||
),
|
||||
SizedBox(width: 4),
|
||||
Text(
|
||||
'$owner / $name',
|
||||
style: TextStyle(
|
||||
fontSize: 17,
|
||||
color: theme.palette.secondaryText,
|
||||
),
|
||||
),
|
||||
SizedBox(width: 4),
|
||||
Text(
|
||||
'#$number',
|
||||
style: TextStyle(
|
||||
fontSize: 17,
|
||||
color: theme.palette.tertiaryText,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
SizedBox(height: 8),
|
||||
Text(
|
||||
issue.title,
|
||||
style: TextStyle(
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
SizedBox(height: 8),
|
||||
StateLabel(
|
||||
issue.state == 'open'
|
||||
? StateLabelStatus.issueOpened
|
||||
: StateLabelStatus.issueClosed,
|
||||
small: true),
|
||||
SizedBox(height: 16),
|
||||
CommonStyle.border,
|
||||
],
|
||||
)),
|
||||
Column(children: [
|
||||
for (var comment in comments) ...[
|
||||
Padding(
|
||||
padding: EdgeInsets.only(left: 10),
|
||||
child: CommentItem(
|
||||
avatar: Avatar(
|
||||
url: comment.user.avatarUrl,
|
||||
linkUrl: '/gitee/${comment.user.login}',
|
||||
),
|
||||
createdAt: DateTime.parse(comment.createdAt),
|
||||
body: comment.body,
|
||||
login: comment.user.login,
|
||||
prefix: 'gitee')),
|
||||
CommonStyle.border,
|
||||
SizedBox(height: 16),
|
||||
],
|
||||
]),
|
||||
]);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
65
lib/screens/ge_issue_comment.dart
Normal file
65
lib/screens/ge_issue_comment.dart
Normal file
@ -0,0 +1,65 @@
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:git_touch/models/auth.dart';
|
||||
import 'package:git_touch/models/gitee.dart';
|
||||
import 'package:git_touch/models/theme.dart';
|
||||
import 'package:git_touch/scaffolds/common.dart';
|
||||
import 'package:git_touch/utils/utils.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class GeIssueCommentScreen extends StatefulWidget {
|
||||
final String owner;
|
||||
final String name;
|
||||
final String number;
|
||||
GeIssueCommentScreen(this.owner, this.name, this.number);
|
||||
|
||||
@override
|
||||
_GeIssueCommentScreenState createState() => _GeIssueCommentScreenState();
|
||||
}
|
||||
|
||||
class _GeIssueCommentScreenState extends State<GeIssueCommentScreen> {
|
||||
var _body = '';
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Provider.of<ThemeModel>(context);
|
||||
final auth = Provider.of<AuthModel>(context);
|
||||
return CommonScaffold(
|
||||
title: Text('New Comment'),
|
||||
body: Column(
|
||||
children: <Widget>[
|
||||
Padding(
|
||||
padding: CommonStyle.padding,
|
||||
child: CupertinoTextField(
|
||||
style: TextStyle(color: theme.palette.text),
|
||||
placeholder: 'Body',
|
||||
onChanged: (v) {
|
||||
setState(() {
|
||||
_body = v;
|
||||
});
|
||||
},
|
||||
maxLines: 10,
|
||||
),
|
||||
),
|
||||
CupertinoButton.filled(
|
||||
child: Text('Comment'),
|
||||
onPressed: () async {
|
||||
final res = await auth.fetchGitee(
|
||||
'/repos/${widget.owner}/${widget.name}/issues/${widget.number}/comments',
|
||||
isPost: true,
|
||||
body: {'body': _body, 'repo': widget.name},
|
||||
).then((v) {
|
||||
return GiteeIssue.fromJson(v);
|
||||
});
|
||||
await theme.push(
|
||||
context,
|
||||
'/gitee/${widget.owner}/${widget.name}/issues/${widget.number}',
|
||||
replace: true,
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
77
lib/screens/ge_issue_form.dart
Normal file
77
lib/screens/ge_issue_form.dart
Normal file
@ -0,0 +1,77 @@
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:git_touch/models/auth.dart';
|
||||
import 'package:git_touch/models/gitee.dart';
|
||||
import 'package:git_touch/models/theme.dart';
|
||||
import 'package:git_touch/scaffolds/common.dart';
|
||||
import 'package:git_touch/utils/utils.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class GeIssueFormScreen extends StatefulWidget {
|
||||
final String owner;
|
||||
final String name;
|
||||
GeIssueFormScreen(this.owner, this.name);
|
||||
|
||||
@override
|
||||
_GeIssueFormScreenState createState() => _GeIssueFormScreenState();
|
||||
}
|
||||
|
||||
class _GeIssueFormScreenState extends State<GeIssueFormScreen> {
|
||||
var _title = '';
|
||||
var _body = '';
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Provider.of<ThemeModel>(context);
|
||||
final auth = Provider.of<AuthModel>(context);
|
||||
return CommonScaffold(
|
||||
title: Text('Submit an issue'),
|
||||
body: Column(
|
||||
children: <Widget>[
|
||||
Padding(
|
||||
padding: CommonStyle.padding,
|
||||
child: CupertinoTextField(
|
||||
style: TextStyle(color: theme.palette.text),
|
||||
placeholder: 'Title',
|
||||
onChanged: (v) {
|
||||
setState(() {
|
||||
_title = v;
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: CommonStyle.padding,
|
||||
child: CupertinoTextField(
|
||||
style: TextStyle(color: theme.palette.text),
|
||||
placeholder: 'Body',
|
||||
onChanged: (v) {
|
||||
setState(() {
|
||||
_body = v;
|
||||
});
|
||||
},
|
||||
maxLines: 10,
|
||||
),
|
||||
),
|
||||
CupertinoButton.filled(
|
||||
child: Text('Submit'),
|
||||
onPressed: () async {
|
||||
final res = await auth.fetchGitee(
|
||||
'/repos/${widget.owner}/issues',
|
||||
isPost: true,
|
||||
body: {'body': _body, 'title': _title, 'repo': widget.name},
|
||||
).then((v) {
|
||||
return GiteeIssue.fromJson(v);
|
||||
});
|
||||
await theme.push(
|
||||
context,
|
||||
'/gitee/${widget.owner}/${widget.name}/issues/${res.number}',
|
||||
replace: true,
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
46
lib/screens/ge_issues.dart
Normal file
46
lib/screens/ge_issues.dart
Normal file
@ -0,0 +1,46 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:git_touch/models/auth.dart';
|
||||
import 'package:git_touch/models/gitee.dart';
|
||||
import 'package:git_touch/scaffolds/list_stateful.dart';
|
||||
import 'package:git_touch/utils/utils.dart';
|
||||
import 'package:git_touch/widgets/action_entry.dart';
|
||||
import 'package:git_touch/widgets/app_bar_title.dart';
|
||||
import 'package:git_touch/widgets/issue_item.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class GeIssuesScreen extends StatelessWidget {
|
||||
final String owner;
|
||||
final String name;
|
||||
final bool isPr;
|
||||
GeIssuesScreen(this.owner, this.name, {this.isPr = false});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ListStatefulScaffold<GiteeIssue, int>(
|
||||
title: AppBarTitle(isPr ? 'Pull Requests' : 'Issues'),
|
||||
fetch: (page) async {
|
||||
final res = await context
|
||||
.read<AuthModel>()
|
||||
.fetchGiteeWithPage('/repos/$owner/$name/issues', page: page);
|
||||
return ListPayload(
|
||||
cursor: res.cursor,
|
||||
hasMore: res.hasMore,
|
||||
items: [for (var v in res.data) GiteeIssue.fromJson(v)],
|
||||
);
|
||||
},
|
||||
actionBuilder: () => ActionEntry(
|
||||
iconData: Octicons.plus,
|
||||
url: '/gitee/$owner/$name/issues/new',
|
||||
),
|
||||
itemBuilder: (p) => IssueItem(
|
||||
author: p.user.login,
|
||||
avatarUrl: p.user.avatarUrl,
|
||||
commentCount: p.comments,
|
||||
subtitle: '#' + p.number,
|
||||
title: p.title,
|
||||
updatedAt: DateTime.parse(p.updatedAt),
|
||||
url: '/gitee/$owner/$name/issues/${p.number}',
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
40
lib/screens/ge_pulls.dart
Normal file
40
lib/screens/ge_pulls.dart
Normal file
@ -0,0 +1,40 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:git_touch/models/auth.dart';
|
||||
import 'package:git_touch/models/gitee.dart';
|
||||
import 'package:git_touch/scaffolds/list_stateful.dart';
|
||||
import 'package:git_touch/widgets/app_bar_title.dart';
|
||||
import 'package:git_touch/widgets/issue_item.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class GePullsScreen extends StatelessWidget {
|
||||
final String owner;
|
||||
final String name;
|
||||
final bool isPr;
|
||||
GePullsScreen(this.owner, this.name, {this.isPr = false});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ListStatefulScaffold<GiteePull, int>(
|
||||
title: AppBarTitle(isPr ? 'Pull Requests' : 'Issues'),
|
||||
fetch: (page) async {
|
||||
final res = await context
|
||||
.read<AuthModel>()
|
||||
.fetchGiteeWithPage('/repos/$owner/$name/pulls', page: page);
|
||||
return ListPayload(
|
||||
cursor: res.cursor,
|
||||
hasMore: res.hasMore,
|
||||
items: [for (var v in res.data) GiteePull.fromJson(v)],
|
||||
);
|
||||
},
|
||||
itemBuilder: (p) => IssueItem(
|
||||
author: p.user.login,
|
||||
avatarUrl: p.user.avatarUrl,
|
||||
commentCount: 0, // fix this
|
||||
subtitle: '#' + p.number.toString(),
|
||||
title: p.title,
|
||||
updatedAt: DateTime.parse(p.updatedAt),
|
||||
url: p.htmlUrl,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -92,13 +92,13 @@ class GeRepoScreen extends StatelessWidget {
|
||||
leftIconData: Octicons.issue_opened,
|
||||
text: Text('Issues'),
|
||||
rightWidget: Text(numberFormat.format(p.openIssuesCount)),
|
||||
url: 'https://gitee.com/$owner/$name/issues', // TODO:
|
||||
url: '/gitee/$owner/$name/issues',
|
||||
),
|
||||
if (p.pullRequestsEnabled)
|
||||
TableViewItem(
|
||||
leftIconData: Octicons.git_pull_request,
|
||||
text: Text('Pull requests'),
|
||||
url: 'https://gitee.com/$owner/$name/pulls', // TODO:
|
||||
url: '/gitee/$owner/$name/pulls',
|
||||
),
|
||||
TableViewItem(
|
||||
leftIconData: Octicons.history,
|
||||
|
@ -42,7 +42,7 @@ class GhIssuesScreen extends StatelessWidget {
|
||||
author: p.author?.login,
|
||||
avatarUrl: p.author?.avatarUrl,
|
||||
commentCount: p.comments.totalCount,
|
||||
number: p.number,
|
||||
subtitle: '#' + p.number.toString(),
|
||||
title: p.title,
|
||||
updatedAt: p.updatedAt,
|
||||
labels: p.labels.nodes.isEmpty
|
||||
|
@ -37,7 +37,7 @@ class GhPullsScreen extends StatelessWidget {
|
||||
author: p.author?.login,
|
||||
avatarUrl: p.author?.avatarUrl,
|
||||
commentCount: p.comments.totalCount,
|
||||
number: p.number,
|
||||
subtitle: '#' + p.number.toString(),
|
||||
title: p.title,
|
||||
updatedAt: p.updatedAt,
|
||||
labels: p.labels.nodes.isEmpty
|
||||
|
@ -198,7 +198,7 @@ class _GhSearchScreenState extends State<GhSearchScreen> {
|
||||
author: p['author']['login'],
|
||||
avatarUrl: p['author']['avatarUrl'],
|
||||
commentCount: p['comments']['totalCount'],
|
||||
number: p['number'],
|
||||
subtitle: '#' + p['number'].toString(),
|
||||
title: p['title'],
|
||||
updatedAt: DateTime.parse(p['updatedAt']),
|
||||
url: '/github' + Uri.parse(p['url']).path,
|
||||
|
@ -52,6 +52,7 @@ class GlIssueScreen extends StatelessWidget {
|
||||
createdAt: issue.createdAt,
|
||||
body: issue.description,
|
||||
login: issue.author.username,
|
||||
prefix: 'gitlab',
|
||||
),
|
||||
),
|
||||
CommonStyle.border,
|
||||
@ -80,6 +81,7 @@ class GlIssueScreen extends StatelessWidget {
|
||||
createdAt: note.createdAt,
|
||||
body: note.body,
|
||||
login: note.author.username,
|
||||
prefix: 'gitlab',
|
||||
),
|
||||
)
|
||||
],
|
||||
|
@ -34,7 +34,7 @@ class GlIssuesScreen extends StatelessWidget {
|
||||
author: p.author.username,
|
||||
avatarUrl: p.author.avatarUrl,
|
||||
commentCount: p.userNotesCount,
|
||||
number: p.iid,
|
||||
subtitle: '#' + p.iid.toString(),
|
||||
title: p.title,
|
||||
updatedAt: p.updatedAt,
|
||||
labels: p.labels.isEmpty
|
||||
|
@ -33,7 +33,7 @@ class GlMergeRequestsScreen extends StatelessWidget {
|
||||
author: p.author.username,
|
||||
avatarUrl: p.author.avatarUrl,
|
||||
commentCount: p.userNotesCount,
|
||||
number: p.iid,
|
||||
subtitle: '#' + p.iid.toString(),
|
||||
title: p.title,
|
||||
updatedAt: p.updatedAt,
|
||||
labels: p.labels.isEmpty
|
||||
|
@ -34,7 +34,7 @@ class GtIssuesScreen extends StatelessWidget {
|
||||
author: p.user.login,
|
||||
avatarUrl: p.user.avatarUrl,
|
||||
commentCount: p.comments,
|
||||
number: p.number,
|
||||
subtitle: '#' + p.number.toString(),
|
||||
title: p.title,
|
||||
updatedAt: p.updatedAt,
|
||||
url: p.htmlUrl,
|
||||
|
@ -137,6 +137,7 @@ class CommentItem extends StatelessWidget {
|
||||
final String login;
|
||||
final DateTime createdAt;
|
||||
final String body;
|
||||
final String prefix;
|
||||
final List<Widget> widgets;
|
||||
|
||||
CommentItem.gh(Map<String, dynamic> payload)
|
||||
@ -147,13 +148,15 @@ class CommentItem extends StatelessWidget {
|
||||
login = payload['author']['login'],
|
||||
createdAt = DateTime.parse(payload['createdAt']),
|
||||
body = payload['body'],
|
||||
widgets = [GhEmojiAction(payload)];
|
||||
widgets = [GhEmojiAction(payload)],
|
||||
prefix = 'github';
|
||||
|
||||
CommentItem({
|
||||
@required this.avatar,
|
||||
@required this.login,
|
||||
@required this.createdAt,
|
||||
@required this.body,
|
||||
@required this.prefix,
|
||||
this.widgets,
|
||||
});
|
||||
|
||||
@ -170,7 +173,7 @@ class CommentItem extends StatelessWidget {
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
UserName(login),
|
||||
UserName(login, prefix),
|
||||
SizedBox(height: 2),
|
||||
Text(
|
||||
timeago.format(createdAt),
|
||||
|
@ -34,7 +34,7 @@ comments {
|
||||
|
||||
class IssueItem extends StatelessWidget {
|
||||
final String url;
|
||||
final int number;
|
||||
final String subtitle;
|
||||
final String title;
|
||||
final int commentCount;
|
||||
final DateTime updatedAt;
|
||||
@ -45,7 +45,7 @@ class IssueItem extends StatelessWidget {
|
||||
|
||||
IssueItem({
|
||||
@required this.url,
|
||||
@required this.number,
|
||||
@required this.subtitle,
|
||||
@required this.title,
|
||||
@required this.commentCount,
|
||||
@required this.updatedAt,
|
||||
@ -83,7 +83,7 @@ class IssueItem extends StatelessWidget {
|
||||
children: [
|
||||
TextSpan(text: '$title '),
|
||||
TextSpan(
|
||||
text: '#$number',
|
||||
text: '$subtitle',
|
||||
style: TextStyle(
|
||||
color: theme.palette.tertiaryText,
|
||||
fontWeight: FontWeight.normal,
|
||||
|
@ -5,14 +5,15 @@ import 'package:provider/provider.dart';
|
||||
|
||||
class UserName extends StatelessWidget {
|
||||
final String login;
|
||||
final String prefix;
|
||||
|
||||
UserName(this.login);
|
||||
UserName(this.login, this.prefix);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Provider.of<ThemeModel>(context);
|
||||
return Link(
|
||||
url: '/github/$login',
|
||||
url: '/$prefix/$login',
|
||||
child: Container(
|
||||
// padding: EdgeInsets.all(2),
|
||||
decoration: BoxDecoration(
|
||||
|
Loading…
x
Reference in New Issue
Block a user