From 2c67b68512cc8deb2ecc110202bb2ede58c8001e Mon Sep 17 00:00:00 2001 From: vjrj Date: Wed, 27 Jun 2018 16:26:06 +0200 Subject: [PATCH] More redux and api work --- lib/firesApp.dart | 12 +++++-- lib/mainCommon.dart | 27 ++++++++++++--- lib/mainDev.dart | 11 +++++-- lib/mainProd.dart | 2 +- lib/models/firesApi.dart | 14 ++++++++ lib/redux/actions.dart | 2 ++ lib/redux/appActions.dart | 29 ++++++++++++++++ lib/redux/errorReducer.dart | 3 ++ lib/redux/fetchDataMiddleware.dart | 36 ++++++++++++++++++++ lib/redux/fireMapReducer.dart | 5 +++ lib/redux/loadedReducer.dart | 3 ++ lib/redux/loadingReducer.dart | 3 ++ lib/redux/reducers.dart | 22 +++++++++++++ lib/redux/userIdReducer.dart | 3 ++ lib/redux/userTokenReducer.dart | 3 ++ lib/redux/yourLocationActions.dart | 41 +++++++++++++++++++++++ lib/redux/yourLocationsReducer.dart | 51 +++++++++++++++++++++++++++++ 17 files changed, 256 insertions(+), 11 deletions(-) create mode 100644 lib/models/firesApi.dart create mode 100644 lib/redux/actions.dart create mode 100644 lib/redux/appActions.dart create mode 100644 lib/redux/errorReducer.dart create mode 100644 lib/redux/fetchDataMiddleware.dart create mode 100644 lib/redux/fireMapReducer.dart create mode 100644 lib/redux/loadedReducer.dart create mode 100644 lib/redux/loadingReducer.dart create mode 100644 lib/redux/reducers.dart create mode 100644 lib/redux/userIdReducer.dart create mode 100644 lib/redux/userTokenReducer.dart create mode 100644 lib/redux/yourLocationActions.dart create mode 100644 lib/redux/yourLocationsReducer.dart diff --git a/lib/firesApp.dart b/lib/firesApp.dart index e6eaac9..e514ff7 100644 --- a/lib/firesApp.dart +++ b/lib/firesApp.dart @@ -8,6 +8,9 @@ import 'homePage.dart'; import 'introPage.dart'; import 'sandbox.dart'; import 'theme.dart'; +import 'package:flutter_redux/flutter_redux.dart'; +import 'package:redux/redux.dart'; +import 'models/appState.dart'; class FiresApp extends StatelessWidget { static final WidgetBuilder introWidget = (context) => new IntroPage(); @@ -20,12 +23,15 @@ class FiresApp extends StatelessWidget { Sandbox.routeName: (BuildContext context) => new Sandbox(), }; + final Store store; + // globals.getIt.registerSingleton - FiresApp(); + FiresApp(this.store); @override Widget build(BuildContext context) { - return new MaterialApp( + return new StoreProvider(store: this.store, child: + new MaterialApp( localizationsDelegates: [ S.delegate, GlobalMaterialLocalizations.delegate, @@ -38,6 +44,6 @@ class FiresApp extends StatelessWidget { introWidget, continueWidget, 'showInitialWizard-2018-06-27-01'), onGenerateTitle: (context) => S.of(context).appName, theme: firesTheme, - routes: routes); + routes: routes)); } } diff --git a/lib/mainCommon.dart b/lib/mainCommon.dart index 0b6978e..0480087 100644 --- a/lib/mainCommon.dart +++ b/lib/mainCommon.dart @@ -2,27 +2,44 @@ import 'dart:async'; import 'package:comunes_flutter/comunes_flutter.dart'; import 'package:flutter/material.dart'; +import 'package:redux/redux.dart'; import 'firebaseMessagingConf.dart'; import 'firesApp.dart'; import 'globals.dart' as globals; +import 'models/appState.dart'; +import 'redux/reducers.dart'; import 'yourLocationPersist.dart'; +import 'models/firesApi.dart'; + +import 'package:get_it/get_it.dart'; Future> loadSecrets() async { return await SecretLoader(secretPath: 'assets/private-settings.json').load(); } -void mainCommon() { +void mainCommon(List> otherMiddleware) { + final store = new Store( + appStateReducer, + initialState: new AppState(), + middleware: otherMiddleware, + ); + + globals.getIt.registerSingleton(new FiresApi()); + loadSecrets().then((secrets) { globals.gmapKey = secrets['gmapKey']; globals.firesApiKey = secrets['firesApiKey']; globals.firesApiUrl = secrets['firesApiUrl'] + "api/v1/"; globals.prefs.then((prefs) { loadYourLocationsWithPrefs(prefs); - firebaseConfig(); + firebaseConfig(); - // Run baby run! - runApp(new FiresApp()); - }); + // Run baby run! + runApp(new FiresApp(store)); }); + }); + + // Listen to store changes, and re-render when the state is updated + // store.onChange.listen(render); } diff --git a/lib/mainDev.dart b/lib/mainDev.dart index caf3d04..c5c4ebc 100644 --- a/lib/mainDev.dart +++ b/lib/mainDev.dart @@ -1,7 +1,14 @@ +import 'package:redux_logging/redux_logging.dart'; + import 'globals.dart' as globals; import 'mainCommon.dart'; void main() { globals.isDevelopment = true; - mainCommon(); -} \ No newline at end of file + + List devMiddlewares = [ + new LoggingMiddleware(formatter: LoggingMiddleware.multiLineFormatter) + ]; + + mainCommon(devMiddlewares); +} diff --git a/lib/mainProd.dart b/lib/mainProd.dart index fdbd716..d9d5125 100644 --- a/lib/mainProd.dart +++ b/lib/mainProd.dart @@ -3,5 +3,5 @@ import 'mainCommon.dart'; void main() { globals.isDevelopment = false; - mainCommon(); + mainCommon([]); } \ No newline at end of file diff --git a/lib/models/firesApi.dart b/lib/models/firesApi.dart new file mode 100644 index 0000000..1662c4c --- /dev/null +++ b/lib/models/firesApi.dart @@ -0,0 +1,14 @@ +import 'yourLocation.dart'; +import 'dart:async'; +import 'package:jaguar_resty/jaguar_resty.dart' as resty; + +class FiresApi { + + Future createUser(String token) async { + + } + + Future> fetchYourLocations() async { + + } +} diff --git a/lib/redux/actions.dart b/lib/redux/actions.dart new file mode 100644 index 0000000..e6fc95b --- /dev/null +++ b/lib/redux/actions.dart @@ -0,0 +1,2 @@ +export 'appActions.dart'; +export 'yourLocationActions.dart'; \ No newline at end of file diff --git a/lib/redux/appActions.dart b/lib/redux/appActions.dart new file mode 100644 index 0000000..8db77da --- /dev/null +++ b/lib/redux/appActions.dart @@ -0,0 +1,29 @@ +import '../models/yourLocation.dart'; + +abstract class AppActions {} + +class FetchYourLocationsAction extends AppActions {} + +class FetchYourLocationsSucceededAction extends AppActions { + final List fetchedYourLocations; + + FetchYourLocationsSucceededAction(this.fetchedYourLocations); +} + +class FetchYourLocationsFailedAction extends AppActions { + final Exception error; + + FetchYourLocationsFailedAction(this.error); +} + +class OnUserTokenAction extends AppActions { + final String token; + + OnUserTokenAction(this.token); +} + +class OnUserCreatedAction extends AppActions { + final String userId; + + OnUserCreatedAction(this.userId); +} \ No newline at end of file diff --git a/lib/redux/errorReducer.dart b/lib/redux/errorReducer.dart new file mode 100644 index 0000000..a8403cb --- /dev/null +++ b/lib/redux/errorReducer.dart @@ -0,0 +1,3 @@ +String errorReducer(String error, action) { + return error; +} \ No newline at end of file diff --git a/lib/redux/fetchDataMiddleware.dart b/lib/redux/fetchDataMiddleware.dart new file mode 100644 index 0000000..a0afc0b --- /dev/null +++ b/lib/redux/fetchDataMiddleware.dart @@ -0,0 +1,36 @@ +import 'package:redux/redux.dart'; +import 'actions.dart'; +import '../models/yourLocation.dart'; +import '../models/appState.dart'; +import '../globals.dart' as globals; +import '../models/firesApi.dart'; + +// A middleware takes in 3 parameters: your Store, which you can use to +// read state or dispatch new actions, the action that was dispatched, +// and a `next` function. The first two you know about, and the `next` +// function is responsible for sending the action to your Reducer, or +// the next Middleware if you provide more than one. +// +// Middleware do not return any values themselves. They simply forward +// actions on to the Reducer or swallow actions in some special cases. +void fetchYourLocationsMiddleware(Store store, action, NextDispatcher next) { + // If our Middleware encounters a `FetchYourLocationAction` + if (action is FetchYourLocationsAction) { + + final api = globals.getIt.get(); + + // Use the api to fetch the YourLocations + api.fetchYourLocations().then((List YourLocations) { + // If it succeeds, dispatch a success action with the YourLocations. + // Our reducer will then update the State using these YourLocations. + store.dispatch(new FetchYourLocationsSucceededAction(YourLocations)); + }).catchError((Exception error) { + // If it fails, dispatch a failure action. The reducer will + // update the state with the error. + store.dispatch(new FetchYourLocationsFailedAction(error)); + }); + } + + // Make sure our actions continue on to the reducer. + next(action); +} \ No newline at end of file diff --git a/lib/redux/fireMapReducer.dart b/lib/redux/fireMapReducer.dart new file mode 100644 index 0000000..b2119bb --- /dev/null +++ b/lib/redux/fireMapReducer.dart @@ -0,0 +1,5 @@ +import '../models/fireMapState.dart'; + +FireMapState fireMapReducer(FireMapState state, action) { + return state; +} \ No newline at end of file diff --git a/lib/redux/loadedReducer.dart b/lib/redux/loadedReducer.dart new file mode 100644 index 0000000..80e5026 --- /dev/null +++ b/lib/redux/loadedReducer.dart @@ -0,0 +1,3 @@ +bool loadedReducer(isLoaded, action) { + return isLoaded; +} \ No newline at end of file diff --git a/lib/redux/loadingReducer.dart b/lib/redux/loadingReducer.dart new file mode 100644 index 0000000..a5b7e16 --- /dev/null +++ b/lib/redux/loadingReducer.dart @@ -0,0 +1,3 @@ +bool loadingReducer(isLoading, action) { + return isLoading; +} \ No newline at end of file diff --git a/lib/redux/reducers.dart b/lib/redux/reducers.dart new file mode 100644 index 0000000..74bd530 --- /dev/null +++ b/lib/redux/reducers.dart @@ -0,0 +1,22 @@ +import '../models/appState.dart'; +import 'yourLocationsReducer.dart'; +import 'loadedReducer.dart'; +import 'loadingReducer.dart'; +import 'errorReducer.dart'; +import 'userIdReducer.dart'; +import 'userTokenReducer.dart'; +import 'fireMapReducer.dart'; + +// We create the State reducer by combining many smaller reducers into one! +AppState appStateReducer(AppState state, action) { + + return AppState( + yourLocations: yourLocationsReducer(state.yourLocations, action), + userId: userReducer(state.userId, action), + token: userTokenReducer(state.token, action), + isLoading: loadingReducer(state.isLoading, action), + isLoaded: loadedReducer(state.isLoaded, action), + error: errorReducer(state.error, action), + fireMapState: fireMapReducer(state.fireMapState, action) + ); +} diff --git a/lib/redux/userIdReducer.dart b/lib/redux/userIdReducer.dart new file mode 100644 index 0000000..3108d0d --- /dev/null +++ b/lib/redux/userIdReducer.dart @@ -0,0 +1,3 @@ +String userReducer(String userId, action) { + return userId; +} \ No newline at end of file diff --git a/lib/redux/userTokenReducer.dart b/lib/redux/userTokenReducer.dart new file mode 100644 index 0000000..5aee7c3 --- /dev/null +++ b/lib/redux/userTokenReducer.dart @@ -0,0 +1,3 @@ +String userTokenReducer(String userToken, action) { + return userToken; +} \ No newline at end of file diff --git a/lib/redux/yourLocationActions.dart b/lib/redux/yourLocationActions.dart new file mode 100644 index 0000000..1af9878 --- /dev/null +++ b/lib/redux/yourLocationActions.dart @@ -0,0 +1,41 @@ +import 'package:bson_objectid/bson_objectid.dart'; + +import '../models/yourLocation.dart'; + +abstract class YourLocationActions {} + +class AddYourLocationAction extends YourLocationActions { + YourLocation loc; + + AddYourLocationAction(this.loc); +} + +class DeleteYourLocationAction extends YourLocationActions { + ObjectId id; + DeleteYourLocationAction(this.id); +} + +class UpdateYourLocationAction extends YourLocationActions { + ObjectId id; + YourLocation loc; + + UpdateYourLocationAction(this.id, this.loc); +} + +class ToggleSubscriptionAction extends YourLocationActions { + ObjectId id; + + ToggleSubscriptionAction(this.id); +} + +class SubscribeAction extends YourLocationActions { + ObjectId id; + + SubscribeAction(this.id); +} + +class UnSubscribeAction extends YourLocationActions { + ObjectId id; + + UnSubscribeAction(this.id); +} diff --git a/lib/redux/yourLocationsReducer.dart b/lib/redux/yourLocationsReducer.dart new file mode 100644 index 0000000..1dfe505 --- /dev/null +++ b/lib/redux/yourLocationsReducer.dart @@ -0,0 +1,51 @@ +import 'package:redux/redux.dart'; + +import '../models/yourLocation.dart'; +import 'actions.dart'; + +final yourLocationsReducer = combineReducers>([ + new TypedReducer, AddYourLocationAction>(_addYourLocation), + new TypedReducer, DeleteYourLocationAction>( + _deleteYourLocation), + new TypedReducer, UpdateYourLocationAction>( + _updateYourLocation), + + /* new TypedReducer, ToggleSubscriptionAction>(_toggleSubscriptionAction), + new TypedReducer, SubscribeAction>(_setLoadedYourLocations), + new TypedReducer, UnSubscribeAction>(_setNoYourLocations), */ +]); + +List _addYourLocation( + List yourLocations, AddYourLocationAction action) { + return new List.from(yourLocations)..add(action.loc); +} + +List _deleteYourLocation( + List yourLocations, DeleteYourLocationAction action) { + return yourLocations + .where((yourLocation) => yourLocation.id != action.id) + .toList(); +} + +List _updateYourLocation( + List yourLocations, UpdateYourLocationAction action) { + return yourLocations + .map((yourLocation) => + yourLocation.id == action.id ? action.loc : yourLocation) + .toList(); +} +/* +List _toggleSubscriptionAction(List yourLocations, UpdateYourLocationAction action) { + return yourLocations + .map((yourLocation) => yourLocation.id == action.id ? action.loc : yourLocation) + .toList(); +} + +List _setLoadedYourLocations(List yourLocations, YourLocationsLoadedAction action) { + return action.yourLocations; +} + +List _setNoYourLocations(List yourLocations, YourLocationsNotLoadedAction action) { + return []; +} +*/