forked from davidpanic/graphql-flutter
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
updated deps added extended bloc example with fetchMore and refetch
- Loading branch information
1 parent
4b71898
commit a924eb2
Showing
14 changed files
with
573 additions
and
170 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,146 @@ | ||
import 'package:flutter/material.dart'; | ||
import 'package:flutter_bloc/flutter_bloc.dart'; | ||
|
||
import 'blocs/repos/events.dart'; | ||
import 'blocs/repos/models.dart'; | ||
import 'blocs/repos/my_repos_bloc.dart'; | ||
import 'blocs/repos/states.dart'; | ||
|
||
class BlocPage extends StatefulWidget { | ||
@override | ||
_BlocPageState createState() => _BlocPageState(); | ||
} | ||
|
||
class _BlocPageState extends State<BlocPage> { | ||
@override | ||
void initState() { | ||
super.initState(); | ||
final bloc = BlocProvider.of<MyGithubReposBloc>(context); | ||
bloc.add(LoadMyRepos(numOfReposToLoad: 50)); | ||
} | ||
|
||
@override | ||
Widget build(BuildContext context) { | ||
return Scaffold( | ||
appBar: AppBar( | ||
title: Text("Flutter Bloc GraphQL Example"), | ||
), | ||
body: Container( | ||
padding: const EdgeInsets.symmetric(horizontal: 8.0), | ||
child: Column( | ||
mainAxisAlignment: MainAxisAlignment.start, | ||
mainAxisSize: MainAxisSize.max, | ||
children: <Widget>[ | ||
TextField( | ||
decoration: const InputDecoration( | ||
labelText: 'Number of repositories (default 50)', | ||
), | ||
keyboardType: TextInputType.number, | ||
textAlign: TextAlign.center, | ||
onChanged: (String n) { | ||
final reposBloc = BlocProvider.of<MyGithubReposBloc>(context); | ||
reposBloc | ||
.add(LoadMyRepos(numOfReposToLoad: int.parse(n) ?? 50)); | ||
}, | ||
), | ||
SizedBox( | ||
height: 10, | ||
), | ||
new LoadRepositories( | ||
bloc: BlocProvider.of<MyGithubReposBloc>(context), | ||
) | ||
], | ||
), | ||
), | ||
); | ||
} | ||
} | ||
|
||
class LoadRepositories extends StatelessWidget { | ||
final MyGithubReposBloc bloc; | ||
|
||
const LoadRepositories({Key key, this.bloc}) : super(key: key); | ||
|
||
@override | ||
Widget build(BuildContext context) { | ||
return BlocBuilder<MyGithubReposBloc, MyGithubReposState>( | ||
bloc: bloc, | ||
builder: (BuildContext context, MyGithubReposState state) { | ||
if (state is ReposLoading) { | ||
return Expanded( | ||
child: Container( | ||
child: Center( | ||
child: CircularProgressIndicator( | ||
semanticsLabel: "Loading ...", | ||
), | ||
), | ||
), | ||
); | ||
} | ||
|
||
if (state is ReposNotLoaded) { | ||
return Text("${state.errors}"); | ||
} | ||
|
||
if (state is ReposLoaded) { | ||
final List<Repo> repositories = state.results; | ||
|
||
return Expanded( | ||
child: ListView.builder( | ||
itemCount: state.results.length, | ||
itemBuilder: (BuildContext context, int index) => | ||
StarrableRepository( | ||
repository: repositories[index], | ||
reposBloc: bloc, | ||
), | ||
), | ||
); | ||
} | ||
|
||
return Text(null); | ||
}, | ||
); | ||
} | ||
} | ||
|
||
class StarrableRepository extends StatelessWidget { | ||
const StarrableRepository({ | ||
Key key, | ||
@required this.repository, | ||
@required this.reposBloc, | ||
}) : assert(reposBloc != null), | ||
assert(repository != null), | ||
super(key: key); | ||
|
||
final Repo repository; | ||
final MyGithubReposBloc reposBloc; | ||
|
||
@override | ||
Widget build(BuildContext context) { | ||
return ListTile( | ||
leading: _isRepoStarred(), | ||
trailing: _showLoadingIndicator(), | ||
title: Text(repository.name), | ||
onTap: () { | ||
reposBloc.add(MutateToggleStar(repo: repository)); | ||
}, | ||
); | ||
} | ||
|
||
Widget _showLoadingIndicator() { | ||
if (repository.isLoading) | ||
return CircularProgressIndicator(); | ||
else | ||
return null; | ||
} | ||
|
||
Widget _isRepoStarred() { | ||
if (repository.viewerHasStarred) | ||
return Icon( | ||
Icons.star, | ||
color: Colors.amber, | ||
); | ||
else | ||
return Icon(Icons.star_border); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
import 'dart:async'; | ||
import 'package:bloc/bloc.dart'; | ||
import 'package:graphql/client.dart'; | ||
import 'package:meta/meta.dart'; | ||
import 'package:graphql/internal.dart'; | ||
|
||
import 'event.dart'; | ||
import 'state.dart'; | ||
|
||
abstract class GraphqlBloc<T> extends Bloc<GraphqlEvent<T>, GraphqlState<T>> { | ||
GraphQLClient client; | ||
ObservableQuery result; | ||
WatchQueryOptions options; | ||
|
||
GraphqlBloc({this.client, @required this.options}) { | ||
result = client.watchQuery(options); | ||
|
||
result.stream.listen((QueryResult result) { | ||
if (!result.loading && result.data != null) { | ||
add( | ||
GraphqlLoadedEvent<T>( | ||
data: parseData(result.data as Map<String, dynamic>), | ||
result: result, | ||
), | ||
); | ||
} | ||
|
||
if (result.hasException) { | ||
add(GraphqlErrorEvent(error: result.exception, result: result)); | ||
} | ||
}); | ||
|
||
_runQuery(); | ||
} | ||
|
||
void dispose() { | ||
result.close(); | ||
} | ||
|
||
T parseData(Map<String, dynamic> data); | ||
|
||
Future<void> _runQuery() async { | ||
result.fetchResults(); | ||
} | ||
|
||
void _fetchMore(FetchMoreOptions options) { | ||
result.fetchMore(options); | ||
} | ||
|
||
void _refetch() => result.refetch(); | ||
|
||
@override | ||
GraphqlState<T> get initialState => GraphqlLoading<T>(); | ||
|
||
@override | ||
Stream<GraphqlState<T>> mapEventToState(GraphqlEvent<T> event) async* { | ||
if (event is GraphqlLoadedEvent<T>) { | ||
yield GraphqlLoaded<T>(data: event.data, result: event.result); | ||
} | ||
|
||
if (event is GraphqlErrorEvent<T>) { | ||
yield GraphqlErrorState<T>(error: event.error, result: event.result); | ||
} | ||
|
||
if (event is GraphqlRefetchEvent<T>) { | ||
yield GraphqlRefetchState<T>(data: state.data, result: null); | ||
_refetch(); | ||
} | ||
|
||
if (state is GraphqlLoaded && event is GraphqlFetchMoreEvent<T>) { | ||
yield GraphqlFetchMoreState<T>(data: state.data, result: null); | ||
_fetchMore(event.options); | ||
} | ||
} | ||
} |
26 changes: 26 additions & 0 deletions
26
examples/flutter_bloc/lib/extended-bloc/graphql/event.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import 'package:graphql/client.dart'; | ||
import 'package:meta/meta.dart'; | ||
|
||
abstract class GraphqlEvent<T> {} | ||
|
||
class GraphqlErrorEvent<T> extends GraphqlEvent<T> { | ||
final OperationException error; | ||
final QueryResult result; | ||
|
||
GraphqlErrorEvent({@required this.error, @required this.result}); | ||
} | ||
|
||
class GraphqlLoadedEvent<T> extends GraphqlEvent<T> { | ||
final T data; | ||
final QueryResult result; | ||
|
||
GraphqlLoadedEvent({@required this.data, @required this.result}); | ||
} | ||
|
||
class GraphqlRefetchEvent<T> extends GraphqlEvent<T> {} | ||
|
||
class GraphqlFetchMoreEvent<T> extends GraphqlEvent<T> { | ||
final FetchMoreOptions options; | ||
|
||
GraphqlFetchMoreEvent({@required this.options}); | ||
} |
Oops, something went wrong.