feat(gitee): branches, labels, contributors, refactor(RouterScreen) (#153)

* feat: labels, contributors, fix: bio in search

* feat: branch, cancel/confirm to showPicker

* refactor(router): RouterScreen fallback params
This commit is contained in:
Shreyas Thirumalai 2021-01-09 22:22:45 +05:30 committed by GitHub
parent 85a393dd2e
commit f723eef83a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 487 additions and 171 deletions

View File

@ -124,6 +124,15 @@ class GiteeBlob {
_$GiteeBlobFromJson(json);
}
@JsonSerializable(fieldRename: FieldRename.snake)
class GiteeLabel {
String color;
String name;
GiteeLabel();
factory GiteeLabel.fromJson(Map<String, dynamic> json) =>
_$GiteeLabelFromJson(json);
}
@JsonSerializable(fieldRename: FieldRename.snake)
class GiteeIssue {
int comments;
@ -138,6 +147,7 @@ class GiteeIssue {
GiteeRepo repository;
GiteeRepoOwner user;
String number;
List<GiteeLabel> labels;
int id;
GiteeIssue();
factory GiteeIssue.fromJson(Map<String, dynamic> json) =>
@ -155,6 +165,7 @@ class GiteePull {
String title;
String state;
GiteeRepoOwner user;
List<GiteeLabel> labels;
int number;
int id;
GiteePull();
@ -211,3 +222,20 @@ class GiteeCommitFile {
factory GiteeCommitFile.fromJson(Map<String, dynamic> json) =>
_$GiteeCommitFileFromJson(json);
}
@JsonSerializable(fieldRename: FieldRename.snake)
class GiteeContributor {
String name;
int contributions;
GiteeContributor();
factory GiteeContributor.fromJson(Map<String, dynamic> json) =>
_$GiteeContributorFromJson(json);
}
@JsonSerializable(fieldRename: FieldRename.snake)
class GiteeBranch {
String name;
GiteeBranch();
factory GiteeBranch.fromJson(Map<String, dynamic> json) =>
_$GiteeBranchFromJson(json);
}

View File

@ -206,6 +206,18 @@ Map<String, dynamic> _$GiteeBlobToJson(GiteeBlob instance) => <String, dynamic>{
'content': instance.content,
};
GiteeLabel _$GiteeLabelFromJson(Map<String, dynamic> json) {
return GiteeLabel()
..color = json['color'] as String
..name = json['name'] as String;
}
Map<String, dynamic> _$GiteeLabelToJson(GiteeLabel instance) =>
<String, dynamic>{
'color': instance.color,
'name': instance.name,
};
GiteeIssue _$GiteeIssueFromJson(Map<String, dynamic> json) {
return GiteeIssue()
..comments = json['comments'] as int
@ -224,6 +236,10 @@ GiteeIssue _$GiteeIssueFromJson(Map<String, dynamic> json) {
? null
: GiteeRepoOwner.fromJson(json['user'] as Map<String, dynamic>)
..number = json['number'] as String
..labels = (json['labels'] as List)
?.map((e) =>
e == null ? null : GiteeLabel.fromJson(e as Map<String, dynamic>))
?.toList()
..id = json['id'] as int;
}
@ -241,6 +257,7 @@ Map<String, dynamic> _$GiteeIssueToJson(GiteeIssue instance) =>
'repository': instance.repository,
'user': instance.user,
'number': instance.number,
'labels': instance.labels,
'id': instance.id,
};
@ -257,6 +274,10 @@ GiteePull _$GiteePullFromJson(Map<String, dynamic> json) {
..user = json['user'] == null
? null
: GiteeRepoOwner.fromJson(json['user'] as Map<String, dynamic>)
..labels = (json['labels'] as List)
?.map((e) =>
e == null ? null : GiteeLabel.fromJson(e as Map<String, dynamic>))
?.toList()
..number = json['number'] as int
..id = json['id'] as int;
}
@ -271,6 +292,7 @@ Map<String, dynamic> _$GiteePullToJson(GiteePull instance) => <String, dynamic>{
'title': instance.title,
'state': instance.state,
'user': instance.user,
'labels': instance.labels,
'number': instance.number,
'id': instance.id,
};
@ -349,3 +371,24 @@ Map<String, dynamic> _$GiteeCommitFileToJson(GiteeCommitFile instance) =>
'status': instance.status,
'patch': instance.patch,
};
GiteeContributor _$GiteeContributorFromJson(Map<String, dynamic> json) {
return GiteeContributor()
..name = json['name'] as String
..contributions = json['contributions'] as int;
}
Map<String, dynamic> _$GiteeContributorToJson(GiteeContributor instance) =>
<String, dynamic>{
'name': instance.name,
'contributions': instance.contributions,
};
GiteeBranch _$GiteeBranchFromJson(Map<String, dynamic> json) {
return GiteeBranch()..name = json['name'] as String;
}
Map<String, dynamic> _$GiteeBranchToJson(GiteeBranch instance) =>
<String, dynamic>{
'name': instance.name,
};

View File

@ -317,39 +317,80 @@ class ThemeModel with ChangeNotifier {
await showCupertinoModalPopup(
context: context,
builder: (context) {
return Container(
height: 216,
child: CupertinoPicker(
backgroundColor: palette.background,
children: <Widget>[
for (var v in groupItem.items)
Text(v.text, style: TextStyle(color: palette.text)),
],
itemExtent: 40,
scrollController: FixedExtentScrollController(
initialItem: groupItem.items
.toList()
.indexWhere((v) => v.value == groupItem.value)),
onSelectedItemChanged: (index) {
_selectedItem = groupItem.items[index].value;
return Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Container(
alignment: Alignment.bottomCenter,
decoration: BoxDecoration(
color: palette.background,
border: Border(
bottom: BorderSide(
color: palette.grayBackground,
width: 0.0,
),
),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
CupertinoButton(
child: Text('Cancel'),
onPressed: () {
Navigator.pop(context);
_selectedItem = groupItem.value;
},
padding: const EdgeInsets.symmetric(
horizontal: 16.0,
vertical: 5.0,
),
),
CupertinoButton(
child: Text('Confirm'),
onPressed: () {
Navigator.pop(context);
groupItem.onClose(_selectedItem);
},
padding: const EdgeInsets.symmetric(
horizontal: 16.0,
vertical: 5.0,
),
)
],
),
),
Container(
height: 216,
child: CupertinoPicker(
backgroundColor: palette.background,
children: <Widget>[
for (var v in groupItem.items)
Text(v.text, style: TextStyle(color: palette.text)),
],
itemExtent: 40,
scrollController: FixedExtentScrollController(
initialItem: groupItem.items
.toList()
.indexWhere((v) => v.value == groupItem.value)),
onSelectedItemChanged: (index) {
_selectedItem = groupItem.items[index].value;
if (groupItem.onChange != null) {
if (_debounce?.isActive ?? false) {
_debounce.cancel();
}
if (groupItem.onChange != null) {
if (_debounce?.isActive ?? false) {
_debounce.cancel();
}
_debounce = Timer(const Duration(milliseconds: 500), () {
groupItem.onChange(_selectedItem);
});
}
},
),
_debounce = Timer(const Duration(milliseconds: 500), () {
groupItem.onChange(_selectedItem);
});
}
},
),
)
],
);
},
);
if (groupItem.onClose != null) {
groupItem.onClose(_selectedItem);
}
}
showActions(BuildContext context, List<ActionItem> actionItems) async {

View File

@ -12,6 +12,7 @@ import 'package:git_touch/screens/code_theme.dart';
import 'package:git_touch/screens/ge_blob.dart';
import 'package:git_touch/screens/ge_commit.dart';
import 'package:git_touch/screens/ge_commits.dart';
import 'package:git_touch/screens/ge_contributors.dart';
import 'package:git_touch/screens/ge_files.dart';
import 'package:git_touch/screens/ge_issue.dart';
import 'package:git_touch/screens/ge_issue_comment.dart';
@ -81,10 +82,12 @@ class CommonRouter {
CommonRouter.login,
CommonRouter.settings
];
static final codeTheme = RouterScreen('/choose-code-theme', (context, p) {
static final codeTheme =
RouterScreen('/choose-code-theme', (context, parameters) {
return CodeThemeScreen();
});
static final login = RouterScreen('/login', (context, p) => LoginScreen());
static final login =
RouterScreen('/login', (context, parameters) => LoginScreen());
static final settings =
RouterScreen('/settings', (context, parameters) => SettingsScreen());
}
@ -109,9 +112,9 @@ class GithubRouter {
GithubRouter.gistObject,
GithubRouter.compare,
];
static final user = RouterScreen('/:login', (_, p) {
final login = p['login'].first;
final tab = p['tab']?.first;
static final user = RouterScreen('/:login', (context, parameters) {
final login = parameters['login'].first;
final tab = parameters['tab']?.first;
switch (tab) {
case 'followers':
return GhUsersScreen(login, UsersScreenType.follower);
@ -135,75 +138,93 @@ class GithubRouter {
return GhUserScreen(login);
}
});
static final repo = RouterScreen('/:owner/:name', (_, p) {
if (p['ref'] == null) {
return GhRepoScreen(p['owner'].first, p['name'].first);
static final repo = RouterScreen('/:owner/:name', (context, parameters) {
if (parameters['ref'] == null) {
return GhRepoScreen(parameters['owner'].first, parameters['name'].first);
} else {
return GhRepoScreen(p['owner'].first, p['name'].first,
branch: p['ref'].first);
return GhRepoScreen(parameters['owner'].first, parameters['name'].first,
branch: parameters['ref'].first);
}
});
static final gistObject = RouterScreen('/:login/gists/:id/:file', (_, p) {
static final gistObject =
RouterScreen('/:login/gists/:id/:file', (context, parameters) {
return GistObjectScreen(
p['login'].first,
p['id'].first,
p['file'].first,
raw: p['raw']?.first,
content: p['content'].first,
parameters['login'].first,
parameters['id'].first,
parameters['file'].first,
raw: parameters['raw']?.first,
content: parameters['content'].first,
);
});
static final gistFiles = RouterScreen('/:login/gists/:id', (_, p) {
return GhGistsFilesScreen(p['login'].first, p['id'].first);
static final gistFiles =
RouterScreen('/:login/gists/:id', (context, parameters) {
return GhGistsFilesScreen(
parameters['login'].first, parameters['id'].first);
});
static final issueAdd = RouterScreen('/:owner/:name/issues/new', (_, p) {
return GhIssueFormScreen(p['owner'].first, p['name'].first);
static final issueAdd =
RouterScreen('/:owner/:name/issues/new', (context, parameters) {
return GhIssueFormScreen(
parameters['owner'].first, parameters['name'].first);
});
static final issues = RouterScreen('/:owner/:name/issues',
(context, p) => GhIssuesScreen(p['owner'].first, p['name'].first));
static final pulls = RouterScreen('/:owner/:name/pulls',
(context, p) => GhPullsScreen(p['owner'].first, p['name'].first));
static final issues = RouterScreen(
'/:owner/:name/issues',
(context, parameters) =>
GhIssuesScreen(parameters['owner'].first, parameters['name'].first));
static final pulls = RouterScreen(
'/:owner/:name/pulls',
(context, parameters) =>
GhPullsScreen(parameters['owner'].first, parameters['name'].first));
static final issue = RouterScreen(
'/:owner/:name/issues/:number',
(context, p) => GhIssueScreen(
p['owner'].first, p['name'].first, int.parse(p['number'].first)));
(context, parameters) => GhIssueScreen(parameters['owner'].first,
parameters['name'].first, int.parse(parameters['number'].first)));
static final pull = RouterScreen(
'/:owner/:name/pull/:number',
(context, p) => GhIssueScreen(
p['owner'].first, p['name'].first, int.parse(p['number'].first),
(context, parameters) => GhIssueScreen(parameters['owner'].first,
parameters['name'].first, int.parse(parameters['number'].first),
isPullRequest: true));
static final files = RouterScreen(
'/:owner/:name/pull/:number/files',
(context, p) => GhFilesScreen(
p['owner'].first,
p['name'].first,
int.parse(p['number'].first),
(context, parameters) => GhFilesScreen(
parameters['owner'].first,
parameters['name'].first,
int.parse(parameters['number'].first),
));
static final compare = RouterScreen(
'/:owner/:name/compare/:before/:head',
(context, p) => GhComparisonScreen(p['owner'].first, p['name'].first,
p['before'].first, p['head'].first));
static final commits = RouterScreen('/:owner/:name/commits',
(context, p) => GhCommitsScreen(p['owner'].first, p['name'].first));
static final object = RouterScreen('/:owner/:name/blob/:ref', (_, p) {
(context, parameters) => GhComparisonScreen(
parameters['owner'].first,
parameters['name'].first,
parameters['before'].first,
parameters['head'].first));
static final commits = RouterScreen(
'/:owner/:name/commits',
(context, parameters) =>
GhCommitsScreen(parameters['owner'].first, parameters['name'].first));
static final object =
RouterScreen('/:owner/:name/blob/:ref', (context, parameters) {
return GhObjectScreen(
p['owner'].first,
p['name'].first,
p['ref'].first,
path: p['path']?.first,
raw: p['raw']?.first,
parameters['owner'].first,
parameters['name'].first,
parameters['ref'].first,
path: parameters['path']?.first,
raw: parameters['raw']?.first,
);
});
static final stargazers = RouterScreen('/:owner/:name/stargazers', (_, p) {
return GhUsersScreen(p['owner'].first, UsersScreenType.star,
repoName: p['name'].first);
static final stargazers =
RouterScreen('/:owner/:name/stargazers', (context, parameters) {
return GhUsersScreen(parameters['owner'].first, UsersScreenType.star,
repoName: parameters['name'].first);
});
static final watchers = RouterScreen('/:owner/:name/watchers', (_, p) {
return GhUsersScreen(p['owner'].first, UsersScreenType.watch,
repoName: p['name'].first);
static final watchers =
RouterScreen('/:owner/:name/watchers', (context, parameters) {
return GhUsersScreen(parameters['owner'].first, UsersScreenType.watch,
repoName: parameters['name'].first);
});
static final contributors =
RouterScreen('/:owner/:name/contributors', (_, p) {
return GhContributorsScreen(p['owner'].first, p['name'].first);
RouterScreen('/:owner/:name/contributors', (context, parameters) {
return GhContributorsScreen(
parameters['owner'].first, parameters['name'].first);
});
}
@ -224,44 +245,50 @@ class GitlabRouter {
GitlabRouter.groupMembers,
GitlabRouter.issue,
];
static final user = RouterScreen(
'/user/:id', (context, p) => GlUserScreen(int.parse(p['id'].first)));
static final user = RouterScreen('/user/:id',
(context, parameters) => GlUserScreen(int.parse(parameters['id'].first)));
static final group = RouterScreen(
'/group/:id', (context, p) => GlGroupScreen(int.parse(p['id'].first)));
'/group/:id',
(context, parameters) =>
GlGroupScreen(int.parse(parameters['id'].first)));
static final blob = RouterScreen(
'/projects/:id/blob/:ref',
(context, params) => GlBlobScreen(
int.parse(params['id'].first), params['ref'].first,
path: params['path']?.first));
(context, parameters) => GlBlobScreen(
int.parse(parameters['id'].first), parameters['ref'].first,
path: parameters['path']?.first));
static final tree = RouterScreen(
'/projects/:id/tree/:ref',
(context, params) => GlTreeScreen(
int.parse(params['id'].first), params['ref'].first,
path: params['path']?.first));
static final project = RouterScreen('/projects/:id',
(context, params) => GlProjectScreen(int.parse(params['id'].first)));
static final starrers = RouterScreen('/projects/:id/starrers',
(context, params) => GlStarrersScreen(int.parse(params['id'].first)));
(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 starrers = RouterScreen(
'/projects/:id/starrers',
(context, parameters) =>
GlStarrersScreen(int.parse(parameters['id'].first)));
static final issues = RouterScreen(
'/projects/:id/issues',
(context, params) => GlIssuesScreen(
params['id'].first,
prefix: params['prefix'].first,
(context, parameters) => GlIssuesScreen(
parameters['id'].first,
prefix: parameters['prefix'].first,
));
static final mergeRequests = RouterScreen(
'/projects/:id/merge_requests',
(context, params) => GlMergeRequestsScreen(
params['id'].first,
prefix: params['prefix'].first,
(context, parameters) => GlMergeRequestsScreen(
parameters['id'].first,
prefix: parameters['prefix'].first,
));
static final commits = RouterScreen(
'/projects/:id/commits',
(context, params) =>
GlCommitsScreen(params['id'].first, prefix: params['prefix'].first));
(context, parameters) => GlCommitsScreen(parameters['id'].first,
prefix: parameters['prefix'].first));
static final commit = RouterScreen(
'/projects/:id/commit/:sha',
(context, params) =>
GlCommitScreen(params['id'].first, sha: params['sha'].first));
(context, parameters) =>
GlCommitScreen(parameters['id'].first, sha: parameters['sha'].first));
static final projectMembers = RouterScreen(
'/projects/:id/members',
(context, parameters) =>
@ -272,10 +299,10 @@ class GitlabRouter {
GlMembersScreen(int.parse(parameters['id'].first), 'groups'));
static final issue = RouterScreen(
'/gitlab/projects/:id/issues/:iid',
(context, params) {
(context, parameters) {
return GlIssueScreen(
int.parse(params['id'].first),
int.parse(params['iid'].first),
int.parse(parameters['id'].first),
int.parse(parameters['iid'].first),
);
},
);
@ -297,9 +324,9 @@ class GiteaRouter {
];
static final status =
RouterScreen('/status', (context, parameters) => GtStatusScreen());
static final user = RouterScreen('/:login', (context, p) {
final login = p['login'].first;
final tab = p['tab']?.first;
static final user = RouterScreen('/:login', (context, parameters) {
final login = parameters['login'].first;
final tab = parameters['tab']?.first;
switch (tab) {
case 'followers':
return GtUsersScreen.followers(login);
@ -321,32 +348,45 @@ class GiteaRouter {
});
static final repo = RouterScreen(
'/:owner/:name',
(context, params) =>
GtRepoScreen(params['owner'].first, params['name'].first),
(context, parameters) =>
GtRepoScreen(parameters['owner'].first, parameters['name'].first),
);
static final object = RouterScreen(
'/:owner/:name/blob',
(context, params) => GtObjectScreen(
params['owner'].first,
params['name'].first,
path: params['path']?.first,
(context, parameters) => GtObjectScreen(
parameters['owner'].first,
parameters['name'].first,
path: parameters['path']?.first,
),
);
static final stargazers = RouterScreen('/:owner/:name/stargazers', (_, p) {
return GtUsersScreen.stargazers(p['owner'].first, p['name'].first);
static final stargazers =
RouterScreen('/:owner/:name/stargazers', (context, parameters) {
return GtUsersScreen.stargazers(
parameters['owner'].first, parameters['name'].first);
});
static final watchers = RouterScreen('/:owner/:name/watchers', (_, p) {
return GtUsersScreen.watchers(p['owner'].first, p['name'].first);
static final watchers =
RouterScreen('/:owner/:name/watchers', (context, parameters) {
return GtUsersScreen.watchers(
parameters['owner'].first, parameters['name'].first);
});
static final forks = RouterScreen('/:owner/:name/forks', (_, p) {
return GtReposScreen.forks(p['owner'].first, p['name'].first);
static final forks =
RouterScreen('/:owner/:name/forks', (context, parameters) {
return GtReposScreen.forks(
parameters['owner'].first, parameters['name'].first);
});
static final commits = RouterScreen('/:owner/:name/commits',
(_, p) => GtCommitsScreen(p['owner'].first, p['name'].first));
static final issues = RouterScreen('/:owner/:name/issues',
(_, p) => GtIssuesScreen(p['owner'].first, p['name'].first));
static final pulls = RouterScreen('/:owner/:name/pulls',
(_, p) => GtIssuesScreen(p['owner'].first, p['name'].first, isPr: true));
static final commits = RouterScreen(
'/:owner/:name/commits',
(context, parameters) =>
GtCommitsScreen(parameters['owner'].first, parameters['name'].first));
static final issues = RouterScreen(
'/:owner/:name/issues',
(context, parameters) =>
GtIssuesScreen(parameters['owner'].first, parameters['name'].first));
static final pulls = RouterScreen(
'/:owner/:name/pulls',
(context, parameters) => GtIssuesScreen(
parameters['owner'].first, parameters['name'].first,
isPr: true));
}
class BitbucketRouter {
@ -364,40 +404,46 @@ class BitbucketRouter {
];
static final user = RouterScreen(
'/:login',
(context, params) => BbUserScreen(params['login'].first,
isTeam: params['team'].first == '1'));
(context, parameters) => BbUserScreen(parameters['login'].first,
isTeam: parameters['team'].first == '1'));
static final repo = RouterScreen(
'/:owner/:name',
(context, params) =>
BbRepoScreen(params['owner'].first, params['name'].first),
(context, parameters) =>
BbRepoScreen(parameters['owner'].first, parameters['name'].first),
);
static final object = RouterScreen(
'/:owner/:name/src/:ref',
(context, params) => BbObjectScreen(
params['owner'].first,
params['name'].first,
params['ref'].first,
path: params['path']?.first,
(context, parameters) => BbObjectScreen(
parameters['owner'].first,
parameters['name'].first,
parameters['ref'].first,
path: parameters['path']?.first,
),
);
static final issues = RouterScreen('/:owner/:name/issues',
(_, p) => BbIssuesScreen(p['owner'].first, p['name'].first));
static final issues = RouterScreen(
'/:owner/:name/issues',
(context, parameters) =>
BbIssuesScreen(parameters['owner'].first, parameters['name'].first));
static final commits = RouterScreen(
'/:owner/:name/commits/:ref',
(_, p) =>
BbCommitsScreen(p['owner'].first, p['name'].first, p['ref'].first));
static final pulls = RouterScreen('/:owner/:name/pulls',
(_, p) => BbPullsScreen(p['owner'].first, p['name'].first));
static final issueAdd = RouterScreen('/:owner/:name/issues/new',
(_, p) => BbIssueFormScreen(p['owner'].first, p['name'].first));
(context, parameters) => BbCommitsScreen(parameters['owner'].first,
parameters['name'].first, parameters['ref'].first));
static final pulls = RouterScreen(
'/:owner/:name/pulls',
(context, parameters) =>
BbPullsScreen(parameters['owner'].first, parameters['name'].first));
static final issueAdd = RouterScreen(
'/:owner/:name/issues/new',
(context, parameters) => BbIssueFormScreen(
parameters['owner'].first, parameters['name'].first));
static final issue = RouterScreen(
'/:owner/:name/issues/:number',
(_, p) =>
BbIssueScreen(p['owner'].first, p['name'].first, p['number'].first));
(context, parameters) => BbIssueScreen(parameters['owner'].first,
parameters['name'].first, parameters['number'].first));
static final issueComment = RouterScreen(
'/:owner/:name/issues/:number/comment',
(_, p) => BbIssueCommentScreen(
p['owner'].first, p['name'].first, p['number'].first));
(context, parameters) => BbIssueCommentScreen(parameters['owner'].first,
parameters['name'].first, parameters['number'].first));
}
class GiteeRouter {
@ -421,13 +467,14 @@ class GiteeRouter {
GiteeRouter.pullComment,
GiteeRouter.files,
GiteeRouter.commit,
GiteeRouter.contributors,
];
static final search = RouterScreen('/search', (context, parameters) {
return GeSearchScreen();
});
static final user = RouterScreen('/:login', (context, p) {
final login = p['login'].first;
final tab = p['tab']?.first;
static final user = RouterScreen('/:login', (context, parameters) {
final login = parameters['login'].first;
final tab = parameters['tab']?.first;
switch (tab) {
case 'followers':
return GeUsersScreen.followers(login);
@ -444,21 +491,37 @@ class GiteeRouter {
});
static final repo = RouterScreen(
'/:owner/:name',
(context, params) =>
GeRepoScreen(params['owner'].first, params['name'].first),
(context, parameters) {
if (parameters['branch'] == null) {
return GeRepoScreen(
parameters['owner'].first, parameters['name'].first);
} else {
return GeRepoScreen(parameters['owner'].first, parameters['name'].first,
branch: parameters['branch'].first);
}
},
);
static final stargazers = RouterScreen('/:owner/:name/stargazers', (_, p) {
return GeUsersScreen.stargazers(p['owner'].first, p['name'].first);
static final stargazers =
RouterScreen('/:owner/:name/stargazers', (context, parameters) {
return GeUsersScreen.stargazers(
parameters['owner'].first, parameters['name'].first);
});
static final watchers = RouterScreen('/:owner/:name/watchers', (_, p) {
return GeUsersScreen.watchers(p['owner'].first, p['name'].first);
static final watchers =
RouterScreen('/:owner/:name/watchers', (context, parameters) {
return GeUsersScreen.watchers(
parameters['owner'].first, parameters['name'].first);
});
static final forks = RouterScreen('/:owner/:name/forks', (_, p) {
return GeReposScreen.forks(p['owner'].first, p['name'].first);
static final forks =
RouterScreen('/:owner/:name/forks', (context, parameters) {
return GeReposScreen.forks(
parameters['owner'].first, parameters['name'].first);
});
static final commits = RouterScreen(
'/:owner/:name/commits',
(_, p) => GeCommitsScreen(p['owner'].first, p['name'].first),
(context, parameters) => GeCommitsScreen(
parameters['owner'].first, parameters['name'].first,
branch:
parameters['branch'] != null ? parameters['branch'].first : null),
);
static final tree = RouterScreen(
'/:owner/:name/tree/:sha',
@ -543,4 +606,9 @@ class GiteeRouter {
(context, parameters) => GeCommitScreen(parameters['owner'].first,
parameters['name'].first, parameters['sha'].first),
);
static final contributors = RouterScreen(
'/:owner/:name/contributors',
(context, parameters) => GeContributorsScreen(
parameters['owner'].first, parameters['name'].first),
);
}

View File

@ -10,17 +10,17 @@ import '../generated/l10n.dart';
class GeCommitsScreen extends StatelessWidget {
final String owner;
final String name;
// final String branch; // TODO:
GeCommitsScreen(this.owner, this.name);
final String branch;
GeCommitsScreen(this.owner, this.name, {this.branch});
@override
Widget build(BuildContext context) {
return ListStatefulScaffold<GiteeCommit, int>(
title: AppBarTitle(S.of(context).commits),
fetch: (page) async {
final res = await context
.read<AuthModel>()
.fetchGiteeWithPage('/repos/$owner/$name/commits', page: page);
final res = await context.read<AuthModel>().fetchGiteeWithPage(
'/repos/$owner/$name/commits?sha=$branch',
page: page);
return ListPayload(
cursor: res.cursor,
hasMore: res.hasMore,

View File

@ -0,0 +1,80 @@
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'package:git_touch/models/gitee.dart';
import 'package:git_touch/models/theme.dart';
import 'package:git_touch/scaffolds/list_stateful.dart';
import 'package:git_touch/utils/utils.dart';
import 'package:git_touch/widgets/app_bar_title.dart';
import 'package:provider/provider.dart';
import 'package:git_touch/models/auth.dart';
import '../generated/l10n.dart';
class GeContributorsScreen extends StatelessWidget {
final String owner;
final String name;
GeContributorsScreen(this.owner, this.name);
Widget build(BuildContext context) {
return ListStatefulScaffold<GiteeContributor, int>(
title: AppBarTitle(S.of(context).contributors),
fetch: (page) async {
page = page ?? 1;
final res = await context
.read<AuthModel>()
.fetchGiteeWithPage('/repos/$owner/$name/contributors')
.then((v) {
return [
for (var contributor in v.data)
GiteeContributor.fromJson(contributor)
];
});
return ListPayload(
cursor: page + 1,
items: res,
hasMore: res.isNotEmpty,
);
},
itemBuilder: (v) {
final theme = context.read<ThemeModel>();
return Container(
padding: CommonStyle.padding,
child: Row(
children: <Widget>[
SizedBox(width: 10),
Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Row(
children: <Widget>[
Text(
v.name,
style: TextStyle(
color: theme.palette.primary,
fontSize: 18,
fontWeight: FontWeight.w600,
),
),
],
),
SizedBox(height: 6),
if (v.contributions != null)
DefaultTextStyle(
style: TextStyle(
color: theme.palette.secondaryText,
fontSize: 16,
),
child: Text(
"Contributions: " + v.contributions.toString()),
),
],
),
)
],
),
);
},
);
}
}

View File

@ -6,6 +6,7 @@ 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';
import 'package:provider/provider.dart';
class GeIssuesScreen extends StatelessWidget {
@ -40,6 +41,12 @@ class GeIssuesScreen extends StatelessWidget {
title: p.title,
updatedAt: DateTime.parse(p.updatedAt),
url: '/gitee/$owner/$name/issues/${p.number}',
labels: p.labels.isEmpty
? null
: Wrap(spacing: 4, runSpacing: 4, children: [
for (var label in p.labels)
MyLabel(name: label.name, cssColor: label.color)
]),
),
);
}

View File

@ -4,6 +4,7 @@ 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:git_touch/widgets/label.dart';
import 'package:provider/provider.dart';
class GePullsScreen extends StatelessWidget {
@ -34,6 +35,12 @@ class GePullsScreen extends StatelessWidget {
title: p.title,
updatedAt: DateTime.parse(p.updatedAt),
url: '/gitee/$owner/$name/pulls/${p.number}',
labels: p.labels.isEmpty
? null
: Wrap(spacing: 4, runSpacing: 4, children: [
for (var label in p.labels)
MyLabel(name: label.name, cssColor: label.color)
]),
),
);
}

View File

@ -1,8 +1,8 @@
import 'dart:convert';
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/refresh_stateful.dart';
import 'package:git_touch/utils/utils.dart';
import 'package:git_touch/widgets/app_bar_title.dart';
@ -18,11 +18,13 @@ import '../generated/l10n.dart';
class GeRepoScreen extends StatelessWidget {
final String owner;
final String name;
GeRepoScreen(this.owner, this.name);
final String branch;
GeRepoScreen(this.owner, this.name, {this.branch});
@override
Widget build(BuildContext context) {
return RefreshStatefulScaffold<Tuple2<GiteeRepo, MarkdownViewData>>(
return RefreshStatefulScaffold<
Tuple3<GiteeRepo, MarkdownViewData, List<GiteeBranch>>>(
title: AppBarTitle(S.of(context).repository),
fetch: () async {
final auth = context.read<AuthModel>();
@ -43,11 +45,16 @@ class GeRepoScreen extends StatelessWidget {
return utf8.decode(res.bodyBytes).normalizedHtml;
});
final readmeData = MarkdownViewData(context, md: md, html: html);
return Tuple2(repo, readmeData);
final branches =
await auth.fetchGitee('/repos/$owner/$name/branches').then((v) {
return [for (var branch in v) GiteeBranch.fromJson(branch)];
});
return Tuple3(repo, readmeData, branches);
},
bodyBuilder: (t, setState) {
final p = t.item1;
final branches = t.item3;
final theme = context.read<ThemeModel>();
return Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
@ -86,7 +93,8 @@ class GeRepoScreen extends StatelessWidget {
leftIconData: Octicons.code,
text: Text('Code'),
rightWidget: Text(p.license ?? ''),
url: '/gitee/$owner/$name/tree/${p.defaultBranch}',
url:
'/gitee/$owner/$name/tree/${branch == null ? p.defaultBranch : branch}',
),
TableViewItem(
leftIconData: Octicons.issue_opened,
@ -103,8 +111,42 @@ class GeRepoScreen extends StatelessWidget {
TableViewItem(
leftIconData: Octicons.history,
text: Text('Commits'),
url: '/gitee/$owner/$name/commits',
url:
'/gitee/$owner/$name/commits?branch=${branch == null ? p.defaultBranch : branch}',
),
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, '/gitee/$owner/$name?branch=$ref',
replace: true);
}
},
),
);
},
),
TableViewItem(
leftIconData: Octicons.organization,
text: Text('Contributors'),
url: '/gitee/$owner/$name/contributors'),
],
),
CommonStyle.verticalGap,

View File

@ -131,7 +131,7 @@ class _GeSearchScreenState extends State<GeSearchScreen> {
login: p.login,
name: p.name,
avatarUrl: p.avatarUrl,
bio: Text(p.htmlUrl),
bio: Text(p.bio != null ? p.bio : p.htmlUrl),
);
default:
return IssueItem(