build: upgrade provider

This commit is contained in:
Rongjian Zhang 2020-10-04 20:37:23 +08:00
parent 1269b66eb4
commit 15ccf72a27
55 changed files with 216 additions and 180 deletions

View File

@ -14,8 +14,8 @@ class BbCommitsScreen extends StatelessWidget {
Future<ListPayload<BbCommit, String>> _query(BuildContext context, Future<ListPayload<BbCommit, String>> _query(BuildContext context,
[String nextUrl]) async { [String nextUrl]) async {
final auth = Provider.of<AuthModel>(context); final res = await context
final res = await auth .read<AuthModel>()
.fetchBbWithPage(nextUrl ?? '/repositories/$owner/$name/commits/$ref'); .fetchBbWithPage(nextUrl ?? '/repositories/$owner/$name/commits/$ref');
return ListPayload( return ListPayload(
cursor: res.cursor, cursor: res.cursor,

View File

@ -9,8 +9,7 @@ import 'package:provider/provider.dart';
class BbExploreScreen extends StatelessWidget { class BbExploreScreen extends StatelessWidget {
Future<ListPayload<BbRepo, String>> _query(BuildContext context, Future<ListPayload<BbRepo, String>> _query(BuildContext context,
[String nextUrl]) async { [String nextUrl]) async {
final auth = Provider.of<AuthModel>(context); final res = await context.read<AuthModel>().fetchBbWithPage(
final res = await auth.fetchBbWithPage(
nextUrl ?? '/repositories?role=member&sort=-updated_on'); nextUrl ?? '/repositories?role=member&sort=-updated_on');
return ListPayload( return ListPayload(
cursor: res.cursor, cursor: res.cursor,

View File

@ -14,8 +14,8 @@ class BbIssuesScreen extends StatelessWidget {
Future<ListPayload<BbIssues, String>> _query(BuildContext context, Future<ListPayload<BbIssues, String>> _query(BuildContext context,
[String nextUrl]) async { [String nextUrl]) async {
final auth = Provider.of<AuthModel>(context); final res = await context
final res = await auth .read<AuthModel>()
.fetchBbWithPage(nextUrl ?? '/repositories/$owner/$name/issues'); .fetchBbWithPage(nextUrl ?? '/repositories/$owner/$name/issues');
return ListPayload( return ListPayload(
cursor: res.cursor, cursor: res.cursor,

View File

@ -14,8 +14,8 @@ class BbPullsScreen extends StatelessWidget {
Future<ListPayload<BbPulls, String>> _query(BuildContext context, Future<ListPayload<BbPulls, String>> _query(BuildContext context,
[String nextUrl]) async { [String nextUrl]) async {
final auth = Provider.of<AuthModel>(context); final res = await context
final res = await auth .read<AuthModel>()
.fetchBbWithPage(nextUrl ?? '/repositories/$owner/$name/pullrequests'); .fetchBbWithPage(nextUrl ?? '/repositories/$owner/$name/pullrequests');
return ListPayload( return ListPayload(
cursor: res.cursor, cursor: res.cursor,

View File

@ -24,7 +24,7 @@ class BbRepoScreen extends StatelessWidget {
return RefreshStatefulScaffold<Tuple2<BbRepo, String>>( return RefreshStatefulScaffold<Tuple2<BbRepo, String>>(
title: AppBarTitle('Repository'), title: AppBarTitle('Repository'),
fetchData: () async { fetchData: () async {
final auth = Provider.of<AuthModel>(context); final auth = context.read<AuthModel>();
final r = await auth.fetchBbJson('/repositories/$owner/$name'); final r = await auth.fetchBbJson('/repositories/$owner/$name');
final repo = BbRepo.fromJson(r); final repo = BbRepo.fromJson(r);
final res = await auth.fetchBb( final res = await auth.fetchBb(

View File

@ -10,8 +10,9 @@ import 'package:timeago/timeago.dart' as timeago;
class BbTeamsScreen extends StatelessWidget { class BbTeamsScreen extends StatelessWidget {
Future<ListPayload<BbUser, String>> _query(BuildContext context, Future<ListPayload<BbUser, String>> _query(BuildContext context,
[String nextUrl]) async { [String nextUrl]) async {
final auth = Provider.of<AuthModel>(context); final res = await context
final res = await auth.fetchBbWithPage(nextUrl ?? '/teams?role=member'); .read<AuthModel>()
.fetchBbWithPage(nextUrl ?? '/teams?role=member');
return ListPayload( return ListPayload(
cursor: res.cursor, cursor: res.cursor,
hasMore: res.hasMore, hasMore: res.hasMore,

View File

@ -22,7 +22,11 @@ class BbUserScreen extends StatelessWidget {
final _accountId = auth.activeAccount.accountId; final _accountId = auth.activeAccount.accountId;
final _login = login ?? auth.activeAccount.login; final _login = login ?? auth.activeAccount.login;
return RefreshStatefulScaffold<Tuple2<BbUser, Iterable<BbRepo>>>( return RefreshStatefulScaffold<Tuple2<BbUser, Iterable<BbRepo>>>(
title: Text(isViewer ? 'Me' : isTeam ? 'Team' : 'User'), title: Text(isViewer
? 'Me'
: isTeam
? 'Team'
: 'User'),
fetchData: () async { fetchData: () async {
final res = await Future.wait([ final res = await Future.wait([
auth.fetchBbJson('/${isTeam ? 'teams' : 'users'}/$_accountId'), auth.fetchBbJson('/${isTeam ? 'teams' : 'users'}/$_accountId'),

View File

@ -15,7 +15,7 @@ class GhCommitsScreen extends StatelessWidget {
Future<ListPayload<GhCommitsCommit, String>> _query(BuildContext context, Future<ListPayload<GhCommitsCommit, String>> _query(BuildContext context,
[String cursor]) async { [String cursor]) async {
final res = await Provider.of<AuthModel>(context).gqlClient.execute( final res = await context.read<AuthModel>().gqlClient.execute(
GhCommitsQuery( GhCommitsQuery(
variables: GhCommitsArguments( variables: GhCommitsArguments(
owner: owner, owner: owner,

View File

@ -19,11 +19,9 @@ class GhComparisonScreen extends StatelessWidget {
return RefreshStatefulScaffold( return RefreshStatefulScaffold(
title: AppBarTitle('Files'), title: AppBarTitle('Files'),
fetchData: () async { fetchData: () async {
final auth = Provider.of<AuthModel>(context); final res = await context.read<AuthModel>().ghClient.getJSON(
final res = await auth.ghClient.getJSON( '/repos/$owner/$name/compare/$before...$head',
'/repos/$owner/$name/compare/$before...$head', convert: (vs) => GithubComparisonItem.fromJson(vs));
convert: (vs) => GithubComparisonItem.fromJson(vs),
);
return res.files; return res.files;
}, },
actionBuilder: (v, _) { actionBuilder: (v, _) {

View File

@ -14,11 +14,14 @@ class GhContributorsScreen extends StatelessWidget {
Future<ListPayload<GithubContributorItem, int>> _query(BuildContext context, Future<ListPayload<GithubContributorItem, int>> _query(BuildContext context,
[int page = 1]) async { [int page = 1]) async {
final auth = Provider.of<AuthModel>(context); final res = await context
final res = await auth.ghClient.getJSON<List, List<GithubContributorItem>>( .read<AuthModel>()
'/repos/$owner/$name/contributors?page=$page', .ghClient
convert: (vs) => [for (var v in vs) GithubContributorItem.fromJson(v)], .getJSON<List, List<GithubContributorItem>>(
); '/repos/$owner/$name/contributors?page=$page',
convert: (vs) =>
[for (var v in vs) GithubContributorItem.fromJson(v)],
);
return ListPayload( return ListPayload(
cursor: page + 1, cursor: page + 1,
items: res, items: res,

View File

@ -16,11 +16,13 @@ class GhFilesScreen extends StatelessWidget {
Future<ListPayload<GithubFilesItem, int>> _query(BuildContext context, Future<ListPayload<GithubFilesItem, int>> _query(BuildContext context,
[int page = 1]) async { [int page = 1]) async {
final auth = Provider.of<AuthModel>(context); final res = await context
final res = await auth.ghClient.getJSON<List, List<GithubFilesItem>>( .read<AuthModel>()
'/repos/$owner/$name/pulls/$pullNumber/files?page=$page', .ghClient
convert: (vs) => [for (var v in vs) GithubFilesItem.fromJson(v)], .getJSON<List, List<GithubFilesItem>>(
); '/repos/$owner/$name/pulls/$pullNumber/files?page=$page',
convert: (vs) => [for (var v in vs) GithubFilesItem.fromJson(v)],
);
return ListPayload( return ListPayload(
cursor: page + 1, cursor: page + 1,
items: res, items: res,

View File

@ -13,11 +13,13 @@ class GhGistsScreen extends StatelessWidget {
Future<ListPayload<GithubGistsItem, int>> _query(BuildContext context, Future<ListPayload<GithubGistsItem, int>> _query(BuildContext context,
[int page = 1]) async { [int page = 1]) async {
final auth = Provider.of<AuthModel>(context); final res = await context
final res = await auth.ghClient.getJSON<List, List<GithubGistsItem>>( .read<AuthModel>()
'/users/$login/gists?page=$page', .ghClient
convert: (vs) => [for (var v in vs) GithubGistsItem.fromJson(v)], .getJSON<List, List<GithubGistsItem>>(
); '/users/$login/gists?page=$page',
convert: (vs) => [for (var v in vs) GithubGistsItem.fromJson(v)],
);
return ListPayload( return ListPayload(
cursor: page + 1, cursor: page + 1,
items: res, items: res,

View File

@ -14,14 +14,12 @@ class GhGistsFilesScreen extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final auth = Provider.of<AuthModel>(context);
return RefreshStatefulScaffold<GithubGistsItem>( return RefreshStatefulScaffold<GithubGistsItem>(
title: AppBarTitle('Files'), title: AppBarTitle('Files'),
fetchData: () async { fetchData: () async {
final data = await auth.ghClient.getJSON( final data = await context.read<AuthModel>().ghClient.getJSON(
'/gists/$id', '/gists/$id',
convert: (vs) => GithubGistsItem.fromJson(vs), convert: (vs) => GithubGistsItem.fromJson(vs));
);
return data; return data;
}, },
bodyBuilder: (payload, _) { bodyBuilder: (payload, _) {

View File

@ -407,7 +407,7 @@ __typename
} }
} }
var data = await Provider.of<AuthModel>(context).query(''' var data = await context.read<AuthModel>().query('''
fragment CommentParts on Comment { fragment CommentParts on Comment {
id id
createdAt createdAt
@ -467,7 +467,6 @@ fragment ReactableParts on Reactable {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final auth = Provider.of<AuthModel>(context);
return LongListStatefulScaffold( return LongListStatefulScaffold(
title: Text(isPullRequest ? 'Pull Request' : 'Issue'), title: Text(isPullRequest ? 'Pull Request' : 'Issue'),
trailingBuilder: (payload, setState) { trailingBuilder: (payload, setState) {
@ -479,14 +478,15 @@ fragment ReactableParts on Reactable {
ActionItem( ActionItem(
text: payload['closed'] ? 'Reopen issue' : 'Close issue', text: payload['closed'] ? 'Reopen issue' : 'Close issue',
onTap: (_) async { onTap: (_) async {
final res = await auth.gqlClient.execute( final res = await context
GhOpenIssueQuery( .read<AuthModel>()
variables: GhOpenIssueArguments( .gqlClient
id: payload['id'], .execute(GhOpenIssueQuery(
open: payload['closed'], variables: GhOpenIssueArguments(
), id: payload['id'],
), open: payload['closed'],
); ),
));
setState(() { setState(() {
payload['closed'] = res.data.reopenIssue?.issue?.closed ?? payload['closed'] = res.data.reopenIssue?.issue?.closed ??
res.data.closeIssue.issue.closed; res.data.closeIssue.issue.closed;

View File

@ -23,7 +23,6 @@ class _GhIssueFormScreenState extends State<GhIssueFormScreen> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final theme = Provider.of<ThemeModel>(context); final theme = Provider.of<ThemeModel>(context);
final auth = Provider.of<AuthModel>(context);
return CommonScaffold( return CommonScaffold(
title: Text('Submit an issue'), title: Text('Submit an issue'),
@ -58,8 +57,10 @@ class _GhIssueFormScreenState extends State<GhIssueFormScreen> {
child: Text('Submit'), child: Text('Submit'),
onPressed: () async { onPressed: () async {
final slug = RepositorySlug(widget.owner, widget.name); final slug = RepositorySlug(widget.owner, widget.name);
final res = await context
final res = await auth.ghClient.issues .read<AuthModel>()
.ghClient
.issues
.create(slug, IssueRequest(title: _title, body: _body)); .create(slug, IssueRequest(title: _title, body: _body));
await theme.push( await theme.push(
context, context,

View File

@ -16,13 +16,12 @@ class GhIssuesScreen extends StatelessWidget {
Future<ListPayload<GhIssuesIssue, String>> _query(BuildContext context, Future<ListPayload<GhIssuesIssue, String>> _query(BuildContext context,
[String cursor]) async { [String cursor]) async {
final res = final res = await context.read<AuthModel>().gqlClient.execute(GhIssuesQuery(
await Provider.of<AuthModel>(context).gqlClient.execute(GhIssuesQuery( variables: GhIssuesArguments(
variables: GhIssuesArguments( owner: owner,
owner: owner, name: name,
name: name, cursor: cursor,
cursor: cursor, )));
)));
final issues = res.data.repository.issues; final issues = res.data.repository.issues;
return ListPayload( return ListPayload(
cursor: issues.pageInfo.endCursor, cursor: issues.pageInfo.endCursor,

View File

@ -21,18 +21,19 @@ class GhNewsScreenState extends State<GhNewsScreen> {
Future.microtask(() async { Future.microtask(() async {
// Check if there are unread notification items. // Check if there are unread notification items.
// 1 item is enough since count is not displayed for now. // 1 item is enough since count is not displayed for now.
var items = await Provider.of<AuthModel>(context) var items = await context
.read<AuthModel>()
.ghClient .ghClient
.getJSON('/notifications?per_page=1'); .getJSON('/notifications?per_page=1');
if (items is List && items.isNotEmpty) { if (items is List && items.isNotEmpty) {
Provider.of<NotificationModel>(context).setCount(1); context.read<NotificationModel>().setCount(1);
} }
}); });
} }
Future<ListPayload<GithubEvent, int>> fetchEvents([int page = 1]) async { Future<ListPayload<GithubEvent, int>> fetchEvents([int page = 1]) async {
final auth = Provider.of<AuthModel>(context); final auth = context.read<AuthModel>();
final login = auth.activeAccount.login; final login = auth.activeAccount.login;
final events = await auth.ghClient.getJSON( final events = await auth.ghClient.getJSON(

View File

@ -21,13 +21,13 @@ class GhNotificationScreen extends StatefulWidget {
class GhNotificationScreenState extends State<GhNotificationScreen> { class GhNotificationScreenState extends State<GhNotificationScreen> {
Future<Map<String, NotificationGroup>> fetchNotifications(int index) async { Future<Map<String, NotificationGroup>> fetchNotifications(int index) async {
final ns = await Provider.of<AuthModel>(context).ghClient.getJSON( final ns = await context.read<AuthModel>().ghClient.getJSON(
'/notifications?all=${index == 2}&participating=${index == 1}', '/notifications?all=${index == 2}&participating=${index == 1}',
convert: (vs) => convert: (vs) =>
[for (var v in vs) GithubNotificationItem.fromJson(v)], [for (var v in vs) GithubNotificationItem.fromJson(v)],
); );
if (index == 0) { if (index == 0) {
Provider.of<NotificationModel>(context).setCount(ns.length); context.read<NotificationModel>().setCount(ns.length);
} }
Map<String, NotificationGroup> _groupMap = {}; Map<String, NotificationGroup> _groupMap = {};
@ -82,7 +82,7 @@ ${item.key}: pullRequest(number: ${item.subject.number}) {
if (schema == '{}') return _groupMap; if (schema == '{}') return _groupMap;
// Fimber.d(schema); // Fimber.d(schema);
var data = await Provider.of<AuthModel>(context).query(schema); var data = await context.read<AuthModel>().query(schema);
_groupMap.forEach((repo, group) { _groupMap.forEach((repo, group) {
group.items.forEach((item) { group.items.forEach((item) {
var groupData = data[group.key]; var groupData = data[group.key];
@ -121,9 +121,12 @@ ${item.key}: pullRequest(number: ${item.subject.number}) {
), ),
GestureDetector( GestureDetector(
onTap: () async { onTap: () async {
final auth = Provider.of<AuthModel>(context); await context
await auth.ghClient.activity.markRepositoryNotificationsRead( .read<AuthModel>()
RepositorySlug.full(group.fullName)); .ghClient
.activity
.markRepositoryNotificationsRead(
RepositorySlug.full(group.fullName));
// await _onSwitchTab(); // TODO: // await _onSwitchTab(); // TODO:
}, },
child: Icon( child: Icon(
@ -171,10 +174,12 @@ ${item.key}: pullRequest(number: ${item.subject.number}) {
actionBuilder: (_, refresh) => ActionEntry( actionBuilder: (_, refresh) => ActionEntry(
iconData: Icons.done_all, iconData: Icons.done_all,
onTap: () async { onTap: () async {
var value = await Provider.of<ThemeModel>(context) final value = await context
.read<ThemeModel>()
.showConfirm(context, Text('Mark all as read?')); .showConfirm(context, Text('Mark all as read?'));
if (value) { if (value) {
await Provider.of<AuthModel>(context) await context
.read<AuthModel>()
.ghClient .ghClient
.activity .activity
.markNotificationsRead(); .markNotificationsRead();

View File

@ -34,8 +34,10 @@ class GhObjectScreen extends StatelessWidget {
} }
final suffix = path == null ? '' : '/$path'; final suffix = path == null ? '' : '/$path';
final auth = Provider.of<AuthModel>(context); final res = await context
final res = await auth.ghClient.repositories .read<AuthModel>()
.ghClient
.repositories
.getContents(RepositorySlug(owner, name), suffix, ref: ref); .getContents(RepositorySlug(owner, name), suffix, ref: ref);
if (res.isDirectory) { if (res.isDirectory) {
res.tree.sort((a, b) { res.tree.sort((a, b) {

View File

@ -18,11 +18,13 @@ class GhOrgReposScreen extends StatelessWidget {
Future<ListPayload<Repository, int>> _query(BuildContext context, Future<ListPayload<Repository, int>> _query(BuildContext context,
[int page = 1]) async { [int page = 1]) async {
final auth = Provider.of<AuthModel>(context); final rs = await context
final rs = await auth.ghClient.getJSON<List, List<Repository>>( .read<AuthModel>()
'/orgs/$owner/repos?sort=updated&page=$page', .ghClient
convert: (vs) => [for (var v in vs) Repository.fromJson(v)], .getJSON<List, List<Repository>>(
); '/orgs/$owner/repos?sort=updated&page=$page',
convert: (vs) => [for (var v in vs) Repository.fromJson(v)],
);
return ListPayload( return ListPayload(
cursor: page + 1, cursor: page + 1,
items: rs, items: rs,

View File

@ -14,13 +14,12 @@ class GhPullsScreen extends StatelessWidget {
Future<ListPayload<GhPullsPullRequest, String>> _query(BuildContext context, Future<ListPayload<GhPullsPullRequest, String>> _query(BuildContext context,
[String cursor]) async { [String cursor]) async {
final res = final res = await context.read<AuthModel>().gqlClient.execute(GhPullsQuery(
await Provider.of<AuthModel>(context).gqlClient.execute(GhPullsQuery( variables: GhPullsArguments(
variables: GhPullsArguments( owner: owner,
owner: owner, name: name,
name: name, cursor: cursor,
cursor: cursor, )));
)));
final pulls = res.data.repository.pullRequests; final pulls = res.data.repository.pullRequests;
return ListPayload( return ListPayload(
cursor: pulls.pageInfo.endCursor, cursor: pulls.pageInfo.endCursor,

View File

@ -26,13 +26,12 @@ class GhRepoScreen extends StatelessWidget {
GhRepoScreen(this.owner, this.name, {this.branch}); GhRepoScreen(this.owner, this.name, {this.branch});
Future<GhRepoRepository> _query(BuildContext context) async { Future<GhRepoRepository> _query(BuildContext context) async {
var res = await Provider.of<AuthModel>(context).gqlClient.execute( var res = await context.read<AuthModel>().gqlClient.execute(GhRepoQuery(
GhRepoQuery( variables: GhRepoArguments(
variables: GhRepoArguments( owner: owner,
owner: owner, name: name,
name: name, branchSpecified: branch != null,
branchSpecified: branch != null, branch: branch ?? '')));
branch: branch ?? '')));
return res.data.repository; return res.data.repository;
} }
@ -50,17 +49,19 @@ class GhRepoScreen extends StatelessWidget {
} }
Future<String> _fetchContributors(BuildContext context) async { Future<String> _fetchContributors(BuildContext context) async {
final auth = Provider.of<AuthModel>(context); final res = await context
final res = await auth.ghClient.getJSON( .read<AuthModel>()
'/repos/$owner/$name/stats/contributors', .ghClient
); .getJSON('/repos/$owner/$name/stats/contributors');
return res.length.toString(); return res.length.toString();
} }
Future<String> _fetchReadme(BuildContext context) async { Future<String> _fetchReadme(BuildContext context) async {
try { try {
final auth = Provider.of<AuthModel>(context); final res = await context
final res = await auth.ghClient.repositories .read<AuthModel>()
.ghClient
.repositories
.getReadme(RepositorySlug(owner, name)); .getReadme(RepositorySlug(owner, name));
return res.text; return res.text;
} catch (e) { } catch (e) {
@ -72,7 +73,6 @@ class GhRepoScreen extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final theme = Provider.of<ThemeModel>(context); final theme = Provider.of<ThemeModel>(context);
final auth = Provider.of<AuthModel>(context);
return RefreshStatefulScaffold<Tuple3<GhRepoRepository, String, String>>( return RefreshStatefulScaffold<Tuple3<GhRepoRepository, String, String>>(
title: AppBarTitle('Repository'), title: AppBarTitle('Repository'),
fetchData: () async { fetchData: () async {
@ -136,15 +136,19 @@ class GhRepoScreen extends StatelessWidget {
switch (v) { switch (v) {
case GhRepoSubscriptionState.SUBSCRIBED: case GhRepoSubscriptionState.SUBSCRIBED:
case GhRepoSubscriptionState.IGNORED: case GhRepoSubscriptionState.IGNORED:
final res = await auth.ghClient.activity final res = await context
.read<AuthModel>()
.ghClient
.activity
.setRepositorySubscription( .setRepositorySubscription(
RepositorySlug( RepositorySlug(
repo.owner.login, repo.name), repo.owner.login, repo.name),
subscribed: v == subscribed: v ==
GhRepoSubscriptionState.SUBSCRIBED, GhRepoSubscriptionState
ignored: .SUBSCRIBED,
v == GhRepoSubscriptionState.IGNORED, ignored: v ==
); GhRepoSubscriptionState.IGNORED,
);
setState(() { setState(() {
if (res.subscribed) { if (res.subscribed) {
repo.viewerSubscription = repo.viewerSubscription =
@ -156,13 +160,16 @@ class GhRepoScreen extends StatelessWidget {
}); });
break; break;
case GhRepoSubscriptionState.UNSUBSCRIBED: case GhRepoSubscriptionState.UNSUBSCRIBED:
await auth.ghClient.activity await context
.read<AuthModel>()
.ghClient
.activity
.deleteRepositorySubscription( .deleteRepositorySubscription(
RepositorySlug( RepositorySlug(
repo.owner.login, repo.owner.login,
repo.name, repo.name,
), ),
); );
setState(() { setState(() {
repo.viewerSubscription = repo.viewerSubscription =
GhRepoSubscriptionState.UNSUBSCRIBED; GhRepoSubscriptionState.UNSUBSCRIBED;
@ -181,11 +188,19 @@ class GhRepoScreen extends StatelessWidget {
text: repo.viewerHasStarred ? 'Unstar' : 'Star', text: repo.viewerHasStarred ? 'Unstar' : 'Star',
onPressed: () async { onPressed: () async {
if (repo.viewerHasStarred) { if (repo.viewerHasStarred) {
await auth.ghClient.activity.unstar( await context
RepositorySlug(repo.owner.login, repo.name)); .read<AuthModel>()
.ghClient
.activity
.unstar(
RepositorySlug(repo.owner.login, repo.name));
} else { } else {
await auth.ghClient.activity.star( await context
RepositorySlug(repo.owner.login, repo.name)); .read<AuthModel>()
.ghClient
.activity
.star(
RepositorySlug(repo.owner.login, repo.name));
} }
setState(() { setState(() {
repo.viewerHasStarred = !repo.viewerHasStarred; repo.viewerHasStarred = !repo.viewerHasStarred;

View File

@ -21,10 +21,10 @@ class GhReposScreen extends StatelessWidget {
Future<ListPayload<GhReposRepository, String>> _query(BuildContext context, Future<ListPayload<GhReposRepository, String>> _query(BuildContext context,
[String cursor]) async { [String cursor]) async {
final res = await Provider.of<AuthModel>(context).gqlClient.execute( final auth = context.read<AuthModel>();
GhReposQuery( final res = await auth.gqlClient.execute(GhReposQuery(
variables: variables:
GhReposArguments(owner: owner, isStar: isStar, after: cursor))); GhReposArguments(owner: owner, isStar: isStar, after: cursor)));
final data = res.data.user; final data = res.data.user;
if (isStar) { if (isStar) {
return ListPayload( return ListPayload(

View File

@ -46,7 +46,8 @@ class _GhSearchScreenState extends State<GhSearchScreen> {
_loading = true; _loading = true;
}); });
try { try {
var data = await Provider.of<AuthModel>(context).query(''' final auth = context.read<AuthModel>();
final data = await auth.query('''
{ {
repository: search(first: $pageSize, type: REPOSITORY, query: "$keyword") { repository: search(first: $pageSize, type: REPOSITORY, query: "$keyword") {
nodes { nodes {

View File

@ -14,7 +14,7 @@ class GhUserOrganizationScreen extends StatelessWidget {
Future<ListPayload<GithubUserOrganizationItem, int>> _query( Future<ListPayload<GithubUserOrganizationItem, int>> _query(
BuildContext context, BuildContext context,
[int page = 1]) async { [int page = 1]) async {
final auth = Provider.of<AuthModel>(context); final auth = context.read<AuthModel>();
final res = final res =
await auth.ghClient.getJSON<List, List<GithubUserOrganizationItem>>( await auth.ghClient.getJSON<List, List<GithubUserOrganizationItem>>(
'/users/$login/orgs?page=$page', '/users/$login/orgs?page=$page',

View File

@ -42,17 +42,17 @@ class GhUsersScreen extends StatelessWidget {
Future<ListPayload<GhUsersUser, String>> _queryUsers(BuildContext context, Future<ListPayload<GhUsersUser, String>> _queryUsers(BuildContext context,
[String cursor]) async { [String cursor]) async {
final res = await Provider.of<AuthModel>(context).gqlClient.execute( final auth = context.read<AuthModel>();
GhUsersQuery( final res = await auth.gqlClient.execute(GhUsersQuery(
variables: GhUsersArguments( variables: GhUsersArguments(
login: login, login: login,
repoName: repoName, repoName: repoName,
isFollowers: type == UsersScreenType.follower, isFollowers: type == UsersScreenType.follower,
isFollowing: type == UsersScreenType.following, isFollowing: type == UsersScreenType.following,
isStar: type == UsersScreenType.star, isStar: type == UsersScreenType.star,
isWatch: type == UsersScreenType.watch, isWatch: type == UsersScreenType.watch,
isMember: type == UsersScreenType.member, isMember: type == UsersScreenType.member,
after: cursor))); after: cursor)));
switch (type) { switch (type) {
case UsersScreenType.follower: case UsersScreenType.follower:

View File

@ -19,7 +19,8 @@ class GlBlobScreen extends StatelessWidget {
return RefreshStatefulScaffold<GitlabBlob>( return RefreshStatefulScaffold<GitlabBlob>(
title: AppBarTitle(path ?? ''), title: AppBarTitle(path ?? ''),
fetchData: () async { fetchData: () async {
final res = await Provider.of<AuthModel>(context).fetchGitlab( final auth = context.read<AuthModel>();
final res = await auth.fetchGitlab(
'/projects/$id/repository/files/${path.urlencode}?ref=$ref'); '/projects/$id/repository/files/${path.urlencode}?ref=$ref');
return GitlabBlob.fromJson(res); return GitlabBlob.fromJson(res);
}, },

View File

@ -17,7 +17,7 @@ class GlCommitScreen extends StatelessWidget {
GlCommitScreen(this.id, {this.sha}); GlCommitScreen(this.id, {this.sha});
Future<List<GitlabDiff>> _query(BuildContext context, [int page = 1]) async { Future<List<GitlabDiff>> _query(BuildContext context, [int page = 1]) async {
final auth = Provider.of<AuthModel>(context); final auth = context.read<AuthModel>();
final res = await auth final res = await auth
.fetchGitlabWithPage('/projects/$id/repository/commits/$sha/diff'); .fetchGitlabWithPage('/projects/$id/repository/commits/$sha/diff');
return (res.data as List).map((v) => GitlabDiff.fromJson(v)).toList(); return (res.data as List).map((v) => GitlabDiff.fromJson(v)).toList();

View File

@ -14,7 +14,7 @@ class GlCommitsScreen extends StatelessWidget {
Future<ListPayload<GitlabCommit, int>> _query(BuildContext context, Future<ListPayload<GitlabCommit, int>> _query(BuildContext context,
[int page = 1]) async { [int page = 1]) async {
final auth = Provider.of<AuthModel>(context); final auth = context.read<AuthModel>();
final res = await auth final res = await auth
.fetchGitlabWithPage('/projects/$id/repository/commits?page=$page'); .fetchGitlabWithPage('/projects/$id/repository/commits?page=$page');
return ListPayload( return ListPayload(

View File

@ -10,7 +10,7 @@ import 'package:timeago/timeago.dart' as timeago;
class GlExploreScreen extends StatelessWidget { class GlExploreScreen extends StatelessWidget {
Future<ListPayload<GitlabProject, int>> _query(BuildContext context, Future<ListPayload<GitlabProject, int>> _query(BuildContext context,
[int page = 1]) async { [int page = 1]) async {
final auth = Provider.of<AuthModel>(context); final auth = context.read<AuthModel>();
final res = await auth final res = await auth
.fetchGitlabWithPage('/projects?order_by=last_activity_at&page=$page'); .fetchGitlabWithPage('/projects?order_by=last_activity_at&page=$page');
return ListPayload( return ListPayload(

View File

@ -20,7 +20,7 @@ class GlGroupScreen extends StatelessWidget {
return RefreshStatefulScaffold<Tuple2<GitlabGroup, int>>( return RefreshStatefulScaffold<Tuple2<GitlabGroup, int>>(
title: Text('Group'), title: Text('Group'),
fetchData: () async { fetchData: () async {
final auth = Provider.of<AuthModel>(context); final auth = context.read<AuthModel>();
final res = await Future.wait([ final res = await Future.wait([
auth.fetchGitlab('/groups/$id'), auth.fetchGitlab('/groups/$id'),
auth.fetchGitlabWithPage('/groups/$id/members?per_page=1') auth.fetchGitlabWithPage('/groups/$id/members?per_page=1')

View File

@ -9,7 +9,7 @@ import 'package:provider/provider.dart';
class GlGroupsScreenn extends StatelessWidget { class GlGroupsScreenn extends StatelessWidget {
Future<ListPayload<GitlabGroup, int>> _query(BuildContext context, Future<ListPayload<GitlabGroup, int>> _query(BuildContext context,
[int page = 1]) async { [int page = 1]) async {
final auth = Provider.of<AuthModel>(context); final auth = context.read<AuthModel>();
final res = await auth.fetchGitlabWithPage('/groups?page=$page'); final res = await auth.fetchGitlabWithPage('/groups?page=$page');
return ListPayload( return ListPayload(
cursor: res.cursor, cursor: res.cursor,

View File

@ -22,13 +22,11 @@ class GlIssueScreen extends StatelessWidget {
title: Text('Issue #$iid'), title: Text('Issue #$iid'),
fetchData: () async { fetchData: () async {
final type = isMr ? 'merge_requests' : 'issues'; final type = isMr ? 'merge_requests' : 'issues';
final auth = context.read<AuthModel>();
final items = await Future.wait([ final items = await Future.wait([
Provider.of<AuthModel>(context) auth.fetchGitlab('/projects/$projectId/$type/$iid'),
.fetchGitlab('/projects/$projectId/$type/$iid'), auth.fetchGitlab('/projects/$projectId/$type/$iid/notes?sort=asc'),
Provider.of<AuthModel>(context) auth.fetchGitlab('/projects/$projectId/$type/$iid/award_emoji'),
.fetchGitlab('/projects/$projectId/$type/$iid/notes?sort=asc'),
Provider.of<AuthModel>(context)
.fetchGitlab('/projects/$projectId/$type/$iid/award_emoji'),
]); ]);
return Tuple3( return Tuple3(
GitlabTodoTarget.fromJson(items[0]), GitlabTodoTarget.fromJson(items[0]),

View File

@ -14,7 +14,7 @@ class GlIssuesScreen extends StatelessWidget {
Future<ListPayload<GitlabIssue, int>> _query(BuildContext context, Future<ListPayload<GitlabIssue, int>> _query(BuildContext context,
[int page = 1]) async { [int page = 1]) async {
final auth = Provider.of<AuthModel>(context); final auth = context.read<AuthModel>();
final res = await auth final res = await auth
.fetchGitlabWithPage('/projects/$id/issues?state=opened&page=$page'); .fetchGitlabWithPage('/projects/$id/issues?state=opened&page=$page');
return ListPayload( return ListPayload(

View File

@ -13,7 +13,7 @@ class GlMembersScreen extends StatelessWidget {
Future<ListPayload<GitlabUser, int>> _query(BuildContext context, Future<ListPayload<GitlabUser, int>> _query(BuildContext context,
[int page = 1]) async { [int page = 1]) async {
final auth = Provider.of<AuthModel>(context); final auth = context.read<AuthModel>();
final res = await auth.fetchGitlabWithPage('/$type/$id/members?page=$page'); final res = await auth.fetchGitlabWithPage('/$type/$id/members?page=$page');
return ListPayload( return ListPayload(
cursor: res.cursor, cursor: res.cursor,

View File

@ -14,7 +14,7 @@ class GlMergeRequestsScreen extends StatelessWidget {
Future<ListPayload<GitlabIssue, int>> _query(BuildContext context, Future<ListPayload<GitlabIssue, int>> _query(BuildContext context,
[int page = 1]) async { [int page = 1]) async {
final res = await Provider.of<AuthModel>(context).fetchGitlabWithPage( final res = await context.read<AuthModel>().fetchGitlabWithPage(
'/projects/$id/merge_requests?state=opened&page=$page'); '/projects/$id/merge_requests?state=opened&page=$page');
return ListPayload( return ListPayload(
cursor: res.cursor, cursor: res.cursor,

View File

@ -28,7 +28,7 @@ class GlProjectScreen extends StatelessWidget {
int, String>>( int, String>>(
title: AppBarTitle('Project'), title: AppBarTitle('Project'),
fetchData: () async { fetchData: () async {
final auth = Provider.of<AuthModel>(context); final auth = context.read<AuthModel>();
final res = await Future.wait([ final res = await Future.wait([
auth.fetchGitlab('/projects/$id?statistics=1'), auth.fetchGitlab('/projects/$id?statistics=1'),
auth.fetchGitlab('/projects/$id/languages'), auth.fetchGitlab('/projects/$id/languages'),

View File

@ -16,7 +16,7 @@ class GlProjectActivityScreen extends StatelessWidget {
Future<ListPayload<GitlabEvent, int>> _query(BuildContext context, Future<ListPayload<GitlabEvent, int>> _query(BuildContext context,
[int page]) async { [int page]) async {
final auth = Provider.of<AuthModel>(context); final auth = context.read<AuthModel>();
final vs = await auth.fetchGitlab('/projects/$id/events'); final vs = await auth.fetchGitlab('/projects/$id/events');
final events = (vs as List).map((v) => GitlabEvent.fromJson(v)).toList(); final events = (vs as List).map((v) => GitlabEvent.fromJson(v)).toList();
return ListPayload(cursor: page, items: events, hasMore: false); return ListPayload(cursor: page, items: events, hasMore: false);

View File

@ -47,10 +47,11 @@ class _GlSearchScreenState extends State<GlSearchScreen> {
_loading = true; _loading = true;
}); });
try { try {
final projects = await Provider.of<AuthModel>(context) final auth = context.read<AuthModel>();
final projects = await auth
.fetchGitlabWithPage('/search?scope=projects&search=$keyword'); .fetchGitlabWithPage('/search?scope=projects&search=$keyword');
final users = await Provider.of<AuthModel>(context) final users =
.fetchGitlabWithPage('/search?scope=users&search=$keyword'); await auth.fetchGitlabWithPage('/search?scope=users&search=$keyword');
_projects = [for (var v in projects.data) GitlabProject.fromJson(v)]; _projects = [for (var v in projects.data) GitlabProject.fromJson(v)];
_users = [for (var v in users.data) GitlabUser.fromJson(v)]; _users = [for (var v in users.data) GitlabUser.fromJson(v)];
} finally { } finally {

View File

@ -13,9 +13,9 @@ class GlStarrersScreen extends StatelessWidget {
Future<ListPayload<GitlabStarrer, int>> _query(BuildContext context, Future<ListPayload<GitlabStarrer, int>> _query(BuildContext context,
[int page = 1]) async { [int page = 1]) async {
final auth = Provider.of<AuthModel>(context); final res = await context
final res = .read<AuthModel>()
await auth.fetchGitlabWithPage('/projects/$id/starrers?page=$page'); .fetchGitlabWithPage('/projects/$id/starrers?page=$page');
return ListPayload( return ListPayload(
cursor: res.cursor, cursor: res.cursor,
hasMore: res.hasMore, hasMore: res.hasMore,

View File

@ -64,7 +64,7 @@ class GlTodosScreen extends StatelessWidget {
return RefreshStatefulScaffold<Iterable<GitlabTodo>>( return RefreshStatefulScaffold<Iterable<GitlabTodo>>(
title: Text('Todos'), title: Text('Todos'),
fetchData: () async { fetchData: () async {
final vs = await Provider.of<AuthModel>(context).fetchGitlab('/todos'); final vs = await context.read<AuthModel>().fetchGitlab('/todos');
return (vs as List).map((v) => GitlabTodo.fromJson(v)); return (vs as List).map((v) => GitlabTodo.fromJson(v));
}, },
bodyBuilder: (data, _) { bodyBuilder: (data, _) {

View File

@ -21,7 +21,7 @@ class GlUserScreen extends StatelessWidget {
return RefreshStatefulScaffold<Tuple2<GitlabUser, Iterable<GitlabProject>>>( return RefreshStatefulScaffold<Tuple2<GitlabUser, Iterable<GitlabProject>>>(
title: Text(isViewer ? 'Me' : 'User'), title: Text(isViewer ? 'Me' : 'User'),
fetchData: () async { fetchData: () async {
final auth = Provider.of<AuthModel>(context); final auth = context.read<AuthModel>();
final _id = id ?? auth.activeAccount.gitlabId; final _id = id ?? auth.activeAccount.gitlabId;
final res = await Future.wait([ final res = await Future.wait([
auth.fetchGitlab('/users/$_id'), auth.fetchGitlab('/users/$_id'),

View File

@ -14,8 +14,8 @@ class GtCommitsScreen extends StatelessWidget {
Future<ListPayload<GiteaCommit, int>> _query(BuildContext context, Future<ListPayload<GiteaCommit, int>> _query(BuildContext context,
[int page = 1]) async { [int page = 1]) async {
final auth = Provider.of<AuthModel>(context); final res = await context
final res = await auth .read<AuthModel>()
.fetchGiteaWithPage('/repos/$owner/$name/commits?page=$page&limit=20'); .fetchGiteaWithPage('/repos/$owner/$name/commits?page=$page&limit=20');
return ListPayload( return ListPayload(
cursor: res.cursor, cursor: res.cursor,

View File

@ -14,9 +14,8 @@ class GtIssuesScreen extends StatelessWidget {
Future<ListPayload<GiteaIssue, int>> _query(BuildContext context, Future<ListPayload<GiteaIssue, int>> _query(BuildContext context,
[int page = 1]) async { [int page = 1]) async {
final auth = Provider.of<AuthModel>(context);
final type = isPr ? 'pulls' : 'issues'; final type = isPr ? 'pulls' : 'issues';
final res = await auth.fetchGiteaWithPage( final res = await context.read<AuthModel>().fetchGiteaWithPage(
'/repos/$owner/$name/issues?state=open&page=$page&limit=20&type=$type'); '/repos/$owner/$name/issues?state=open&page=$page&limit=20&type=$type');
return ListPayload( return ListPayload(
cursor: res.cursor, cursor: res.cursor,

View File

@ -21,7 +21,8 @@ class GtObjectScreen extends StatelessWidget {
title: AppBarTitle(path ?? 'Files'), title: AppBarTitle(path ?? 'Files'),
fetchData: () async { fetchData: () async {
final suffix = path == null ? '' : '/$path'; final suffix = path == null ? '' : '/$path';
final res = await Provider.of<AuthModel>(context) final res = await context
.read<AuthModel>()
.fetchGitea('/repos/$owner/$name/contents$suffix'); .fetchGitea('/repos/$owner/$name/contents$suffix');
return res; return res;
}, },

View File

@ -19,7 +19,7 @@ class GtOrgScreen extends StatelessWidget {
return RefreshStatefulScaffold<Tuple2<GiteaOrg, List<GiteaRepository>>>( return RefreshStatefulScaffold<Tuple2<GiteaOrg, List<GiteaRepository>>>(
title: Text(login), title: Text(login),
fetchData: () async { fetchData: () async {
final auth = Provider.of<AuthModel>(context); final auth = context.read<AuthModel>();
final res = await Future.wait([ final res = await Future.wait([
auth.fetchGitea('/orgs/$login'), auth.fetchGitea('/orgs/$login'),
auth.fetchGitea('/orgs/$login/repos'), auth.fetchGitea('/orgs/$login/repos'),

View File

@ -10,8 +10,9 @@ class GtOrgsScreen extends StatelessWidget {
// final String branch; // TODO: // final String branch; // TODO:
Future<ListPayload<GiteaOrg, int>> _query(BuildContext context, Future<ListPayload<GiteaOrg, int>> _query(BuildContext context,
[int page = 1]) async { [int page = 1]) async {
final auth = Provider.of<AuthModel>(context); final res = await context
final res = await auth.fetchGiteaWithPage('/orgs?limit=20&page=$page'); .read<AuthModel>()
.fetchGiteaWithPage('/orgs?limit=20&page=$page');
// TODO: https://github.com/go-gitea/gitea/issues/10199 // TODO: https://github.com/go-gitea/gitea/issues/10199
return ListPayload( return ListPayload(
cursor: page + 1, cursor: page + 1,

View File

@ -23,7 +23,7 @@ class GtRepoScreen extends StatelessWidget {
return RefreshStatefulScaffold<Tuple2<GiteaRepository, String>>( return RefreshStatefulScaffold<Tuple2<GiteaRepository, String>>(
title: AppBarTitle('Repository'), title: AppBarTitle('Repository'),
fetchData: () async { fetchData: () async {
final auth = Provider.of<AuthModel>(context); final auth = context.read<AuthModel>();
final res = await Future.wait([ final res = await Future.wait([
auth.fetchGitea('/repos/$owner/$name'), auth.fetchGitea('/repos/$owner/$name'),
auth.fetchGitea('/repos/$owner/$name/contents/README.md'), auth.fetchGitea('/repos/$owner/$name/contents/README.md'),

View File

@ -21,7 +21,7 @@ class GtUserScreen extends StatelessWidget {
return RefreshStatefulScaffold<Tuple2<GiteaUser, List<GiteaRepository>>>( return RefreshStatefulScaffold<Tuple2<GiteaUser, List<GiteaRepository>>>(
title: Text(isViewer ? 'Me' : 'User'), title: Text(isViewer ? 'Me' : 'User'),
fetchData: () async { fetchData: () async {
final auth = Provider.of<AuthModel>(context); final auth = context.read<AuthModel>();
final res = await Future.wait([ final res = await Future.wait([
auth.fetchGitea(isViewer ? '/user' : '/users/$login'), auth.fetchGitea(isViewer ? '/user' : '/users/$login'),
auth.fetchGitea(isViewer ? '/user/repos' : '/users/$login/repos'), auth.fetchGitea(isViewer ? '/user/repos' : '/users/$login/repos'),

View File

@ -127,8 +127,9 @@ class _LoginScreenState extends State<LoginScreen> {
} }
void showError(err) { void showError(err) {
final theme = Provider.of<ThemeModel>(context); context
theme.showConfirm(context, Text('Something bad happens: $err')); .read<ThemeModel>()
.showConfirm(context, Text('Something bad happens: $err'));
} }
@override @override

View File

@ -44,7 +44,7 @@ class Avatar extends StatelessWidget {
return Link( return Link(
child: widget, child: widget,
onTap: () { onTap: () {
Provider.of<ThemeModel>(context).push(context, linkUrl); context.read<ThemeModel>().push(context, linkUrl);
}, },
); );
} }

View File

@ -41,7 +41,7 @@ class _GhEmojiActionState extends State<GhEmojiAction> {
var operation = isRemove ? 'remove' : 'add'; var operation = isRemove ? 'remove' : 'add';
try { try {
await Provider.of<AuthModel>(context).query(''' await context.read<AuthModel>().query('''
mutation { mutation {
${operation}Reaction(input: {subjectId: "$id", content: $emojiKey}) { ${operation}Reaction(input: {subjectId: "$id", content: $emojiKey}) {
clientMutationId clientMutationId
@ -53,8 +53,7 @@ mutation {
payload[emojiKey]['viewerHasReacted'] = !isRemove; payload[emojiKey]['viewerHasReacted'] = !isRemove;
}); });
} catch (e) { } catch (e) {
final theme = Provider.of<ThemeModel>(context); context.read<ThemeModel>().showWarning(context, e);
theme.showWarning(context, e);
} }
} }

View File

@ -29,6 +29,8 @@ class MarkdownView extends StatelessWidget {
return MarkdownBody( return MarkdownBody(
onTapLink: (url) { onTapLink: (url) {
final theme = context.read<ThemeModel>();
if (basePaths != null && if (basePaths != null &&
!url.startsWith('https://') && !url.startsWith('https://') &&
!url.startsWith('http://')) { !url.startsWith('http://')) {
@ -38,7 +40,7 @@ class MarkdownView extends StatelessWidget {
var y = path.join(x, url); var y = path.join(x, url);
if (y.startsWith('/')) y = y.substring(1); if (y.startsWith('/')) y = y.substring(1);
return Provider.of<ThemeModel>(context).push(context, return theme.push(context,
'/${basePaths[0]}/${basePaths[1]}/${basePaths[2]}?path=${y.urlencode}'); '/${basePaths[0]}/${basePaths[1]}/${basePaths[2]}?path=${y.urlencode}');
} }
@ -48,22 +50,22 @@ class MarkdownView extends StatelessWidget {
m = matchPattern(url, '/{owner}/{name}/pull/{number}'); m = matchPattern(url, '/{owner}/{name}/pull/{number}');
if (m != null) { if (m != null) {
return Provider.of<ThemeModel>(context).push(context, url); return theme.push(context, url);
} }
m = matchPattern(url, '/{owner}/{name}/issues/{number}'); m = matchPattern(url, '/{owner}/{name}/issues/{number}');
if (m != null) { if (m != null) {
return Provider.of<ThemeModel>(context).push(context, url); return theme.push(context, url);
} }
m = matchPattern(url, '/{owner}/{name}'); m = matchPattern(url, '/{owner}/{name}');
if (m != null) { if (m != null) {
return Provider.of<ThemeModel>(context).push(context, url); return theme.push(context, url);
} }
m = matchPattern(url, '/{login}'); m = matchPattern(url, '/{login}');
if (m != null) { if (m != null) {
return Provider.of<ThemeModel>(context).push(context, url); return theme.push(context, url);
} }
} }

View File

@ -83,7 +83,8 @@ class _NotificationItemState extends State<NotificationItem> {
loading = true; loading = true;
}); });
try { try {
await Provider.of<AuthModel>(context) await context
.read<AuthModel>()
.ghClient .ghClient
.activity .activity
.markThreadRead(payload.id); .markThreadRead(payload.id);

View File

@ -30,7 +30,7 @@ dependencies:
flutter_svg: ^0.19.0 flutter_svg: ^0.19.0
launch_review: ^2.0.0 launch_review: ^2.0.0
timeago: ^2.0.18 timeago: ^2.0.18
provider: ^3.2.0 provider: ^4.3.2
filesize: ^1.0.4 filesize: ^1.0.4
tuple: ^1.0.2 tuple: ^1.0.2
uri: ^0.11.3 uri: ^0.11.3