115 lines
		
	
	
		
			2.5 KiB
		
	
	
	
		
			Dart
		
	
	
	
			
		
		
	
	
			115 lines
		
	
	
		
			2.5 KiB
		
	
	
	
		
			Dart
		
	
	
	
| 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:extera_next/config/setting_keys.dart';
 | |
| import 'package:extera_next/widgets/lock_screen.dart';
 | |
| 
 | |
| class AppLockWidget extends StatefulWidget {
 | |
|   const AppLockWidget({
 | |
|     required this.child,
 | |
|     required this.pincode,
 | |
|     required this.clients,
 | |
|     super.key,
 | |
|   });
 | |
| 
 | |
|   final List<Client> clients;
 | |
|   final String? pincode;
 | |
|   final Widget child;
 | |
| 
 | |
|   @override
 | |
|   State<AppLockWidget> createState() => AppLock();
 | |
| }
 | |
| 
 | |
| class AppLock extends State<AppLockWidget> 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<void> 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<T> pauseWhile<T>(Future<T> future) async {
 | |
|     _paused = true;
 | |
|     try {
 | |
|       return await future;
 | |
|     } finally {
 | |
|       _paused = false;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   static AppLock of(BuildContext context) => Provider.of<AppLock>(
 | |
|         context,
 | |
|         listen: false,
 | |
|       );
 | |
| 
 | |
|   @override
 | |
|   Widget build(BuildContext context) => Provider<AppLock>(
 | |
|         create: (_) => this,
 | |
|         child: Stack(
 | |
|           fit: StackFit.expand,
 | |
|           children: [
 | |
|             widget.child,
 | |
|             if (isLocked) const LockScreen(),
 | |
|           ],
 | |
|         ),
 | |
|       );
 | |
| }
 |