Skip to content

Commit

Permalink
fix query variable change,
Browse files Browse the repository at this point in the history
add variable input to example
(add gpg)
  • Loading branch information
micimize committed Oct 4, 2018
1 parent ba05ee9 commit dca7b85
Show file tree
Hide file tree
Showing 6 changed files with 149 additions and 121 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
.vs/
.vscode/
.idea/libraries/
.idea/workspace.xml
.idea/tasks.xml
Expand Down
192 changes: 113 additions & 79 deletions example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import 'package:graphql_flutter/graphql_flutter.dart';
import './mutations/addStar.dart' as mutations;
import './queries/readRepositories.dart' as queries;

const String YOUR_PERSONAL_ACCESS_TOKEN = '<YOUR_PERSONAL_ACCESS_TOKEN_HERE>';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
Expand All @@ -13,7 +15,7 @@ class MyApp extends StatelessWidget {
final HttpLink link = HttpLink(
uri: 'https://api.github.com/graphql',
headers: <String, String>{
'Authorization': 'Bearer <YOUR_PERSONAL_ACCESS_TOKEN>',
'Authorization': 'Bearer $YOUR_PERSONAL_ACCESS_TOKEN',
},
);

Expand Down Expand Up @@ -52,94 +54,126 @@ class MyHomePage extends StatefulWidget {
}

class _MyHomePageState extends State<MyHomePage> {
int numberOfRepos = 50;

void changeQuery(String number) {
setState(() {
numberOfRepos = int.parse(number) ?? 50;
});
}

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Query(
options: QueryOptions(
document: queries.readRepositories,
pollInterval: 4,
// you can optionally override some http options through the contexts
//
context: <String, dynamic>{
'headers': <String, String>{
'Authorization': 'Bearer <YOUR_PERSONAL_ACCESS_TOKEN>',
},
},
),
builder: (QueryResult result) {
if (result.loading) {
return const CircularProgressIndicator();
}

if (result.hasErrors) {
return Text(result.errors.toString());
}

// result.data can be either a [List<dynamic>] or a [Map<String, dynamic>]
final List<dynamic> repositories =
result.data['viewer']['repositories']['nodes'];

return ListView.builder(
itemCount: repositories.length,
itemBuilder: (BuildContext context, int index) {
final Map<String, dynamic> repository = repositories[index];

return Mutation(
options: MutationOptions(
document: mutations.addStar,
),
builder: (
RunMutation addStar,
QueryResult addStarResult,
) {
if (addStarResult.data != null &&
addStarResult.data.isNotEmpty) {
repository['viewerHasStarred'] = addStarResult
.data['addStar']['starrable']['viewerHasStarred'];
}

return ListTile(
leading: repository['viewerHasStarred']
? const Icon(
Icons.star,
color: Colors.amber,
)
: const Icon(Icons.star_border),
title: Text(repository['name']),
onTap: () {
// optimistic ui updates are not implemented yet, therefore changes may take some time to show
addStar(<String, dynamic>{
'starrableId': repository['id'],
});
},
);
body: Container(
padding: const EdgeInsets.fromLTRB(8.0, 0.0, 8.0, 0.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
mainAxisSize: MainAxisSize.max,
children: <Widget>[
TextField(
decoration: const InputDecoration(
labelText: 'Number of repos (default 50)',
),
keyboardType: TextInputType.number,
onSubmitted: changeQuery,
),
Query(
options: QueryOptions(
document: queries.readRepositories,
variables: <String, dynamic>{'numberOfRepos': numberOfRepos},
pollInterval: 4,
// you can optionally override some http options through the contexts
//
context: <String, dynamic>{
'headers': <String, String>{
'Authorization': 'Bearer $YOUR_PERSONAL_ACCESS_TOKEN',
},
},
onCompleted: (QueryResult onCompleteResult) {
showDialog<AlertDialog>(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: const Text('Thanks for your star!'),
actions: <Widget>[
SimpleDialogOption(
child: const Text('Dismiss'),
onPressed: () {
Navigator.of(context).pop();
),
builder: (QueryResult result) {
if (result.loading) {
return Container(
padding: const EdgeInsets.all(8.0),
child: const CircularProgressIndicator(),
);
}

if (result.hasErrors) {
return Text('\nErrors: \n ' + result.errors.join(',\n '));
}

// result.data can be either a [List<dynamic>] or a [Map<String, dynamic>]
final List<dynamic> repositories =
result.data['viewer']['repositories']['nodes'];

return Expanded(
child: ListView.builder(
itemCount: repositories.length,
itemBuilder: (BuildContext context, int index) {
final Map<String, dynamic> repository =
repositories[index];

return Mutation(
options: MutationOptions(
document: mutations.addStar,
),
builder: (
RunMutation addStar,
QueryResult addStarResult,
) {
if (addStarResult.data != null &&
addStarResult.data.isNotEmpty) {
repository['viewerHasStarred'] =
addStarResult.data['addStar']['starrable']
['viewerHasStarred'];
}

return ListTile(
leading: repository['viewerHasStarred']
? const Icon(
Icons.star,
color: Colors.amber,
)
: const Icon(Icons.star_border),
title: Text(repository['name']),
onTap: () {
// optimistic ui updates are not implemented yet, therefore changes may take some time to show
addStar(<String, dynamic>{
'starrableId': repository['id'],
});
},
)
],
);
},
onCompleted: (QueryResult onCompleteResult) {
showDialog<AlertDialog>(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: const Text('Thanks for your star!'),
actions: <Widget>[
SimpleDialogOption(
child: const Text('Dismiss'),
onPressed: () {
Navigator.of(context).pop();
},
)
],
);
},
);
},
);
},
);
},
);
},
);
},
),
);
},
),
],
),
),
);
}
Expand Down
5 changes: 2 additions & 3 deletions example/lib/mutations/addStar.dart
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
final String addStar = '''
const String addStar = '''
mutation AddStar(\$starrableId: ID!) {
addStar(input: {starrableId: \$starrableId}) {
starrable {
viewerHasStarred
}
}
}
'''
.replaceAll('\n', ' ');
''';
9 changes: 4 additions & 5 deletions example/lib/queries/readRepositories.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
final String readRepositories = '''
query ReadRepositories {
const String readRepositories = '''
query ReadRepositories(\$numberOfRepos: Int!) {
viewer {
repositories(last: 50) {
repositories(last: \$numberOfRepos) {
nodes {
id
name
Expand All @@ -10,5 +10,4 @@ final String readRepositories = '''
}
}
}
'''
.replaceAll('\n', ' ');
''';
6 changes: 1 addition & 5 deletions lib/src/core/query_options.dart
Original file line number Diff line number Diff line change
Expand Up @@ -154,11 +154,7 @@ class WatchQueryOptions extends QueryOptions {
return false;
}

if (a == null && b != null) {
return true;
}

if (a != null && b == null) {
if (a == null || b == null) {
return true;
}

Expand Down
57 changes: 28 additions & 29 deletions lib/src/widgets/query.dart
Original file line number Diff line number Diff line change
Expand Up @@ -26,34 +26,16 @@ class Query extends StatefulWidget {
}

class QueryState extends State<Query> {
GraphQLClient client;
ObservableQuery observableQuery;

@override
void initState() {
super.initState();
}

@override
void dispose() {
observableQuery?.close();
super.dispose();
}

@override
void didChangeDependencies() async {
/// Gets the client from the closest wrapping [GraphQLProvider].
client = GraphQLProvider.of(context).value;
assert(client != null);

// override the default [QueryOptions] fetchPolicy.
WatchQueryOptions get _options {
FetchPolicy fetchPolicy = widget.options.fetchPolicy;

if (fetchPolicy == FetchPolicy.cacheFirst) {
fetchPolicy = FetchPolicy.cacheAndNetwork;
}

final WatchQueryOptions options = WatchQueryOptions(
return WatchQueryOptions(
document: widget.options.document,
variables: widget.options.variables,
fetchPolicy: fetchPolicy,
Expand All @@ -62,22 +44,39 @@ class QueryState extends State<Query> {
fetchResults: true,
context: widget.options.context,
);
}

void query(WatchQueryOptions options) {
final GraphQLClient client = GraphQLProvider.of(context).value;
assert(client != null);
observableQuery = client.watchQuery(options);
}

bool shouldCreateNewObservable = true;
@override
void didChangeDependencies() {
super.didChangeDependencies();
query(_options);
}

if (observableQuery != null) {
if (observableQuery.options.areEqualTo(options)) {
shouldCreateNewObservable = false;
}
@override
void didUpdateWidget(Query oldWidget) {
super.didUpdateWidget(oldWidget);

await observableQuery.close();
}
final WatchQueryOptions newOptions = _options;

final bool shouldCreateNewObservable =
!observableQuery.options.areEqualTo(newOptions);

if (shouldCreateNewObservable) {
observableQuery = client.watchQuery(options);
observableQuery?.close();
query(newOptions);
}
}

super.didChangeDependencies();
@override
void dispose() {
observableQuery?.close();
super.dispose();
}

@override
Expand Down

0 comments on commit dca7b85

Please sign in to comment.