mirror of
https://github.com/git-touch/git-touch
synced 2025-03-07 20:57:44 +01:00
refactor: me screen
This commit is contained in:
parent
36e772c85f
commit
7496129973
@ -15,8 +15,10 @@ class GithubUser with EquatableMixin {
|
||||
|
||||
GithubUserRepositoryOwner repositoryOwner;
|
||||
|
||||
GithubUserUser viewer;
|
||||
|
||||
@override
|
||||
List<Object> get props => [repositoryOwner];
|
||||
List<Object> get props => [repositoryOwner, viewer];
|
||||
Map<String, dynamic> toJson() => _$GithubUserToJson(this);
|
||||
}
|
||||
|
||||
@ -694,15 +696,17 @@ class GithubUserMemberStatusable with EquatableMixin {
|
||||
|
||||
@JsonSerializable(explicitToJson: true)
|
||||
class GithubUserArguments extends JsonSerializable with EquatableMixin {
|
||||
GithubUserArguments({this.login});
|
||||
GithubUserArguments({this.login, this.isViewer});
|
||||
|
||||
factory GithubUserArguments.fromJson(Map<String, dynamic> json) =>
|
||||
_$GithubUserArgumentsFromJson(json);
|
||||
|
||||
final String login;
|
||||
|
||||
final bool isViewer;
|
||||
|
||||
@override
|
||||
List<Object> get props => [login];
|
||||
List<Object> get props => [login, isViewer];
|
||||
Map<String, dynamic> toJson() => _$GithubUserArgumentsToJson(this);
|
||||
}
|
||||
|
||||
@ -720,6 +724,12 @@ class GithubUserQuery extends GraphQLQuery<GithubUser, GithubUserArguments> {
|
||||
type: NamedTypeNode(
|
||||
name: NameNode(value: 'String'), isNonNull: true),
|
||||
defaultValue: DefaultValueNode(value: null),
|
||||
directives: []),
|
||||
VariableDefinitionNode(
|
||||
variable: VariableNode(name: NameNode(value: 'isViewer')),
|
||||
type: NamedTypeNode(
|
||||
name: NameNode(value: 'Boolean'), isNonNull: true),
|
||||
defaultValue: DefaultValueNode(value: null),
|
||||
directives: [])
|
||||
],
|
||||
directives: [],
|
||||
@ -732,7 +742,13 @@ class GithubUserQuery extends GraphQLQuery<GithubUser, GithubUserArguments> {
|
||||
name: NameNode(value: 'login'),
|
||||
value: VariableNode(name: NameNode(value: 'login')))
|
||||
],
|
||||
directives: [],
|
||||
directives: [
|
||||
DirectiveNode(name: NameNode(value: 'skip'), arguments: [
|
||||
ArgumentNode(
|
||||
name: NameNode(value: 'if'),
|
||||
value: VariableNode(name: NameNode(value: 'isViewer')))
|
||||
])
|
||||
],
|
||||
selectionSet: SelectionSetNode(selections: [
|
||||
FieldNode(
|
||||
name: NameNode(value: '__typename'),
|
||||
@ -1502,6 +1518,166 @@ class GithubUserQuery extends GraphQLQuery<GithubUser, GithubUserArguments> {
|
||||
selectionSet: null)
|
||||
]))
|
||||
]))
|
||||
])),
|
||||
FieldNode(
|
||||
name: NameNode(value: 'viewer'),
|
||||
alias: null,
|
||||
arguments: [],
|
||||
directives: [
|
||||
DirectiveNode(name: NameNode(value: 'include'), arguments: [
|
||||
ArgumentNode(
|
||||
name: NameNode(value: 'if'),
|
||||
value: VariableNode(name: NameNode(value: 'isViewer')))
|
||||
])
|
||||
],
|
||||
selectionSet: SelectionSetNode(selections: [
|
||||
FieldNode(
|
||||
name: NameNode(value: 'login'),
|
||||
alias: null,
|
||||
arguments: [],
|
||||
directives: [],
|
||||
selectionSet: null),
|
||||
FieldNode(
|
||||
name: NameNode(value: 'avatarUrl'),
|
||||
alias: null,
|
||||
arguments: [],
|
||||
directives: [],
|
||||
selectionSet: null),
|
||||
FieldNode(
|
||||
name: NameNode(value: 'url'),
|
||||
alias: null,
|
||||
arguments: [],
|
||||
directives: [],
|
||||
selectionSet: null),
|
||||
FieldNode(
|
||||
name: NameNode(value: 'name'),
|
||||
alias: null,
|
||||
arguments: [],
|
||||
directives: [],
|
||||
selectionSet: null),
|
||||
FieldNode(
|
||||
name: NameNode(value: 'bio'),
|
||||
alias: null,
|
||||
arguments: [],
|
||||
directives: [],
|
||||
selectionSet: null),
|
||||
FieldNode(
|
||||
name: NameNode(value: 'company'),
|
||||
alias: null,
|
||||
arguments: [],
|
||||
directives: [],
|
||||
selectionSet: null),
|
||||
FieldNode(
|
||||
name: NameNode(value: 'location'),
|
||||
alias: null,
|
||||
arguments: [],
|
||||
directives: [],
|
||||
selectionSet: null),
|
||||
FieldNode(
|
||||
name: NameNode(value: 'email'),
|
||||
alias: null,
|
||||
arguments: [],
|
||||
directives: [],
|
||||
selectionSet: null),
|
||||
FieldNode(
|
||||
name: NameNode(value: 'websiteUrl'),
|
||||
alias: null,
|
||||
arguments: [],
|
||||
directives: [],
|
||||
selectionSet: null),
|
||||
FieldNode(
|
||||
name: NameNode(value: 'createdAt'),
|
||||
alias: null,
|
||||
arguments: [],
|
||||
directives: [],
|
||||
selectionSet: null),
|
||||
FieldNode(
|
||||
name: NameNode(value: 'starredRepositories'),
|
||||
alias: null,
|
||||
arguments: [],
|
||||
directives: [],
|
||||
selectionSet: SelectionSetNode(selections: [
|
||||
FieldNode(
|
||||
name: NameNode(value: 'totalCount'),
|
||||
alias: null,
|
||||
arguments: [],
|
||||
directives: [],
|
||||
selectionSet: null)
|
||||
])),
|
||||
FieldNode(
|
||||
name: NameNode(value: 'followers'),
|
||||
alias: null,
|
||||
arguments: [],
|
||||
directives: [],
|
||||
selectionSet: SelectionSetNode(selections: [
|
||||
FieldNode(
|
||||
name: NameNode(value: 'totalCount'),
|
||||
alias: null,
|
||||
arguments: [],
|
||||
directives: [],
|
||||
selectionSet: null)
|
||||
])),
|
||||
FieldNode(
|
||||
name: NameNode(value: 'following'),
|
||||
alias: null,
|
||||
arguments: [],
|
||||
directives: [],
|
||||
selectionSet: SelectionSetNode(selections: [
|
||||
FieldNode(
|
||||
name: NameNode(value: 'totalCount'),
|
||||
alias: null,
|
||||
arguments: [],
|
||||
directives: [],
|
||||
selectionSet: null)
|
||||
])),
|
||||
FieldNode(
|
||||
name: NameNode(value: 'repositories'),
|
||||
alias: null,
|
||||
arguments: [],
|
||||
directives: [],
|
||||
selectionSet: SelectionSetNode(selections: [
|
||||
FieldNode(
|
||||
name: NameNode(value: 'totalCount'),
|
||||
alias: null,
|
||||
arguments: [],
|
||||
directives: [],
|
||||
selectionSet: null)
|
||||
])),
|
||||
FieldNode(
|
||||
name: NameNode(value: 'contributionsCollection'),
|
||||
alias: null,
|
||||
arguments: [],
|
||||
directives: [],
|
||||
selectionSet: SelectionSetNode(selections: [
|
||||
FieldNode(
|
||||
name: NameNode(value: 'contributionCalendar'),
|
||||
alias: null,
|
||||
arguments: [],
|
||||
directives: [],
|
||||
selectionSet: SelectionSetNode(selections: [
|
||||
FieldNode(
|
||||
name: NameNode(value: 'weeks'),
|
||||
alias: null,
|
||||
arguments: [],
|
||||
directives: [],
|
||||
selectionSet: SelectionSetNode(selections: [
|
||||
FieldNode(
|
||||
name: NameNode(value: 'contributionDays'),
|
||||
alias: null,
|
||||
arguments: [],
|
||||
directives: [],
|
||||
selectionSet:
|
||||
SelectionSetNode(selections: [
|
||||
FieldNode(
|
||||
name: NameNode(value: 'color'),
|
||||
alias: null,
|
||||
arguments: [],
|
||||
directives: [],
|
||||
selectionSet: null)
|
||||
]))
|
||||
]))
|
||||
]))
|
||||
]))
|
||||
]))
|
||||
]))
|
||||
]);
|
||||
|
@ -11,12 +11,16 @@ GithubUser _$GithubUserFromJson(Map<String, dynamic> json) {
|
||||
..repositoryOwner = json['repositoryOwner'] == null
|
||||
? null
|
||||
: GithubUserRepositoryOwner.fromJson(
|
||||
json['repositoryOwner'] as Map<String, dynamic>);
|
||||
json['repositoryOwner'] as Map<String, dynamic>)
|
||||
..viewer = json['viewer'] == null
|
||||
? null
|
||||
: GithubUserUser.fromJson(json['viewer'] as Map<String, dynamic>);
|
||||
}
|
||||
|
||||
Map<String, dynamic> _$GithubUserToJson(GithubUser instance) =>
|
||||
<String, dynamic>{
|
||||
'repositoryOwner': instance.repositoryOwner?.toJson(),
|
||||
'viewer': instance.viewer?.toJson(),
|
||||
};
|
||||
|
||||
GithubUserRepositoryOwner _$GithubUserRepositoryOwnerFromJson(
|
||||
@ -546,6 +550,7 @@ Map<String, dynamic> _$GithubUserMemberStatusableToJson(
|
||||
GithubUserArguments _$GithubUserArgumentsFromJson(Map<String, dynamic> json) {
|
||||
return GithubUserArguments(
|
||||
login: json['login'] as String,
|
||||
isViewer: json['isViewer'] as bool,
|
||||
);
|
||||
}
|
||||
|
||||
@ -553,4 +558,5 @@ Map<String, dynamic> _$GithubUserArgumentsToJson(
|
||||
GithubUserArguments instance) =>
|
||||
<String, dynamic>{
|
||||
'login': instance.login,
|
||||
'isViewer': instance.isViewer,
|
||||
};
|
||||
|
@ -1,5 +1,5 @@
|
||||
query($login: String!) {
|
||||
repositoryOwner(login: $login) {
|
||||
query($login: String!, $isViewer: Boolean!) {
|
||||
repositoryOwner(login: $login) @skip(if: $isViewer) {
|
||||
__typename
|
||||
login
|
||||
avatarUrl
|
||||
@ -149,4 +149,37 @@ query($login: String!) {
|
||||
}
|
||||
}
|
||||
}
|
||||
viewer @include(if: $isViewer) {
|
||||
login
|
||||
avatarUrl
|
||||
url
|
||||
name
|
||||
bio
|
||||
company
|
||||
location
|
||||
email
|
||||
websiteUrl
|
||||
createdAt
|
||||
starredRepositories {
|
||||
totalCount
|
||||
}
|
||||
followers {
|
||||
totalCount
|
||||
}
|
||||
following {
|
||||
totalCount
|
||||
}
|
||||
repositories {
|
||||
totalCount
|
||||
}
|
||||
contributionsCollection {
|
||||
contributionCalendar {
|
||||
weeks {
|
||||
contributionDays {
|
||||
color
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -13,7 +13,6 @@ import 'package:git_touch/screens/gitlab_tree.dart';
|
||||
import 'package:git_touch/screens/gitlab_user.dart';
|
||||
import 'package:git_touch/screens/issue_form.dart';
|
||||
import 'package:git_touch/screens/issues.dart';
|
||||
import 'package:git_touch/screens/me.dart';
|
||||
import 'package:git_touch/screens/notification.dart';
|
||||
import 'package:git_touch/screens/object.dart';
|
||||
import 'package:git_touch/screens/repository.dart';
|
||||
@ -129,7 +128,7 @@ class _HomeState extends State<Home> {
|
||||
case 3:
|
||||
return SearchScreen();
|
||||
case 4:
|
||||
return MeScreen();
|
||||
return UserScreen('');
|
||||
}
|
||||
break;
|
||||
case PlatformType.gitlab:
|
||||
|
@ -1,158 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:git_touch/graphql/github_me.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';
|
||||
import 'package:git_touch/widgets/entry_item.dart';
|
||||
import 'package:git_touch/widgets/table_view.dart';
|
||||
import 'package:git_touch/widgets/text_contains_organization.dart';
|
||||
import 'package:git_touch/widgets/user_item.dart';
|
||||
import 'package:git_touch/models/auth.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class MeScreen extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return RefreshStatefulScaffold<GithubMeUser>(
|
||||
fetchData: () async {
|
||||
final data = await Provider.of<AuthModel>(context)
|
||||
.gqlClient
|
||||
.execute(GithubMeQuery());
|
||||
return data.data.viewer;
|
||||
},
|
||||
title: AppBarTitle('Me'),
|
||||
bodyBuilder: (user, _) {
|
||||
final theme = Provider.of<ThemeModel>(context);
|
||||
final login = user.login;
|
||||
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: <Widget>[
|
||||
UserItem(
|
||||
login: user.login,
|
||||
name: user.name,
|
||||
avatarUrl: user.avatarUrl,
|
||||
bio: Text(user.bio ?? ''),
|
||||
inUserScreen: true,
|
||||
),
|
||||
CommonStyle.border,
|
||||
Row(children: [
|
||||
EntryItem(
|
||||
count: user.repositories.totalCount,
|
||||
text: 'Repositories',
|
||||
url: '/$login?tab=repositories',
|
||||
),
|
||||
EntryItem(
|
||||
count: user.starredRepositories.totalCount,
|
||||
text: 'Stars',
|
||||
url: '/$login?tab=stars',
|
||||
),
|
||||
EntryItem(
|
||||
count: user.followers.totalCount,
|
||||
text: 'Followers',
|
||||
url: '/$login?tab=followers',
|
||||
),
|
||||
EntryItem(
|
||||
count: user.following.totalCount,
|
||||
text: 'Following',
|
||||
url: '/$login?tab=following',
|
||||
),
|
||||
]),
|
||||
CommonStyle.verticalGap,
|
||||
Container(
|
||||
color: theme.palette.background,
|
||||
padding: CommonStyle.padding,
|
||||
child: SingleChildScrollView(
|
||||
scrollDirection: Axis.horizontal,
|
||||
reverse: true,
|
||||
child: Wrap(
|
||||
spacing: 3,
|
||||
children: user
|
||||
.contributionsCollection.contributionCalendar.weeks
|
||||
.map((week) {
|
||||
return Wrap(
|
||||
direction: Axis.vertical,
|
||||
spacing: 3,
|
||||
children: week.contributionDays.map((day) {
|
||||
var color = convertColor(day.color);
|
||||
if (theme.brightness == Brightness.dark) {
|
||||
color = Color.fromRGBO(0xff - color.red,
|
||||
0xff - color.green, 0xff - color.blue, 1);
|
||||
}
|
||||
return SizedBox(
|
||||
width: 10,
|
||||
height: 10,
|
||||
child: DecoratedBox(
|
||||
decoration: BoxDecoration(color: color),
|
||||
),
|
||||
);
|
||||
}).toList(),
|
||||
);
|
||||
}).toList(),
|
||||
),
|
||||
),
|
||||
),
|
||||
CommonStyle.verticalGap,
|
||||
TableView(
|
||||
hasIcon: true,
|
||||
items: [
|
||||
if (isNotNullOrEmpty(user.company))
|
||||
TableViewItem(
|
||||
leftIconData: Octicons.organization,
|
||||
text: TextContainsOrganization(
|
||||
user.company,
|
||||
style: TextStyle(fontSize: 16, color: theme.palette.text),
|
||||
oneLine: true,
|
||||
),
|
||||
),
|
||||
if (isNotNullOrEmpty(user.location))
|
||||
TableViewItem(
|
||||
leftIconData: Octicons.location,
|
||||
text: Text(user.location),
|
||||
onTap: () {
|
||||
launchUrl('https://www.google.com/maps/place/' +
|
||||
user.location.replaceAll(RegExp(r'\s+'), ''));
|
||||
},
|
||||
),
|
||||
if (isNotNullOrEmpty(user.email))
|
||||
TableViewItem(
|
||||
leftIconData: Octicons.mail,
|
||||
text: Text(user.email),
|
||||
onTap: () {
|
||||
launchUrl('mailto:' + user.email);
|
||||
},
|
||||
),
|
||||
if (isNotNullOrEmpty(user.websiteUrl))
|
||||
TableViewItem(
|
||||
leftIconData: Octicons.link,
|
||||
text: Text(user.websiteUrl),
|
||||
onTap: () {
|
||||
var url = user.websiteUrl;
|
||||
if (!url.startsWith('http')) {
|
||||
url = 'http://$url';
|
||||
}
|
||||
launchUrl(url);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
CommonStyle.verticalGap,
|
||||
TableView(
|
||||
hasIcon: true,
|
||||
items: [
|
||||
TableViewItem(
|
||||
leftIconData: Octicons.settings,
|
||||
text: Text('Settings'),
|
||||
url: '/settings',
|
||||
),
|
||||
],
|
||||
),
|
||||
CommonStyle.verticalGap,
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
@ -43,6 +43,8 @@ class UserScreen extends StatelessWidget {
|
||||
|
||||
UserScreen(this.login);
|
||||
|
||||
bool get isViewer => login.isEmpty;
|
||||
|
||||
Iterable<Widget> _buildPinnedItems(Iterable<GithubUserRepository> pinnedItems,
|
||||
Iterable<GithubUserRepository> repositories) {
|
||||
String title;
|
||||
@ -58,7 +60,6 @@ class UserScreen extends StatelessWidget {
|
||||
if (items.isEmpty) return [];
|
||||
|
||||
return [
|
||||
CommonStyle.verticalGap,
|
||||
if (title != null) TableViewHeader(title),
|
||||
...join(
|
||||
CommonStyle.border,
|
||||
@ -70,7 +71,7 @@ class UserScreen extends StatelessWidget {
|
||||
}
|
||||
|
||||
Widget _buildHeader(BuildContext context, String avatarUrl, String name,
|
||||
DateTime createdAt, String bio) {
|
||||
String login, DateTime createdAt, String bio) {
|
||||
final theme = Provider.of<ThemeModel>(context);
|
||||
|
||||
return Container(
|
||||
@ -153,8 +154,8 @@ class UserScreen extends StatelessWidget {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: <Widget>[
|
||||
_buildHeader(
|
||||
context, user.avatarUrl, user.name, user.createdAt, user.bio),
|
||||
_buildHeader(context, user.avatarUrl, user.name, user.login,
|
||||
user.createdAt, user.bio),
|
||||
CommonStyle.border,
|
||||
Row(children: [
|
||||
EntryItem(
|
||||
@ -255,11 +256,24 @@ class UserScreen extends StatelessWidget {
|
||||
),
|
||||
],
|
||||
),
|
||||
..._buildPinnedItems(
|
||||
user.pinnedItems.nodes
|
||||
.where((n) => n is GithubUserRepository)
|
||||
.cast<GithubUserRepository>(),
|
||||
user.repositories.nodes),
|
||||
CommonStyle.verticalGap,
|
||||
if (isViewer)
|
||||
TableView(
|
||||
hasIcon: true,
|
||||
items: [
|
||||
TableViewItem(
|
||||
leftIconData: Octicons.settings,
|
||||
text: Text('Settings'),
|
||||
url: '/settings',
|
||||
),
|
||||
],
|
||||
)
|
||||
else
|
||||
..._buildPinnedItems(
|
||||
user.pinnedItems.nodes
|
||||
.where((n) => n is GithubUserRepository)
|
||||
.cast<GithubUserRepository>(),
|
||||
user.repositories.nodes),
|
||||
CommonStyle.verticalGap,
|
||||
],
|
||||
);
|
||||
@ -270,19 +284,19 @@ class UserScreen extends StatelessWidget {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: <Widget>[
|
||||
_buildHeader(context, payload.avatarUrl, payload.name,
|
||||
_buildHeader(context, payload.avatarUrl, payload.name, payload.login,
|
||||
payload.createdAt, payload.description),
|
||||
CommonStyle.border,
|
||||
Row(children: [
|
||||
EntryItem(
|
||||
count: payload.pinnableItems.totalCount,
|
||||
text: 'Repositories',
|
||||
url: '/$login?tab=repositories',
|
||||
url: '/${payload.login}?tab=repositories',
|
||||
),
|
||||
EntryItem(
|
||||
count: payload.membersWithRole.totalCount,
|
||||
text: 'Members',
|
||||
url: '/$login?tab=people',
|
||||
url: '/${payload.login}?tab=people',
|
||||
),
|
||||
]),
|
||||
CommonStyle.verticalGap,
|
||||
@ -320,6 +334,7 @@ class UserScreen extends StatelessWidget {
|
||||
),
|
||||
],
|
||||
),
|
||||
CommonStyle.verticalGap,
|
||||
..._buildPinnedItems(
|
||||
payload.pinnedItems.nodes
|
||||
.where((n) => n is GithubUserRepository)
|
||||
@ -338,10 +353,12 @@ class UserScreen extends StatelessWidget {
|
||||
return RefreshStatefulScaffold<GithubUserRepositoryOwner>(
|
||||
fetchData: () async {
|
||||
final data = await Provider.of<AuthModel>(context).gqlClient.execute(
|
||||
GithubUserQuery(variables: GithubUserArguments(login: login)));
|
||||
return data.data.repositoryOwner;
|
||||
GithubUserQuery(
|
||||
variables:
|
||||
GithubUserArguments(login: login, isViewer: isViewer)));
|
||||
return isViewer ? data.data.viewer : data.data.repositoryOwner;
|
||||
},
|
||||
title: AppBarTitle('User'), // TODO:
|
||||
title: AppBarTitle(isViewer ? 'Me' : 'User'), // TODO:
|
||||
actionBuilder: (payload, _) {
|
||||
if (payload == null)
|
||||
return ActionButton(
|
||||
@ -361,11 +378,12 @@ class UserScreen extends StatelessWidget {
|
||||
onPress: (_) async {
|
||||
if (user.viewerIsFollowing) {
|
||||
await Provider.of<AuthModel>(context)
|
||||
.deleteWithCredentials('/user/following/$login');
|
||||
.deleteWithCredentials(
|
||||
'/user/following/${user.login}');
|
||||
user.viewerIsFollowing = false;
|
||||
} else {
|
||||
Provider.of<AuthModel>(context)
|
||||
.putWithCredentials('/user/following/$login');
|
||||
Provider.of<AuthModel>(context).putWithCredentials(
|
||||
'/user/following/${user.login}');
|
||||
user.viewerIsFollowing = true;
|
||||
}
|
||||
},
|
||||
@ -392,6 +410,9 @@ class UserScreen extends StatelessWidget {
|
||||
}
|
||||
},
|
||||
bodyBuilder: (payload, _) {
|
||||
if (isViewer) {
|
||||
return _buildUser(context, payload as GithubUserUser);
|
||||
}
|
||||
switch (payload.resolveType) {
|
||||
case 'User':
|
||||
return _buildUser(context, payload as GithubUserUser);
|
||||
|
Loading…
x
Reference in New Issue
Block a user