import 'package:flutter/material.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:matrix/matrix.dart'; import 'package:provider/provider.dart'; import 'package:fluffychat/config/setting_keys.dart'; import 'package:fluffychat/widgets/lock_screen.dart'; class AppLockWidget extends StatefulWidget { const AppLockWidget({ required this.child, required this.pincode, required this.clients, super.key, }); final List clients; final String? pincode; final Widget child; @override State createState() => AppLock(); } class AppLock extends State with WidgetsBindingObserver { String? _pincode; bool _isLocked = false; bool _paused = false; bool get isActive => _pincode != null && int.tryParse(_pincode!) != null && _pincode!.length == 4 && !_paused; @override void initState() { _pincode = widget.pincode; _isLocked = isActive; super.initState(); WidgetsBinding.instance.addObserver(this); WidgetsBinding.instance.addPostFrameCallback(_checkLoggedIn); } void _checkLoggedIn(_) async { if (widget.clients.any((client) => client.isLogged())) return; await changePincode(null); setState(() { _isLocked = false; }); } @override void didChangeAppLifecycleState(AppLifecycleState state) { if (isActive && state == AppLifecycleState.hidden && !_isLocked && isActive) { showLockScreen(); } } bool get isLocked => _isLocked; Future changePincode(String? pincode) async { await const FlutterSecureStorage().write( key: SettingKeys.appLockKey, value: pincode, ); _pincode = pincode; return; } bool unlock(String pincode) { final isCorrect = pincode == _pincode; if (isCorrect) { setState(() { _isLocked = false; }); } return isCorrect; } void showLockScreen() => setState(() { _isLocked = true; }); Future pauseWhile(Future future) async { _paused = true; try { return await future; } finally { _paused = false; } } static AppLock of(BuildContext context) => Provider.of( context, listen: false, ); @override Widget build(BuildContext context) => Provider( create: (_) => this, child: Stack( fit: StackFit.expand, children: [ widget.child, if (isLocked) const LockScreen(), ], ), ); }