mirror of
https://github.com/git-touch/git-touch
synced 2025-02-02 08:56:54 +01:00
feat(gitee): comment actions (issue/PR) (#150)
This commit is contained in:
parent
efe882a0df
commit
e9454c3dce
@ -278,25 +278,53 @@ class AuthModel with ChangeNotifier {
|
||||
|
||||
Future fetchGitee(
|
||||
String p, {
|
||||
isPost = false,
|
||||
requestType = 'GET',
|
||||
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'});
|
||||
Map<String, String> headers = {
|
||||
'Authorization': 'token $token',
|
||||
HttpHeaders.contentTypeHeader: 'application/json'
|
||||
};
|
||||
switch (requestType) {
|
||||
case 'DELETE':
|
||||
{
|
||||
await http.delete(
|
||||
'${activeAccount.domain}/api/v5$p',
|
||||
headers: headers,
|
||||
);
|
||||
break;
|
||||
}
|
||||
case 'POST':
|
||||
{
|
||||
res = await http.post(
|
||||
'${activeAccount.domain}/api/v5$p',
|
||||
headers: headers,
|
||||
body: jsonEncode(body),
|
||||
);
|
||||
break;
|
||||
}
|
||||
case 'PATCH':
|
||||
{
|
||||
res = await http.patch(
|
||||
'${activeAccount.domain}/api/v5$p',
|
||||
headers: headers,
|
||||
body: jsonEncode(body),
|
||||
);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
res = await http.get('${activeAccount.domain}/api/v5$p',
|
||||
headers: headers);
|
||||
break;
|
||||
}
|
||||
}
|
||||
final info = json.decode(utf8.decode(res.bodyBytes));
|
||||
return info;
|
||||
if (requestType != 'DELETE') {
|
||||
final info = json.decode(utf8.decode(res.bodyBytes));
|
||||
return info;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
Future<DataWithPage> fetchGiteeWithPage(String path,
|
||||
|
@ -164,6 +164,7 @@ class GiteePull {
|
||||
|
||||
@JsonSerializable(fieldRename: FieldRename.snake)
|
||||
class GiteeComment {
|
||||
int id;
|
||||
String body;
|
||||
String createdAt;
|
||||
GiteeRepoOwner user;
|
||||
|
@ -277,6 +277,7 @@ Map<String, dynamic> _$GiteePullToJson(GiteePull instance) => <String, dynamic>{
|
||||
|
||||
GiteeComment _$GiteeCommentFromJson(Map<String, dynamic> json) {
|
||||
return GiteeComment()
|
||||
..id = json['id'] as int
|
||||
..body = json['body'] as String
|
||||
..createdAt = json['created_at'] as String
|
||||
..user = json['user'] == null
|
||||
@ -286,6 +287,7 @@ GiteeComment _$GiteeCommentFromJson(Map<String, dynamic> json) {
|
||||
|
||||
Map<String, dynamic> _$GiteeCommentToJson(GiteeComment instance) =>
|
||||
<String, dynamic>{
|
||||
'id': instance.id,
|
||||
'body': instance.body,
|
||||
'created_at': instance.createdAt,
|
||||
'user': instance.user,
|
||||
|
@ -505,9 +505,14 @@ class GiteeRouter {
|
||||
});
|
||||
static final issueComment = RouterScreen(
|
||||
'/:owner/:name/issues/:number/comment', (context, parameters) {
|
||||
return GeIssueCommentScreen(parameters['owner'].first,
|
||||
parameters['name'].first, parameters['number'].first,
|
||||
isPr: false);
|
||||
return GeIssueCommentScreen(
|
||||
parameters['owner'].first,
|
||||
parameters['name'].first,
|
||||
parameters['number'].first,
|
||||
isPr: false,
|
||||
body: parameters['body'] != null ? parameters['body'].first : '',
|
||||
id: parameters['id'] != null ? parameters['id'].first : '',
|
||||
);
|
||||
});
|
||||
static final pull = RouterScreen(
|
||||
'/:owner/:name/pulls/:number',
|
||||
@ -519,9 +524,14 @@ class GiteeRouter {
|
||||
);
|
||||
static final pullComment = RouterScreen('/:owner/:name/pulls/:number/comment',
|
||||
(context, parameters) {
|
||||
return GeIssueCommentScreen(parameters['owner'].first,
|
||||
parameters['name'].first, parameters['number'].first,
|
||||
isPr: true);
|
||||
return GeIssueCommentScreen(
|
||||
parameters['owner'].first,
|
||||
parameters['name'].first,
|
||||
parameters['number'].first,
|
||||
isPr: true,
|
||||
body: parameters['body'] != null ? parameters['body'].first : '',
|
||||
id: parameters['id'] != null ? parameters['id'].first : '',
|
||||
);
|
||||
});
|
||||
static final files =
|
||||
RouterScreen('/:owner/:name/pulls/:number/files', (context, parameters) {
|
||||
|
@ -24,7 +24,6 @@ class GeCommitScreen extends StatelessWidget {
|
||||
fetch: () async {
|
||||
final auth = context.read<AuthModel>();
|
||||
final items = await auth.fetchGitee('/repos/$owner/$name/commits/$sha');
|
||||
print(GiteeCommit.fromJson(items));
|
||||
return GiteeCommit.fromJson(items);
|
||||
},
|
||||
actionBuilder: (data, _) => ActionButton(
|
||||
|
@ -2,6 +2,7 @@ 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_button.dart';
|
||||
import 'package:git_touch/widgets/action_entry.dart';
|
||||
import 'package:git_touch/widgets/avatar.dart';
|
||||
import 'package:git_touch/widgets/link.dart';
|
||||
@ -20,6 +21,38 @@ class GeIssueScreen extends StatelessWidget {
|
||||
|
||||
GeIssueScreen(this.owner, this.name, this.number, {this.isPr: false});
|
||||
|
||||
List<ActionItem> _buildCommentActionItem(
|
||||
BuildContext context, GiteeComment comment) {
|
||||
final auth = context.read<AuthModel>();
|
||||
final theme = context.read<ThemeModel>();
|
||||
return [
|
||||
ActionItem(
|
||||
iconData: Octicons.pencil,
|
||||
text: 'Edit',
|
||||
onTap: (_) {
|
||||
final uri = Uri(
|
||||
path: '/gitee/$owner/$name/issues/$number/comment',
|
||||
queryParameters: {
|
||||
'body': comment.body,
|
||||
'id': comment.id.toString(),
|
||||
},
|
||||
).toString();
|
||||
theme.push(context, uri);
|
||||
}),
|
||||
ActionItem(
|
||||
iconData: Octicons.trashcan,
|
||||
text: 'Delete',
|
||||
onTap: (_) async {
|
||||
await auth.fetchGitee(
|
||||
'/repos/$owner/$name/issues/comments/${comment.id}',
|
||||
requestType: 'DELETE');
|
||||
await theme.push(context, '/gitee/$owner/$name/issues/$number',
|
||||
replace: true);
|
||||
},
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return RefreshStatefulScaffold<Tuple2<GiteeIssue, List<GiteeComment>>>(
|
||||
@ -97,14 +130,17 @@ class GeIssueScreen extends StatelessWidget {
|
||||
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')),
|
||||
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',
|
||||
commentActionItemList:
|
||||
_buildCommentActionItem(context, comment),
|
||||
)),
|
||||
CommonStyle.border,
|
||||
SizedBox(height: 16),
|
||||
],
|
||||
|
@ -1,7 +1,6 @@
|
||||
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';
|
||||
@ -12,33 +11,42 @@ class GeIssueCommentScreen extends StatefulWidget {
|
||||
final String name;
|
||||
final String number;
|
||||
final bool isPr;
|
||||
GeIssueCommentScreen(this.owner, this.name, this.number, {this.isPr: false});
|
||||
final String body;
|
||||
final String id;
|
||||
GeIssueCommentScreen(this.owner, this.name, this.number,
|
||||
{this.isPr: false, this.body: '', this.id: ''});
|
||||
|
||||
@override
|
||||
_GeIssueCommentScreenState createState() => _GeIssueCommentScreenState();
|
||||
}
|
||||
|
||||
class _GeIssueCommentScreenState extends State<GeIssueCommentScreen> {
|
||||
var _body = '';
|
||||
bool isEdit = false;
|
||||
TextEditingController _controller = new TextEditingController();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_controller.text = widget.body;
|
||||
if (_controller.text != '') {
|
||||
isEdit = true;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Provider.of<ThemeModel>(context);
|
||||
final auth = Provider.of<AuthModel>(context);
|
||||
return CommonScaffold(
|
||||
title: Text('New Comment'),
|
||||
title: Text(isEdit ? 'Update Comment' : 'New Comment'),
|
||||
body: Column(
|
||||
children: <Widget>[
|
||||
Padding(
|
||||
padding: CommonStyle.padding,
|
||||
child: CupertinoTextField(
|
||||
controller: _controller,
|
||||
style: TextStyle(color: theme.palette.text),
|
||||
placeholder: 'Body',
|
||||
onChanged: (v) {
|
||||
setState(() {
|
||||
_body = v;
|
||||
});
|
||||
},
|
||||
maxLines: 10,
|
||||
),
|
||||
),
|
||||
@ -46,13 +54,19 @@ class _GeIssueCommentScreenState extends State<GeIssueCommentScreen> {
|
||||
child: Text('Comment'),
|
||||
onPressed: () async {
|
||||
if (!widget.isPr) {
|
||||
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);
|
||||
});
|
||||
if (!isEdit) {
|
||||
final res = await auth.fetchGitee(
|
||||
'/repos/${widget.owner}/${widget.name}/issues/${widget.number}/comments',
|
||||
requestType: 'POST',
|
||||
body: {'body': _controller.text, 'repo': widget.name},
|
||||
);
|
||||
} else {
|
||||
final res = await auth.fetchGitee(
|
||||
'/repos/${widget.owner}/${widget.name}/issues/comments/${int.parse(widget.id)}',
|
||||
requestType: 'PATCH',
|
||||
body: {'body': _controller.text, 'repo': widget.name},
|
||||
);
|
||||
}
|
||||
Navigator.pop(context, '');
|
||||
await theme.push(
|
||||
context,
|
||||
@ -60,13 +74,25 @@ class _GeIssueCommentScreenState extends State<GeIssueCommentScreen> {
|
||||
replace: true,
|
||||
);
|
||||
} else {
|
||||
final res = await auth.fetchGitee(
|
||||
'/repos/${widget.owner}/${widget.name}/pulls/${widget.number}/comments',
|
||||
isPost: true,
|
||||
body: {'body': _body, 'repo': widget.name},
|
||||
).then((v) {
|
||||
return GiteePull.fromJson(v);
|
||||
});
|
||||
if (!isEdit) {
|
||||
final res = await auth.fetchGitee(
|
||||
'/repos/${widget.owner}/${widget.name}/pulls/${widget.number}/comments',
|
||||
requestType: 'POST',
|
||||
body: {'body': _controller.text, 'repo': widget.name},
|
||||
);
|
||||
Navigator.pop(context, '');
|
||||
await theme.push(
|
||||
context,
|
||||
'/gitee/${widget.owner}/${widget.name}/pulls/${widget.number}',
|
||||
replace: true,
|
||||
);
|
||||
} else {
|
||||
final res = await auth.fetchGitee(
|
||||
'/repos/${widget.owner}/${widget.name}/pulls/comments/${int.parse(widget.id)}',
|
||||
requestType: 'PATCH',
|
||||
body: {'body': _controller.text, 'repo': widget.name},
|
||||
);
|
||||
}
|
||||
Navigator.pop(context, '');
|
||||
await theme.push(
|
||||
context,
|
||||
|
@ -58,7 +58,7 @@ class _GeIssueFormScreenState extends State<GeIssueFormScreen> {
|
||||
onPressed: () async {
|
||||
final res = await auth.fetchGitee(
|
||||
'/repos/${widget.owner}/issues',
|
||||
isPost: true,
|
||||
requestType: 'POST',
|
||||
body: {'body': _body, 'title': _title, 'repo': widget.name},
|
||||
).then((v) {
|
||||
return GiteeIssue.fromJson(v);
|
||||
|
@ -2,6 +2,7 @@ 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_button.dart';
|
||||
import 'package:git_touch/widgets/action_entry.dart';
|
||||
import 'package:git_touch/widgets/avatar.dart';
|
||||
import 'package:git_touch/widgets/link.dart';
|
||||
@ -20,6 +21,38 @@ class GePullScreen extends StatelessWidget {
|
||||
|
||||
GePullScreen(this.owner, this.name, this.number, {this.isPr: false});
|
||||
|
||||
List<ActionItem> _buildCommentActionItem(
|
||||
BuildContext context, GiteeComment comment) {
|
||||
final auth = context.read<AuthModel>();
|
||||
final theme = context.read<ThemeModel>();
|
||||
return [
|
||||
ActionItem(
|
||||
iconData: Octicons.pencil,
|
||||
text: 'Edit',
|
||||
onTap: (_) {
|
||||
final uri = Uri(
|
||||
path: '/gitee/$owner/$name/pulls/$number/comment',
|
||||
queryParameters: {
|
||||
'body': comment.body,
|
||||
'id': comment.id.toString(),
|
||||
},
|
||||
).toString();
|
||||
theme.push(context, uri);
|
||||
}),
|
||||
ActionItem(
|
||||
iconData: Octicons.trashcan,
|
||||
text: 'Delete',
|
||||
onTap: (_) async {
|
||||
await auth.fetchGitee(
|
||||
'/repos/$owner/$name/pulls/comments/${comment.id}',
|
||||
requestType: 'DELETE');
|
||||
await theme.push(context, '/gitee/$owner/$name/pulls/$number',
|
||||
replace: true);
|
||||
},
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return RefreshStatefulScaffold<
|
||||
@ -206,14 +239,17 @@ class GePullScreen extends StatelessWidget {
|
||||
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')),
|
||||
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',
|
||||
commentActionItemList:
|
||||
_buildCommentActionItem(context, comment),
|
||||
)),
|
||||
CommonStyle.border,
|
||||
SizedBox(height: 16),
|
||||
],
|
||||
|
@ -24,12 +24,14 @@ class ActionItem {
|
||||
return [
|
||||
ActionItem(
|
||||
text: 'Share',
|
||||
iconData: Octicons.rocket,
|
||||
onTap: (_) {
|
||||
Share.share(url);
|
||||
},
|
||||
),
|
||||
ActionItem(
|
||||
text: 'Open in Browser',
|
||||
iconData: Octicons.globe,
|
||||
onTap: (_) {
|
||||
launchUrl(url);
|
||||
},
|
||||
@ -68,12 +70,18 @@ class ActionButton extends StatelessWidget {
|
||||
title: Text(title),
|
||||
actions: items.asMap().entries.map((entry) {
|
||||
return CupertinoActionSheetAction(
|
||||
child: Text(
|
||||
entry.value.text,
|
||||
style: TextStyle(
|
||||
fontWeight: selected == entry.key
|
||||
? FontWeight.w500
|
||||
: FontWeight.w400),
|
||||
child: Row(
|
||||
children: [
|
||||
Icon(entry.value.iconData),
|
||||
SizedBox(width: 10),
|
||||
Text(
|
||||
entry.value.text,
|
||||
style: TextStyle(
|
||||
fontWeight: selected == entry.key
|
||||
? FontWeight.w500
|
||||
: FontWeight.w400),
|
||||
),
|
||||
],
|
||||
),
|
||||
onPressed: () {
|
||||
Navigator.pop(context, entry.key);
|
||||
@ -106,7 +114,13 @@ class ActionButton extends StatelessWidget {
|
||||
return items.asMap().entries.map((entry) {
|
||||
return PopupMenuItem(
|
||||
value: entry.key,
|
||||
child: Text(entry.value.text),
|
||||
child: Row(
|
||||
children: [
|
||||
Icon(entry.value.iconData),
|
||||
SizedBox(width: 10),
|
||||
Text(entry.value.text)
|
||||
],
|
||||
),
|
||||
);
|
||||
}).toList();
|
||||
},
|
||||
|
@ -139,6 +139,7 @@ class CommentItem extends StatelessWidget {
|
||||
final String body;
|
||||
final String prefix;
|
||||
final List<Widget> widgets;
|
||||
final List<ActionItem> commentActionItemList;
|
||||
|
||||
CommentItem.gh(Map<String, dynamic> payload)
|
||||
: avatar = Avatar(
|
||||
@ -149,7 +150,8 @@ class CommentItem extends StatelessWidget {
|
||||
createdAt = DateTime.parse(payload['createdAt']),
|
||||
body = payload['body'],
|
||||
widgets = [GhEmojiAction(payload)],
|
||||
prefix = 'github';
|
||||
prefix = 'github',
|
||||
commentActionItemList = []; // TODO
|
||||
|
||||
CommentItem({
|
||||
@required this.avatar,
|
||||
@ -158,6 +160,7 @@ class CommentItem extends StatelessWidget {
|
||||
@required this.body,
|
||||
@required this.prefix,
|
||||
this.widgets,
|
||||
this.commentActionItemList,
|
||||
});
|
||||
|
||||
@override
|
||||
@ -183,6 +186,15 @@ class CommentItem extends StatelessWidget {
|
||||
],
|
||||
),
|
||||
),
|
||||
Align(
|
||||
alignment: Alignment.centerRight,
|
||||
child: ActionButton(
|
||||
iconData: Octicons.kebab_horizontal,
|
||||
title: 'Comment Actions',
|
||||
items: [
|
||||
if (commentActionItemList != null) ...commentActionItemList
|
||||
],
|
||||
)),
|
||||
]),
|
||||
SizedBox(height: 12),
|
||||
MarkdownFlutterView(body, padding: EdgeInsets.zero), // TODO: link
|
||||
|
Loading…
x
Reference in New Issue
Block a user