Remove biometric auth
This commit is contained in:
parent
a8ac3544e2
commit
1cdd5bb406
|
|
@ -9,7 +9,6 @@ const String kSharedPrefSecret = 'secret';
|
||||||
const String kSharedPrefEnableDarkMode = 'enable_dark_mode';
|
const String kSharedPrefEnableDarkMode = 'enable_dark_mode';
|
||||||
const String kSharedPrefEmailPayment = 'email_payment';
|
const String kSharedPrefEmailPayment = 'email_payment';
|
||||||
const String kSharedPrefAppVersion = 'app_version';
|
const String kSharedPrefAppVersion = 'app_version';
|
||||||
const String kSharedPrefRequireAuthentication = 'require_authentication';
|
|
||||||
|
|
||||||
const int kMinMajorAppVersion = 4;
|
const int kMinMajorAppVersion = 4;
|
||||||
const int kMinMinorAppVersion = 5;
|
const int kMinMinorAppVersion = 5;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,3 @@
|
||||||
import 'dart:async';
|
|
||||||
|
|
||||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
|
||||||
import 'package:intl/intl.dart';
|
import 'package:intl/intl.dart';
|
||||||
import 'package:invoiceninja_flutter/redux/company/company_selectors.dart';
|
import 'package:invoiceninja_flutter/redux/company/company_selectors.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/app/app_builder.dart';
|
import 'package:invoiceninja_flutter/ui/app/app_builder.dart';
|
||||||
|
|
@ -38,7 +35,6 @@ import 'package:invoiceninja_flutter/redux/product/product_middleware.dart';
|
||||||
import 'package:invoiceninja_flutter/redux/invoice/invoice_middleware.dart';
|
import 'package:invoiceninja_flutter/redux/invoice/invoice_middleware.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/invoice/invoice_screen.dart';
|
import 'package:invoiceninja_flutter/ui/invoice/invoice_screen.dart';
|
||||||
import 'package:invoiceninja_flutter/utils/localization.dart';
|
import 'package:invoiceninja_flutter/utils/localization.dart';
|
||||||
import 'package:local_auth/local_auth.dart';
|
|
||||||
//import 'package:quick_actions/quick_actions.dart';
|
//import 'package:quick_actions/quick_actions.dart';
|
||||||
|
|
||||||
// STARTER: import - do not remove comment
|
// STARTER: import - do not remove comment
|
||||||
|
|
@ -57,13 +53,10 @@ import 'package:invoiceninja_flutter/redux/quote/quote_middleware.dart';
|
||||||
void main() async {
|
void main() async {
|
||||||
final prefs = await SharedPreferences.getInstance();
|
final prefs = await SharedPreferences.getInstance();
|
||||||
final enableDarkMode = prefs.getBool(kSharedPrefEnableDarkMode) ?? false;
|
final enableDarkMode = prefs.getBool(kSharedPrefEnableDarkMode) ?? false;
|
||||||
final requireAuthentication =
|
|
||||||
prefs.getBool(kSharedPrefRequireAuthentication) ?? false;
|
|
||||||
|
|
||||||
final store = Store<AppState>(appReducer,
|
final store = Store<AppState>(appReducer,
|
||||||
initialState: AppState(
|
initialState: AppState(
|
||||||
enableDarkMode: enableDarkMode,
|
enableDarkMode: enableDarkMode),
|
||||||
requireAuthentication: requireAuthentication),
|
|
||||||
middleware: []
|
middleware: []
|
||||||
..addAll(createStoreAuthMiddleware())
|
..addAll(createStoreAuthMiddleware())
|
||||||
..addAll(createStoreDashboardMiddleware())
|
..addAll(createStoreDashboardMiddleware())
|
||||||
|
|
@ -91,26 +84,6 @@ class InvoiceNinjaApp extends StatefulWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
class InvoiceNinjaAppState extends State<InvoiceNinjaApp> {
|
class InvoiceNinjaAppState extends State<InvoiceNinjaApp> {
|
||||||
bool _authenticated = false;
|
|
||||||
|
|
||||||
Future<Null> _authenticate() async {
|
|
||||||
bool authenticated = false;
|
|
||||||
try {
|
|
||||||
authenticated = await LocalAuthentication().authenticateWithBiometrics(
|
|
||||||
localizedReason: 'Please authenticate to access the app',
|
|
||||||
useErrorDialogs: true,
|
|
||||||
stickyAuth: false);
|
|
||||||
} catch (e) {
|
|
||||||
print(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mounted) {
|
|
||||||
setState(() {
|
|
||||||
_authenticated = authenticated;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
|
@ -130,16 +103,6 @@ class InvoiceNinjaAppState extends State<InvoiceNinjaApp> {
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
void didChangeDependencies() {
|
|
||||||
final state = widget.store.state;
|
|
||||||
if (state.uiState.requireAuthentication && !_authenticated) {
|
|
||||||
_authenticate();
|
|
||||||
}
|
|
||||||
|
|
||||||
super.didChangeDependencies();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return StoreProvider<AppState>(
|
return StoreProvider<AppState>(
|
||||||
|
|
@ -147,7 +110,6 @@ class InvoiceNinjaAppState extends State<InvoiceNinjaApp> {
|
||||||
child: AppBuilder(builder: (context) {
|
child: AppBuilder(builder: (context) {
|
||||||
final state = widget.store.state;
|
final state = widget.store.state;
|
||||||
Intl.defaultLocale = localeSelector(state);
|
Intl.defaultLocale = localeSelector(state);
|
||||||
final localization = AppLocalization(Locale(Intl.defaultLocale));
|
|
||||||
|
|
||||||
return MaterialApp(
|
return MaterialApp(
|
||||||
debugShowCheckedModeBanner: false,
|
debugShowCheckedModeBanner: false,
|
||||||
|
|
@ -155,40 +117,7 @@ class InvoiceNinjaAppState extends State<InvoiceNinjaApp> {
|
||||||
const AppLocalizationsDelegate(),
|
const AppLocalizationsDelegate(),
|
||||||
GlobalMaterialLocalizations.delegate,
|
GlobalMaterialLocalizations.delegate,
|
||||||
],
|
],
|
||||||
home: state.uiState.requireAuthentication && !_authenticated
|
home: InitScreen(),
|
||||||
? Material(
|
|
||||||
color: Colors.grey,
|
|
||||||
child: Column(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
|
||||||
children: <Widget>[
|
|
||||||
Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
|
||||||
children: <Widget>[
|
|
||||||
Icon(
|
|
||||||
FontAwesomeIcons.lock,
|
|
||||||
size: 24.0,
|
|
||||||
color: Colors.grey[400],
|
|
||||||
),
|
|
||||||
SizedBox(
|
|
||||||
width: 12.0,
|
|
||||||
),
|
|
||||||
Text(
|
|
||||||
localization.locked,
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 32.0,
|
|
||||||
color: Colors.grey[400],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
RaisedButton(
|
|
||||||
onPressed: () => _authenticate(),
|
|
||||||
child: Text(localization.authenticate),
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
)
|
|
||||||
: InitScreen(),
|
|
||||||
locale: Locale(localeSelector(state)),
|
locale: Locale(localeSelector(state)),
|
||||||
theme: state.uiState.enableDarkMode
|
theme: state.uiState.enableDarkMode
|
||||||
? ThemeData(
|
? ThemeData(
|
||||||
|
|
|
||||||
|
|
@ -28,12 +28,8 @@ class LoadStaticSuccess {
|
||||||
class UserSettingsChanged implements PersistUI {
|
class UserSettingsChanged implements PersistUI {
|
||||||
final bool enableDarkMode;
|
final bool enableDarkMode;
|
||||||
final bool emailPayment;
|
final bool emailPayment;
|
||||||
final bool requireAuthentication;
|
|
||||||
|
|
||||||
UserSettingsChanged(
|
UserSettingsChanged({this.enableDarkMode, this.emailPayment});
|
||||||
{this.enableDarkMode,
|
|
||||||
this.emailPayment,
|
|
||||||
this.requireAuthentication});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class LoadDataSuccess {
|
class LoadDataSuccess {
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ part 'app_state.g.dart';
|
||||||
|
|
||||||
abstract class AppState implements Built<AppState, AppStateBuilder> {
|
abstract class AppState implements Built<AppState, AppStateBuilder> {
|
||||||
factory AppState(
|
factory AppState(
|
||||||
{String appVersion, bool enableDarkMode, bool requireAuthentication}) {
|
{String appVersion, bool enableDarkMode}) {
|
||||||
return _$AppState._(
|
return _$AppState._(
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
isSaving: false,
|
isSaving: false,
|
||||||
|
|
@ -33,8 +33,7 @@ abstract class AppState implements Built<AppState, AppStateBuilder> {
|
||||||
companyState4: CompanyState(),
|
companyState4: CompanyState(),
|
||||||
companyState5: CompanyState(),
|
companyState5: CompanyState(),
|
||||||
uiState: UIState(CompanyEntity(),
|
uiState: UIState(CompanyEntity(),
|
||||||
enableDarkMode: enableDarkMode,
|
enableDarkMode: enableDarkMode),
|
||||||
requireAuthentication: requireAuthentication),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -43,13 +43,10 @@ void _loadAuthLocal(Store<AppState> store, dynamic action) async {
|
||||||
|
|
||||||
final bool enableDarkMode = prefs.getBool(kSharedPrefEnableDarkMode) ?? false;
|
final bool enableDarkMode = prefs.getBool(kSharedPrefEnableDarkMode) ?? false;
|
||||||
final bool emailPayment = prefs.getBool(kSharedPrefEmailPayment) ?? false;
|
final bool emailPayment = prefs.getBool(kSharedPrefEmailPayment) ?? false;
|
||||||
final bool requireAuthentication =
|
|
||||||
prefs.getBool(kSharedPrefRequireAuthentication) ?? false;
|
|
||||||
|
|
||||||
store.dispatch(UserSettingsChanged(
|
store.dispatch(UserSettingsChanged(
|
||||||
enableDarkMode: enableDarkMode,
|
enableDarkMode: enableDarkMode,
|
||||||
emailPayment: emailPayment,
|
emailPayment: emailPayment));
|
||||||
requireAuthentication: requireAuthentication));
|
|
||||||
|
|
||||||
Navigator.of(action.context).pushReplacementNamed(LoginScreen.route);
|
Navigator.of(action.context).pushReplacementNamed(LoginScreen.route);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,8 +19,6 @@ UIState uiReducer(UIState state, dynamic action) {
|
||||||
selectedCompanyIndexReducer(state.selectedCompanyIndex, action)
|
selectedCompanyIndexReducer(state.selectedCompanyIndex, action)
|
||||||
..currentRoute = currentRouteReducer(state.currentRoute, action)
|
..currentRoute = currentRouteReducer(state.currentRoute, action)
|
||||||
..enableDarkMode = darkModeReducer(state.enableDarkMode, action)
|
..enableDarkMode = darkModeReducer(state.enableDarkMode, action)
|
||||||
..requireAuthentication = requireAuthenticationReducer(
|
|
||||||
state.requireAuthentication, action)
|
|
||||||
..emailPayment = emailPaymentReducer(state.emailPayment, action)
|
..emailPayment = emailPaymentReducer(state.emailPayment, action)
|
||||||
..productUIState.replace(productUIReducer(state.productUIState, action))
|
..productUIState.replace(productUIReducer(state.productUIState, action))
|
||||||
..clientUIState.replace(clientUIReducer(state.clientUIState, action))
|
..clientUIState.replace(clientUIReducer(state.clientUIState, action))
|
||||||
|
|
@ -54,15 +52,6 @@ bool updateDarkModeReducer(bool enableDarkMode, UserSettingsChanged action) {
|
||||||
return action.enableDarkMode ?? enableDarkMode;
|
return action.enableDarkMode ?? enableDarkMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
Reducer<bool> requireAuthenticationReducer = combineReducers([
|
|
||||||
TypedReducer<bool, UserSettingsChanged>(updateRequireAuthenticationReducer),
|
|
||||||
]);
|
|
||||||
|
|
||||||
bool updateRequireAuthenticationReducer(
|
|
||||||
bool requireAuthentication, UserSettingsChanged action) {
|
|
||||||
return action.requireAuthentication ?? requireAuthentication;
|
|
||||||
}
|
|
||||||
|
|
||||||
Reducer<String> currentRouteReducer = combineReducers([
|
Reducer<String> currentRouteReducer = combineReducers([
|
||||||
TypedReducer<String, UpdateCurrentRoute>(updateCurrentRouteReducer),
|
TypedReducer<String, UpdateCurrentRoute>(updateCurrentRouteReducer),
|
||||||
]);
|
]);
|
||||||
|
|
|
||||||
|
|
@ -15,12 +15,11 @@ part 'ui_state.g.dart';
|
||||||
|
|
||||||
abstract class UIState implements Built<UIState, UIStateBuilder> {
|
abstract class UIState implements Built<UIState, UIStateBuilder> {
|
||||||
factory UIState(CompanyEntity company,
|
factory UIState(CompanyEntity company,
|
||||||
{bool enableDarkMode, bool requireAuthentication}) {
|
{bool enableDarkMode}) {
|
||||||
return _$UIState._(
|
return _$UIState._(
|
||||||
selectedCompanyIndex: 0,
|
selectedCompanyIndex: 0,
|
||||||
currentRoute: LoginScreen.route,
|
currentRoute: LoginScreen.route,
|
||||||
enableDarkMode: enableDarkMode ?? false,
|
enableDarkMode: enableDarkMode ?? false,
|
||||||
requireAuthentication: requireAuthentication ?? false,
|
|
||||||
emailPayment: false,
|
emailPayment: false,
|
||||||
productUIState: ProductUIState(),
|
productUIState: ProductUIState(),
|
||||||
clientUIState: ClientUIState(),
|
clientUIState: ClientUIState(),
|
||||||
|
|
@ -40,8 +39,6 @@ abstract class UIState implements Built<UIState, UIStateBuilder> {
|
||||||
|
|
||||||
bool get enableDarkMode;
|
bool get enableDarkMode;
|
||||||
|
|
||||||
bool get requireAuthentication;
|
|
||||||
|
|
||||||
bool get emailPayment;
|
bool get emailPayment;
|
||||||
|
|
||||||
ProductUIState get productUIState;
|
ProductUIState get productUIState;
|
||||||
|
|
|
||||||
|
|
@ -40,9 +40,6 @@ class _$UIStateSerializer implements StructuredSerializer<UIState> {
|
||||||
'enableDarkMode',
|
'enableDarkMode',
|
||||||
serializers.serialize(object.enableDarkMode,
|
serializers.serialize(object.enableDarkMode,
|
||||||
specifiedType: const FullType(bool)),
|
specifiedType: const FullType(bool)),
|
||||||
'requireAuthentication',
|
|
||||||
serializers.serialize(object.requireAuthentication,
|
|
||||||
specifiedType: const FullType(bool)),
|
|
||||||
'emailPayment',
|
'emailPayment',
|
||||||
serializers.serialize(object.emailPayment,
|
serializers.serialize(object.emailPayment,
|
||||||
specifiedType: const FullType(bool)),
|
specifiedType: const FullType(bool)),
|
||||||
|
|
@ -95,10 +92,6 @@ class _$UIStateSerializer implements StructuredSerializer<UIState> {
|
||||||
result.enableDarkMode = serializers.deserialize(value,
|
result.enableDarkMode = serializers.deserialize(value,
|
||||||
specifiedType: const FullType(bool)) as bool;
|
specifiedType: const FullType(bool)) as bool;
|
||||||
break;
|
break;
|
||||||
case 'requireAuthentication':
|
|
||||||
result.requireAuthentication = serializers.deserialize(value,
|
|
||||||
specifiedType: const FullType(bool)) as bool;
|
|
||||||
break;
|
|
||||||
case 'emailPayment':
|
case 'emailPayment':
|
||||||
result.emailPayment = serializers.deserialize(value,
|
result.emailPayment = serializers.deserialize(value,
|
||||||
specifiedType: const FullType(bool)) as bool;
|
specifiedType: const FullType(bool)) as bool;
|
||||||
|
|
@ -142,8 +135,6 @@ class _$UIState extends UIState {
|
||||||
@override
|
@override
|
||||||
final bool enableDarkMode;
|
final bool enableDarkMode;
|
||||||
@override
|
@override
|
||||||
final bool requireAuthentication;
|
|
||||||
@override
|
|
||||||
final bool emailPayment;
|
final bool emailPayment;
|
||||||
@override
|
@override
|
||||||
final ProductUIState productUIState;
|
final ProductUIState productUIState;
|
||||||
|
|
@ -165,7 +156,6 @@ class _$UIState extends UIState {
|
||||||
{this.selectedCompanyIndex,
|
{this.selectedCompanyIndex,
|
||||||
this.currentRoute,
|
this.currentRoute,
|
||||||
this.enableDarkMode,
|
this.enableDarkMode,
|
||||||
this.requireAuthentication,
|
|
||||||
this.emailPayment,
|
this.emailPayment,
|
||||||
this.productUIState,
|
this.productUIState,
|
||||||
this.clientUIState,
|
this.clientUIState,
|
||||||
|
|
@ -183,9 +173,6 @@ class _$UIState extends UIState {
|
||||||
if (enableDarkMode == null) {
|
if (enableDarkMode == null) {
|
||||||
throw new BuiltValueNullFieldError('UIState', 'enableDarkMode');
|
throw new BuiltValueNullFieldError('UIState', 'enableDarkMode');
|
||||||
}
|
}
|
||||||
if (requireAuthentication == null) {
|
|
||||||
throw new BuiltValueNullFieldError('UIState', 'requireAuthentication');
|
|
||||||
}
|
|
||||||
if (emailPayment == null) {
|
if (emailPayment == null) {
|
||||||
throw new BuiltValueNullFieldError('UIState', 'emailPayment');
|
throw new BuiltValueNullFieldError('UIState', 'emailPayment');
|
||||||
}
|
}
|
||||||
|
|
@ -220,7 +207,6 @@ class _$UIState extends UIState {
|
||||||
selectedCompanyIndex == other.selectedCompanyIndex &&
|
selectedCompanyIndex == other.selectedCompanyIndex &&
|
||||||
currentRoute == other.currentRoute &&
|
currentRoute == other.currentRoute &&
|
||||||
enableDarkMode == other.enableDarkMode &&
|
enableDarkMode == other.enableDarkMode &&
|
||||||
requireAuthentication == other.requireAuthentication &&
|
|
||||||
emailPayment == other.emailPayment &&
|
emailPayment == other.emailPayment &&
|
||||||
productUIState == other.productUIState &&
|
productUIState == other.productUIState &&
|
||||||
clientUIState == other.clientUIState &&
|
clientUIState == other.clientUIState &&
|
||||||
|
|
@ -240,13 +226,9 @@ class _$UIState extends UIState {
|
||||||
$jc(
|
$jc(
|
||||||
$jc(
|
$jc(
|
||||||
$jc(
|
$jc(
|
||||||
$jc(
|
$jc($jc(0, selectedCompanyIndex.hashCode),
|
||||||
$jc(
|
currentRoute.hashCode),
|
||||||
$jc(0,
|
enableDarkMode.hashCode),
|
||||||
selectedCompanyIndex.hashCode),
|
|
||||||
currentRoute.hashCode),
|
|
||||||
enableDarkMode.hashCode),
|
|
||||||
requireAuthentication.hashCode),
|
|
||||||
emailPayment.hashCode),
|
emailPayment.hashCode),
|
||||||
productUIState.hashCode),
|
productUIState.hashCode),
|
||||||
clientUIState.hashCode),
|
clientUIState.hashCode),
|
||||||
|
|
@ -262,7 +244,6 @@ class _$UIState extends UIState {
|
||||||
..add('selectedCompanyIndex', selectedCompanyIndex)
|
..add('selectedCompanyIndex', selectedCompanyIndex)
|
||||||
..add('currentRoute', currentRoute)
|
..add('currentRoute', currentRoute)
|
||||||
..add('enableDarkMode', enableDarkMode)
|
..add('enableDarkMode', enableDarkMode)
|
||||||
..add('requireAuthentication', requireAuthentication)
|
|
||||||
..add('emailPayment', emailPayment)
|
..add('emailPayment', emailPayment)
|
||||||
..add('productUIState', productUIState)
|
..add('productUIState', productUIState)
|
||||||
..add('clientUIState', clientUIState)
|
..add('clientUIState', clientUIState)
|
||||||
|
|
@ -291,11 +272,6 @@ class UIStateBuilder implements Builder<UIState, UIStateBuilder> {
|
||||||
set enableDarkMode(bool enableDarkMode) =>
|
set enableDarkMode(bool enableDarkMode) =>
|
||||||
_$this._enableDarkMode = enableDarkMode;
|
_$this._enableDarkMode = enableDarkMode;
|
||||||
|
|
||||||
bool _requireAuthentication;
|
|
||||||
bool get requireAuthentication => _$this._requireAuthentication;
|
|
||||||
set requireAuthentication(bool requireAuthentication) =>
|
|
||||||
_$this._requireAuthentication = requireAuthentication;
|
|
||||||
|
|
||||||
bool _emailPayment;
|
bool _emailPayment;
|
||||||
bool get emailPayment => _$this._emailPayment;
|
bool get emailPayment => _$this._emailPayment;
|
||||||
set emailPayment(bool emailPayment) => _$this._emailPayment = emailPayment;
|
set emailPayment(bool emailPayment) => _$this._emailPayment = emailPayment;
|
||||||
|
|
@ -341,7 +317,6 @@ class UIStateBuilder implements Builder<UIState, UIStateBuilder> {
|
||||||
_selectedCompanyIndex = _$v.selectedCompanyIndex;
|
_selectedCompanyIndex = _$v.selectedCompanyIndex;
|
||||||
_currentRoute = _$v.currentRoute;
|
_currentRoute = _$v.currentRoute;
|
||||||
_enableDarkMode = _$v.enableDarkMode;
|
_enableDarkMode = _$v.enableDarkMode;
|
||||||
_requireAuthentication = _$v.requireAuthentication;
|
|
||||||
_emailPayment = _$v.emailPayment;
|
_emailPayment = _$v.emailPayment;
|
||||||
_productUIState = _$v.productUIState?.toBuilder();
|
_productUIState = _$v.productUIState?.toBuilder();
|
||||||
_clientUIState = _$v.clientUIState?.toBuilder();
|
_clientUIState = _$v.clientUIState?.toBuilder();
|
||||||
|
|
@ -376,7 +351,6 @@ class UIStateBuilder implements Builder<UIState, UIStateBuilder> {
|
||||||
selectedCompanyIndex: selectedCompanyIndex,
|
selectedCompanyIndex: selectedCompanyIndex,
|
||||||
currentRoute: currentRoute,
|
currentRoute: currentRoute,
|
||||||
enableDarkMode: enableDarkMode,
|
enableDarkMode: enableDarkMode,
|
||||||
requireAuthentication: requireAuthentication,
|
|
||||||
emailPayment: emailPayment,
|
emailPayment: emailPayment,
|
||||||
productUIState: productUIState.build(),
|
productUIState: productUIState.build(),
|
||||||
clientUIState: clientUIState.build(),
|
clientUIState: clientUIState.build(),
|
||||||
|
|
|
||||||
|
|
@ -23,16 +23,6 @@ class SettingsList extends StatelessWidget {
|
||||||
secondary: Icon(FontAwesomeIcons.moon),
|
secondary: Icon(FontAwesomeIcons.moon),
|
||||||
activeColor: Theme.of(context).accentColor,
|
activeColor: Theme.of(context).accentColor,
|
||||||
),
|
),
|
||||||
SwitchListTile(
|
|
||||||
title: Text(AppLocalization.of(context).biometricAuthentication),
|
|
||||||
value: viewModel.requireAuthentication,
|
|
||||||
onChanged: (value) =>
|
|
||||||
viewModel.onRequireAuthenticationChanged(context, value),
|
|
||||||
secondary: Icon(viewModel.requireAuthentication
|
|
||||||
? FontAwesomeIcons.lock
|
|
||||||
: FontAwesomeIcons.unlockAlt),
|
|
||||||
activeColor: Theme.of(context).accentColor,
|
|
||||||
),
|
|
||||||
ListTile(
|
ListTile(
|
||||||
leading: Icon(FontAwesomeIcons.syncAlt),
|
leading: Icon(FontAwesomeIcons.syncAlt),
|
||||||
title: Text(AppLocalization.of(context).refreshData),
|
title: Text(AppLocalization.of(context).refreshData),
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,6 @@ import 'package:invoiceninja_flutter/ui/app/app_builder.dart';
|
||||||
import 'package:invoiceninja_flutter/utils/completers.dart';
|
import 'package:invoiceninja_flutter/utils/completers.dart';
|
||||||
import 'package:invoiceninja_flutter/utils/localization.dart';
|
import 'package:invoiceninja_flutter/utils/localization.dart';
|
||||||
import 'package:invoiceninja_flutter/utils/platforms.dart';
|
import 'package:invoiceninja_flutter/utils/platforms.dart';
|
||||||
import 'package:local_auth/local_auth.dart';
|
|
||||||
import 'package:redux/redux.dart';
|
import 'package:redux/redux.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/auth/login_vm.dart';
|
import 'package:invoiceninja_flutter/ui/auth/login_vm.dart';
|
||||||
import 'package:invoiceninja_flutter/ui/settings/settings_list.dart';
|
import 'package:invoiceninja_flutter/ui/settings/settings_list.dart';
|
||||||
|
|
@ -35,18 +34,13 @@ class SettingsListVM {
|
||||||
final Function(BuildContext context) onLogoutTap;
|
final Function(BuildContext context) onLogoutTap;
|
||||||
final Function(BuildContext context) onRefreshTap;
|
final Function(BuildContext context) onRefreshTap;
|
||||||
final Function(BuildContext context, bool value) onDarkModeChanged;
|
final Function(BuildContext context, bool value) onDarkModeChanged;
|
||||||
final Function(BuildContext context, bool value)
|
|
||||||
onRequireAuthenticationChanged;
|
|
||||||
final bool enableDarkMode;
|
final bool enableDarkMode;
|
||||||
final bool requireAuthentication;
|
|
||||||
|
|
||||||
SettingsListVM({
|
SettingsListVM({
|
||||||
@required this.onLogoutTap,
|
@required this.onLogoutTap,
|
||||||
@required this.onRefreshTap,
|
@required this.onRefreshTap,
|
||||||
@required this.onDarkModeChanged,
|
@required this.onDarkModeChanged,
|
||||||
@required this.onRequireAuthenticationChanged,
|
|
||||||
@required this.enableDarkMode,
|
@required this.enableDarkMode,
|
||||||
@required this.requireAuthentication,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
static SettingsListVM fromStore(Store<AppState> store) {
|
static SettingsListVM fromStore(Store<AppState> store) {
|
||||||
|
|
@ -102,26 +96,7 @@ class SettingsListVM {
|
||||||
store.dispatch(UserSettingsChanged(enableDarkMode: value));
|
store.dispatch(UserSettingsChanged(enableDarkMode: value));
|
||||||
AppBuilder.of(context).rebuild();
|
AppBuilder.of(context).rebuild();
|
||||||
},
|
},
|
||||||
onRequireAuthenticationChanged: (BuildContext context, bool value) async {
|
|
||||||
bool authenticated = false;
|
|
||||||
try {
|
|
||||||
authenticated = await LocalAuthentication()
|
|
||||||
.authenticateWithBiometrics(
|
|
||||||
localizedReason:
|
|
||||||
AppLocalization.of(context).authenticateToChangeSetting,
|
|
||||||
useErrorDialogs: true,
|
|
||||||
stickyAuth: false);
|
|
||||||
} catch (e) {
|
|
||||||
print(e);
|
|
||||||
}
|
|
||||||
if (authenticated) {
|
|
||||||
final SharedPreferences prefs = await SharedPreferences.getInstance();
|
|
||||||
prefs.setBool(kSharedPrefRequireAuthentication, value);
|
|
||||||
store.dispatch(UserSettingsChanged(requireAuthentication: value));
|
|
||||||
} else {}
|
|
||||||
},
|
|
||||||
enableDarkMode: store.state.uiState.enableDarkMode,
|
enableDarkMode: store.state.uiState.enableDarkMode,
|
||||||
requireAuthentication: store.state.uiState.requireAuthentication,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,12 +14,6 @@ class AppLocalization {
|
||||||
|
|
||||||
static final Map<String, Map<String, String>> _localizedValues = {
|
static final Map<String, Map<String, String>> _localizedValues = {
|
||||||
'en': {
|
'en': {
|
||||||
'authenticate_to_change_setting':
|
|
||||||
'Please authenticate to change this setting',
|
|
||||||
'locked': 'Locked',
|
|
||||||
'authenticate': 'Authenticate',
|
|
||||||
'please_authenticate': 'Please authenticate',
|
|
||||||
'biometric_authentication': 'Biometric Authentication',
|
|
||||||
'clone_to_invoice': 'Clone to Invoice',
|
'clone_to_invoice': 'Clone to Invoice',
|
||||||
'clone_to_quote': 'Clone to Quote',
|
'clone_to_quote': 'Clone to Quote',
|
||||||
'view_invoice': 'View Invoice',
|
'view_invoice': 'View Invoice',
|
||||||
|
|
@ -8328,20 +8322,6 @@ class AppLocalization {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
String get authenticateToChangeSetting =>
|
|
||||||
_localizedValues[locale.languageCode]['authenticate_to_change_setting'];
|
|
||||||
|
|
||||||
String get locked => _localizedValues[locale.languageCode]['locked'];
|
|
||||||
|
|
||||||
String get authenticate =>
|
|
||||||
_localizedValues[locale.languageCode]['authenticate'];
|
|
||||||
|
|
||||||
String get pleaseAuthenticate =>
|
|
||||||
_localizedValues[locale.languageCode]['please_authenticate'];
|
|
||||||
|
|
||||||
String get biometricAuthentication =>
|
|
||||||
_localizedValues[locale.languageCode]['biometric_authentication'];
|
|
||||||
|
|
||||||
String get cloneToInvoice =>
|
String get cloneToInvoice =>
|
||||||
_localizedValues[locale.languageCode]['clone_to_invoice'];
|
_localizedValues[locale.languageCode]['clone_to_invoice'];
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,6 @@ dependencies:
|
||||||
cached_network_image: ^0.4.2
|
cached_network_image: ^0.4.2
|
||||||
share: ^0.5.3
|
share: ^0.5.3
|
||||||
quick_actions: ^0.2.1
|
quick_actions: ^0.2.1
|
||||||
local_auth : ^0.2.1
|
|
||||||
intl: ^0.15.7
|
intl: ^0.15.7
|
||||||
flutter_slidable: ^0.4.6
|
flutter_slidable: ^0.4.6
|
||||||
#flutter_html_view: ^0.5.8
|
#flutter_html_view: ^0.5.8
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue