feat: New simplified lockscreen design
This commit is contained in:
parent
1c863fe769
commit
90789d9feb
4 changed files with 121 additions and 76 deletions
|
|
@ -2519,5 +2519,13 @@
|
|||
"invite": "Invite",
|
||||
"requests": "Requests",
|
||||
"inviteGroupChat": "📨 Invite group chat",
|
||||
"invitePrivateChat": "📨 Invite private chat"
|
||||
"invitePrivateChat": "📨 Invite private chat",
|
||||
"invalidInput": "Invalid input!",
|
||||
"wrongPinEntered": "Wrong pin entered! Try again in {seconds} seconds...",
|
||||
"@wrongPinEntered": {
|
||||
"type": "text",
|
||||
"placeholders": {
|
||||
"seconds": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,88 +1,134 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:flutter_app_lock/flutter_app_lock.dart';
|
||||
import 'package:flutter_gen/gen_l10n/l10n.dart';
|
||||
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
||||
import 'package:pin_code_text_field/pin_code_text_field.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
import 'package:fluffychat/config/app_config.dart';
|
||||
import 'package:fluffychat/config/setting_keys.dart';
|
||||
import 'package:fluffychat/config/themes.dart';
|
||||
import 'layouts/login_scaffold.dart';
|
||||
import 'package:fluffychat/utils/error_reporter.dart';
|
||||
import 'package:fluffychat/widgets/theme_builder.dart';
|
||||
|
||||
class LockScreen extends StatefulWidget {
|
||||
const LockScreen({Key? key}) : super(key: key);
|
||||
const LockScreen({super.key});
|
||||
|
||||
@override
|
||||
LockScreenState createState() => LockScreenState();
|
||||
State<LockScreen> createState() => _LockScreenState();
|
||||
}
|
||||
|
||||
class LockScreenState extends State<LockScreen> {
|
||||
class _LockScreenState extends State<LockScreen> {
|
||||
String? _errorText;
|
||||
int _coolDownSeconds = 5;
|
||||
bool _inputBlocked = false;
|
||||
final TextEditingController _textEditingController = TextEditingController();
|
||||
final FocusNode _focusNode = FocusNode();
|
||||
bool _wrongInput = false;
|
||||
|
||||
void tryUnlock(BuildContext context) async {
|
||||
setState(() {
|
||||
_errorText = null;
|
||||
});
|
||||
if (_textEditingController.text.length < 4) return;
|
||||
|
||||
final enteredPin = int.tryParse(_textEditingController.text);
|
||||
if (enteredPin == null || _textEditingController.text.length != 4) {
|
||||
setState(() {
|
||||
_errorText = L10n.of(context)!.invalidInput;
|
||||
});
|
||||
_textEditingController.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
final correctPin = int.tryParse(
|
||||
await const FlutterSecureStorage().read(key: SettingKeys.appLockKey) ??
|
||||
'',
|
||||
);
|
||||
if (correctPin == null) {
|
||||
ErrorReporter(
|
||||
context,
|
||||
'Lockscreen was displayed but pin was not stored correctly',
|
||||
).onErrorCallback(
|
||||
Exception(),
|
||||
);
|
||||
AppLock.of(context)!.didUnlock();
|
||||
return;
|
||||
}
|
||||
|
||||
if (correctPin == enteredPin) {
|
||||
AppLock.of(context)!.didUnlock();
|
||||
return;
|
||||
}
|
||||
setState(() {
|
||||
_errorText = L10n.of(context)!.wrongPinEntered(_coolDownSeconds);
|
||||
_inputBlocked = true;
|
||||
});
|
||||
Future.delayed(Duration(seconds: _coolDownSeconds)).then((_) {
|
||||
setState(() {
|
||||
_inputBlocked = false;
|
||||
_coolDownSeconds *= 2;
|
||||
_errorText = null;
|
||||
});
|
||||
});
|
||||
_textEditingController.clear();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MaterialApp(
|
||||
theme: FluffyThemes.buildTheme(context, Brightness.light),
|
||||
darkTheme: FluffyThemes.buildTheme(context, Brightness.dark),
|
||||
localizationsDelegates: L10n.localizationsDelegates,
|
||||
supportedLocales: L10n.supportedLocales,
|
||||
home: Builder(
|
||||
builder: (context) => LoginScaffold(
|
||||
appBar: AppBar(
|
||||
automaticallyImplyLeading: false,
|
||||
elevation: 0,
|
||||
centerTitle: true,
|
||||
title: Text(L10n.of(context)!.pleaseEnterYourPin),
|
||||
backgroundColor: Colors.transparent,
|
||||
),
|
||||
body: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).colorScheme.background,
|
||||
gradient: LinearGradient(
|
||||
begin: Alignment.topRight,
|
||||
end: Alignment.bottomLeft,
|
||||
stops: const [
|
||||
0.1,
|
||||
0.4,
|
||||
0.6,
|
||||
0.9,
|
||||
],
|
||||
colors: [
|
||||
Theme.of(context).secondaryHeaderColor.withAlpha(16),
|
||||
Theme.of(context).primaryColor.withAlpha(16),
|
||||
Theme.of(context).colorScheme.secondary.withAlpha(16),
|
||||
Theme.of(context).colorScheme.background.withAlpha(16),
|
||||
],
|
||||
),
|
||||
return ThemeBuilder(
|
||||
builder: (context, themeMode, primaryColor) => MaterialApp(
|
||||
title: AppConfig.applicationName,
|
||||
themeMode: themeMode,
|
||||
theme: FluffyThemes.buildTheme(context, Brightness.light, primaryColor),
|
||||
darkTheme:
|
||||
FluffyThemes.buildTheme(context, Brightness.dark, primaryColor),
|
||||
localizationsDelegates: L10n.localizationsDelegates,
|
||||
supportedLocales: L10n.supportedLocales,
|
||||
home: Builder(
|
||||
builder: (context) => Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text(L10n.of(context)!.pleaseEnterYourPin),
|
||||
centerTitle: true,
|
||||
),
|
||||
alignment: Alignment.center,
|
||||
child: PinCodeTextField(
|
||||
autofocus: true,
|
||||
controller: _textEditingController,
|
||||
focusNode: _focusNode,
|
||||
pinBoxRadius: AppConfig.borderRadius,
|
||||
pinTextStyle: const TextStyle(fontSize: 32),
|
||||
hideCharacter: true,
|
||||
hasError: _wrongInput,
|
||||
onDone: (String input) async {
|
||||
if (input ==
|
||||
await ([TargetPlatform.linux]
|
||||
.contains(Theme.of(context).platform)
|
||||
? SharedPreferences.getInstance().then(
|
||||
(prefs) => prefs.getString(SettingKeys.appLockKey),
|
||||
)
|
||||
: const FlutterSecureStorage()
|
||||
.read(key: SettingKeys.appLockKey))) {
|
||||
AppLock.of(context)!.didUnlock();
|
||||
} else {
|
||||
_textEditingController.clear();
|
||||
setState(() => _wrongInput = true);
|
||||
_focusNode.requestFocus();
|
||||
}
|
||||
},
|
||||
extendBodyBehindAppBar: true,
|
||||
body: Center(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: ConstrainedBox(
|
||||
constraints: const BoxConstraints(
|
||||
maxWidth: FluffyThemes.columnWidth,
|
||||
),
|
||||
child: ListView(
|
||||
shrinkWrap: true,
|
||||
children: [
|
||||
Center(
|
||||
child: _inputBlocked
|
||||
? const CircularProgressIndicator.adaptive()
|
||||
: Image.asset(
|
||||
'assets/info-logo.png',
|
||||
width: 256,
|
||||
),
|
||||
),
|
||||
TextField(
|
||||
controller: _textEditingController,
|
||||
textInputAction: TextInputAction.done,
|
||||
keyboardType: TextInputType.number,
|
||||
obscureText: true,
|
||||
autofocus: true,
|
||||
textAlign: TextAlign.center,
|
||||
readOnly: _inputBlocked,
|
||||
onChanged: (_) => tryUnlock(context),
|
||||
onSubmitted: (_) => tryUnlock(context),
|
||||
style: const TextStyle(fontSize: 40),
|
||||
decoration: InputDecoration(
|
||||
errorText: _errorText,
|
||||
hintText: '****',
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -1357,14 +1357,6 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.4.0"
|
||||
pin_code_text_field:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: pin_code_text_field
|
||||
sha256: "3484c3ed4731327688734596d1fba1741f75da19366055116ecedcdffd87741a"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.8.0"
|
||||
platform:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
|
|||
|
|
@ -70,7 +70,6 @@ dependencies:
|
|||
pasteboard: ^0.2.0
|
||||
path_provider: ^2.0.9
|
||||
permission_handler: ^10.0.0
|
||||
pin_code_text_field: ^1.8.0
|
||||
provider: ^6.0.2
|
||||
punycode: ^1.0.0
|
||||
qr_code_scanner: ^1.0.0
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue