diff --git a/lib/scaffolds/refresh_stateful.dart b/lib/scaffolds/refresh_stateful.dart index 584a5b6..fbcc6a9 100644 --- a/lib/scaffolds/refresh_stateful.dart +++ b/lib/scaffolds/refresh_stateful.dart @@ -5,11 +5,9 @@ import 'package:git_touch/scaffolds/utils.dart'; class RefreshStatefulScaffold extends StatefulWidget { final Widget title; - final Widget Function(T data, void Function(VoidCallback fn) setState) - bodyBuilder; + final Widget Function(T data, void Function(T newData) setData) bodyBuilder; final Future Function() fetch; - final Widget Function(T data, void Function(VoidCallback fn) setState) - actionBuilder; + final Widget Function(T data, void Function(T newData) setData) actionBuilder; final Widget action; final canRefresh; @@ -62,13 +60,21 @@ class _RefreshStatefulScaffoldState Widget get _action { if (widget.action != null) return widget.action; if (widget.actionBuilder == null || _data == null) return null; - return widget.actionBuilder(_data, setState); + return widget.actionBuilder(_data, (v) { + setState(() { + _data = v; + }); + }); } @override Widget build(BuildContext context) { Widget child = ErrorLoadingWrapper( - bodyBuilder: () => widget.bodyBuilder(_data, setState), + bodyBuilder: () => widget.bodyBuilder(_data, (v) { + setState(() { + _data = v; + }); + }), error: _error, loading: _data == null, reload: _refresh, diff --git a/lib/screens/bb_repo.dart b/lib/screens/bb_repo.dart index 8d54d05..5a135e1 100644 --- a/lib/screens/bb_repo.dart +++ b/lib/screens/bb_repo.dart @@ -40,7 +40,7 @@ class BbRepoScreen extends StatelessWidget { }); return Tuple3(repo, readme, branches); }, - bodyBuilder: (t, setState) { + bodyBuilder: (t, _) { final theme = Provider.of(context); final p = t.item1; final branches = t.item3; diff --git a/lib/screens/ge_repo.dart b/lib/screens/ge_repo.dart index 7713796..aedad8b 100644 --- a/lib/screens/ge_repo.dart +++ b/lib/screens/ge_repo.dart @@ -67,7 +67,7 @@ class GeRepoScreen extends StatelessWidget { StatusPayload statusPayload = StatusPayload(isWatching, isStarred); return Tuple4(repo, readmeData, branches, statusPayload); }, - bodyBuilder: (t, setState) { + bodyBuilder: (t, setData) { final p = t.item1; final branches = t.item3; final theme = context.read(); @@ -92,9 +92,9 @@ class GeRepoScreen extends StatelessWidget { await context.read().fetchGitee( '/user/subscriptions/$owner/$name?watch_type=$watchType', requestType: t.item4.isWatching ? 'DELETE' : 'PUT'); - setState(() { - t.item4.isWatching = !t.item4.isWatching; - }); + + t.item4.isWatching = !t.item4.isWatching; + setData(t); }, ), SizedBox(width: 8), @@ -106,9 +106,8 @@ class GeRepoScreen extends StatelessWidget { '/user/starred/$owner/$name', requestType: t.item4.isStarred ? 'DELETE' : 'PUT'); - setState(() { - t.item4.isStarred = !t.item4.isStarred; - }); + t.item4.isStarred = !t.item4.isStarred; + setData(t); }, ) ]) diff --git a/lib/screens/ge_user.dart b/lib/screens/ge_user.dart index b8445f0..2ad12f8 100644 --- a/lib/screens/ge_user.dart +++ b/lib/screens/ge_user.dart @@ -42,13 +42,13 @@ class GeUserScreen extends StatelessWidget { : null, actionBuilder: isViewer ? null - : (p, setState) { + : (p, _) { return ActionButton( title: 'User Actions', items: [...ActionItem.getUrlActions(p.item1.htmlUrl)], ); }, - bodyBuilder: (p, setState) { + bodyBuilder: (p, _) { final user = p.item1; final repos = p.item2; diff --git a/lib/screens/gh_repo.dart b/lib/screens/gh_repo.dart index 4b57a5b..9548680 100644 --- a/lib/screens/gh_repo.dart +++ b/lib/screens/gh_repo.dart @@ -85,7 +85,7 @@ class GhRepoScreen extends StatelessWidget { return Tuple3(repo, countFuture, readmeData); }, - actionBuilder: (data, setState) { + actionBuilder: (data, _) { final repo = data.item1; return ActionButton( title: S.of(context).repositoryActions, @@ -102,7 +102,7 @@ class GhRepoScreen extends StatelessWidget { ], ); }, - bodyBuilder: (data, setState) { + bodyBuilder: (data, setData) { final repo = data.item1; final contributionFuture = data.item2; final readmeData = data.item3; @@ -133,49 +133,34 @@ class GhRepoScreen extends StatelessWidget { ActionItem( text: _buildWatchState(v), onTap: (_) async { + final activityApi = + context.read().ghClient.activity; switch (v) { case GSubscriptionState.SUBSCRIBED: case GSubscriptionState.IGNORED: - await context - .read() - .ghClient - .activity - .setRepositorySubscription( - RepositorySlug( - repo.owner.login, repo.name), - subscribed: v == - GSubscriptionState.SUBSCRIBED, - ignored: - v == GSubscriptionState.IGNORED, - ); - setState(() { - // if (res.subscribed) { - // repo.viewerSubscription = - // GSubscriptionState.SUBSCRIBED; - // } else if (res.ignored) { - // repo.viewerSubscription = - // GSubscriptionState.IGNORED; - // } - }); + await activityApi.setRepositorySubscription( + RepositorySlug( + repo.owner.login, repo.name), + subscribed: + v == GSubscriptionState.SUBSCRIBED, + ignored: v == GSubscriptionState.IGNORED, + ); break; case GSubscriptionState.UNSUBSCRIBED: - await context - .read() - .ghClient - .activity + await activityApi .deleteRepositorySubscription( - RepositorySlug( - repo.owner.login, - repo.name, - ), - ); - setState(() { - // repo.viewerSubscription = - // GSubscriptionState.UNSUBSCRIBED; - }); + RepositorySlug( + repo.owner.login, + repo.name, + ), + ); break; default: } + + setData(data.withItem1(repo.rebuild((b) { + b.viewerSubscription = v; + }))); }, ) ]); @@ -186,24 +171,18 @@ class GhRepoScreen extends StatelessWidget { active: repo.viewerHasStarred, text: repo.viewerHasStarred ? 'Unstar' : 'Star', onTap: () async { + final activityApi = + context.read().ghClient.activity; if (repo.viewerHasStarred) { - await context - .read() - .ghClient - .activity - .unstar( - RepositorySlug(repo.owner.login, repo.name)); + await activityApi.unstar( + RepositorySlug(repo.owner.login, repo.name)); } else { - await context - .read() - .ghClient - .activity - .star( - RepositorySlug(repo.owner.login, repo.name)); + await activityApi.star( + RepositorySlug(repo.owner.login, repo.name)); } - setState(() { - // repo.viewerHasStarred = !repo.viewerHasStarred; - }); + setData(data.withItem1(repo.rebuild((b) { + b.viewerHasStarred = !repo.viewerHasStarred; + }))); }, ), ], diff --git a/lib/screens/gh_user.dart b/lib/screens/gh_user.dart index f5cc703..3d880e6 100644 --- a/lib/screens/gh_user.dart +++ b/lib/screens/gh_user.dart @@ -59,12 +59,12 @@ class _Repos extends StatelessWidget { class _User extends StatelessWidget { final GUserParts p; final bool isViewer; - const _User(this.p, {this.isViewer = false}); + final List rightWidgets; + const _User(this.p, {this.isViewer = false, this.rightWidgets = const []}); @override Widget build(BuildContext context) { final theme = Provider.of(context); - final auth = Provider.of(context); final login = p.login; return Column( @@ -77,25 +77,7 @@ class _User extends StatelessWidget { createdAt: p.createdAt, bio: p.bio, isViewer: isViewer, - rightWidgets: [ - if (p.viewerCanFollow) - MutationButton( - active: p.viewerIsFollowing, - text: p.viewerIsFollowing - ? S.of(context).unfollow - : S.of(context).follow, - onTap: () async { - if (p.viewerIsFollowing) { - await auth.ghClient.users.unfollowUser(p.login); - } else { - await auth.ghClient.users.followUser(p.login); - } - // setState(() { - // // p.viewerIsFollowing = !p.viewerIsFollowing; - // }); - }, - ) - ], + rightWidgets: rightWidgets, ), CommonStyle.border, Row(children: [ @@ -297,7 +279,7 @@ class GhViewer extends StatelessWidget { iconData: Icons.settings, url: '/settings', ), - bodyBuilder: (p, setState) { + bodyBuilder: (p, _) { return _User(p, isViewer: true); }, ); @@ -318,18 +300,44 @@ class GhUser extends StatelessWidget { return res.data; }, title: AppBarTitle(login), - actionBuilder: (payload, setState) { + actionBuilder: (payload, _) { return ActionButton( title: 'User Actions', items: ActionItem.getUrlActions(payload.repositoryOwner.url), ); }, - bodyBuilder: (p, setState) { - if (p.repositoryOwner.G__typename == 'User') { - return _User(p.repositoryOwner as GUserData_repositoryOwner__asUser); + bodyBuilder: (data, setData) { + if (data.repositoryOwner.G__typename == 'User') { + final p = data.repositoryOwner as GUserData_repositoryOwner__asUser; + return _User( + p, + rightWidgets: [ + if (p.viewerCanFollow) + MutationButton( + active: p.viewerIsFollowing, + text: p.viewerIsFollowing + ? S.of(context).unfollow + : S.of(context).follow, + onTap: () async { + if (p.viewerIsFollowing) { + await auth.ghClient.users.unfollowUser(p.login); + } else { + await auth.ghClient.users.followUser(p.login); + } + setData(data.rebuild((b) { + final u = b.repositoryOwner + as GUserData_repositoryOwner__asUser; + b.repositoryOwner = u.rebuild((b1) { + b1.viewerIsFollowing = !b1.viewerIsFollowing; + }); + })); + }, + ) + ], + ); } else { - return _Org( - p.repositoryOwner as GUserData_repositoryOwner__asOrganization); + return _Org(data.repositoryOwner + as GUserData_repositoryOwner__asOrganization); } }, ); diff --git a/lib/screens/gl_project.dart b/lib/screens/gl_project.dart index 7e14ea3..50f8a4f 100644 --- a/lib/screens/gl_project.dart +++ b/lib/screens/gl_project.dart @@ -74,7 +74,7 @@ class GlProjectScreen extends StatelessWidget { return Tuple5(p, langFuture, memberCountFuture, readmeData, branches); }, - actionBuilder: (t, setState) { + actionBuilder: (t, _) { return ActionButton( title: S.of(context).projectActions, items: [ diff --git a/lib/screens/go_repo.dart b/lib/screens/go_repo.dart index 1c85bad..216e631 100644 --- a/lib/screens/go_repo.dart +++ b/lib/screens/go_repo.dart @@ -54,7 +54,7 @@ class GoRepoScreen extends StatelessWidget { return Tuple3(repo, readmeData, branches); }, - bodyBuilder: (t, setState) { + bodyBuilder: (t, _) { final p = t.item1; final branches = t.item3; final theme = context.read(); diff --git a/lib/screens/gt_repo.dart b/lib/screens/gt_repo.dart index bc8ff19..7a7b398 100644 --- a/lib/screens/gt_repo.dart +++ b/lib/screens/gt_repo.dart @@ -47,7 +47,7 @@ class GtRepoScreen extends StatelessWidget { return Tuple2(repo, readmeData); }, - bodyBuilder: (t, setState) { + bodyBuilder: (t, _) { final p = t.item1; return Column( crossAxisAlignment: CrossAxisAlignment.stretch, diff --git a/lib/widgets/user_header.dart b/lib/widgets/user_header.dart index d6c0f89..b0efc82 100644 --- a/lib/widgets/user_header.dart +++ b/lib/widgets/user_header.dart @@ -21,14 +21,15 @@ class UserHeader extends StatelessWidget { @required this.bio, bool isViewer = false, List rightWidgets, - }) : this.rightWidgets = [ - ...(rightWidgets ?? []), + }) : rightWidgets = [ if (isViewer) MutationButton( active: false, text: 'Switch accounts', url: '/login', ) + else + ...(rightWidgets ?? []), ]; @override