mirror of
https://github.com/git-touch/git-touch
synced 2025-02-21 14:01:02 +01:00
parent
0864af7855
commit
be30bcb7d8
@ -301,3 +301,15 @@ class GithubContentReferenceItem {
|
|||||||
factory GithubContentReferenceItem.fromJson(Map<String, dynamic> json) =>
|
factory GithubContentReferenceItem.fromJson(Map<String, dynamic> json) =>
|
||||||
_$GithubContentReferenceItemFromJson(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
|
..checkSuite = json['check_suite'] == null
|
||||||
? null
|
? null
|
||||||
: GithubCheckSuiteItem.fromJson(
|
: 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) =>
|
Map<String, dynamic> _$GithubEventPayloadToJson(GithubEventPayload instance) =>
|
||||||
@ -132,6 +136,7 @@ Map<String, dynamic> _$GithubEventPayloadToJson(GithubEventPayload instance) =>
|
|||||||
'installation': instance.installation,
|
'installation': instance.installation,
|
||||||
'check_run': instance.checkRun,
|
'check_run': instance.checkRun,
|
||||||
'check_suite': instance.checkSuite,
|
'check_suite': instance.checkSuite,
|
||||||
|
'content_reference': instance.contentReference,
|
||||||
};
|
};
|
||||||
|
|
||||||
GithubEventIssue _$GithubEventIssueFromJson(Map<String, dynamic> json) {
|
GithubEventIssue _$GithubEventIssueFromJson(Map<String, dynamic> json) {
|
||||||
@ -415,3 +420,23 @@ Map<String, dynamic> _$GithubContentReferenceItemToJson(
|
|||||||
'id': instance.id,
|
'id': instance.id,
|
||||||
'reference': instance.reference,
|
'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/bb_user.dart';
|
||||||
import 'package:git_touch/screens/code_theme.dart';
|
import 'package:git_touch/screens/code_theme.dart';
|
||||||
import 'package:git_touch/screens/gh_commits.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/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';
|
||||||
@ -71,6 +72,7 @@ class GithubRouter {
|
|||||||
GithubRouter.object,
|
GithubRouter.object,
|
||||||
GithubRouter.stargazers,
|
GithubRouter.stargazers,
|
||||||
GithubRouter.watchers,
|
GithubRouter.watchers,
|
||||||
|
GithubRouter.contributors,
|
||||||
];
|
];
|
||||||
static final user = RouterScreen('/:login', (_, p) {
|
static final user = RouterScreen('/:login', (_, p) {
|
||||||
final login = p['login'].first;
|
final login = p['login'].first;
|
||||||
@ -135,6 +137,10 @@ class GithubRouter {
|
|||||||
return GhUsersScreen(p['owner'].first, UsersScreenType.watch,
|
return GhUsersScreen(p['owner'].first, UsersScreenType.watch,
|
||||||
repoName: p['name'].first);
|
repoName: p['name'].first);
|
||||||
});
|
});
|
||||||
|
static final contributors =
|
||||||
|
RouterScreen('/:owner/:name/contributors', (_, p) {
|
||||||
|
return GhContributorsScreen(p['owner'].first, p['name'].first);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
class GitlabRouter {
|
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 {
|
Future<String> _fetchReadme(BuildContext context) async {
|
||||||
try {
|
try {
|
||||||
final auth = Provider.of<AuthModel>(context);
|
final auth = Provider.of<AuthModel>(context);
|
||||||
@ -67,14 +75,16 @@ class GhRepoScreen extends StatelessWidget {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final theme = Provider.of<ThemeModel>(context);
|
final theme = Provider.of<ThemeModel>(context);
|
||||||
final auth = Provider.of<AuthModel>(context);
|
final auth = Provider.of<AuthModel>(context);
|
||||||
return RefreshStatefulScaffold<Tuple2<GhRepoRepository, String>>(
|
return RefreshStatefulScaffold<Tuple3<GhRepoRepository, String, String>>(
|
||||||
title: AppBarTitle('Repository'),
|
title: AppBarTitle('Repository'),
|
||||||
fetchData: () async {
|
fetchData: () async {
|
||||||
final rs = await Future.wait([
|
final rs = await Future.wait([
|
||||||
_query(context),
|
_query(context),
|
||||||
_fetchReadme(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) {
|
actionBuilder: (data, setState) {
|
||||||
final repo = data.item1;
|
final repo = data.item1;
|
||||||
@ -96,6 +106,7 @@ class GhRepoScreen extends StatelessWidget {
|
|||||||
bodyBuilder: (data, setState) {
|
bodyBuilder: (data, setState) {
|
||||||
final repo = data.item1;
|
final repo = data.item1;
|
||||||
final readme = data.item2;
|
final readme = data.item2;
|
||||||
|
final contributorsCount = data.item3;
|
||||||
final ref = branch == null ? repo.defaultBranchRef : repo.ref;
|
final ref = branch == null ? repo.defaultBranchRef : repo.ref;
|
||||||
final license = repo.licenseInfo?.spdxId ?? repo.licenseInfo?.name;
|
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)
|
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