diff --git a/lib/screens/search.dart b/lib/screens/search.dart index 32e45a7..b7b3f3f 100644 --- a/lib/screens/search.dart +++ b/lib/screens/search.dart @@ -136,10 +136,7 @@ class _SearchScreenState extends State { case 0: return RepositoryItem(data); case 1: - return UserItem.fromData( - data, - isOrganization: data['__typename'] == 'Organization', - ); + return UserItem.fromData(data); case 2: default: return IssueItem( diff --git a/lib/screens/user.dart b/lib/screens/user.dart index bb009da..4abf0c1 100644 --- a/lib/screens/user.dart +++ b/lib/screens/user.dart @@ -22,89 +22,83 @@ import 'package:primer/primer.dart'; class UserScreen extends StatelessWidget { final String login; - final bool isOrganization; - UserScreen(this.login, {this.isOrganization = false}); + UserScreen(this.login); - Future queryUser(BuildContext context) async { + Future _query(BuildContext context) async { var _login = login ?? Provider.of(context).activeAccount.login; var data = await Provider.of(context).query(''' { - user(login: "$_login") { - $userGqlChunk - company - location - email - websiteUrl - starredRepositories { - totalCount - } - followers { - totalCount - } - following { - totalCount - } - repositories(first: 6, ownerAffiliations: OWNER, orderBy: {field: STARGAZERS, direction: DESC}) { - totalCount - nodes { - $repoChunk + repositoryOwner(login: "$_login") { + __typename + ... on User { + $userGqlChunk + company + location + email + websiteUrl + starredRepositories { + totalCount } - } - pinnedItems(first: 6) { - nodes { - ... on Repository { + followers { + totalCount + } + following { + totalCount + } + repositories(first: 6, ownerAffiliations: OWNER, orderBy: {field: STARGAZERS, direction: DESC}) { + totalCount + nodes { $repoChunk } } - } - viewerCanFollow - viewerIsFollowing - url - } -} -'''); - return data['user']; - } - - Future queryOrganization(BuildContext context) async { - // Use pinnableItems instead of organization here due to token permission - var data = await Provider.of(context).query(''' -{ - organization(login: "$login") { - login - name - avatarUrl - description - location - email - websiteUrl - url - pinnedItems(first: 6) { - nodes { - ... on Repository { - $repoChunk + pinnedItems(first: 6) { + nodes { + ... on Repository { + $repoChunk + } } } + viewerCanFollow + viewerIsFollowing + url } - pinnableItems(first: 6, types: [REPOSITORY]) { - totalCount - nodes { - ... on Repository { - $repoChunk + ... on Organization { + login + name + avatarUrl + description + location + email + websiteUrl + url + pinnedItems(first: 6) { + nodes { + ... on Repository { + $repoChunk + } } } - } - membersWithRole { - totalCount + pinnableItems(first: 6, types: [REPOSITORY]) { + totalCount + nodes { + ... on Repository { + $repoChunk + } + } + } + membersWithRole { + totalCount + } } } } -'''); - return data['organization']; +'''); // Use pinnableItems instead of organization here due to token permission + + return data['repositoryOwner']; } - Future> fetchContributions( + Future> _fetchContributions( BuildContext context) async { var _login = login ?? Provider.of(context).activeAccount.login; switch (Provider.of(context).activeAccount.platform) { @@ -123,73 +117,78 @@ class UserScreen extends StatelessWidget { Widget build(BuildContext context) { return RefreshStatefulScaffold( fetchData: () { - return Future.wait( - isOrganization - ? [ - queryOrganization(context), - Future.value([].cast()) - ] - : [ - queryUser(context), - fetchContributions(context), - ], - ); + return Future.wait([ + _query(context), + _fetchContributions(context), + ]); }, - title: AppBarTitle(isOrganization ? 'Organization' : 'User'), + title: AppBarTitle('User'), // TODO: actionBuilder: (payload) { var data = payload.data; - - if (isOrganization) { + if (data == null) return ActionButton( - title: 'Organization Actions', - items: [ - if (data != null) ...[ - ActionItem.share(payload.data[0]['url']), - ActionItem.launch(payload.data[0]['url']), - ], - ], + title: "Actions", + items: [], ); - } - if (login == null) { - return ActionEntry( - iconData: Icons.settings, - onTap: () { - Provider.of(context).pushRoute( - context, (_) => SettingsScreen(), - fullscreenDialog: true); - }, - ); - } else { - return ActionButton( - title: 'User Actions', - items: [ - if (data != null && data[0]['viewerCanFollow']) - ActionItem( - text: data[0]['viewerIsFollowing'] ? 'Unfollow' : 'Follow', - onPress: () async { - if (data[0]['viewerIsFollowing']) { - await Provider.of(context) - .deleteWithCredentials('/user/following/$login'); - data[0]['viewerIsFollowing'] = false; - } else { - Provider.of(context) - .putWithCredentials('/user/following/$login'); - data[0]['viewerIsFollowing'] = true; - } - }, - ), - if (data != null) ...[ - ActionItem.share(data[0]['url']), - ActionItem.launch(data[0]['url']), + switch (data[0]['__typename']) { + case 'User': + if (login == null) { + return ActionEntry( + iconData: Icons.settings, + onTap: () { + Provider.of(context).pushRoute( + context, (_) => SettingsScreen(), + fullscreenDialog: true); + }, + ); + } else { + return ActionButton( + title: 'User Actions', + items: [ + if (data != null && data[0]['viewerCanFollow']) + ActionItem( + text: + data[0]['viewerIsFollowing'] ? 'Unfollow' : 'Follow', + onPress: () async { + if (data[0]['viewerIsFollowing']) { + await Provider.of(context) + .deleteWithCredentials('/user/following/$login'); + data[0]['viewerIsFollowing'] = false; + } else { + Provider.of(context) + .putWithCredentials('/user/following/$login'); + data[0]['viewerIsFollowing'] = true; + } + }, + ), + if (data != null) ...[ + ActionItem.share(data[0]['url']), + ActionItem.launch(data[0]['url']), + ], + ], + ); + } + break; + case 'Organization': + return ActionButton( + title: 'Organization Actions', + items: [ + if (data != null) ...[ + ActionItem.share(payload.data[0]['url']), + ActionItem.launch(payload.data[0]['url']), + ], ], - ], - ); + ); + default: + return null; } }, bodyBuilder: (payload) { var data = payload.data[0]; var contributions = payload.data[1]; + final isOrganization = data['__typename'] == 'Organization'; + return Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ diff --git a/lib/widgets/text_contains_organization.dart b/lib/widgets/text_contains_organization.dart index fd926ec..81ae520 100644 --- a/lib/widgets/text_contains_organization.dart +++ b/lib/widgets/text_contains_organization.dart @@ -22,8 +22,8 @@ class TextContainsOrganization extends StatelessWidget { if (chunks[index].isNotEmpty) { spans.add(TextSpan(text: chunks[index])); } - spans.add(createLinkSpan(context, orgs[index], - (_) => UserScreen(orgs[index].substring(1), isOrganization: true))); + spans.add(createLinkSpan( + context, orgs[index], (_) => UserScreen(orgs[index].substring(1)))); } if (chunks.last.isNotEmpty) { spans.add(TextSpan(text: chunks.last)); diff --git a/lib/widgets/user_item.dart b/lib/widgets/user_item.dart index 7390b89..1ead80d 100644 --- a/lib/widgets/user_item.dart +++ b/lib/widgets/user_item.dart @@ -19,7 +19,6 @@ class UserItem extends StatelessWidget { final String avatarUrl; final String bio; final bool inUserScreen; - final bool isOrganization; UserItem({ this.login, @@ -27,11 +26,9 @@ class UserItem extends StatelessWidget { this.avatarUrl, this.bio, this.inUserScreen = false, - this.isOrganization = false, }); UserItem.fromData( data, { - this.isOrganization = false, this.inUserScreen = false, }) : login = data['login'], name = data['name'], @@ -41,9 +38,7 @@ class UserItem extends StatelessWidget { @override Widget build(BuildContext context) { return Link( - screenBuilder: inUserScreen - ? null - : (_) => UserScreen(login, isOrganization: isOrganization), + screenBuilder: inUserScreen ? null : (_) => UserScreen(login), child: Container( padding: CommonStyle.padding, child: Row(