-
-
Notifications
You must be signed in to change notification settings - Fork 220
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
OnLoading Boilerplate #31
Comments
@o1298098 many thanks ! |
@o1298098 do you think I should use the same strategy to subscribe to a stream subscription like GraphQL subscriptions ? pls, see that it's possible with pure Dart or with a Flutter lib (examples)[https://github.com/dmh2000/Flutter-GraphqlX] . What strategy you would use for graphql + fish ? in fact, let me share an amazing framework for fast development with graphql: hasura.io In fact, I noticed that you almost didn't choose to use FutureBuilder, even that it's a quite less boilerplate, so let me ask you why ? :) Flutter-Movie git/master~19* 2262s
❯ grep -rni futurebuilder ./lib
./lib/views/start_page/view.dart:58: body: FutureBuilder(
./lib/customwidgets/share_card.dart:119: return FutureBuilder<Widget>(
./lib/customwidgets/medialist_card.dart:228: child: FutureBuilder<UserListModel>(
./lib/customwidgets/searchbar_delegate.dart:62: return FutureBuilder<SearchResultModel>(
./lib/customwidgets/searchbar_delegate.dart:95: return FutureBuilder<List<String>>(
./lib/customwidgets/searchbar_delegate.dart:185: return FutureBuilder<SearchResultModel>(
|
Yes, you should, GraphQL Engine is an amazing project. GraphQL is more flexible in obtaining data and is a good choice for mobile applications. I also plan to use GraphQL in new projects. |
@o1298098 great tip! thanks :) To update the language, I noticed that you started to write a ./lib/style/themestyle_widget.dart , but in fact, it's not connected to the main code. I am trying to implement the automatically language reload using a Locale in GlobalState and calling
As described in the i18n plugin. It's in the reducer, but maybe because the Locale state is outside, it doesn't refresh as in this application. Do we have a way to refresh the context for ALL application, in a way that the Language could be updated dynamically during the runtime ? (it works only for the screen painted with the language selector) |
Already solved, I was lacking the
In the router visitor to propagate the global state.... In fact, I think it's a glue, it should be an intrinsic part of the framework..... |
I have tried this before, but it didn't work as expected. |
Instead of 'Future createApp() async {' in the app.dart file, try to create a Statefull Widget (it's also better for refreshing, as I wrote you before). import 'package:diga1/config/themes.dart'; [0/327]
import 'package:diga1/helpers/persistor.dart';
import 'package:diga1/global/store.dart';
/// Main application
class App extends StatefulWidget {
App({Key key}) : super(key: key);
@override
_AppState createState() => _AppState();
}
class _AppState extends State<App> {
// see https://api.flutter.dev/flutter/material/MaterialApp-class.html for more info
// home_page is configured in Router to be the landing page, and we use it when
// building the MaterialApp widget, in 'home' property.
final AbstractRoutes routes = Routes.routes;
/// Initialize secure persistance with a signleton for a future use
/// ```dart
/// Persistor.write('jwt_token', 'my_token');
/// Persistor.read('jwt_token').then((t) => print(t));
/// ```
/// Main Application Initialization
/// There are two reasons why you need to wrap MaterialApp
/// Because this ensures that toast can be displayed in front of all other controls
/// Context can be cached so that it can be invoked anywhere without passing in context
final i18n = I18n.delegate;
/// Dynamically change the language and instantly show the new language
/// see [i18-plugin](https://github.com/esskar/vscode-flutter-i18n-json)
@override
void initState() {
Persistor.getInstance();
I18n.onLocaleChanged = onLocaleChange;
super.initState();
}
void onLocaleChange(Locale locale) {
setState(() {
I18n.locale = locale;
});
}
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Diga1',
localizationsDelegates: [
i18n,
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
],
supportedLocales: i18n.supportedLocales,
localeResolutionCallback: i18n.resolution(fallback: new Locale("en", "US")),
debugShowCheckedModeBanner: true,
theme: Themes.lightTheme,
// we send a Map<String, dynamic> arguments to initialize the State
// e.g. home: routes.buildPage('home_page', {'name': 'john', 'age': 32}),
home: routes.buildPage('start_page', {'name': 'Diga1'}),
onGenerateRoute: (RouteSettings settings) {
return MaterialPageRoute<Object>(builder: (BuildContext context) {
return routes.buildPage(settings.name, settings.arguments);
});
},
);
}
} on the Global Store, first we update the Locale in the onLocaleChanged callback, and afterwards we send the cloned state with a new locale only to propagate. GlobalState _onChangeLocale(GlobalState state, Action action) {
final Locale locale = action.payload;
I18n.onLocaleChanged(locale);
return state.clone()..locale = locale;
} Notice that in fact, the locale 'lives' in the i18n.dart file, but we propagate it also from the global, so it will trigger a global refresh. page.connectExtraStore<GlobalState>(GlobalStore.store,
(Object pagestate, GlobalState appState) {
final GlobalBaseState p = pagestate;
//print(appState.user?.toJson());
if (p.locale != appState.locale) {
if (pagestate is Cloneable) {
final Object copy = pagestate.clone();
final GlobalBaseState newState = copy;
newState.locale = appState.locale;
return newState;
}
}
if (p.user != appState.user) {
if (pagestate is Cloneable) {
final Object copy = pagestate.clone();
final GlobalBaseState newState = copy;
newState.user = appState.user;
return newState;
}
}
return pagestate;
});
}
} and also on the state of the views you want to 'refresh' class LoginState implements GlobalBaseState, Cloneable<LoginState> {
// LOGIN form
String emailAddress;
String password;
TextEditingController emailTextController;
TextEditingController passwordTextController;
// FORGOT PASSWORD Form
String emailReset;
TextEditingController forgotTextController;
// for the globalbasestate
@override
Locale locale;
@override
User user;
@override
LoginState clone() {
return LoginState()
..emailTextController = emailTextController
..passwordTextController = passwordTextController
..forgotTextController = forgotTextController
..user = user;
}
}
LoginState initState(Map<String, dynamic> args) {
return LoginState();
} |
thanks @henry-hz, it work😄 |
@henry-hz, I created a GraphQL Api for this project, and now I can get data by subscription. I plan to replace some widgets with StreamBuilder. |
@o1298098 hey, that's good news, very powerful real-time, without touching the web-socket 101 upgrade... : ) |
@henry-hz, GraphQLPlayground |
|
Hi @o1298098 ,
I thought that maybe, instead of using the i.e.
and creating all the boilerplate (reducer, action, dispatch),
why not refactor and use the FutureBuilder instead, checking if the request is done (not null) ?
I tried to write a POC with this simpler approach, but the view was not automatically rendered...
so I would like to ask you if refactoring with FutueBuilder is possible, and if not, why fish-redux does not support it ?
thanks for sharing your amazing app!
Henry
The text was updated successfully, but these errors were encountered: