import 'package:aman_kassa_flutter/core/locator.dart'; import 'package:aman_kassa_flutter/core/logger.dart'; import 'package:aman_kassa_flutter/core/models/choice.dart'; import 'package:aman_kassa_flutter/core/models/response.dart'; import 'package:aman_kassa_flutter/core/route_names.dart'; import 'package:aman_kassa_flutter/core/services/ApiService.dart'; import 'package:aman_kassa_flutter/core/services/DataService.dart'; import 'package:aman_kassa_flutter/core/services/navigator_service.dart'; import 'package:aman_kassa_flutter/redux/actions/setting_actions.dart'; import 'package:aman_kassa_flutter/redux/actions/user_actions.dart'; import 'package:aman_kassa_flutter/redux/constants/setting_const.dart'; import 'package:aman_kassa_flutter/redux/state/setting_state.dart'; import 'package:aman_kassa_flutter/redux/store.dart'; import 'package:aman_kassa_flutter/shared/app_colors.dart'; import 'package:aman_kassa_flutter/views/home/components/header_title.dart'; import 'package:aman_kassa_flutter/views/lockscreen/passcodescreen.dart'; import 'package:aman_kassa_flutter/widgets/loader/Dialogs.dart'; import 'package:flutter/material.dart'; import 'package:flutter_redux/flutter_redux.dart'; import 'package:logger/logger.dart'; import 'package:shared_preferences/shared_preferences.dart'; import './tabs/KassaTab.dart'; import './tabs/AdditionalTab.dart'; import './tabs/CalculatorTab.dart'; import './components/popup_menu.dart'; import 'components/bottom_bar.dart'; class HomeView extends StatefulWidget { @override _HomeViewState createState() => _HomeViewState(); } class _HomeViewState extends State with WidgetsBindingObserver { Logger log = getLogger('HomeView'); PageController pageController; int selectedTabIndex; DataService _dataService = locator(); ApiService _api = locator(); NavigatorService _navigatorService = locator(); final GlobalKey _keyLoader = new GlobalKey(); final lastKnownStateKey = 'lastKnownStateKey'; final backgroundedTimeKey = 'backgroundedTimeKey'; final pinLockMillis = 2000; // 2 seconds Future _paused() async { final sp = await SharedPreferences.getInstance(); sp.setInt(lastKnownStateKey, AppLifecycleState.paused.index); } Future _inactive() async { final sp = await SharedPreferences.getInstance(); final prevState = sp.getInt(lastKnownStateKey); final prevStateIsNotPaused = prevState != null && AppLifecycleState.values[prevState] != AppLifecycleState.paused; final bool pinIsExist = Redux.store.state.settingState?.pinCode?.isNotEmpty; final bool pinSkipped = Redux.store.state.settingState.pinSkip; if(prevStateIsNotPaused && pinSkipped == false && pinIsExist == true) { // save App backgrounded time to Shared preferences sp.setInt(backgroundedTimeKey, DateTime.now().millisecondsSinceEpoch); } // update previous state as inactive sp.setInt(lastKnownStateKey, AppLifecycleState.inactive.index); } Future _resumed() async { final sp = await SharedPreferences.getInstance(); final bgTime = sp.getInt(backgroundedTimeKey) ?? 0; final allowedBackgroundTime = bgTime + pinLockMillis; final shouldShowPIN = DateTime.now().millisecondsSinceEpoch > allowedBackgroundTime; if(shouldShowPIN && bgTime > 0) { Redux.store.dispatch(changePinLockedFromSetting(true)); // show PIN screen // Navigator.pushReplacement(context, MaterialPageRoute( // builder: (_) => PassCodeScreen( title: 'Безопасность',))); Navigator.of(context).push(MaterialPageRoute( builder: (_) => WillPopScope( onWillPop: () async { return false; }, child: PassCodeScreen( title: 'Безопасность',) ) )); } sp.remove(backgroundedTimeKey); // clean sp.setInt(lastKnownStateKey, AppLifecycleState.resumed.index);// previous state } _checkLockPin () async { if ( Redux.store.state.settingState.pinLocked == true) { await Future.delayed(Duration(milliseconds: 200)); Navigator.of(context).push(MaterialPageRoute( builder: (_) => WillPopScope( onWillPop: () async { return false; }, child: PassCodeScreen( title: 'Безопасность',) ) )); } } @override void initState() { super.initState(); WidgetsBinding.instance.addObserver(this); selectedTabIndex = 0; pageController = new PageController(initialPage: selectedTabIndex); Redux.store.dispatch(checkSmena); _dataService.checkDbFill(Redux.store.state.userState.user); _checkLockPin(); } @override void didChangeAppLifecycleState(AppLifecycleState state) { super.didChangeAppLifecycleState(state); print('state = $state'); switch(state) { case AppLifecycleState.resumed: _resumed(); break; case AppLifecycleState.paused: _paused(); break; case AppLifecycleState.inactive: _inactive(); break; default: break; } } @override void dispose() { WidgetsBinding.instance.removeObserver(this); pageController.dispose(); super.dispose(); } void _onSelectChoice(Choice choice) async { if (choice.command == 'exit') { Dialogs.showLoadingDialog(context, _keyLoader); Response result = await _api.logout(Redux.store.state.userState.user.token); if(result.operation && result.status == 200) { Redux.store.dispatch(logoutAction); } Navigator.of(_keyLoader.currentContext, rootNavigator: true).pop(); } else if (choice.command == 'infokkm') { _navigatorService.push(InfoKkmViewRoute); } else if (choice.command == 'settings') { _navigatorService.push(SettingsViewRoute); } } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( titleSpacing: 5.0, brightness: Brightness.light, title: HeaderTitle(), actions: [ PopupMenu( onSelectChoice: _onSelectChoice, ) ], backgroundColor: fillColor, ), body:StoreConnector( converter: (store) => store.state.settingState, builder: (context, vm) { return PageView( pageSnapping: true, onPageChanged: (index) { setState(() { selectedTabIndex = index; }); }, controller: pageController, children: [ vm.mode == SettingModeKassa ? KassaTab(0) : CalculatorTab(0), AdditionalTab(1), ], ); } ), bottomNavigationBar: BottomBar( pageController: pageController, selectedTabIndex: selectedTabIndex, ), ); } }