fix(github): repo and user mutations

This commit is contained in:
Rongjian Zhang 2021-01-31 15:49:28 +08:00
parent 31c43eebc8
commit 10477a7071
10 changed files with 93 additions and 100 deletions

View File

@ -5,11 +5,9 @@ import 'package:git_touch/scaffolds/utils.dart';
class RefreshStatefulScaffold<T> 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<T> 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<T>
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,

View File

@ -40,7 +40,7 @@ class BbRepoScreen extends StatelessWidget {
});
return Tuple3(repo, readme, branches);
},
bodyBuilder: (t, setState) {
bodyBuilder: (t, _) {
final theme = Provider.of<ThemeModel>(context);
final p = t.item1;
final branches = t.item3;

View File

@ -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<ThemeModel>();
@ -92,9 +92,9 @@ class GeRepoScreen extends StatelessWidget {
await context.read<AuthModel>().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);
},
)
])

View File

@ -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;

View File

@ -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<AuthModel>().ghClient.activity;
switch (v) {
case GSubscriptionState.SUBSCRIBED:
case GSubscriptionState.IGNORED:
await context
.read<AuthModel>()
.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<AuthModel>()
.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<AuthModel>().ghClient.activity;
if (repo.viewerHasStarred) {
await context
.read<AuthModel>()
.ghClient
.activity
.unstar(
RepositorySlug(repo.owner.login, repo.name));
await activityApi.unstar(
RepositorySlug(repo.owner.login, repo.name));
} else {
await context
.read<AuthModel>()
.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;
})));
},
),
],

View File

@ -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<Widget> rightWidgets;
const _User(this.p, {this.isViewer = false, this.rightWidgets = const []});
@override
Widget build(BuildContext context) {
final theme = Provider.of<ThemeModel>(context);
final auth = Provider.of<AuthModel>(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);
}
},
);

View File

@ -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: [

View File

@ -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<ThemeModel>();

View File

@ -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,

View File

@ -21,14 +21,15 @@ class UserHeader extends StatelessWidget {
@required this.bio,
bool isViewer = false,
List<Widget> rightWidgets,
}) : this.rightWidgets = [
...(rightWidgets ?? []),
}) : rightWidgets = [
if (isViewer)
MutationButton(
active: false,
text: 'Switch accounts',
url: '/login',
)
else
...(rightWidgets ?? []),
];
@override