mirror of
https://github.com/git-touch/git-touch
synced 2025-03-23 22:50:05 +01:00
refactor: user and organization screen
This commit is contained in:
parent
72649bb98e
commit
1f301ab3ef
@ -15,7 +15,6 @@ import 'screens/news.dart';
|
||||
import 'screens/search.dart';
|
||||
import 'screens/login.dart';
|
||||
import 'screens/issue.dart';
|
||||
import 'screens/organization.dart';
|
||||
import 'screens/trending.dart';
|
||||
import 'utils/utils.dart';
|
||||
|
||||
@ -106,7 +105,7 @@ class _HomeState extends State<Home> {
|
||||
case 3:
|
||||
return SearchScreen();
|
||||
case 4:
|
||||
return UserScreen.self();
|
||||
return UserScreen(null);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,140 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/cupertino.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/widgets/app_bar_title.dart';
|
||||
import 'package:git_touch/widgets/entry_item.dart';
|
||||
import 'package:git_touch/widgets/repository_item.dart';
|
||||
import 'package:git_touch/widgets/table_view.dart';
|
||||
import 'package:git_touch/widgets/user_item.dart';
|
||||
import 'package:git_touch/models/auth.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:git_touch/widgets/action_button.dart';
|
||||
import '../utils/utils.dart';
|
||||
|
||||
class OrganizationScreen extends StatelessWidget {
|
||||
final String login;
|
||||
|
||||
OrganizationScreen(this.login);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return RefreshStatefulScaffold(
|
||||
fetchData: () async {
|
||||
// Use pinnableItems instead of organization here due to token permission
|
||||
var data = await Provider.of<AuthModel>(context).query('''
|
||||
{
|
||||
organization(login: "$login") {
|
||||
name
|
||||
avatarUrl
|
||||
description
|
||||
location
|
||||
email
|
||||
websiteUrl
|
||||
url
|
||||
pinnedItems(first: 6) {
|
||||
nodes {
|
||||
... on Repository {
|
||||
$repoChunk
|
||||
}
|
||||
}
|
||||
}
|
||||
pinnableItems(first: 6, types: [REPOSITORY]) {
|
||||
totalCount
|
||||
nodes {
|
||||
... on Repository {
|
||||
$repoChunk
|
||||
}
|
||||
}
|
||||
}
|
||||
membersWithRole {
|
||||
totalCount
|
||||
}
|
||||
}
|
||||
}
|
||||
''');
|
||||
return data['organization'];
|
||||
},
|
||||
title: AppBarTitle('Organization'),
|
||||
actionBuilder: (payload) {
|
||||
return ActionButton(
|
||||
title: 'Organization Actions',
|
||||
items: [
|
||||
if (payload.data != null) ...[
|
||||
ActionItem.share(payload.data['url']),
|
||||
ActionItem.launch(payload.data['url']),
|
||||
],
|
||||
],
|
||||
);
|
||||
},
|
||||
bodyBuilder: (payload) {
|
||||
var data = payload.data;
|
||||
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: <Widget>[
|
||||
UserItem(
|
||||
login: login,
|
||||
name: data['name'],
|
||||
avatarUrl: data['avatarUrl'],
|
||||
bio: data['description'],
|
||||
),
|
||||
CommonStyle.border,
|
||||
Row(children: <Widget>[
|
||||
EntryItem(
|
||||
count: data['pinnableItems']['totalCount'],
|
||||
text: 'Repositories',
|
||||
screenBuilder: (context) =>
|
||||
RepositoriesScreen.ofOrganization(login),
|
||||
),
|
||||
EntryItem(
|
||||
count: data['membersWithRole']['totalCount'],
|
||||
text: 'Members',
|
||||
screenBuilder: (context) => UsersScreen.members(login),
|
||||
),
|
||||
]),
|
||||
CommonStyle.verticalGap,
|
||||
TableView(
|
||||
hasIcon: true,
|
||||
items: [
|
||||
if (isNotNullOrEmpty(data['location']))
|
||||
TableViewItem(
|
||||
leftIconData: Octicons.location,
|
||||
text: Text(data['location']),
|
||||
onTap: () {
|
||||
launchUrl('https://www.google.com/maps/place/' +
|
||||
(data['location'] as String)
|
||||
.replaceAll(RegExp(r'\s+'), ''));
|
||||
},
|
||||
),
|
||||
if (isNotNullOrEmpty(data['email']))
|
||||
TableViewItem(
|
||||
leftIconData: Octicons.mail,
|
||||
text: Text(data['email']),
|
||||
onTap: () {
|
||||
launchUrl('mailto:' + data['email']);
|
||||
},
|
||||
),
|
||||
if (isNotNullOrEmpty(data['websiteUrl']))
|
||||
TableViewItem(
|
||||
leftIconData: Octicons.link,
|
||||
text: Text(data['websiteUrl']),
|
||||
onTap: () {
|
||||
var url = data['websiteUrl'] as String;
|
||||
if (!url.startsWith('http')) {
|
||||
url = 'http://$url';
|
||||
}
|
||||
launchUrl(url);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
...buildPinnedItems(
|
||||
data['pinnedItems']['nodes'], data['pinnableItems']['nodes']),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
@ -2,31 +2,31 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:git_touch/models/theme.dart';
|
||||
import 'package:git_touch/scaffolds/refresh_stateful.dart';
|
||||
import 'package:git_touch/screens/repositories.dart';
|
||||
import 'package:git_touch/screens/settings.dart';
|
||||
import 'package:git_touch/screens/users.dart';
|
||||
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/screens/repositories.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_contributions.dart';
|
||||
import 'package:git_touch/widgets/user_item.dart';
|
||||
import 'package:primer/primer.dart';
|
||||
import 'package:github_contributions/github_contributions.dart';
|
||||
import 'package:git_touch/models/auth.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import '../widgets/entry_item.dart';
|
||||
import 'package:git_touch/widgets/repository_item.dart';
|
||||
import 'package:git_touch/widgets/action_button.dart';
|
||||
import '../screens/users.dart';
|
||||
import '../screens/settings.dart';
|
||||
import '../utils/utils.dart';
|
||||
import 'package:primer/primer.dart';
|
||||
|
||||
class UserScreen extends StatelessWidget {
|
||||
final String login;
|
||||
final bool isOrganization;
|
||||
|
||||
UserScreen(this.login);
|
||||
UserScreen.self() : login = null;
|
||||
UserScreen(this.login, {this.isOrganization = false});
|
||||
|
||||
Future query(BuildContext context) async {
|
||||
Future queryUser(BuildContext context) async {
|
||||
var _login = login ?? Provider.of<AuthModel>(context).activeAccount.login;
|
||||
var data = await Provider.of<AuthModel>(context).query('''
|
||||
{
|
||||
@ -67,6 +67,43 @@ class UserScreen extends StatelessWidget {
|
||||
return data['user'];
|
||||
}
|
||||
|
||||
Future queryOrganization(BuildContext context) async {
|
||||
// Use pinnableItems instead of organization here due to token permission
|
||||
var data = await Provider.of<AuthModel>(context).query('''
|
||||
{
|
||||
organization(login: "$login") {
|
||||
login
|
||||
name
|
||||
avatarUrl
|
||||
description
|
||||
location
|
||||
email
|
||||
websiteUrl
|
||||
url
|
||||
pinnedItems(first: 6) {
|
||||
nodes {
|
||||
... on Repository {
|
||||
$repoChunk
|
||||
}
|
||||
}
|
||||
}
|
||||
pinnableItems(first: 6, types: [REPOSITORY]) {
|
||||
totalCount
|
||||
nodes {
|
||||
... on Repository {
|
||||
$repoChunk
|
||||
}
|
||||
}
|
||||
}
|
||||
membersWithRole {
|
||||
totalCount
|
||||
}
|
||||
}
|
||||
}
|
||||
''');
|
||||
return data['organization'];
|
||||
}
|
||||
|
||||
Future<List<ContributionsInfo>> fetchContributions(
|
||||
BuildContext context) async {
|
||||
var _login = login ?? Provider.of<AuthModel>(context).activeAccount.login;
|
||||
@ -87,12 +124,33 @@ class UserScreen extends StatelessWidget {
|
||||
return RefreshStatefulScaffold(
|
||||
fetchData: () {
|
||||
return Future.wait(
|
||||
[query(context), fetchContributions(context)],
|
||||
isOrganization
|
||||
? [
|
||||
queryOrganization(context),
|
||||
Future.value([].cast<ContributionsInfo>())
|
||||
]
|
||||
: [
|
||||
queryUser(context),
|
||||
fetchContributions(context),
|
||||
],
|
||||
);
|
||||
},
|
||||
title: AppBarTitle('User'),
|
||||
title: AppBarTitle(isOrganization ? 'Organization' : 'User'),
|
||||
actionBuilder: (payload) {
|
||||
var data = payload.data;
|
||||
|
||||
if (isOrganization) {
|
||||
return ActionButton(
|
||||
title: 'Organization Actions',
|
||||
items: [
|
||||
if (data != null) ...[
|
||||
ActionItem.share(payload.data[0]['url']),
|
||||
ActionItem.launch(payload.data[0]['url']),
|
||||
],
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
if (login == null) {
|
||||
return ActionEntry(
|
||||
iconData: Icons.settings,
|
||||
@ -131,36 +189,57 @@ class UserScreen extends StatelessWidget {
|
||||
},
|
||||
bodyBuilder: (payload) {
|
||||
var data = payload.data[0];
|
||||
var contributions = payload.data[1] as List<ContributionsInfo>;
|
||||
var _login =
|
||||
login ?? Provider.of<AuthModel>(context).activeAccount.login;
|
||||
|
||||
var contributions = payload.data[1];
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: <Widget>[
|
||||
UserItem.fromData(data, inUserScreen: true),
|
||||
UserItem(
|
||||
login: data['login'],
|
||||
name: data['name'],
|
||||
avatarUrl: data['avatarUrl'],
|
||||
bio: isOrganization ? data['description'] : data['bio'],
|
||||
inUserScreen: true,
|
||||
),
|
||||
CommonStyle.border,
|
||||
Row(children: <Widget>[
|
||||
EntryItem(
|
||||
count: data['repositories']['totalCount'],
|
||||
text: 'Repositories',
|
||||
screenBuilder: (context) => RepositoriesScreen(_login),
|
||||
),
|
||||
EntryItem(
|
||||
count: data['starredRepositories']['totalCount'],
|
||||
text: 'Stars',
|
||||
screenBuilder: (context) => RepositoriesScreen.stars(_login),
|
||||
),
|
||||
EntryItem(
|
||||
count: data['followers']['totalCount'],
|
||||
text: 'Followers',
|
||||
screenBuilder: (context) => UsersScreen.followers(_login),
|
||||
),
|
||||
EntryItem(
|
||||
count: data['following']['totalCount'],
|
||||
text: 'Following',
|
||||
screenBuilder: (context) => UsersScreen.following(_login),
|
||||
),
|
||||
Row(children: [
|
||||
if (isOrganization) ...[
|
||||
EntryItem(
|
||||
count: data['pinnableItems']['totalCount'],
|
||||
text: 'Repositories',
|
||||
screenBuilder: (context) =>
|
||||
RepositoriesScreen.ofOrganization(data['login']),
|
||||
),
|
||||
EntryItem(
|
||||
count: data['membersWithRole']['totalCount'],
|
||||
text: 'Members',
|
||||
screenBuilder: (context) =>
|
||||
UsersScreen.members(data['login']),
|
||||
),
|
||||
] else ...[
|
||||
EntryItem(
|
||||
count: data['repositories']['totalCount'],
|
||||
text: 'Repositories',
|
||||
screenBuilder: (context) => RepositoriesScreen(data['login']),
|
||||
),
|
||||
EntryItem(
|
||||
count: data['starredRepositories']['totalCount'],
|
||||
text: 'Stars',
|
||||
screenBuilder: (context) =>
|
||||
RepositoriesScreen.stars(data['login']),
|
||||
),
|
||||
EntryItem(
|
||||
count: data['followers']['totalCount'],
|
||||
text: 'Followers',
|
||||
screenBuilder: (context) =>
|
||||
UsersScreen.followers(data['login']),
|
||||
),
|
||||
EntryItem(
|
||||
count: data['following']['totalCount'],
|
||||
text: 'Following',
|
||||
screenBuilder: (context) =>
|
||||
UsersScreen.following(data['login']),
|
||||
),
|
||||
]
|
||||
]),
|
||||
CommonStyle.verticalGap,
|
||||
if (contributions.isNotEmpty) ...[
|
||||
@ -170,7 +249,7 @@ class UserScreen extends StatelessWidget {
|
||||
TableView(
|
||||
hasIcon: true,
|
||||
items: [
|
||||
if (isNotNullOrEmpty(data['company']))
|
||||
if (!isOrganization && isNotNullOrEmpty(data['company']))
|
||||
TableViewItem(
|
||||
leftIconData: Octicons.organization,
|
||||
text: TextContainsOrganization(data['company'],
|
||||
@ -211,7 +290,9 @@ class UserScreen extends StatelessWidget {
|
||||
],
|
||||
),
|
||||
...buildPinnedItems(
|
||||
data['pinnedItems']['nodes'], data['repositories']['nodes']),
|
||||
data['pinnedItems']['nodes'],
|
||||
data[isOrganization ? 'pinnableItems' : 'repositories']
|
||||
['nodes']),
|
||||
CommonStyle.verticalGap,
|
||||
],
|
||||
);
|
||||
|
@ -1,6 +1,5 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:git_touch/screens/organization.dart';
|
||||
import 'package:git_touch/screens/repository.dart';
|
||||
import 'package:git_touch/screens/user.dart';
|
||||
import 'package:git_touch/widgets/avatar.dart';
|
||||
@ -135,10 +134,11 @@ class RepositoryItem extends StatelessWidget {
|
||||
children: <Widget>[
|
||||
Link(
|
||||
child: Avatar.small(url: payload['owner']['avatarUrl']),
|
||||
screenBuilder: (_) =>
|
||||
payload['owner']['__typename'] == 'Organization'
|
||||
? OrganizationScreen(payload['owner']['login'])
|
||||
: UserScreen(payload['owner']['login']),
|
||||
screenBuilder: (_) => UserScreen(
|
||||
payload['owner']['login'],
|
||||
isOrganization:
|
||||
payload['owner']['__typename'] == 'Organization',
|
||||
),
|
||||
),
|
||||
SizedBox(width: 8),
|
||||
Expanded(
|
||||
|
@ -1,5 +1,5 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:git_touch/screens/organization.dart';
|
||||
import 'package:git_touch/screens/user.dart';
|
||||
import 'package:git_touch/utils/utils.dart';
|
||||
|
||||
class TextContainsOrganization extends StatelessWidget {
|
||||
@ -23,7 +23,7 @@ class TextContainsOrganization extends StatelessWidget {
|
||||
spans.add(TextSpan(text: chunks[index]));
|
||||
}
|
||||
spans.add(createLinkSpan(context, orgs[index],
|
||||
(_) => OrganizationScreen(orgs[index].substring(1))));
|
||||
(_) => UserScreen(orgs[index].substring(1), isOrganization: true)));
|
||||
}
|
||||
if (chunks.last.isNotEmpty) {
|
||||
spans.add(TextSpan(text: chunks.last));
|
||||
|
@ -1,5 +1,4 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:git_touch/screens/organization.dart';
|
||||
import 'package:git_touch/screens/user.dart';
|
||||
import 'package:git_touch/utils/utils.dart';
|
||||
import 'package:git_touch/widgets/avatar.dart';
|
||||
@ -44,8 +43,7 @@ class UserItem extends StatelessWidget {
|
||||
return Link(
|
||||
screenBuilder: inUserScreen
|
||||
? null
|
||||
: (_) =>
|
||||
isOrganization ? OrganizationScreen(login) : UserScreen(login),
|
||||
: (_) => UserScreen(login, isOrganization: isOrganization),
|
||||
child: Container(
|
||||
padding: CommonStyle.padding,
|
||||
child: Row(
|
||||
|
Loading…
x
Reference in New Issue
Block a user