From 6e33dc4ac23cf3fc09811693167b35d4628ca51b Mon Sep 17 00:00:00 2001 From: shreyas1599 Date: Mon, 11 Jan 2021 23:03:10 +0530 Subject: [PATCH 1/2] feat(gitlab): branches --- lib/models/gitlab.dart | 9 +++++++ lib/models/gitlab.g.dart | 12 +++++++++ lib/router.dart | 27 +++++++++++++------ lib/screens/gl_commits.dart | 8 +++--- lib/screens/gl_project.dart | 52 ++++++++++++++++++++++++++++++++----- 5 files changed, 90 insertions(+), 18 deletions(-) diff --git a/lib/models/gitlab.dart b/lib/models/gitlab.dart index efb6f122..6dfb2b64 100644 --- a/lib/models/gitlab.dart +++ b/lib/models/gitlab.dart @@ -210,3 +210,12 @@ class GitlabStarrer { factory GitlabStarrer.fromJson(Map json) => _$GitlabStarrerFromJson(json); } + +@JsonSerializable(fieldRename: FieldRename.snake) +class GitlabBranch { + String name; + bool merged; + GitlabBranch(); + factory GitlabBranch.fromJson(Map json) => + _$GitlabBranchFromJson(json); +} diff --git a/lib/models/gitlab.g.dart b/lib/models/gitlab.g.dart index 5192722f..c3bc7ab8 100644 --- a/lib/models/gitlab.g.dart +++ b/lib/models/gitlab.g.dart @@ -364,3 +364,15 @@ Map _$GitlabStarrerToJson(GitlabStarrer instance) => 'starred_since': instance.starredSince?.toIso8601String(), 'user': instance.user, }; + +GitlabBranch _$GitlabBranchFromJson(Map json) { + return GitlabBranch() + ..name = json['name'] as String + ..merged = json['merged'] as bool; +} + +Map _$GitlabBranchToJson(GitlabBranch instance) => + { + 'name': instance.name, + 'merged': instance.merged, + }; diff --git a/lib/router.dart b/lib/router.dart index 7dab53e8..f48b00c1 100644 --- a/lib/router.dart +++ b/lib/router.dart @@ -264,10 +264,14 @@ class GitlabRouter { (context, parameters) => GlTreeScreen( int.parse(parameters['id'].first), parameters['ref'].first, path: parameters['path']?.first)); - static final project = RouterScreen( - '/projects/:id', - (context, parameters) => - GlProjectScreen(int.parse(parameters['id'].first))); + static final project = RouterScreen('/projects/:id', (context, parameters) { + if (parameters['branch'] == null) { + return GlProjectScreen(int.parse(parameters['id'].first)); + } else { + return GlProjectScreen(int.parse(parameters['id'].first), + branch: parameters['branch'].first); + } + }); static final starrers = RouterScreen( '/projects/:id/starrers', (context, parameters) => @@ -284,10 +288,17 @@ class GitlabRouter { parameters['id'].first, prefix: parameters['prefix'].first, )); - static final commits = RouterScreen( - '/projects/:id/commits', - (context, parameters) => GlCommitsScreen(parameters['id'].first, - prefix: parameters['prefix'].first)); + static final commits = + RouterScreen('/projects/:id/commits', (context, parameters) { + if (parameters['branch'] == null) { + return GlCommitsScreen(parameters['id'].first, + prefix: parameters['prefix'].first); + } else { + return GlCommitsScreen(parameters['id'].first, + prefix: parameters['prefix'].first, + branch: parameters['branch'].first); + } + }); static final commit = RouterScreen( '/projects/:id/commit/:sha', (context, parameters) => diff --git a/lib/screens/gl_commits.dart b/lib/screens/gl_commits.dart index 2e96a9d5..8536a268 100644 --- a/lib/screens/gl_commits.dart +++ b/lib/screens/gl_commits.dart @@ -10,8 +10,8 @@ import '../generated/l10n.dart'; class GlCommitsScreen extends StatelessWidget { final String id; final String prefix; - // final String branch; // TODO: - GlCommitsScreen(this.id, {this.prefix}); + final String branch; + GlCommitsScreen(this.id, {this.prefix, this.branch}); @override Widget build(BuildContext context) { @@ -20,8 +20,8 @@ class GlCommitsScreen extends StatelessWidget { fetch: (page) async { page = page ?? 1; final auth = context.read(); - final res = await auth - .fetchGitlabWithPage('/projects/$id/repository/commits?page=$page'); + final res = await auth.fetchGitlabWithPage( + '/projects/$id/repository/commits?ref_name=$branch&page=$page'); return ListPayload( cursor: res.cursor, hasMore: res.hasMore, diff --git a/lib/screens/gl_project.dart b/lib/screens/gl_project.dart index a60a41e0..7e14ea36 100644 --- a/lib/screens/gl_project.dart +++ b/lib/screens/gl_project.dart @@ -19,13 +19,14 @@ import '../generated/l10n.dart'; class GlProjectScreen extends StatelessWidget { final int id; - GlProjectScreen(this.id); + final String branch; + GlProjectScreen(this.id, {this.branch}); @override Widget build(BuildContext context) { return RefreshStatefulScaffold< - Tuple4>, Future, - MarkdownViewData>>( + Tuple5>, Future, + MarkdownViewData, List>>( title: AppBarTitle(S.of(context).project), fetch: () async { final auth = context.read(); @@ -64,7 +65,14 @@ class GlProjectScreen extends StatelessWidget { }), ); } - return Tuple4(p, langFuture, memberCountFuture, readmeData); + + final branches = await auth + .fetchGitlab('/projects/$id/repository/branches') + .then((v) { + return [for (var branch in v) GitlabBranch.fromJson(branch)]; + }); + + return Tuple5(p, langFuture, memberCountFuture, readmeData, branches); }, actionBuilder: (t, setState) { return ActionButton( @@ -79,6 +87,7 @@ class GlProjectScreen extends StatelessWidget { final langFuture = t.item2; final memberCountFuture = t.item3; final readmeData = t.item4; + final branches = t.item5; final theme = Provider.of(context); final auth = Provider.of(context); @@ -165,7 +174,8 @@ class GlProjectScreen extends StatelessWidget { rightWidget: p.statistics == null ? null : Text(filesize(p.statistics.repositorySize)), - url: '/gitlab/projects/$id/tree/${p.defaultBranch}', + url: + '/gitlab/projects/$id/tree/${branch == null ? p.defaultBranch : branch}', ), if (p.issuesEnabled) TableViewItem( @@ -186,8 +196,38 @@ class GlProjectScreen extends StatelessWidget { rightWidget: p.statistics == null ? null : Text(p.statistics.commitCount.toString()), - url: '/gitlab/projects/$id/commits?prefix=$prefix', + url: + '/gitlab/projects/$id/commits?prefix=$prefix&branch=${branch == null ? p.defaultBranch : branch}', // EDIT ), + if (branches != null) + TableViewItem( + leftIconData: Octicons.git_branch, + text: Text(S.of(context).branches), + rightWidget: Text( + (branch == null ? p.defaultBranch : branch) + + ' • ' + + branches.length.toString()), + onTap: () async { + if (branches.length < 2) return; + + await theme.showPicker( + context, + PickerGroupItem( + value: branch, + items: branches + .map((b) => PickerItem(b.name, text: b.name)) + .toList(), + onClose: (ref) { + if (ref != branch) { + theme.push( + context, '/gitlab/projects/$id?branch=$ref', + replace: true); + } + }, + ), + ); + }, + ), ], ), CommonStyle.verticalGap, From 8371ba8d22bf0a17d054931ce39665a98de5db92 Mon Sep 17 00:00:00 2001 From: shreyas1599 Date: Tue, 12 Jan 2021 00:01:08 +0530 Subject: [PATCH 2/2] feat(gitlab):issueAdd, fix:incorrect router paths --- lib/router.dart | 8 +++- lib/screens/gl_issue_form.dart | 76 ++++++++++++++++++++++++++++++++++ lib/screens/gl_issues.dart | 10 +++-- 3 files changed, 90 insertions(+), 4 deletions(-) create mode 100644 lib/screens/gl_issue_form.dart diff --git a/lib/router.dart b/lib/router.dart index f48b00c1..0d43b8ca 100644 --- a/lib/router.dart +++ b/lib/router.dart @@ -33,6 +33,7 @@ import 'package:git_touch/screens/gh_files.dart'; import 'package:git_touch/screens/gh_gists_files.dart'; import 'package:git_touch/screens/gh_org_repos.dart'; import 'package:git_touch/screens/gl_commit.dart'; +import 'package:git_touch/screens/gl_issue_form.dart'; import 'package:git_touch/screens/gl_starrers.dart'; import 'package:git_touch/screens/gt_commits.dart'; import 'package:git_touch/screens/gt_issue.dart'; @@ -246,6 +247,7 @@ class GitlabRouter { GitlabRouter.commit, GitlabRouter.projectMembers, GitlabRouter.groupMembers, + GitlabRouter.issueAdd, GitlabRouter.issue, ]; static final user = RouterScreen('/user/:id', @@ -312,7 +314,7 @@ class GitlabRouter { (context, parameters) => GlMembersScreen(int.parse(parameters['id'].first), 'groups')); static final issue = RouterScreen( - '/gitlab/projects/:id/issues/:iid', + '/projects/:id/issues/:iid', (context, parameters) { return GlIssueScreen( int.parse(parameters['id'].first), @@ -320,6 +322,10 @@ class GitlabRouter { ); }, ); + static final issueAdd = + RouterScreen('/projects/:id/issues/new', (context, parameters) { + return GlIssueFormScreen(int.parse(parameters['id'].first)); + }); } class GiteaRouter { diff --git a/lib/screens/gl_issue_form.dart b/lib/screens/gl_issue_form.dart new file mode 100644 index 00000000..28fe8e81 --- /dev/null +++ b/lib/screens/gl_issue_form.dart @@ -0,0 +1,76 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:git_touch/models/auth.dart'; +import 'package:git_touch/models/gitlab.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 GlIssueFormScreen extends StatefulWidget { + final int id; + GlIssueFormScreen(this.id); + + @override + _GlIssueFormScreenState createState() => _GlIssueFormScreenState(); +} + +class _GlIssueFormScreenState extends State { + var _title = ''; + var _body = ''; + + @override + Widget build(BuildContext context) { + final theme = Provider.of(context); + final auth = Provider.of(context); + return CommonScaffold( + title: Text('Submit an issue'), + body: Column( + children: [ + 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.fetchGitlab( + '/projects/${widget.id}/issues', + isPost: true, + body: {'description': _body, 'title': _title}, + ).then((v) { + return GitlabIssue.fromJson(v); + }); + await theme.push( + context, + '/gitlab/projects/${widget.id}/issues/${res.iid}', + replace: true, + ); + }, + ), + ], + ), + ); + } +} diff --git a/lib/screens/gl_issues.dart b/lib/screens/gl_issues.dart index 801a1d19..f1110c92 100644 --- a/lib/screens/gl_issues.dart +++ b/lib/screens/gl_issues.dart @@ -2,6 +2,8 @@ import 'package:flutter/material.dart'; import 'package:git_touch/models/auth.dart'; import 'package:git_touch/models/gitlab.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:git_touch/widgets/label.dart'; @@ -17,7 +19,6 @@ class GlIssuesScreen extends StatelessWidget { Widget build(BuildContext context) { return ListStatefulScaffold( title: AppBarTitle(S.of(context).issues), - // TODO: create issue fetch: (page) async { page = page ?? 1; final auth = context.read(); @@ -30,6 +31,10 @@ class GlIssuesScreen extends StatelessWidget { (res.data as List).map((v) => GitlabIssue.fromJson(v)).toList(), ); }, + actionBuilder: () => ActionEntry( + iconData: Octicons.plus, + url: '/gitlab/projects/$id/issues/new', + ), itemBuilder: (p) => IssueItem( author: p.author.username, avatarUrl: p.author.avatarUrl, @@ -43,8 +48,7 @@ class GlIssuesScreen extends StatelessWidget { for (var label in p.labels) MyLabel(name: label, cssColor: '#428BCA') ]), - // url: '/gitlab/projects/${p.projectId}/issues/${p.iid}', - url: '$prefix/issues/${p.iid}', // TODO: + url: '/gitlab/projects/${p.projectId}/issues/${p.iid}', ), ); }