Refactor
This commit is contained in:
parent
66cdde323d
commit
89cf484f67
|
|
@ -53,7 +53,7 @@ class PersistenceRepository {
|
||||||
|
|
||||||
|
|
||||||
Future<FileSystemEntity> delete() async {
|
Future<FileSystemEntity> delete() async {
|
||||||
return await fileStorage.delete();
|
return await fileStorage.exisits().then((exists) => exists ? fileStorage.delete() : null);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<bool> exists() async {
|
Future<bool> exists() async {
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import 'package:invoiceninja/redux/app/app_middleware.dart';
|
||||||
import 'package:invoiceninja/redux/client/client_actions.dart';
|
import 'package:invoiceninja/redux/client/client_actions.dart';
|
||||||
import 'package:invoiceninja/redux/client/client_middleware.dart';
|
import 'package:invoiceninja/redux/client/client_middleware.dart';
|
||||||
import 'package:invoiceninja/redux/invoice/invoice_actions.dart';
|
import 'package:invoiceninja/redux/invoice/invoice_actions.dart';
|
||||||
|
import 'package:invoiceninja/ui/auth/init_screen.dart';
|
||||||
import 'package:invoiceninja/ui/client/client_screen.dart';
|
import 'package:invoiceninja/ui/client/client_screen.dart';
|
||||||
import 'package:invoiceninja/ui/client/edit/client_edit_vm.dart';
|
import 'package:invoiceninja/ui/client/edit/client_edit_vm.dart';
|
||||||
import 'package:invoiceninja/ui/client/view/client_view_vm.dart';
|
import 'package:invoiceninja/ui/client/view/client_view_vm.dart';
|
||||||
|
|
@ -88,10 +89,13 @@ class _InvoiceNinjaAppState extends State<InvoiceNinjaApp> {
|
||||||
|
|
||||||
title: 'Invoice Ninja',
|
title: 'Invoice Ninja',
|
||||||
routes: {
|
routes: {
|
||||||
LoginVM.route: (context) {
|
InitScreen.route: (context) {
|
||||||
widget.store.dispatch(LoadStateRequest(context));
|
widget.store.dispatch(LoadStateRequest(context));
|
||||||
//widget.store.dispatch(LoadUserLogin());
|
//widget.store.dispatch(LoadUserLogin());
|
||||||
return LoginVM();
|
return InitScreen();
|
||||||
|
},
|
||||||
|
LoginScreen.route: (context) {
|
||||||
|
return LoginScreen();
|
||||||
},
|
},
|
||||||
DashboardScreen.route: (context) {
|
DashboardScreen.route: (context) {
|
||||||
widget.store.dispatch(LoadDashboardAction());
|
widget.store.dispatch(LoadDashboardAction());
|
||||||
|
|
|
||||||
|
|
@ -140,7 +140,7 @@ Middleware<AppState> _createLoadState(
|
||||||
..companyState4.replace(company4State)
|
..companyState4.replace(company4State)
|
||||||
..companyState5.replace(company5State));
|
..companyState5.replace(company5State));
|
||||||
store.dispatch(LoadStateSuccess(appState));
|
store.dispatch(LoadStateSuccess(appState));
|
||||||
if (uiState.currentRoute != LoginVM.route &&
|
if (uiState.currentRoute != LoginScreen.route &&
|
||||||
authState.url.isNotEmpty) {
|
authState.url.isNotEmpty) {
|
||||||
NavigatorState navigator = Navigator.of(action.context);
|
NavigatorState navigator = Navigator.of(action.context);
|
||||||
bool isFirst = true;
|
bool isFirst = true;
|
||||||
|
|
@ -153,18 +153,18 @@ Middleware<AppState> _createLoadState(
|
||||||
isFirst = false;
|
isFirst = false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}).catchError((error) => _handleError(store, error));
|
}).catchError((error) => _handleError(store, error, action.context));
|
||||||
}).catchError((error) => _handleError(store, error));
|
}).catchError((error) => _handleError(store, error, action.context));
|
||||||
}).catchError((error) => _handleError(store, error));
|
}).catchError((error) => _handleError(store, error, action.context));
|
||||||
}).catchError((error) => _handleError(store, error));
|
}).catchError((error) => _handleError(store, error, action.context));
|
||||||
}).catchError((error) => _handleError(store, error));
|
}).catchError((error) => _handleError(store, error, action.context));
|
||||||
}).catchError((error) => _handleError(store, error));
|
}).catchError((error) => _handleError(store, error, action.context));
|
||||||
}).catchError((error) => _handleError(store, error));
|
}).catchError((error) => _handleError(store, error, action.context));
|
||||||
} else {
|
} else {
|
||||||
store.dispatch(UserLogout());
|
store.dispatch(UserLogout());
|
||||||
store.dispatch(LoadUserLogin());
|
store.dispatch(LoadUserLogin(action.context));
|
||||||
}
|
}
|
||||||
}).catchError((error) => _handleError(store, error));
|
}).catchError((error) => _handleError(store, error, action.context));
|
||||||
|
|
||||||
next(action);
|
next(action);
|
||||||
};
|
};
|
||||||
|
|
@ -201,10 +201,10 @@ List<String> _getRoutes(AppState state) {
|
||||||
return routes;
|
return routes;
|
||||||
}
|
}
|
||||||
|
|
||||||
_handleError(store, error) {
|
_handleError(store, error, context) {
|
||||||
print(error);
|
print(error);
|
||||||
store.dispatch(UserLogout());
|
store.dispatch(UserLogout());
|
||||||
store.dispatch(LoadUserLogin());
|
store.dispatch(LoadUserLogin(context));
|
||||||
}
|
}
|
||||||
|
|
||||||
Middleware<AppState> _createUserLoggedIn(
|
Middleware<AppState> _createUserLoggedIn(
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ import 'package:invoiceninja/redux/company/company_reducer.dart';
|
||||||
// We create the State reducer by combining many smaller reducers into one!
|
// We create the State reducer by combining many smaller reducers into one!
|
||||||
AppState appReducer(AppState state, action) {
|
AppState appReducer(AppState state, action) {
|
||||||
if (action is UserLogout) {
|
if (action is UserLogout) {
|
||||||
return AppState();
|
return AppState().rebuild((b) => b.authState.replace(state.authState));
|
||||||
} else if (action is LoadStateSuccess) {
|
} else if (action is LoadStateSuccess) {
|
||||||
return action.state.rebuild((b) => b.isLoading = false);
|
return action.state.rebuild((b) => b.isLoading = false);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,10 @@ class LoadStateSuccess {
|
||||||
LoadStateSuccess(this.state);
|
LoadStateSuccess(this.state);
|
||||||
}
|
}
|
||||||
|
|
||||||
class LoadUserLogin {}
|
class LoadUserLogin {
|
||||||
|
final BuildContext context;
|
||||||
|
LoadUserLogin(this.context);
|
||||||
|
}
|
||||||
|
|
||||||
class UserLoginLoaded {
|
class UserLoginLoaded {
|
||||||
final String email;
|
final String email;
|
||||||
|
|
@ -41,5 +44,5 @@ class UserLoginFailure implements StopLoading {
|
||||||
UserLoginFailure(this.error);
|
UserLoginFailure(this.error);
|
||||||
}
|
}
|
||||||
|
|
||||||
class UserLogout {}
|
class UserLogout implements PersistData {}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:invoiceninja/ui/auth/login_vm.dart';
|
||||||
import 'package:redux/redux.dart';
|
import 'package:redux/redux.dart';
|
||||||
import 'package:invoiceninja/redux/auth/auth_actions.dart';
|
import 'package:invoiceninja/redux/auth/auth_actions.dart';
|
||||||
import 'package:invoiceninja/redux/app/app_state.dart';
|
import 'package:invoiceninja/redux/app/app_state.dart';
|
||||||
|
|
@ -39,6 +41,7 @@ _loadAuthLocal(Store<AppState> store, action) async {
|
||||||
String secret = prefs.getString('secret');
|
String secret = prefs.getString('secret');
|
||||||
|
|
||||||
store.dispatch(UserLoginLoaded(email, password, url, secret));
|
store.dispatch(UserLoginLoaded(email, password, url, secret));
|
||||||
|
Navigator.of(action.context).pushReplacementNamed(LoginScreen.route);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ abstract class UIState implements Built<UIState, UIStateBuilder> {
|
||||||
factory UIState() {
|
factory UIState() {
|
||||||
return _$UIState._(
|
return _$UIState._(
|
||||||
selectedCompanyIndex: 0,
|
selectedCompanyIndex: 0,
|
||||||
currentRoute: LoginVM.route,
|
currentRoute: LoginScreen.route,
|
||||||
productUIState: ProductUIState(),
|
productUIState: ProductUIState(),
|
||||||
clientUIState: ClientUIState(),
|
clientUIState: ClientUIState(),
|
||||||
invoiceUIState: InvoiceUIState(),
|
invoiceUIState: InvoiceUIState(),
|
||||||
|
|
|
||||||
|
|
@ -56,7 +56,7 @@ class AppDrawerVM {
|
||||||
while(Navigator.of(context).canPop()) {
|
while(Navigator.of(context).canPop()) {
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
}
|
}
|
||||||
Navigator.of(context).pushReplacementNamed(LoginVM.route);
|
Navigator.of(context).pushReplacementNamed(LoginScreen.route);
|
||||||
store.dispatch(UserLogout());
|
store.dispatch(UserLogout());
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class InitScreen extends StatelessWidget {
|
||||||
|
|
||||||
|
static final String route = '/';
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Container(
|
||||||
|
color: Colors.white,
|
||||||
|
child: Column(
|
||||||
|
children: <Widget>[
|
||||||
|
Expanded(
|
||||||
|
child: Container(),
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
height: 4.0,
|
||||||
|
child: LinearProgressIndicator(),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -6,13 +6,14 @@ import 'package:invoiceninja/ui/app/form_card.dart';
|
||||||
|
|
||||||
import 'package:invoiceninja/utils/keys.dart';
|
import 'package:invoiceninja/utils/keys.dart';
|
||||||
|
|
||||||
class Login extends StatelessWidget {
|
|
||||||
|
class LoginView extends StatefulWidget {
|
||||||
final bool isLoading;
|
final bool isLoading;
|
||||||
final bool isDirty;
|
final bool isDirty;
|
||||||
final AuthState authState;
|
final AuthState authState;
|
||||||
final Function(BuildContext, String, String, String, String) onLoginPressed;
|
final Function(BuildContext, String, String, String, String) onLoginPressed;
|
||||||
|
|
||||||
Login({
|
LoginView({
|
||||||
Key key,
|
Key key,
|
||||||
@required this.isDirty,
|
@required this.isDirty,
|
||||||
@required this.isLoading,
|
@required this.isLoading,
|
||||||
|
|
@ -20,23 +21,47 @@ class Login extends StatelessWidget {
|
||||||
@required this.onLoginPressed,
|
@required this.onLoginPressed,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
_LoginState createState() => new _LoginState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _LoginState extends State<LoginView> {
|
||||||
static final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
|
static final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
|
||||||
|
|
||||||
// add controllers
|
|
||||||
final _emailController = TextEditingController();
|
final _emailController = TextEditingController();
|
||||||
final _passwordController = TextEditingController();
|
final _passwordController = TextEditingController();
|
||||||
final _urlController = TextEditingController();
|
final _urlController = TextEditingController();
|
||||||
final _secretController = TextEditingController();
|
final _secretController = TextEditingController();
|
||||||
|
|
||||||
// keys
|
|
||||||
static final ValueKey _emailKey = new Key(LoginKeys.emailKeyString);
|
static final ValueKey _emailKey = new Key(LoginKeys.emailKeyString);
|
||||||
static final ValueKey _passwordKey = new Key(LoginKeys.passwordKeyString);
|
static final ValueKey _passwordKey = new Key(LoginKeys.passwordKeyString);
|
||||||
static final ValueKey _urlKey = new Key(LoginKeys.urlKeyString);
|
static final ValueKey _urlKey = new Key(LoginKeys.urlKeyString);
|
||||||
static final ValueKey _secretKey = new Key(LoginKeys.secretKeyString);
|
static final ValueKey _secretKey = new Key(LoginKeys.secretKeyString);
|
||||||
|
|
||||||
|
@override
|
||||||
|
void didChangeDependencies() {
|
||||||
|
_emailController.text = widget.authState.email;
|
||||||
|
_passwordController.text = widget.authState.password;
|
||||||
|
_urlController.text = widget.authState.url;
|
||||||
|
_secretController.text = widget.authState.secret;
|
||||||
|
|
||||||
|
super.didChangeDependencies();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_emailController.dispose();
|
||||||
|
_passwordController.dispose();
|
||||||
|
_urlController.dispose();
|
||||||
|
_secretController.dispose();
|
||||||
|
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
if (!authState.isInitialized) {
|
if (!widget.authState.isInitialized) {
|
||||||
return Container();
|
return Container();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -98,13 +123,13 @@ class Login extends StatelessWidget {
|
||||||
*/
|
*/
|
||||||
obscureText: true,
|
obscureText: true,
|
||||||
),
|
),
|
||||||
authState.error == null
|
widget.authState.error == null
|
||||||
? Container()
|
? Container()
|
||||||
: Container(
|
: Container(
|
||||||
padding: EdgeInsets.only(top: 26.0, bottom: 4.0),
|
padding: EdgeInsets.only(top: 26.0, bottom: 4.0),
|
||||||
child: Center(
|
child: Center(
|
||||||
child: Text(
|
child: Text(
|
||||||
authState.error,
|
widget.authState.error,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: Colors.red,
|
color: Colors.red,
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
|
|
@ -116,14 +141,14 @@ class Login extends StatelessWidget {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
ProgressButton(
|
ProgressButton(
|
||||||
label: 'LOGIN',
|
label: AppLocalization.of(context).login.toUpperCase(),
|
||||||
isLoading: this.isLoading,
|
isLoading: widget.isLoading,
|
||||||
isDirty: this.isDirty,
|
isDirty: widget.isDirty,
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
if (!_formKey.currentState.validate()) {
|
if (!_formKey.currentState.validate()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.onLoginPressed(
|
widget.onLoginPressed(
|
||||||
context,
|
context,
|
||||||
_emailController.text,
|
_emailController.text,
|
||||||
_passwordController.text,
|
_passwordController.text,
|
||||||
|
|
|
||||||
|
|
@ -11,18 +11,18 @@ import 'package:invoiceninja/redux/auth/auth_actions.dart';
|
||||||
import 'package:invoiceninja/ui/auth/login.dart';
|
import 'package:invoiceninja/ui/auth/login.dart';
|
||||||
import 'package:invoiceninja/redux/auth/auth_state.dart';
|
import 'package:invoiceninja/redux/auth/auth_state.dart';
|
||||||
|
|
||||||
class LoginVM extends StatelessWidget {
|
class LoginScreen extends StatelessWidget {
|
||||||
LoginVM({Key key}) : super(key: key);
|
LoginScreen({Key key}) : super(key: key);
|
||||||
|
|
||||||
static final String route = '/';
|
static final String route = '/login';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
body: StoreConnector<AppState, _ViewModel>(
|
body: StoreConnector<AppState, LoginVM>(
|
||||||
converter: _ViewModel.fromStore,
|
converter: LoginVM.fromStore,
|
||||||
builder: (context, vm) {
|
builder: (context, vm) {
|
||||||
return Login(
|
return LoginView(
|
||||||
isLoading: vm.isLoading,
|
isLoading: vm.isLoading,
|
||||||
isDirty: vm.isDirty,
|
isDirty: vm.isDirty,
|
||||||
authState: vm.authState,
|
authState: vm.authState,
|
||||||
|
|
@ -34,21 +34,21 @@ class LoginVM extends StatelessWidget {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class _ViewModel {
|
class LoginVM {
|
||||||
bool isLoading;
|
bool isLoading;
|
||||||
bool isDirty;
|
bool isDirty;
|
||||||
AuthState authState;
|
AuthState authState;
|
||||||
final Function(BuildContext, String, String, String, String) onLoginPressed;
|
final Function(BuildContext, String, String, String, String) onLoginPressed;
|
||||||
|
|
||||||
_ViewModel({
|
LoginVM({
|
||||||
@required this.isLoading,
|
@required this.isLoading,
|
||||||
@required this.isDirty,
|
@required this.isDirty,
|
||||||
@required this.authState,
|
@required this.authState,
|
||||||
@required this.onLoginPressed,
|
@required this.onLoginPressed,
|
||||||
});
|
});
|
||||||
|
|
||||||
static _ViewModel fromStore(Store<AppState> store) {
|
static LoginVM fromStore(Store<AppState> store) {
|
||||||
return _ViewModel(
|
return LoginVM(
|
||||||
isDirty: !store.state.authState.isAuthenticated,
|
isDirty: !store.state.authState.isAuthenticated,
|
||||||
isLoading: store.state.isLoading,
|
isLoading: store.state.isLoading,
|
||||||
authState: store.state.authState,
|
authState: store.state.authState,
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@ class AppLocalization {
|
||||||
'secret': 'Secret',
|
'secret': 'Secret',
|
||||||
'name': 'Name',
|
'name': 'Name',
|
||||||
'log_out': 'Log Out',
|
'log_out': 'Log Out',
|
||||||
|
'login': 'Login',
|
||||||
'filter': 'Filter',
|
'filter': 'Filter',
|
||||||
'sort': 'Sort',
|
'sort': 'Sort',
|
||||||
'search': 'Search',
|
'search': 'Search',
|
||||||
|
|
@ -169,6 +170,7 @@ class AppLocalization {
|
||||||
String get secret => _localizedValues[locale.languageCode]['secret'];
|
String get secret => _localizedValues[locale.languageCode]['secret'];
|
||||||
String get name => _localizedValues[locale.languageCode]['name'];
|
String get name => _localizedValues[locale.languageCode]['name'];
|
||||||
String get logOut => _localizedValues[locale.languageCode]['log_out'];
|
String get logOut => _localizedValues[locale.languageCode]['log_out'];
|
||||||
|
String get login => _localizedValues[locale.languageCode]['login'];
|
||||||
String get filter => _localizedValues[locale.languageCode]['filter'];
|
String get filter => _localizedValues[locale.languageCode]['filter'];
|
||||||
String get sort => _localizedValues[locale.languageCode]['sort'];
|
String get sort => _localizedValues[locale.languageCode]['sort'];
|
||||||
String get search => _localizedValues[locale.languageCode]['search'];
|
String get search => _localizedValues[locale.languageCode]['search'];
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue