mirror of
https://github.com/ente-io/ente.git
synced 2025-05-30 14:23:24 +00:00
This does not fix the root cause, this is just a workaround. The root cause is somewhere in didChangeAppLifecycleState in app_lock.dart
191 lines
5.7 KiB
Dart
191 lines
5.7 KiB
Dart
import "dart:convert";
|
|
import "dart:typed_data";
|
|
|
|
import "package:ente_auth/core/configuration.dart";
|
|
import "package:ente_auth/utils/platform_util.dart";
|
|
import "package:ente_crypto_dart/ente_crypto_dart.dart";
|
|
import "package:flutter_secure_storage/flutter_secure_storage.dart";
|
|
import "package:privacy_screen/privacy_screen.dart";
|
|
import "package:shared_preferences/shared_preferences.dart";
|
|
|
|
class LockScreenSettings {
|
|
LockScreenSettings._privateConstructor();
|
|
|
|
static final LockScreenSettings instance =
|
|
LockScreenSettings._privateConstructor();
|
|
static const password = "ls_password";
|
|
static const pin = "ls_pin";
|
|
static const saltKey = "ls_salt";
|
|
static const keyInvalidAttempts = "ls_invalid_attempts";
|
|
static const lastInvalidAttemptTime = "ls_last_invalid_attempt_time";
|
|
static const autoLockTime = "ls_auto_lock_time";
|
|
static const keyHideAppContent = "ls_hide_app_content";
|
|
static const keyAppLockSet = "ls_is_app_lock_set";
|
|
static const keyHasMigratedLockScreenChanges =
|
|
"ls_has_migrated_lock_screen_changes";
|
|
final List<Duration> autoLockDurations = const [
|
|
Duration(milliseconds: 650),
|
|
Duration(seconds: 5),
|
|
Duration(seconds: 15),
|
|
Duration(minutes: 1),
|
|
Duration(minutes: 5),
|
|
Duration(minutes: 30),
|
|
];
|
|
|
|
late SharedPreferences _preferences;
|
|
late FlutterSecureStorage _secureStorage;
|
|
|
|
Future<void> init() async {
|
|
_secureStorage = const FlutterSecureStorage();
|
|
_preferences = await SharedPreferences.getInstance();
|
|
|
|
///Workaround for privacyScreen not working when app is killed and opened.
|
|
await setHideAppContent(getShouldHideAppContent());
|
|
|
|
/// Function to Check if the migration for lock screen changes has
|
|
/// already been done by checking a stored boolean value.
|
|
await runLockScreenChangesMigration();
|
|
}
|
|
|
|
Future<void> runLockScreenChangesMigration() async {
|
|
if (_preferences.getBool(keyHasMigratedLockScreenChanges) != null) {
|
|
return;
|
|
}
|
|
|
|
final bool passwordEnabled = await isPasswordSet();
|
|
final bool pinEnabled = await isPinSet();
|
|
final bool systemLockEnabled =
|
|
Configuration.instance.shouldShowSystemLockScreen();
|
|
|
|
if (passwordEnabled || pinEnabled || systemLockEnabled) {
|
|
await setAppLockEnabled(true);
|
|
}
|
|
|
|
await _preferences.setBool(keyHasMigratedLockScreenChanges, true);
|
|
}
|
|
|
|
Future<void> setHideAppContent(bool hideContent) async {
|
|
if (PlatformUtil.isDesktop()) return;
|
|
!hideContent
|
|
? PrivacyScreen.instance.disable()
|
|
: await PrivacyScreen.instance.enable(
|
|
iosOptions: const PrivacyIosOptions(
|
|
enablePrivacy: true,
|
|
),
|
|
androidOptions: const PrivacyAndroidOptions(
|
|
enableSecure: true,
|
|
),
|
|
blurEffect: PrivacyBlurEffect.extraLight,
|
|
);
|
|
await _preferences.setBool(keyHideAppContent, hideContent);
|
|
}
|
|
|
|
bool getShouldHideAppContent() {
|
|
return _preferences.getBool(keyHideAppContent) ?? true;
|
|
}
|
|
|
|
Future<void> setAutoLockTime(Duration duration) async {
|
|
await _preferences.setInt(autoLockTime, duration.inMilliseconds);
|
|
}
|
|
|
|
int getAutoLockTime() {
|
|
return _preferences.getInt(autoLockTime) ?? 5000;
|
|
}
|
|
|
|
Future<void> setLastInvalidAttemptTime(int time) async {
|
|
await _preferences.setInt(lastInvalidAttemptTime, time);
|
|
}
|
|
|
|
int getlastInvalidAttemptTime() {
|
|
return _preferences.getInt(lastInvalidAttemptTime) ?? 0;
|
|
}
|
|
|
|
int getInvalidAttemptCount() {
|
|
return _preferences.getInt(keyInvalidAttempts) ?? 0;
|
|
}
|
|
|
|
Future<void> setInvalidAttemptCount(int count) async {
|
|
await _preferences.setInt(keyInvalidAttempts, count);
|
|
}
|
|
|
|
Future<void> setAppLockEnabled(bool value) async {
|
|
await _preferences.setBool(keyAppLockSet, value);
|
|
}
|
|
|
|
bool getIsAppLockSet() {
|
|
return _preferences.getBool(keyAppLockSet) ?? false;
|
|
}
|
|
|
|
static Uint8List _generateSalt() {
|
|
return sodium.randombytes.buf(sodium.crypto.pwhash.saltBytes);
|
|
}
|
|
|
|
Future<void> setPin(String userPin) async {
|
|
await _secureStorage.delete(key: saltKey);
|
|
final salt = _generateSalt();
|
|
|
|
final hash = cryptoPwHash(
|
|
utf8.encode(userPin),
|
|
salt,
|
|
sodium.crypto.pwhash.memLimitInteractive,
|
|
sodium.crypto.pwhash.opsLimitSensitive,
|
|
sodium,
|
|
);
|
|
final String saltPin = base64Encode(salt);
|
|
final String hashedPin = base64Encode(hash);
|
|
|
|
await _secureStorage.write(key: saltKey, value: saltPin);
|
|
await _secureStorage.write(key: pin, value: hashedPin);
|
|
await _secureStorage.delete(key: password);
|
|
|
|
return;
|
|
}
|
|
|
|
Future<Uint8List?> getSalt() async {
|
|
final String? salt = await _secureStorage.read(key: saltKey);
|
|
if (salt == null) return null;
|
|
return base64Decode(salt);
|
|
}
|
|
|
|
Future<String?> getPin() async {
|
|
return _secureStorage.read(key: pin);
|
|
}
|
|
|
|
Future<void> setPassword(String pass) async {
|
|
await _secureStorage.delete(key: saltKey);
|
|
final salt = _generateSalt();
|
|
|
|
final hash = cryptoPwHash(
|
|
utf8.encode(pass),
|
|
salt,
|
|
sodium.crypto.pwhash.memLimitInteractive,
|
|
sodium.crypto.pwhash.opsLimitSensitive,
|
|
sodium,
|
|
);
|
|
|
|
await _secureStorage.write(key: saltKey, value: base64Encode(salt));
|
|
await _secureStorage.write(key: password, value: base64Encode(hash));
|
|
await _secureStorage.delete(key: pin);
|
|
|
|
return;
|
|
}
|
|
|
|
Future<String?> getPassword() async {
|
|
return _secureStorage.read(key: password);
|
|
}
|
|
|
|
Future<void> removePinAndPassword() async {
|
|
await _secureStorage.delete(key: saltKey);
|
|
await _secureStorage.delete(key: pin);
|
|
await _secureStorage.delete(key: password);
|
|
}
|
|
|
|
Future<bool> isPinSet() async {
|
|
return await _secureStorage.containsKey(key: pin);
|
|
}
|
|
|
|
Future<bool> isPasswordSet() async {
|
|
return await _secureStorage.containsKey(key: password);
|
|
}
|
|
}
|