diff --git a/lib/screens/organization.dart b/lib/screens/organization.dart index 29ea380..8a4ae9f 100644 --- a/lib/screens/organization.dart +++ b/lib/screens/organization.dart @@ -194,8 +194,8 @@ class _OrganizationScreenState extends State { EntryItem( count: payload['membersWithRole']['totalCount'], text: 'Members', - screenBuilder: (_) => - UsersScreen(login: widget.login, org: true), + screenBuilder: (_) => UsersScreen( + login: widget.login, type: UsersScreenType.orgs), ), ], ), diff --git a/lib/screens/repo.dart b/lib/screens/repo.dart index 573c0ff..b8a62c7 100644 --- a/lib/screens/repo.dart +++ b/lib/screens/repo.dart @@ -180,18 +180,25 @@ class RepoScreen extends StatelessWidget { EntryItem( count: payload['watchers']['totalCount'], text: 'Watchers', - screenBuilder: (context) => - UsersScreen(login: 'pd4d10'), // FIXME: + screenBuilder: (context) => UsersScreen( + login: owner, + name: name, + type: UsersScreenType.repoWatchers, + ), ), EntryItem( count: payload['stargazers']['totalCount'], text: 'Stars', - screenBuilder: (context) => UsersScreen(login: 'pd4d10'), + screenBuilder: (context) => UsersScreen( + login: owner, + name: name, + type: UsersScreenType.repoStars, + ), ), EntryItem( count: payload['forks']['totalCount'], text: 'Forks', - screenBuilder: (context) => UsersScreen(login: 'pd4d10'), + // screenBuilder: (context) => UsersScreen(), ), ], ), diff --git a/lib/screens/user.dart b/lib/screens/user.dart index 506629b..d856c8a 100644 --- a/lib/screens/user.dart +++ b/lib/screens/user.dart @@ -20,18 +20,13 @@ import '../screens/users.dart'; import '../screens/settings.dart'; import '../utils/utils.dart'; -class UserScreen extends StatefulWidget { +class UserScreen extends StatelessWidget { final String login; final bool showSettings; UserScreen(this.login, {this.showSettings = false}); - _UserScreenState createState() => _UserScreenState(); -} - -class _UserScreenState extends State { - Future query() async { - var login = widget.login; + Future query(BuildContext context) async { var data = await Provider.of(context).query(''' { user(login: "$login") { @@ -161,13 +156,13 @@ class _UserScreenState extends State { return RefreshScaffold( onRefresh: () { return Future.wait( - [query(), getContributions(widget.login)], + [query(context), getContributions(login)], ); }, title: AppBarTitle('User'), trailingBuilder: (data) { var payload = data[0]; - if (widget.showSettings) { + if (showSettings) { return Link( child: Icon(Icons.settings, size: 24), screenBuilder: (_) => SettingsScreen(), @@ -183,11 +178,11 @@ class _UserScreenState extends State { onPress: () async { if (payload['viewerIsFollowing']) { await Provider.of(context) - .deleteWithCredentials('/user/following/${widget.login}'); + .deleteWithCredentials('/user/following/$login'); payload['viewerIsFollowing'] = false; } else { Provider.of(context) - .putWithCredentials('/user/following/${widget.login}'); + .putWithCredentials('/user/following/$login'); payload['viewerIsFollowing'] = true; } }, @@ -234,7 +229,7 @@ class _UserScreenState extends State { crossAxisAlignment: CrossAxisAlignment.end, children: [ Text( - payload['name'] ?? widget.login, + payload['name'] ?? login, style: TextStyle( color: PrimerColors.blue500, fontSize: 18, @@ -243,7 +238,7 @@ class _UserScreenState extends State { ), SizedBox(width: 8), Text( - widget.login, + login, style: TextStyle( color: PrimerColors.gray700, fontSize: 16), ), @@ -271,24 +266,25 @@ class _UserScreenState extends State { EntryItem( count: payload['repositories']['totalCount'], text: 'Repositories', - screenBuilder: (context) => ReposScreen(login: widget.login), + screenBuilder: (context) => ReposScreen(login: login), ), EntryItem( count: payload['starredRepositories']['totalCount'], text: 'Stars', screenBuilder: (context) => - ReposScreen(login: widget.login, star: true), + ReposScreen(login: login, star: true), ), EntryItem( count: payload['followers']['totalCount'], text: 'Followers', - screenBuilder: (context) => UsersScreen(login: widget.login), + screenBuilder: (context) => UsersScreen( + login: login, type: UsersScreenType.userFollowers), ), EntryItem( count: payload['following']['totalCount'], text: 'Following', - screenBuilder: (context) => - UsersScreen(login: widget.login, following: true), + screenBuilder: (context) => UsersScreen( + login: login, type: UsersScreenType.userFollowing), ), ]), BorderView(height: 10), diff --git a/lib/screens/users.dart b/lib/screens/users.dart index f014672..a29efa0 100644 --- a/lib/screens/users.dart +++ b/lib/screens/users.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:git_touch/widgets/app_bar_title.dart'; import 'package:primer/primer.dart'; +import 'package:tuple/tuple.dart'; import '../scaffolds/list.dart'; import 'package:git_touch/models/settings.dart'; import 'package:provider/provider.dart'; @@ -9,40 +10,52 @@ import '../widgets/link.dart'; import '../screens/user.dart'; import '../widgets/avatar.dart'; -class UsersScreen extends StatefulWidget { - final String login; - final bool following; - final bool org; - - UsersScreen({ - @required this.login, - this.following = false, - this.org = false, - }); - - @override - _UsersScreenState createState() => _UsersScreenState(); +enum UsersScreenType { + userFollowing, + userFollowers, + repoStars, + repoWatchers, + orgs, } -class _UsersScreenState extends State { - String get login => widget.login; - String get scope => widget.org ? 'organization' : 'user'; - String get resource { - if (widget.org) { - return 'members'; +class UsersScreen extends StatelessWidget { + final UsersScreenType type; + final String login; + final String name; + + UsersScreen({ + @required this.type, + @required this.login, + this.name, + }); + + Tuple3 get queryKeys { + switch (type) { + case UsersScreenType.userFollowing: + return Tuple3('user', 'login: "$login"', 'following'); + case UsersScreenType.userFollowers: + return Tuple3('user', 'login: "$login"', 'followers'); + case UsersScreenType.repoStars: + return Tuple3( + 'repository', 'owner: "$login", name: "$name"', 'stargazers'); + case UsersScreenType.repoWatchers: + return Tuple3( + 'repository', 'owner: "$login", name: "$name"', 'watchers'); + case UsersScreenType.orgs: + return Tuple3('', '', ''); // FIXME: + default: + throw 'Should not be here'; } - if (widget.following) { - return 'following'; - } - return 'followers'; } - Future _queryUsers([String cursor]) async { + Future _queryUsers(BuildContext context, [String cursor]) async { var cursorChunk = cursor == null ? '' : ', after: "$cursor"'; - + var scope = queryKeys.item1; + var params = queryKeys.item2; + var resource = queryKeys.item3; var data = await Provider.of(context).query(''' { - $scope(login: "$login") { + $scope($params) { $resource(first: $pageSize$cursorChunk) { pageInfo { hasNextPage @@ -104,9 +117,9 @@ class _UsersScreenState extends State { @override Widget build(BuildContext context) { return ListScaffold( - title: AppBarTitle(resource), - onRefresh: () => _queryUsers(), - onLoadMore: (cursor) => _queryUsers(cursor), + title: AppBarTitle('Users'), + onRefresh: () => _queryUsers(context), + onLoadMore: (cursor) => _queryUsers(context, cursor), itemBuilder: _buildItem, ); } diff --git a/pubspec.yaml b/pubspec.yaml index 147cf6b..fc750d3 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -34,6 +34,7 @@ dependencies: provider: ^3.1.0 seti: ^0.2.0 filesize: ^1.0.4 + tuple: ^1.0.2 primer: git: url: git://github.com/pd4d10/primer-flutter