mirror of
https://github.com/git-touch/git-touch
synced 2025-02-13 01:50:43 +01:00
feat(gitea): issue, issueComment, labels, refactor(GeIssueComment) (#155)
* feat(gitea): issue, issueAdd, issueComment * rollback grade.properties change * refactor: GeIssueComment, fix: url GtIssueComment * feat: labels
This commit is contained in:
parent
e9222f414b
commit
d74b141279
@ -245,11 +245,55 @@ class AuthModel with ChangeNotifier {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future fetchGitea(String p) async {
|
Future fetchGitea(
|
||||||
final res = await http.get('${activeAccount.domain}/api/v1$p',
|
String p, {
|
||||||
headers: {'Authorization': 'token $token'});
|
requestType = 'GET',
|
||||||
final info = json.decode(utf8.decode(res.bodyBytes));
|
Map<String, dynamic> body = const {},
|
||||||
return info;
|
}) async {
|
||||||
|
http.Response res;
|
||||||
|
Map<String, String> headers = {
|
||||||
|
'Authorization': 'token $token',
|
||||||
|
HttpHeaders.contentTypeHeader: 'application/json'
|
||||||
|
};
|
||||||
|
switch (requestType) {
|
||||||
|
case 'DELETE':
|
||||||
|
{
|
||||||
|
await http.delete(
|
||||||
|
'${activeAccount.domain}/api/v1$p',
|
||||||
|
headers: headers,
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'POST':
|
||||||
|
{
|
||||||
|
res = await http.post(
|
||||||
|
'${activeAccount.domain}/api/v1$p',
|
||||||
|
headers: headers,
|
||||||
|
body: jsonEncode(body),
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'PATCH':
|
||||||
|
{
|
||||||
|
res = await http.patch(
|
||||||
|
'${activeAccount.domain}/api/v1$p',
|
||||||
|
headers: headers,
|
||||||
|
body: jsonEncode(body),
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
res = await http.get('${activeAccount.domain}/api/v1$p',
|
||||||
|
headers: headers);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (requestType != 'DELETE') {
|
||||||
|
final info = json.decode(utf8.decode(res.bodyBytes));
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<DataWithPage> fetchGiteaWithPage(String path,
|
Future<DataWithPage> fetchGiteaWithPage(String path,
|
||||||
|
@ -108,12 +108,23 @@ class GiteaIssue {
|
|||||||
GiteaUser user;
|
GiteaUser user;
|
||||||
int comments;
|
int comments;
|
||||||
DateTime updatedAt;
|
DateTime updatedAt;
|
||||||
|
String state;
|
||||||
String htmlUrl;
|
String htmlUrl;
|
||||||
|
List<GiteaLabel> labels;
|
||||||
GiteaIssue();
|
GiteaIssue();
|
||||||
factory GiteaIssue.fromJson(Map<String, dynamic> json) =>
|
factory GiteaIssue.fromJson(Map<String, dynamic> json) =>
|
||||||
_$GiteaIssueFromJson(json);
|
_$GiteaIssueFromJson(json);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@JsonSerializable(fieldRename: FieldRename.snake)
|
||||||
|
class GiteaLabel {
|
||||||
|
String color;
|
||||||
|
String name;
|
||||||
|
GiteaLabel();
|
||||||
|
factory GiteaLabel.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$GiteaLabelFromJson(json);
|
||||||
|
}
|
||||||
|
|
||||||
@JsonSerializable(fieldRename: FieldRename.snake)
|
@JsonSerializable(fieldRename: FieldRename.snake)
|
||||||
class GiteaHeatmapItem {
|
class GiteaHeatmapItem {
|
||||||
int timestamp;
|
int timestamp;
|
||||||
@ -122,3 +133,17 @@ class GiteaHeatmapItem {
|
|||||||
factory GiteaHeatmapItem.fromJson(Map<String, dynamic> json) =>
|
factory GiteaHeatmapItem.fromJson(Map<String, dynamic> json) =>
|
||||||
_$GiteaHeatmapItemFromJson(json);
|
_$GiteaHeatmapItemFromJson(json);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@JsonSerializable(fieldRename: FieldRename.snake)
|
||||||
|
class GiteaComment {
|
||||||
|
String body;
|
||||||
|
DateTime createdAt;
|
||||||
|
String htmlUrl;
|
||||||
|
String originalAuthor;
|
||||||
|
DateTime updatedAt;
|
||||||
|
int id;
|
||||||
|
GiteaUser user;
|
||||||
|
GiteaComment();
|
||||||
|
factory GiteaComment.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$GiteaCommentFromJson(json);
|
||||||
|
}
|
||||||
|
@ -187,7 +187,12 @@ GiteaIssue _$GiteaIssueFromJson(Map<String, dynamic> json) {
|
|||||||
..updatedAt = json['updated_at'] == null
|
..updatedAt = json['updated_at'] == null
|
||||||
? null
|
? null
|
||||||
: DateTime.parse(json['updated_at'] as String)
|
: DateTime.parse(json['updated_at'] as String)
|
||||||
..htmlUrl = json['html_url'] as String;
|
..state = json['state'] as String
|
||||||
|
..htmlUrl = json['html_url'] as String
|
||||||
|
..labels = (json['labels'] as List)
|
||||||
|
?.map((e) =>
|
||||||
|
e == null ? null : GiteaLabel.fromJson(e as Map<String, dynamic>))
|
||||||
|
?.toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, dynamic> _$GiteaIssueToJson(GiteaIssue instance) =>
|
Map<String, dynamic> _$GiteaIssueToJson(GiteaIssue instance) =>
|
||||||
@ -198,7 +203,21 @@ Map<String, dynamic> _$GiteaIssueToJson(GiteaIssue instance) =>
|
|||||||
'user': instance.user,
|
'user': instance.user,
|
||||||
'comments': instance.comments,
|
'comments': instance.comments,
|
||||||
'updated_at': instance.updatedAt?.toIso8601String(),
|
'updated_at': instance.updatedAt?.toIso8601String(),
|
||||||
|
'state': instance.state,
|
||||||
'html_url': instance.htmlUrl,
|
'html_url': instance.htmlUrl,
|
||||||
|
'labels': instance.labels,
|
||||||
|
};
|
||||||
|
|
||||||
|
GiteaLabel _$GiteaLabelFromJson(Map<String, dynamic> json) {
|
||||||
|
return GiteaLabel()
|
||||||
|
..color = json['color'] as String
|
||||||
|
..name = json['name'] as String;
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> _$GiteaLabelToJson(GiteaLabel instance) =>
|
||||||
|
<String, dynamic>{
|
||||||
|
'color': instance.color,
|
||||||
|
'name': instance.name,
|
||||||
};
|
};
|
||||||
|
|
||||||
GiteaHeatmapItem _$GiteaHeatmapItemFromJson(Map<String, dynamic> json) {
|
GiteaHeatmapItem _$GiteaHeatmapItemFromJson(Map<String, dynamic> json) {
|
||||||
@ -212,3 +231,31 @@ Map<String, dynamic> _$GiteaHeatmapItemToJson(GiteaHeatmapItem instance) =>
|
|||||||
'timestamp': instance.timestamp,
|
'timestamp': instance.timestamp,
|
||||||
'contributions': instance.contributions,
|
'contributions': instance.contributions,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
GiteaComment _$GiteaCommentFromJson(Map<String, dynamic> json) {
|
||||||
|
return GiteaComment()
|
||||||
|
..body = json['body'] as String
|
||||||
|
..createdAt = json['created_at'] == null
|
||||||
|
? null
|
||||||
|
: DateTime.parse(json['created_at'] as String)
|
||||||
|
..htmlUrl = json['html_url'] as String
|
||||||
|
..originalAuthor = json['original_author'] as String
|
||||||
|
..updatedAt = json['updated_at'] == null
|
||||||
|
? null
|
||||||
|
: DateTime.parse(json['updated_at'] as String)
|
||||||
|
..id = json['id'] as int
|
||||||
|
..user = json['user'] == null
|
||||||
|
? null
|
||||||
|
: GiteaUser.fromJson(json['user'] as Map<String, dynamic>);
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> _$GiteaCommentToJson(GiteaComment instance) =>
|
||||||
|
<String, dynamic>{
|
||||||
|
'body': instance.body,
|
||||||
|
'created_at': instance.createdAt?.toIso8601String(),
|
||||||
|
'html_url': instance.htmlUrl,
|
||||||
|
'original_author': instance.originalAuthor,
|
||||||
|
'updated_at': instance.updatedAt?.toIso8601String(),
|
||||||
|
'id': instance.id,
|
||||||
|
'user': instance.user,
|
||||||
|
};
|
||||||
|
@ -35,6 +35,9 @@ import 'package:git_touch/screens/gh_org_repos.dart';
|
|||||||
import 'package:git_touch/screens/gl_commit.dart';
|
import 'package:git_touch/screens/gl_commit.dart';
|
||||||
import 'package:git_touch/screens/gl_starrers.dart';
|
import 'package:git_touch/screens/gl_starrers.dart';
|
||||||
import 'package:git_touch/screens/gt_commits.dart';
|
import 'package:git_touch/screens/gt_commits.dart';
|
||||||
|
import 'package:git_touch/screens/gt_issue.dart';
|
||||||
|
import 'package:git_touch/screens/gt_issue_comment.dart';
|
||||||
|
import 'package:git_touch/screens/gt_issue_form.dart';
|
||||||
import 'package:git_touch/screens/gt_issues.dart';
|
import 'package:git_touch/screens/gt_issues.dart';
|
||||||
import 'package:git_touch/screens/gt_object.dart';
|
import 'package:git_touch/screens/gt_object.dart';
|
||||||
import 'package:git_touch/screens/gt_orgs.dart';
|
import 'package:git_touch/screens/gt_orgs.dart';
|
||||||
@ -321,6 +324,9 @@ class GiteaRouter {
|
|||||||
GiteaRouter.commits,
|
GiteaRouter.commits,
|
||||||
GiteaRouter.issues,
|
GiteaRouter.issues,
|
||||||
GiteaRouter.pulls,
|
GiteaRouter.pulls,
|
||||||
|
GiteaRouter.issueAdd,
|
||||||
|
GiteaRouter.issue,
|
||||||
|
GiteaRouter.issueComment,
|
||||||
];
|
];
|
||||||
static final status =
|
static final status =
|
||||||
RouterScreen('/status', (context, parameters) => GtStatusScreen());
|
RouterScreen('/status', (context, parameters) => GtStatusScreen());
|
||||||
@ -387,6 +393,20 @@ class GiteaRouter {
|
|||||||
(context, parameters) => GtIssuesScreen(
|
(context, parameters) => GtIssuesScreen(
|
||||||
parameters['owner'].first, parameters['name'].first,
|
parameters['owner'].first, parameters['name'].first,
|
||||||
isPr: true));
|
isPr: true));
|
||||||
|
static final issueAdd = RouterScreen(
|
||||||
|
'/:owner/:name/issues/new',
|
||||||
|
(context, parameters) => GtIssueFormScreen(
|
||||||
|
parameters['owner'].first, parameters['name'].first));
|
||||||
|
static final issue = RouterScreen(
|
||||||
|
'/:owner/:name/issues/:number',
|
||||||
|
(context, parameters) => GtIssueScreen(parameters['owner'].first,
|
||||||
|
parameters['name'].first, parameters['number'].first));
|
||||||
|
static final issueComment = RouterScreen(
|
||||||
|
'/:owner/:name/issues/:number/comment',
|
||||||
|
(context, parameters) => GtIssueCommentScreen(parameters['owner'].first,
|
||||||
|
parameters['name'].first, parameters['number'].first,
|
||||||
|
body: parameters['body'] != null ? parameters['body'].first : '',
|
||||||
|
id: parameters['id'] != null ? parameters['id'].first : ''));
|
||||||
}
|
}
|
||||||
|
|
||||||
class BitbucketRouter {
|
class BitbucketRouter {
|
||||||
|
@ -53,53 +53,25 @@ class _GeIssueCommentScreenState extends State<GeIssueCommentScreen> {
|
|||||||
CupertinoButton.filled(
|
CupertinoButton.filled(
|
||||||
child: Text('Comment'),
|
child: Text('Comment'),
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
if (!widget.isPr) {
|
if (!isEdit) {
|
||||||
if (!isEdit) {
|
final res = await auth.fetchGitee(
|
||||||
final res = await auth.fetchGitee(
|
'/repos/${widget.owner}/${widget.name}/${widget.isPr ? 'pulls' : 'issues'}/${widget.number}/comments',
|
||||||
'/repos/${widget.owner}/${widget.name}/issues/${widget.number}/comments',
|
requestType: 'POST',
|
||||||
requestType: 'POST',
|
body: {'body': _controller.text, 'repo': widget.name},
|
||||||
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,
|
|
||||||
'/gitee/${widget.owner}/${widget.name}/issues/${widget.number}',
|
|
||||||
replace: true,
|
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
if (!isEdit) {
|
final res = await auth.fetchGitee(
|
||||||
final res = await auth.fetchGitee(
|
'/repos/${widget.owner}/${widget.name}/${widget.isPr ? 'pulls' : 'issues'}/comments/${int.parse(widget.id)}',
|
||||||
'/repos/${widget.owner}/${widget.name}/pulls/${widget.number}/comments',
|
requestType: 'PATCH',
|
||||||
requestType: 'POST',
|
body: {'body': _controller.text, 'repo': widget.name},
|
||||||
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,
|
|
||||||
'/gitee/${widget.owner}/${widget.name}/pulls/${widget.number}',
|
|
||||||
replace: true,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
Navigator.pop(context, '');
|
||||||
|
await theme.push(
|
||||||
|
context,
|
||||||
|
'/gitee/${widget.owner}/${widget.name}/${widget.isPr ? 'pulls' : 'issues'}/${widget.number}',
|
||||||
|
replace: true,
|
||||||
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
153
lib/screens/gt_issue.dart
Normal file
153
lib/screens/gt_issue.dart
Normal file
@ -0,0 +1,153 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:git_touch/models/gitea.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';
|
||||||
|
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 GtIssueScreen extends StatelessWidget {
|
||||||
|
final String owner;
|
||||||
|
final String name;
|
||||||
|
final String number;
|
||||||
|
final bool isPr;
|
||||||
|
|
||||||
|
GtIssueScreen(this.owner, this.name, this.number, {this.isPr: false});
|
||||||
|
|
||||||
|
List<ActionItem> _buildCommentActionItem(
|
||||||
|
BuildContext context, GiteaComment comment) {
|
||||||
|
final auth = context.read<AuthModel>();
|
||||||
|
final theme = context.read<ThemeModel>();
|
||||||
|
return [
|
||||||
|
ActionItem(
|
||||||
|
iconData: Octicons.pencil,
|
||||||
|
text: 'Edit',
|
||||||
|
onTap: (_) {
|
||||||
|
final uri = Uri(
|
||||||
|
path: '/gitea/$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.fetchGitea(
|
||||||
|
'/repos/$owner/$name/issues/comments/${comment.id}',
|
||||||
|
requestType: 'DELETE');
|
||||||
|
await theme.push(context, '/gitea/$owner/$name/issues/$number',
|
||||||
|
replace: true);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return RefreshStatefulScaffold<Tuple2<GiteaIssue, List<GiteaComment>>>(
|
||||||
|
title: Text("Issue: #$number"),
|
||||||
|
fetch: () async {
|
||||||
|
final auth = context.read<AuthModel>();
|
||||||
|
final items = await Future.wait([
|
||||||
|
auth.fetchGitea('/repos/$owner/$name/issues/$number'),
|
||||||
|
auth.fetchGitea('/repos/$owner/$name/issues/$number/comments')
|
||||||
|
]);
|
||||||
|
return Tuple2(GiteaIssue.fromJson(items[0]),
|
||||||
|
[for (var v in items[1]) GiteaComment.fromJson(v)]);
|
||||||
|
},
|
||||||
|
actionBuilder: (data, _) => ActionEntry(
|
||||||
|
iconData: Octicons.plus,
|
||||||
|
url: '/gitea/$owner/$name/issues/$number/comment',
|
||||||
|
),
|
||||||
|
bodyBuilder: (data, _) {
|
||||||
|
final issue = data.item1;
|
||||||
|
final comments = data.item2;
|
||||||
|
final theme = context.read<ThemeModel>();
|
||||||
|
final auth = context.read<AuthModel>();
|
||||||
|
return Column(children: <Widget>[
|
||||||
|
Container(
|
||||||
|
padding: CommonStyle.padding,
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: <Widget>[
|
||||||
|
Link(
|
||||||
|
url: '/gitea/$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: '/gitea/${comment.user.login}',
|
||||||
|
),
|
||||||
|
createdAt: comment.createdAt,
|
||||||
|
body: comment.body,
|
||||||
|
login: comment.user.login,
|
||||||
|
prefix: 'gitea',
|
||||||
|
commentActionItemList:
|
||||||
|
_buildCommentActionItem(context, comment),
|
||||||
|
)),
|
||||||
|
CommonStyle.border,
|
||||||
|
SizedBox(height: 16),
|
||||||
|
],
|
||||||
|
]),
|
||||||
|
]);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
81
lib/screens/gt_issue_comment.dart
Normal file
81
lib/screens/gt_issue_comment.dart
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:git_touch/models/auth.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 GtIssueCommentScreen extends StatefulWidget {
|
||||||
|
final String owner;
|
||||||
|
final String name;
|
||||||
|
final String number;
|
||||||
|
final bool isPr;
|
||||||
|
final String body;
|
||||||
|
final String id;
|
||||||
|
GtIssueCommentScreen(this.owner, this.name, this.number,
|
||||||
|
{this.isPr: false, this.body: '', this.id: ''});
|
||||||
|
|
||||||
|
@override
|
||||||
|
_GtIssueCommentScreenState createState() => _GtIssueCommentScreenState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _GtIssueCommentScreenState extends State<GtIssueCommentScreen> {
|
||||||
|
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(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',
|
||||||
|
maxLines: 10,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
CupertinoButton.filled(
|
||||||
|
child: Text('Comment'),
|
||||||
|
onPressed: () async {
|
||||||
|
if (!isEdit) {
|
||||||
|
final res = await auth.fetchGitea(
|
||||||
|
'/repos/${widget.owner}/${widget.name}/${widget.isPr ? 'pulls' : 'issues'}/${widget.number}/comments',
|
||||||
|
requestType: 'POST',
|
||||||
|
body: {'body': _controller.text, 'repo': widget.name},
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
final res = await auth.fetchGitea(
|
||||||
|
'/repos/${widget.owner}/${widget.name}/${widget.isPr ? 'pulls' : 'issues'}/comments/${int.parse(widget.id)}',
|
||||||
|
requestType: 'PATCH',
|
||||||
|
body: {'body': _controller.text, 'repo': widget.name},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Navigator.pop(context, '');
|
||||||
|
await theme.push(
|
||||||
|
context,
|
||||||
|
'/gitea/${widget.owner}/${widget.name}/${widget.isPr ? 'pulls' : 'issues'}/${widget.number}',
|
||||||
|
replace: true,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
78
lib/screens/gt_issue_form.dart
Normal file
78
lib/screens/gt_issue_form.dart
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:git_touch/models/auth.dart';
|
||||||
|
import 'package:git_touch/models/gitea.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 GtIssueFormScreen extends StatefulWidget {
|
||||||
|
final String owner;
|
||||||
|
final String name;
|
||||||
|
GtIssueFormScreen(this.owner, this.name);
|
||||||
|
|
||||||
|
@override
|
||||||
|
_GtIssueFormScreenState createState() => _GtIssueFormScreenState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _GtIssueFormScreenState extends State<GtIssueFormScreen> {
|
||||||
|
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.fetchGitea(
|
||||||
|
'/repos/${widget.owner}/${widget.name}/issues',
|
||||||
|
requestType: 'POST',
|
||||||
|
body: {'body': _body, 'title': _title},
|
||||||
|
).then((v) {
|
||||||
|
return GiteaIssue.fromJson(v);
|
||||||
|
});
|
||||||
|
Navigator.pop(context);
|
||||||
|
await theme.push(
|
||||||
|
context,
|
||||||
|
'/gitea/${widget.owner}/${widget.name}/issues',
|
||||||
|
replace: true,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -3,8 +3,11 @@ import 'package:git_touch/generated/l10n.dart';
|
|||||||
import 'package:git_touch/models/auth.dart';
|
import 'package:git_touch/models/auth.dart';
|
||||||
import 'package:git_touch/models/gitea.dart';
|
import 'package:git_touch/models/gitea.dart';
|
||||||
import 'package:git_touch/scaffolds/list_stateful.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/app_bar_title.dart';
|
||||||
import 'package:git_touch/widgets/issue_item.dart';
|
import 'package:git_touch/widgets/issue_item.dart';
|
||||||
|
import 'package:git_touch/widgets/label.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
class GtIssuesScreen extends StatelessWidget {
|
class GtIssuesScreen extends StatelessWidget {
|
||||||
@ -18,7 +21,6 @@ class GtIssuesScreen extends StatelessWidget {
|
|||||||
return ListStatefulScaffold<GiteaIssue, int>(
|
return ListStatefulScaffold<GiteaIssue, int>(
|
||||||
title:
|
title:
|
||||||
AppBarTitle(isPr ? S.of(context).pullRequests : S.of(context).issues),
|
AppBarTitle(isPr ? S.of(context).pullRequests : S.of(context).issues),
|
||||||
// TODO: create issue
|
|
||||||
fetch: (page) async {
|
fetch: (page) async {
|
||||||
final type = isPr ? 'pulls' : 'issues';
|
final type = isPr ? 'pulls' : 'issues';
|
||||||
final res = await context.read<AuthModel>().fetchGiteaWithPage(
|
final res = await context.read<AuthModel>().fetchGiteaWithPage(
|
||||||
@ -30,6 +32,12 @@ class GtIssuesScreen extends StatelessWidget {
|
|||||||
items: (res.data as List).map((v) => GiteaIssue.fromJson(v)).toList(),
|
items: (res.data as List).map((v) => GiteaIssue.fromJson(v)).toList(),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
actionBuilder: () => ActionEntry(
|
||||||
|
iconData: isPr ? null : Octicons.plus,
|
||||||
|
url: isPr
|
||||||
|
? '/gitea/$owner/$name/pulls/new'
|
||||||
|
: '/gitea/$owner/$name/issues/new',
|
||||||
|
),
|
||||||
itemBuilder: (p) => IssueItem(
|
itemBuilder: (p) => IssueItem(
|
||||||
author: p.user.login,
|
author: p.user.login,
|
||||||
avatarUrl: p.user.avatarUrl,
|
avatarUrl: p.user.avatarUrl,
|
||||||
@ -37,7 +45,17 @@ class GtIssuesScreen extends StatelessWidget {
|
|||||||
subtitle: '#' + p.number.toString(),
|
subtitle: '#' + p.number.toString(),
|
||||||
title: p.title,
|
title: p.title,
|
||||||
updatedAt: p.updatedAt,
|
updatedAt: p.updatedAt,
|
||||||
url: p.htmlUrl,
|
url: isPr
|
||||||
|
? p.htmlUrl // TODO: PR endpoints are not complete in Gitea
|
||||||
|
: '/gitea/$owner/$name/issues/${p.number}',
|
||||||
|
labels: isPr
|
||||||
|
? null
|
||||||
|
: p.labels.isEmpty
|
||||||
|
? null
|
||||||
|
: Wrap(spacing: 4, runSpacing: 4, children: [
|
||||||
|
for (var label in p.labels)
|
||||||
|
MyLabel(name: label.name, cssColor: label.color)
|
||||||
|
]),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user