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'); late PageController pageController; late 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 != null && Redux.store!.state.settingState!.pinCode!.length > 3; final bool pinSkipped = Redux.store!.state.settingState?.pinSkip == true; print('prevStateIsNotPaused=$prevStateIsNotPaused, pinIsExist=$pinIsExist, pinSkipped=$pinSkipped'); 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) { await Redux.store!.dispatch(changePinLockedFromSetting(true)); pushToLockScreen(); } sp.remove(backgroundedTimeKey); // clean sp.setInt(lastKnownStateKey, AppLifecycleState.resumed.index);// previous state } void pushToLockScreen() { Navigator.of(context).push(MaterialPageRoute( builder: (_) => WillPopScope( onWillPop: () async { return false; }, child: PassCodeScreen( title: 'Безопасность',) ) )); } _checkLockPin () async { final bool pinIsExist = Redux.store!.state.settingState?.pinCode != null && Redux.store!.state.settingState!.pinCode!.length > 3; final bool pinLocked = Redux.store!.state.settingState?.pinLocked == true; final sp = await SharedPreferences.getInstance(); sp.remove(backgroundedTimeKey); sp.setInt(lastKnownStateKey, AppLifecycleState.resumed.index);// previous state if ( pinIsExist == true && pinLocked == true ) { await Future.delayed(Duration(milliseconds: 50)); pushToLockScreen(); } } @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); } else if (choice.command == 'print') { _navigatorService.push(SettingsPrinterRoute); } else if (choice.command == 'bank') { _navigatorService.push(BankViewRoute); } else if (choice.command == 'tap2phone') { _navigatorService.push(BankSettingViewRoute); } } @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, ), ); } }