ente/lib/ui/tools/lock_screen.dart

145 lines
4.5 KiB
Dart
Raw Normal View History

2023-11-20 11:36:11 +00:00
import "dart:io";
2021-03-21 06:27:42 +00:00
import 'package:flutter/material.dart';
2021-03-21 08:32:10 +00:00
import 'package:logging/logging.dart';
2023-11-20 11:36:11 +00:00
import "package:photos/l10n/l10n.dart";
2022-09-05 09:51:39 +00:00
import 'package:photos/ui/common/gradient_button.dart';
2022-07-01 14:39:02 +00:00
import 'package:photos/ui/tools/app_lock.dart';
2021-03-21 06:27:42 +00:00
import 'package:photos/utils/auth_util.dart';
class LockScreen extends StatefulWidget {
const LockScreen({Key? key}) : super(key: key);
2021-03-21 06:27:42 +00:00
@override
2022-07-03 09:45:00 +00:00
State<LockScreen> createState() => _LockScreenState();
2021-03-21 06:27:42 +00:00
}
class _LockScreenState extends State<LockScreen> with WidgetsBindingObserver {
2021-03-21 08:32:10 +00:00
final _logger = Logger("LockScreen");
bool _isShowingLockScreen = false;
bool _hasPlacedAppInBackground = false;
bool _hasAuthenticationFailed = false;
int? lastAuthenticatingTime;
2021-03-21 08:32:10 +00:00
@override
void initState() {
2023-11-20 11:36:11 +00:00
_logger.info("initiatingState");
2021-03-21 08:32:10 +00:00
super.initState();
WidgetsBinding.instance.addObserver(this);
2023-11-20 11:36:11 +00:00
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
if (isNonMobileIOSDevice()) {
_logger.info('ignore init for non mobile iOS device');
return;
}
_showLockScreen(source: "postFrameInit");
});
2021-03-21 08:32:10 +00:00
}
2021-03-21 06:27:42 +00:00
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
2022-06-06 06:19:20 +00:00
child: Column(
2022-06-11 08:23:52 +00:00
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Stack(
alignment: Alignment.center,
children: [
Opacity(
opacity: 0.2,
child: Image.asset('assets/loading_photos_background.png'),
2022-06-11 08:23:52 +00:00
),
SizedBox(
2023-05-10 03:42:02 +00:00
width: 180,
2022-09-05 09:51:39 +00:00
child: GradientButton(
2023-11-20 11:36:11 +00:00
text: context.l10n.unlock,
2022-09-05 09:51:39 +00:00
iconData: Icons.lock_open_outlined,
2022-06-11 08:23:52 +00:00
onTap: () async {
_showLockScreen(source: "tapUnlock");
2022-06-11 08:23:52 +00:00
},
2022-06-06 06:19:20 +00:00
),
2022-06-11 08:23:52 +00:00
),
],
),
],
),
2021-03-21 06:27:42 +00:00
),
);
}
2021-03-21 08:32:10 +00:00
2023-11-20 11:36:11 +00:00
bool isNonMobileIOSDevice() {
if (Platform.isAndroid) {
return false;
}
var shortestSide = MediaQuery.of(context).size.shortestSide;
return shortestSide > 600 ? true : false;
}
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
_logger.info(state.toString());
2023-11-02 06:34:06 +00:00
if (state == AppLifecycleState.resumed && !_isShowingLockScreen) {
// This is triggered either when the lock screen is dismissed or when
// the app is brought to foreground
_hasPlacedAppInBackground = false;
final bool didAuthInLast5Seconds = lastAuthenticatingTime != null &&
DateTime.now().millisecondsSinceEpoch - lastAuthenticatingTime! <
5000;
if (!_hasAuthenticationFailed && !didAuthInLast5Seconds) {
// Show the lock screen again only if the app is resuming from the
// background, and not when the lock screen was explicitly dismissed
2023-11-20 11:36:11 +00:00
Future.delayed(
Duration.zero,
() => _showLockScreen(source: "lifeCycle"),
);
} else {
_hasAuthenticationFailed = false; // Reset failure state
}
} else if (state == AppLifecycleState.paused ||
state == AppLifecycleState.inactive) {
// This is triggered either when the lock screen pops up or when
// the app is pushed to background
if (!_isShowingLockScreen) {
_hasPlacedAppInBackground = true;
_hasAuthenticationFailed = false; // reset failure state
}
}
}
@override
void dispose() {
2023-11-20 11:36:11 +00:00
_logger.info('disposing');
WidgetsBinding.instance.removeObserver(this);
super.dispose();
}
Future<void> _showLockScreen({String source = ''}) async {
2023-11-02 06:34:06 +00:00
final int id = DateTime.now().millisecondsSinceEpoch;
_logger.info("Showing lock screen $source $id");
2021-03-21 08:32:10 +00:00
try {
_isShowingLockScreen = true;
final result = await requestAuthentication(
context,
2023-11-20 11:36:11 +00:00
context.l10n.authToViewYourMemories,
2022-06-11 08:23:52 +00:00
);
2023-11-02 06:34:06 +00:00
_logger.finest("LockScreen Result $result $id");
_isShowingLockScreen = false;
2021-03-21 08:32:10 +00:00
if (result) {
lastAuthenticatingTime = DateTime.now().millisecondsSinceEpoch;
AppLock.of(context)!.didUnlock();
} else {
if (!_hasPlacedAppInBackground) {
// Treat this as a failure only if user did not explicitly
// put the app in background
_hasAuthenticationFailed = true;
_logger.info("Authentication failed");
}
2021-03-21 08:32:10 +00:00
}
2021-08-09 08:21:18 +00:00
} catch (e, s) {
2023-11-20 11:36:11 +00:00
_isShowingLockScreen = false;
2021-08-09 08:21:18 +00:00
_logger.severe(e, s);
2021-03-21 08:32:10 +00:00
}
}
2021-03-21 06:27:42 +00:00
}