mirror of
https://github.com/git-touch/git-touch
synced 2025-02-20 21:40:44 +01:00
parent
0864af7855
commit
be30bcb7d8
@ -301,3 +301,15 @@ class GithubContentReferenceItem {
|
||||
factory GithubContentReferenceItem.fromJson(Map<String, dynamic> json) =>
|
||||
_$GithubContentReferenceItemFromJson(json);
|
||||
}
|
||||
|
||||
@JsonSerializable(fieldRename: FieldRename.snake)
|
||||
class GithubContributorItem {
|
||||
int id;
|
||||
String login;
|
||||
String avatarUrl;
|
||||
String htmlUrl;
|
||||
int contributions;
|
||||
GithubContributorItem();
|
||||
factory GithubContributorItem.fromJson(Map<String, dynamic> json) =>
|
||||
_$GithubContributorItemFromJson(json);
|
||||
}
|
||||
|
@ -108,7 +108,11 @@ GithubEventPayload _$GithubEventPayloadFromJson(Map<String, dynamic> json) {
|
||||
..checkSuite = json['check_suite'] == null
|
||||
? null
|
||||
: GithubCheckSuiteItem.fromJson(
|
||||
json['check_suite'] as Map<String, dynamic>);
|
||||
json['check_suite'] as Map<String, dynamic>)
|
||||
..contentReference = json['content_reference'] == null
|
||||
? null
|
||||
: GithubContentReferenceItem.fromJson(
|
||||
json['content_reference'] as Map<String, dynamic>);
|
||||
}
|
||||
|
||||
Map<String, dynamic> _$GithubEventPayloadToJson(GithubEventPayload instance) =>
|
||||
@ -132,6 +136,7 @@ Map<String, dynamic> _$GithubEventPayloadToJson(GithubEventPayload instance) =>
|
||||
'installation': instance.installation,
|
||||
'check_run': instance.checkRun,
|
||||
'check_suite': instance.checkSuite,
|
||||
'content_reference': instance.contentReference,
|
||||
};
|
||||
|
||||
GithubEventIssue _$GithubEventIssueFromJson(Map<String, dynamic> json) {
|
||||
@ -415,3 +420,23 @@ Map<String, dynamic> _$GithubContentReferenceItemToJson(
|
||||
'id': instance.id,
|
||||
'reference': instance.reference,
|
||||
};
|
||||
|
||||
GithubContributorItem _$GithubContributorItemFromJson(
|
||||
Map<String, dynamic> json) {
|
||||
return GithubContributorItem()
|
||||
..id = json['id'] as int
|
||||
..login = json['login'] as String
|
||||
..avatarUrl = json['avatar_url'] as String
|
||||
..htmlUrl = json['html_url'] as String
|
||||
..contributions = json['contributions'] as int;
|
||||
}
|
||||
|
||||
Map<String, dynamic> _$GithubContributorItemToJson(
|
||||
GithubContributorItem instance) =>
|
||||
<String, dynamic>{
|
||||
'id': instance.id,
|
||||
'login': instance.login,
|
||||
'avatar_url': instance.avatarUrl,
|
||||
'html_url': instance.htmlUrl,
|
||||
'contributions': instance.contributions,
|
||||
};
|
||||
|
@ -5,6 +5,7 @@ import 'package:git_touch/screens/bb_repo.dart';
|
||||
import 'package:git_touch/screens/bb_user.dart';
|
||||
import 'package:git_touch/screens/code_theme.dart';
|
||||
import 'package:git_touch/screens/gh_commits.dart';
|
||||
import 'package:git_touch/screens/gh_contributors.dart';
|
||||
import 'package:git_touch/screens/gh_org_repos.dart';
|
||||
import 'package:git_touch/screens/gl_commit.dart';
|
||||
import 'package:git_touch/screens/gl_starrers.dart';
|
||||
@ -71,6 +72,7 @@ class GithubRouter {
|
||||
GithubRouter.object,
|
||||
GithubRouter.stargazers,
|
||||
GithubRouter.watchers,
|
||||
GithubRouter.contributors,
|
||||
];
|
||||
static final user = RouterScreen('/:login', (_, p) {
|
||||
final login = p['login'].first;
|
||||
@ -135,6 +137,10 @@ class GithubRouter {
|
||||
return GhUsersScreen(p['owner'].first, UsersScreenType.watch,
|
||||
repoName: p['name'].first);
|
||||
});
|
||||
static final contributors =
|
||||
RouterScreen('/:owner/:name/contributors', (_, p) {
|
||||
return GhContributorsScreen(p['owner'].first, p['name'].first);
|
||||
});
|
||||
}
|
||||
|
||||
class GitlabRouter {
|
||||
|
49
lib/screens/gh_contributors.dart
Normal file
49
lib/screens/gh_contributors.dart
Normal file
@ -0,0 +1,49 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:git_touch/models/github.dart';
|
||||
import 'package:git_touch/models/notification.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:git_touch/widgets/contributor_item.dart';
|
||||
import 'package:github/github.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:git_touch/widgets/event_item.dart';
|
||||
import 'package:git_touch/models/auth.dart';
|
||||
|
||||
class GhContributorsScreen extends StatelessWidget {
|
||||
final String owner;
|
||||
final String name;
|
||||
GhContributorsScreen(this.owner, this.name);
|
||||
|
||||
Future<ListPayload<GithubContributorItem, int>> _query(BuildContext context,
|
||||
[int page = 1]) async {
|
||||
final auth = Provider.of<AuthModel>(context);
|
||||
final res = await auth.ghClient.getJSON<List, List<GithubContributorItem>>(
|
||||
'/repos/$owner/$name/contributors?page=$page',
|
||||
convert: (vs) => [for (var v in vs) GithubContributorItem.fromJson(v)],
|
||||
);
|
||||
return ListPayload(
|
||||
cursor: page + 1,
|
||||
items: res,
|
||||
hasMore: res.isNotEmpty,
|
||||
);
|
||||
}
|
||||
|
||||
Widget build(BuildContext context) {
|
||||
return ListStatefulScaffold<GithubContributorItem, int>(
|
||||
title: AppBarTitle('Contributors'),
|
||||
onRefresh: () => _query(context),
|
||||
onLoadMore: (cursor) => _query(context, cursor),
|
||||
itemBuilder: (v) {
|
||||
final String login = v.login;
|
||||
return ContributorItem(
|
||||
avatarUrl: v.avatarUrl,
|
||||
commits: v.contributions,
|
||||
login: v.login,
|
||||
url: '/$login?tab=contributors',
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
@ -51,6 +51,14 @@ class GhRepoScreen extends StatelessWidget {
|
||||
}
|
||||
}
|
||||
|
||||
Future<String> _fetchContributors(BuildContext context) async {
|
||||
final auth = Provider.of<AuthModel>(context);
|
||||
final res = await auth.ghClient.getJSON(
|
||||
'/repos/$owner/$name/stats/contributors',
|
||||
);
|
||||
return res.length.toString();
|
||||
}
|
||||
|
||||
Future<String> _fetchReadme(BuildContext context) async {
|
||||
try {
|
||||
final auth = Provider.of<AuthModel>(context);
|
||||
@ -67,14 +75,16 @@ class GhRepoScreen extends StatelessWidget {
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Provider.of<ThemeModel>(context);
|
||||
final auth = Provider.of<AuthModel>(context);
|
||||
return RefreshStatefulScaffold<Tuple2<GhRepoRepository, String>>(
|
||||
return RefreshStatefulScaffold<Tuple3<GhRepoRepository, String, String>>(
|
||||
title: AppBarTitle('Repository'),
|
||||
fetchData: () async {
|
||||
final rs = await Future.wait([
|
||||
_query(context),
|
||||
_fetchReadme(context),
|
||||
_fetchContributors(context),
|
||||
]);
|
||||
return Tuple2(rs[0] as GhRepoRepository, rs[1] as String);
|
||||
|
||||
return Tuple3(rs[0] as GhRepoRepository, rs[1] as String, rs[2]);
|
||||
},
|
||||
actionBuilder: (data, setState) {
|
||||
final repo = data.item1;
|
||||
@ -96,6 +106,7 @@ class GhRepoScreen extends StatelessWidget {
|
||||
bodyBuilder: (data, setState) {
|
||||
final repo = data.item1;
|
||||
final readme = data.item2;
|
||||
final contributorsCount = data.item3;
|
||||
final ref = branch == null ? repo.defaultBranchRef : repo.ref;
|
||||
final license = repo.licenseInfo?.spdxId ?? repo.licenseInfo?.name;
|
||||
|
||||
@ -321,6 +332,12 @@ class GhRepoScreen extends StatelessWidget {
|
||||
},
|
||||
),
|
||||
],
|
||||
TableViewItem(
|
||||
leftIconData: Octicons.organization,
|
||||
text: Text('Contributors'),
|
||||
rightWidget: Text(contributorsCount),
|
||||
url: '/$owner/$name/contributors',
|
||||
)
|
||||
],
|
||||
),
|
||||
if (readme != null)
|
||||
|
66
lib/widgets/contributor_item.dart
Normal file
66
lib/widgets/contributor_item.dart
Normal file
@ -0,0 +1,66 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:git_touch/models/theme.dart';
|
||||
import 'package:git_touch/utils/utils.dart';
|
||||
import 'package:git_touch/widgets/avatar.dart';
|
||||
import 'package:git_touch/widgets/link.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class ContributorItem extends StatelessWidget {
|
||||
final String login;
|
||||
final String avatarUrl;
|
||||
final int commits;
|
||||
final String url;
|
||||
|
||||
ContributorItem({
|
||||
@required this.login,
|
||||
@required this.avatarUrl,
|
||||
@required this.commits,
|
||||
@required this.url,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Provider.of<ThemeModel>(context);
|
||||
return Link(
|
||||
url: url,
|
||||
child: Container(
|
||||
padding: CommonStyle.padding,
|
||||
child: Row(
|
||||
children: <Widget>[
|
||||
Avatar(url: avatarUrl, size: AvatarSize.large),
|
||||
SizedBox(width: 10),
|
||||
Expanded(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
Row(
|
||||
children: <Widget>[
|
||||
Text(
|
||||
login,
|
||||
style: TextStyle(
|
||||
color: theme.palette.primary,
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 6),
|
||||
if (commits != null)
|
||||
DefaultTextStyle(
|
||||
style: TextStyle(
|
||||
color: theme.palette.secondaryText,
|
||||
fontSize: 16,
|
||||
),
|
||||
child: Text("Commits: " + commits.toString()),
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user