refactor: users screen

This commit is contained in:
Rongjian Zhang 2019-12-07 23:10:30 +08:00
parent bcaa49a3c8
commit 53dc87c893
7 changed files with 1658 additions and 60 deletions

View File

@ -44,6 +44,11 @@ targets:
queries_glob: lib/graphql/github_repositories.graphql
resolve_type_field: __typename
add_query_prefix: true
- schema: lib/github.schema.json
output: lib/graphql/github_users.dart
queries_glob: lib/graphql/github_users.graphql
resolve_type_field: __typename
add_query_prefix: true
scalar_mapping:
- graphql_type: URI
dart_type: String

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,424 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'github_users.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
GithubUsers _$GithubUsersFromJson(Map<String, dynamic> json) {
return GithubUsers()
..user = json['user'] == null
? null
: GithubUsersUser.fromJson(json['user'] as Map<String, dynamic>)
..organization = json['organization'] == null
? null
: GithubUsersOrganization.fromJson(
json['organization'] as Map<String, dynamic>)
..repository = json['repository'] == null
? null
: GithubUsersRepository.fromJson(
json['repository'] as Map<String, dynamic>);
}
Map<String, dynamic> _$GithubUsersToJson(GithubUsers instance) =>
<String, dynamic>{
'user': instance.user?.toJson(),
'organization': instance.organization?.toJson(),
'repository': instance.repository?.toJson(),
};
GithubUsersUser _$GithubUsersUserFromJson(Map<String, dynamic> json) {
return GithubUsersUser()
..login = json['login'] as String
..name = json['name'] as String
..avatarUrl = json['avatarUrl'] as String
..bio = json['bio'] as String
..followers = json['followers'] == null
? null
: GithubUsersFollowerConnection.fromJson(
json['followers'] as Map<String, dynamic>)
..following = json['following'] == null
? null
: GithubUsersFollowingConnection.fromJson(
json['following'] as Map<String, dynamic>)
..resolveType = json['__typename'] as String;
}
Map<String, dynamic> _$GithubUsersUserToJson(GithubUsersUser instance) =>
<String, dynamic>{
'login': instance.login,
'name': instance.name,
'avatarUrl': instance.avatarUrl,
'bio': instance.bio,
'followers': instance.followers?.toJson(),
'following': instance.following?.toJson(),
'__typename': instance.resolveType,
};
GithubUsersFollowerConnection _$GithubUsersFollowerConnectionFromJson(
Map<String, dynamic> json) {
return GithubUsersFollowerConnection()
..pageInfo = json['pageInfo'] == null
? null
: GithubUsersPageInfo.fromJson(json['pageInfo'] as Map<String, dynamic>)
..nodes = (json['nodes'] as List)
?.map((e) => e == null
? null
: GithubUsersUser.fromJson(e as Map<String, dynamic>))
?.toList();
}
Map<String, dynamic> _$GithubUsersFollowerConnectionToJson(
GithubUsersFollowerConnection instance) =>
<String, dynamic>{
'pageInfo': instance.pageInfo?.toJson(),
'nodes': instance.nodes?.map((e) => e?.toJson())?.toList(),
};
GithubUsersPageInfo _$GithubUsersPageInfoFromJson(Map<String, dynamic> json) {
return GithubUsersPageInfo()
..hasNextPage = json['hasNextPage'] as bool
..endCursor = json['endCursor'] as String;
}
Map<String, dynamic> _$GithubUsersPageInfoToJson(
GithubUsersPageInfo instance) =>
<String, dynamic>{
'hasNextPage': instance.hasNextPage,
'endCursor': instance.endCursor,
};
GithubUsersAuditEntryActor _$GithubUsersAuditEntryActorFromJson(
Map<String, dynamic> json) {
return GithubUsersAuditEntryActor();
}
Map<String, dynamic> _$GithubUsersAuditEntryActorToJson(
GithubUsersAuditEntryActor instance) =>
<String, dynamic>{};
GithubUsersNode _$GithubUsersNodeFromJson(Map<String, dynamic> json) {
return GithubUsersNode()..resolveType = json['__typename'] as String;
}
Map<String, dynamic> _$GithubUsersNodeToJson(GithubUsersNode instance) =>
<String, dynamic>{
'__typename': instance.resolveType,
};
GithubUsersActor _$GithubUsersActorFromJson(Map<String, dynamic> json) {
return GithubUsersActor()
..login = json['login'] as String
..avatarUrl = json['avatarUrl'] as String
..resolveType = json['__typename'] as String;
}
Map<String, dynamic> _$GithubUsersActorToJson(GithubUsersActor instance) =>
<String, dynamic>{
'login': instance.login,
'avatarUrl': instance.avatarUrl,
'__typename': instance.resolveType,
};
GithubUsersRegistryPackageOwner _$GithubUsersRegistryPackageOwnerFromJson(
Map<String, dynamic> json) {
return GithubUsersRegistryPackageOwner()
..resolveType = json['__typename'] as String;
}
Map<String, dynamic> _$GithubUsersRegistryPackageOwnerToJson(
GithubUsersRegistryPackageOwner instance) =>
<String, dynamic>{
'__typename': instance.resolveType,
};
GithubUsersRegistryPackageSearch _$GithubUsersRegistryPackageSearchFromJson(
Map<String, dynamic> json) {
return GithubUsersRegistryPackageSearch()
..resolveType = json['__typename'] as String;
}
Map<String, dynamic> _$GithubUsersRegistryPackageSearchToJson(
GithubUsersRegistryPackageSearch instance) =>
<String, dynamic>{
'__typename': instance.resolveType,
};
GithubUsersProjectOwner _$GithubUsersProjectOwnerFromJson(
Map<String, dynamic> json) {
return GithubUsersProjectOwner()..resolveType = json['__typename'] as String;
}
Map<String, dynamic> _$GithubUsersProjectOwnerToJson(
GithubUsersProjectOwner instance) =>
<String, dynamic>{
'__typename': instance.resolveType,
};
GithubUsersRepositoryOwner _$GithubUsersRepositoryOwnerFromJson(
Map<String, dynamic> json) {
return GithubUsersRepositoryOwner()
..login = json['login'] as String
..avatarUrl = json['avatarUrl'] as String
..resolveType = json['__typename'] as String;
}
Map<String, dynamic> _$GithubUsersRepositoryOwnerToJson(
GithubUsersRepositoryOwner instance) =>
<String, dynamic>{
'login': instance.login,
'avatarUrl': instance.avatarUrl,
'__typename': instance.resolveType,
};
GithubUsersUniformResourceLocatable
_$GithubUsersUniformResourceLocatableFromJson(Map<String, dynamic> json) {
return GithubUsersUniformResourceLocatable()
..resolveType = json['__typename'] as String;
}
Map<String, dynamic> _$GithubUsersUniformResourceLocatableToJson(
GithubUsersUniformResourceLocatable instance) =>
<String, dynamic>{
'__typename': instance.resolveType,
};
GithubUsersProfileOwner _$GithubUsersProfileOwnerFromJson(
Map<String, dynamic> json) {
return GithubUsersProfileOwner()
..login = json['login'] as String
..name = json['name'] as String
..resolveType = json['__typename'] as String;
}
Map<String, dynamic> _$GithubUsersProfileOwnerToJson(
GithubUsersProfileOwner instance) =>
<String, dynamic>{
'login': instance.login,
'name': instance.name,
'__typename': instance.resolveType,
};
GithubUsersSponsorable _$GithubUsersSponsorableFromJson(
Map<String, dynamic> json) {
return GithubUsersSponsorable()..resolveType = json['__typename'] as String;
}
Map<String, dynamic> _$GithubUsersSponsorableToJson(
GithubUsersSponsorable instance) =>
<String, dynamic>{
'__typename': instance.resolveType,
};
GithubUsersFollowingConnection _$GithubUsersFollowingConnectionFromJson(
Map<String, dynamic> json) {
return GithubUsersFollowingConnection()
..pageInfo = json['pageInfo'] == null
? null
: GithubUsersPageInfo.fromJson(json['pageInfo'] as Map<String, dynamic>)
..nodes = (json['nodes'] as List)
?.map((e) => e == null
? null
: GithubUsersUser.fromJson(e as Map<String, dynamic>))
?.toList();
}
Map<String, dynamic> _$GithubUsersFollowingConnectionToJson(
GithubUsersFollowingConnection instance) =>
<String, dynamic>{
'pageInfo': instance.pageInfo?.toJson(),
'nodes': instance.nodes?.map((e) => e?.toJson())?.toList(),
};
GithubUsersOrganization _$GithubUsersOrganizationFromJson(
Map<String, dynamic> json) {
return GithubUsersOrganization()
..login = json['login'] as String
..name = json['name'] as String
..avatarUrl = json['avatarUrl'] as String
..membersWithRole = json['membersWithRole'] == null
? null
: GithubUsersOrganizationMemberConnection.fromJson(
json['membersWithRole'] as Map<String, dynamic>)
..resolveType = json['__typename'] as String;
}
Map<String, dynamic> _$GithubUsersOrganizationToJson(
GithubUsersOrganization instance) =>
<String, dynamic>{
'login': instance.login,
'name': instance.name,
'avatarUrl': instance.avatarUrl,
'membersWithRole': instance.membersWithRole?.toJson(),
'__typename': instance.resolveType,
};
GithubUsersOrganizationMemberConnection
_$GithubUsersOrganizationMemberConnectionFromJson(
Map<String, dynamic> json) {
return GithubUsersOrganizationMemberConnection()
..pageInfo = json['pageInfo'] == null
? null
: GithubUsersPageInfo.fromJson(json['pageInfo'] as Map<String, dynamic>)
..nodes = (json['nodes'] as List)
?.map((e) => e == null
? null
: GithubUsersUser.fromJson(e as Map<String, dynamic>))
?.toList();
}
Map<String, dynamic> _$GithubUsersOrganizationMemberConnectionToJson(
GithubUsersOrganizationMemberConnection instance) =>
<String, dynamic>{
'pageInfo': instance.pageInfo?.toJson(),
'nodes': instance.nodes?.map((e) => e?.toJson())?.toList(),
};
GithubUsersMemberStatusable _$GithubUsersMemberStatusableFromJson(
Map<String, dynamic> json) {
return GithubUsersMemberStatusable()
..resolveType = json['__typename'] as String;
}
Map<String, dynamic> _$GithubUsersMemberStatusableToJson(
GithubUsersMemberStatusable instance) =>
<String, dynamic>{
'__typename': instance.resolveType,
};
GithubUsersRepository _$GithubUsersRepositoryFromJson(
Map<String, dynamic> json) {
return GithubUsersRepository()
..watchers = json['watchers'] == null
? null
: GithubUsersUserConnection.fromJson(
json['watchers'] as Map<String, dynamic>)
..stargazers = json['stargazers'] == null
? null
: GithubUsersStargazerConnection.fromJson(
json['stargazers'] as Map<String, dynamic>)
..resolveType = json['__typename'] as String;
}
Map<String, dynamic> _$GithubUsersRepositoryToJson(
GithubUsersRepository instance) =>
<String, dynamic>{
'watchers': instance.watchers?.toJson(),
'stargazers': instance.stargazers?.toJson(),
'__typename': instance.resolveType,
};
GithubUsersUserConnection _$GithubUsersUserConnectionFromJson(
Map<String, dynamic> json) {
return GithubUsersUserConnection()
..pageInfo = json['pageInfo'] == null
? null
: GithubUsersPageInfo.fromJson(json['pageInfo'] as Map<String, dynamic>)
..nodes = (json['nodes'] as List)
?.map((e) => e == null
? null
: GithubUsersUser.fromJson(e as Map<String, dynamic>))
?.toList();
}
Map<String, dynamic> _$GithubUsersUserConnectionToJson(
GithubUsersUserConnection instance) =>
<String, dynamic>{
'pageInfo': instance.pageInfo?.toJson(),
'nodes': instance.nodes?.map((e) => e?.toJson())?.toList(),
};
GithubUsersStargazerConnection _$GithubUsersStargazerConnectionFromJson(
Map<String, dynamic> json) {
return GithubUsersStargazerConnection()
..pageInfo = json['pageInfo'] == null
? null
: GithubUsersPageInfo.fromJson(json['pageInfo'] as Map<String, dynamic>)
..nodes = (json['nodes'] as List)
?.map((e) => e == null
? null
: GithubUsersUser.fromJson(e as Map<String, dynamic>))
?.toList();
}
Map<String, dynamic> _$GithubUsersStargazerConnectionToJson(
GithubUsersStargazerConnection instance) =>
<String, dynamic>{
'pageInfo': instance.pageInfo?.toJson(),
'nodes': instance.nodes?.map((e) => e?.toJson())?.toList(),
};
GithubUsersPinnableItem _$GithubUsersPinnableItemFromJson(
Map<String, dynamic> json) {
return GithubUsersPinnableItem();
}
Map<String, dynamic> _$GithubUsersPinnableItemToJson(
GithubUsersPinnableItem instance) =>
<String, dynamic>{};
GithubUsersSubscribable _$GithubUsersSubscribableFromJson(
Map<String, dynamic> json) {
return GithubUsersSubscribable()..resolveType = json['__typename'] as String;
}
Map<String, dynamic> _$GithubUsersSubscribableToJson(
GithubUsersSubscribable instance) =>
<String, dynamic>{
'__typename': instance.resolveType,
};
GithubUsersStarrable _$GithubUsersStarrableFromJson(Map<String, dynamic> json) {
return GithubUsersStarrable()
..stargazers = json['stargazers'] == null
? null
: GithubUsersStargazerConnection.fromJson(
json['stargazers'] as Map<String, dynamic>)
..resolveType = json['__typename'] as String;
}
Map<String, dynamic> _$GithubUsersStarrableToJson(
GithubUsersStarrable instance) =>
<String, dynamic>{
'stargazers': instance.stargazers?.toJson(),
'__typename': instance.resolveType,
};
GithubUsersRepositoryInfo _$GithubUsersRepositoryInfoFromJson(
Map<String, dynamic> json) {
return GithubUsersRepositoryInfo()
..resolveType = json['__typename'] as String;
}
Map<String, dynamic> _$GithubUsersRepositoryInfoToJson(
GithubUsersRepositoryInfo instance) =>
<String, dynamic>{
'__typename': instance.resolveType,
};
GithubUsersArguments _$GithubUsersArgumentsFromJson(Map<String, dynamic> json) {
return GithubUsersArguments(
login: json['login'] as String,
repoName: json['repoName'] as String,
after: json['after'] as String,
isFollowers: json['isFollowers'] as bool,
isFollowing: json['isFollowing'] as bool,
isMember: json['isMember'] as bool,
isStar: json['isStar'] as bool,
isWatch: json['isWatch'] as bool,
);
}
Map<String, dynamic> _$GithubUsersArgumentsToJson(
GithubUsersArguments instance) =>
<String, dynamic>{
'login': instance.login,
'repoName': instance.repoName,
'after': instance.after,
'isFollowers': instance.isFollowers,
'isFollowing': instance.isFollowing,
'isMember': instance.isMember,
'isStar': instance.isStar,
'isWatch': instance.isWatch,
};

View File

@ -0,0 +1,84 @@
query(
$login: String!
$repoName: String!
$after: String
$isFollowers: Boolean!
$isFollowing: Boolean!
$isMember: Boolean!
$isStar: Boolean!
$isWatch: Boolean!
) {
user(login: $login) {
login
name
avatarUrl
bio
followers(first: 30, after: $after) @include(if: $isFollowers) {
pageInfo {
hasNextPage
endCursor
}
nodes {
login
name
avatarUrl
bio
}
}
following(first: 30, after: $after) @include(if: $isFollowing) {
pageInfo {
hasNextPage
endCursor
}
nodes {
login
name
avatarUrl
bio
}
}
}
organization(login: $login) @include(if: $isMember) {
login
name
avatarUrl
membersWithRole(first: 30, after: $after) @include(if: $isFollowing) {
pageInfo {
hasNextPage
endCursor
}
nodes {
login
name
avatarUrl
bio
}
}
}
repository(owner: $login, name: $repoName) {
watchers(first: 30, after: $after) @include(if: $isWatch) {
pageInfo {
hasNextPage
endCursor
}
nodes {
login
name
avatarUrl
bio
}
}
stargazers(first: 30, after: $after) @include(if: $isStar) {
pageInfo {
hasNextPage
endCursor
}
nodes {
login
name
avatarUrl
bio
}
}
}
}

View File

@ -5,7 +5,6 @@ import 'package:flutter/cupertino.dart';
import 'package:git_touch/graphql/github_repository.dart';
import 'package:git_touch/models/auth.dart';
import 'package:git_touch/scaffolds/refresh_stateful.dart';
import 'package:git_touch/screens/repositories.dart';
import 'package:git_touch/screens/users.dart';
import 'package:git_touch/utils/utils.dart';
import 'package:git_touch/widgets/app_bar_title.dart';
@ -144,12 +143,14 @@ class RepositoryScreen extends StatelessWidget {
EntryItem(
count: repo.watchers.totalCount,
text: 'Watchers',
screenBuilder: (context) => UsersScreen.watchers(owner, name),
screenBuilder: (context) =>
UsersScreen(owner, UsersScreenType.watch, repoName: name),
),
EntryItem(
count: repo.stargazers.totalCount,
text: 'Stars',
screenBuilder: (context) => UsersScreen.stars(owner, name),
screenBuilder: (context) =>
UsersScreen(owner, UsersScreenType.star, repoName: name),
),
EntryItem(
count: repo.forks.totalCount,

View File

@ -102,12 +102,14 @@ class UserScreen extends StatelessWidget {
EntryItem(
count: user.followers.totalCount,
text: 'Followers',
screenBuilder: (context) => UsersScreen.followers(user.login),
screenBuilder: (context) =>
UsersScreen(user.login, UsersScreenType.follower),
),
EntryItem(
count: user.following.totalCount,
text: 'Following',
screenBuilder: (context) => UsersScreen.following(user.login),
screenBuilder: (context) =>
UsersScreen(user.login, UsersScreenType.following),
),
]),
CommonStyle.verticalGap,
@ -188,7 +190,8 @@ class UserScreen extends StatelessWidget {
EntryItem(
count: payload.membersWithRole.totalCount,
text: 'Members',
screenBuilder: (context) => UsersScreen.members(payload.login),
screenBuilder: (context) =>
UsersScreen(payload.login, UsersScreenType.member),
),
]),
CommonStyle.verticalGap,

View File

@ -1,76 +1,113 @@
import 'package:flutter/material.dart';
import 'package:git_touch/graphql/github_users.dart';
import 'package:git_touch/scaffolds/list_stateful.dart';
import 'package:git_touch/widgets/app_bar_title.dart';
import 'package:git_touch/widgets/user_item.dart';
import 'package:git_touch/models/auth.dart';
import 'package:provider/provider.dart';
import '../utils/utils.dart';
enum UsersScreenType {
follower,
following,
member,
watch,
star,
}
class UsersScreen extends StatelessWidget {
final String scope;
final String params;
final String resource;
final String title;
final String login;
final String repoName;
final UsersScreenType type;
UsersScreen.followers(String login)
: scope = 'user',
params = 'login: "$login"',
resource = 'followers',
title = 'Followers';
UsersScreen.following(String login)
: scope = 'user',
params = 'login: "$login"',
resource = 'following',
title = 'Following';
UsersScreen.stars(String owner, String name)
: scope = 'repository',
params = 'owner: "$owner", name: "$name"',
resource = 'stargazers',
title = 'Stargazers';
UsersScreen.watchers(String owner, String name)
: scope = 'repository',
params = 'owner: "$owner", name: "$name"',
resource = 'watchers',
title = 'Watchers';
UsersScreen.members(String login)
: scope = 'organization',
params = 'login: "$login"',
resource = 'membersWithRole',
title = 'Members';
UsersScreen(this.login, this.type, {this.repoName = ''});
Future<ListPayload> _queryUsers(BuildContext context, [String cursor]) async {
var cursorChunk = cursor == null ? '' : ', after: "$cursor"';
var data = await Provider.of<AuthModel>(context).query('''
{
$scope($params) {
$resource(first: $pageSize$cursorChunk) {
pageInfo {
hasNextPage
endCursor
}
nodes {
$userGqlChunk
}
String get _title {
switch (type) {
case UsersScreenType.follower:
return 'Followers';
case UsersScreenType.following:
return 'Following';
case UsersScreenType.member:
return 'Members';
case UsersScreenType.watch:
return 'Watchers';
case UsersScreenType.star:
return 'Stargazers';
default:
return null;
}
}
}
''');
var repo = data[scope][resource];
return ListPayload(
cursor: repo["pageInfo"]["endCursor"],
hasMore: repo['pageInfo']['hasNextPage'],
items: repo["nodes"],
);
Future<ListPayload<GithubUsersUser, String>> _queryUsers(BuildContext context,
[String cursor]) async {
final res = await Provider.of<AuthModel>(context).gqlClient.execute(
GithubUsersQuery(
variables: GithubUsersArguments(
login: login,
repoName: repoName,
isFollowers: type == UsersScreenType.follower,
isFollowing: type == UsersScreenType.following,
isStar: type == UsersScreenType.star,
isWatch: type == UsersScreenType.watch,
isMember: type == UsersScreenType.member,
after: cursor)));
switch (type) {
case UsersScreenType.follower:
final payload = res.data.user.followers;
return ListPayload(
cursor: payload.pageInfo.endCursor,
hasMore: payload.pageInfo.hasNextPage,
items: payload.nodes,
);
case UsersScreenType.following:
final payload = res.data.user.following;
return ListPayload(
cursor: payload.pageInfo.endCursor,
hasMore: payload.pageInfo.hasNextPage,
items: payload.nodes,
);
case UsersScreenType.member:
final payload = res.data.organization.membersWithRole;
return ListPayload(
cursor: payload.pageInfo.endCursor,
hasMore: payload.pageInfo.hasNextPage,
items: payload.nodes,
);
case UsersScreenType.watch:
final payload = res.data.repository.watchers;
return ListPayload(
cursor: payload.pageInfo.endCursor,
hasMore: payload.pageInfo.hasNextPage,
items: payload.nodes,
);
case UsersScreenType.star:
final payload = res.data.repository.stargazers;
return ListPayload(
cursor: payload.pageInfo.endCursor,
hasMore: payload.pageInfo.hasNextPage,
items: payload.nodes,
);
default:
return null;
}
}
@override
Widget build(BuildContext context) {
return ListStatefulScaffold(
title: AppBarTitle(title),
return ListStatefulScaffold<GithubUsersUser, String>(
title: AppBarTitle(_title),
onRefresh: () => _queryUsers(context),
onLoadMore: (cursor) => _queryUsers(context, cursor),
itemBuilder: (payload) => UserItem.fromData(payload),
itemBuilder: (payload) {
return UserItem(
login: payload.login,
name: payload.name,
avatarUrl: payload.avatarUrl,
bio: payload.bio,
inUserScreen: true,
);
},
);
}
}