mirror of
https://github.com/twonlyapp/twonly-app.git
synced 2026-04-18 17:32:54 +00:00
new: screen lock
This commit is contained in:
parent
f419b3709d
commit
391646d243
15 changed files with 257 additions and 15 deletions
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
## 0.1.4
|
## 0.1.4
|
||||||
|
|
||||||
|
- New: Screen lock for twonly (Can be enabled in the settings.)
|
||||||
- Fix: Several minor issues with the user interface
|
- Fix: Several minor issues with the user interface
|
||||||
|
|
||||||
## 0.1.3
|
## 0.1.3
|
||||||
|
|
|
||||||
26
lib/app.dart
26
lib/app.dart
|
|
@ -19,6 +19,7 @@ import 'package:twonly/src/views/home.view.dart';
|
||||||
import 'package:twonly/src/views/onboarding/onboarding.view.dart';
|
import 'package:twonly/src/views/onboarding/onboarding.view.dart';
|
||||||
import 'package:twonly/src/views/onboarding/register.view.dart';
|
import 'package:twonly/src/views/onboarding/register.view.dart';
|
||||||
import 'package:twonly/src/views/settings/backup/setup_backup.view.dart';
|
import 'package:twonly/src/views/settings/backup/setup_backup.view.dart';
|
||||||
|
import 'package:twonly/src/views/unlock_twonly.view.dart';
|
||||||
|
|
||||||
class App extends StatefulWidget {
|
class App extends StatefulWidget {
|
||||||
const App({super.key});
|
const App({super.key});
|
||||||
|
|
@ -36,9 +37,9 @@ class _AppState extends State<App> with WidgetsBindingObserver {
|
||||||
WidgetsBinding.instance.addObserver(this);
|
WidgetsBinding.instance.addObserver(this);
|
||||||
|
|
||||||
globalCallbackConnectionState = ({required isConnected}) async {
|
globalCallbackConnectionState = ({required isConnected}) async {
|
||||||
await context
|
await context.read<CustomChangeProvider>().updateConnectionState(
|
||||||
.read<CustomChangeProvider>()
|
isConnected,
|
||||||
.updateConnectionState(isConnected);
|
);
|
||||||
await setUserPlan();
|
await setUserPlan();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -134,6 +135,7 @@ class _AppMainWidgetState extends State<AppMainWidget> {
|
||||||
bool _showOnboarding = true;
|
bool _showOnboarding = true;
|
||||||
bool _isLoaded = false;
|
bool _isLoaded = false;
|
||||||
bool _skipBackup = false;
|
bool _skipBackup = false;
|
||||||
|
bool _isTwonlyLocked = true;
|
||||||
int _initialPage = 0;
|
int _initialPage = 0;
|
||||||
|
|
||||||
(Future<int>?, bool) _proofOfWork = (null, false);
|
(Future<int>?, bool) _proofOfWork = (null, false);
|
||||||
|
|
@ -149,6 +151,10 @@ class _AppMainWidgetState extends State<AppMainWidget> {
|
||||||
_isUserCreated = await isUserCreated();
|
_isUserCreated = await isUserCreated();
|
||||||
|
|
||||||
if (_isUserCreated) {
|
if (_isUserCreated) {
|
||||||
|
if (_isTwonlyLocked) {
|
||||||
|
// do not change in case twonly was already unlocked at some point
|
||||||
|
_isTwonlyLocked = gUser.screenLockEnabled;
|
||||||
|
}
|
||||||
if (gUser.appVersion < 62) {
|
if (gUser.appVersion < 62) {
|
||||||
_showDatabaseMigration = true;
|
_showDatabaseMigration = true;
|
||||||
}
|
}
|
||||||
|
|
@ -164,8 +170,10 @@ class _AppMainWidgetState extends State<AppMainWidget> {
|
||||||
if (proof != null) {
|
if (proof != null) {
|
||||||
Log.info('Starting with proof of work calculation.');
|
Log.info('Starting with proof of work calculation.');
|
||||||
// Starting with the proof of work.
|
// Starting with the proof of work.
|
||||||
_proofOfWork =
|
_proofOfWork = (
|
||||||
(calculatePoW(proof.prefix, proof.difficulty.toInt()), false);
|
calculatePoW(proof.prefix, proof.difficulty.toInt()),
|
||||||
|
false,
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
_proofOfWork = (null, disabled);
|
_proofOfWork = (null, disabled);
|
||||||
}
|
}
|
||||||
|
|
@ -187,7 +195,13 @@ class _AppMainWidgetState extends State<AppMainWidget> {
|
||||||
if (_showDatabaseMigration) {
|
if (_showDatabaseMigration) {
|
||||||
child = const Center(child: Text('Please reinstall twonly.'));
|
child = const Center(child: Text('Please reinstall twonly.'));
|
||||||
} else if (_isUserCreated) {
|
} else if (_isUserCreated) {
|
||||||
if (gUser.twonlySafeBackup == null && !_skipBackup) {
|
if (_isTwonlyLocked) {
|
||||||
|
child = UnlockTwonlyView(
|
||||||
|
callbackOnSuccess: () => setState(() {
|
||||||
|
_isTwonlyLocked = false;
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
} else if (gUser.twonlySafeBackup == null && !_skipBackup) {
|
||||||
child = SetupBackupView(
|
child = SetupBackupView(
|
||||||
callBack: () {
|
callBack: () {
|
||||||
_skipBackup = true;
|
_skipBackup = true;
|
||||||
|
|
|
||||||
|
|
@ -3087,6 +3087,48 @@ abstract class AppLocalizations {
|
||||||
/// In en, this message translates to:
|
/// In en, this message translates to:
|
||||||
/// **'Your QR code'**
|
/// **'Your QR code'**
|
||||||
String get profileYourQrCode;
|
String get profileYourQrCode;
|
||||||
|
|
||||||
|
/// No description provided for @settingsScreenLock.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Screen lock'**
|
||||||
|
String get settingsScreenLock;
|
||||||
|
|
||||||
|
/// No description provided for @settingsScreenLockSubtitle.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'To open twonly, you\'ll need to use your smartphone\'s unlock feature.'**
|
||||||
|
String get settingsScreenLockSubtitle;
|
||||||
|
|
||||||
|
/// No description provided for @settingsScreenLockAuthMessageEnable.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Use the screen lock from twonly.'**
|
||||||
|
String get settingsScreenLockAuthMessageEnable;
|
||||||
|
|
||||||
|
/// No description provided for @settingsScreenLockAuthMessageDisable.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Disable the screen lock from twonly.'**
|
||||||
|
String get settingsScreenLockAuthMessageDisable;
|
||||||
|
|
||||||
|
/// No description provided for @unlockTwonly.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Unlock twonly'**
|
||||||
|
String get unlockTwonly;
|
||||||
|
|
||||||
|
/// No description provided for @unlockTwonlyTryAgain.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Try again'**
|
||||||
|
String get unlockTwonlyTryAgain;
|
||||||
|
|
||||||
|
/// No description provided for @unlockTwonlyDesc.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Use your phone\'s unlock settings to unlock twonly'**
|
||||||
|
String get unlockTwonlyDesc;
|
||||||
}
|
}
|
||||||
|
|
||||||
class _AppLocalizationsDelegate
|
class _AppLocalizationsDelegate
|
||||||
|
|
|
||||||
|
|
@ -1729,4 +1729,29 @@ class AppLocalizationsDe extends AppLocalizations {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get profileYourQrCode => 'Dein QR-Code';
|
String get profileYourQrCode => 'Dein QR-Code';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get settingsScreenLock => 'Bildschirmsperre';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get settingsScreenLockSubtitle =>
|
||||||
|
'Um twonly zu öffnen, wird die Entsperrfunktion deines Smartphones verwenden.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get settingsScreenLockAuthMessageEnable =>
|
||||||
|
'Bildschirmsperre von twonly verwenden';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get settingsScreenLockAuthMessageDisable =>
|
||||||
|
'Bildschirmsperre von twonly deaktivieren.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get unlockTwonly => 'twonly entsperren';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get unlockTwonlyTryAgain => 'Erneut versuchen';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get unlockTwonlyDesc =>
|
||||||
|
'Entsperre twonly über die Sperreinstellungen deines Handys';
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1717,4 +1717,29 @@ class AppLocalizationsEn extends AppLocalizations {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get profileYourQrCode => 'Your QR code';
|
String get profileYourQrCode => 'Your QR code';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get settingsScreenLock => 'Screen lock';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get settingsScreenLockSubtitle =>
|
||||||
|
'To open twonly, you\'ll need to use your smartphone\'s unlock feature.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get settingsScreenLockAuthMessageEnable =>
|
||||||
|
'Use the screen lock from twonly.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get settingsScreenLockAuthMessageDisable =>
|
||||||
|
'Disable the screen lock from twonly.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get unlockTwonly => 'Unlock twonly';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get unlockTwonlyTryAgain => 'Try again';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get unlockTwonlyDesc =>
|
||||||
|
'Use your phone\'s unlock settings to unlock twonly';
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1717,4 +1717,29 @@ class AppLocalizationsSv extends AppLocalizations {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get profileYourQrCode => 'Your QR code';
|
String get profileYourQrCode => 'Your QR code';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get settingsScreenLock => 'Screen lock';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get settingsScreenLockSubtitle =>
|
||||||
|
'To open twonly, you\'ll need to use your smartphone\'s unlock feature.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get settingsScreenLockAuthMessageEnable =>
|
||||||
|
'Use the screen lock from twonly.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get settingsScreenLockAuthMessageDisable =>
|
||||||
|
'Disable the screen lock from twonly.';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get unlockTwonly => 'Unlock twonly';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get unlockTwonlyTryAgain => 'Try again';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get unlockTwonlyDesc =>
|
||||||
|
'Use your phone\'s unlock settings to unlock twonly';
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -87,6 +87,9 @@ class UserData {
|
||||||
@JsonKey(defaultValue: false)
|
@JsonKey(defaultValue: false)
|
||||||
bool allowErrorTrackingViaSentry = false;
|
bool allowErrorTrackingViaSentry = false;
|
||||||
|
|
||||||
|
@JsonKey(defaultValue: false)
|
||||||
|
bool screenLockEnabled = false;
|
||||||
|
|
||||||
// -- Custom DATA --
|
// -- Custom DATA --
|
||||||
|
|
||||||
@JsonKey(defaultValue: 100_000)
|
@JsonKey(defaultValue: 100_000)
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ UserData _$UserDataFromJson(Map<String, dynamic> json) =>
|
||||||
..requestedAudioPermission =
|
..requestedAudioPermission =
|
||||||
json['requestedAudioPermission'] as bool? ?? false
|
json['requestedAudioPermission'] as bool? ?? false
|
||||||
..videoStabilizationEnabled =
|
..videoStabilizationEnabled =
|
||||||
json['videoStabilizationEnabled'] as bool? ?? false
|
json['videoStabilizationEnabled'] as bool? ?? true
|
||||||
..showFeedbackShortcut = json['showFeedbackShortcut'] as bool? ?? true
|
..showFeedbackShortcut = json['showFeedbackShortcut'] as bool? ?? true
|
||||||
..showShowImagePreviewWhenSending =
|
..showShowImagePreviewWhenSending =
|
||||||
json['showShowImagePreviewWhenSending'] as bool? ?? false
|
json['showShowImagePreviewWhenSending'] as bool? ?? false
|
||||||
|
|
@ -62,6 +62,7 @@ UserData _$UserDataFromJson(Map<String, dynamic> json) =>
|
||||||
: DateTime.parse(json['signalLastSignedPreKeyUpdated'] as String)
|
: DateTime.parse(json['signalLastSignedPreKeyUpdated'] as String)
|
||||||
..allowErrorTrackingViaSentry =
|
..allowErrorTrackingViaSentry =
|
||||||
json['allowErrorTrackingViaSentry'] as bool? ?? false
|
json['allowErrorTrackingViaSentry'] as bool? ?? false
|
||||||
|
..screenLockEnabled = json['screenLockEnabled'] as bool? ?? false
|
||||||
..currentPreKeyIndexStart =
|
..currentPreKeyIndexStart =
|
||||||
(json['currentPreKeyIndexStart'] as num?)?.toInt() ?? 100000
|
(json['currentPreKeyIndexStart'] as num?)?.toInt() ?? 100000
|
||||||
..currentSignedPreKeyIndexStart =
|
..currentSignedPreKeyIndexStart =
|
||||||
|
|
@ -123,6 +124,7 @@ Map<String, dynamic> _$UserDataToJson(UserData instance) => <String, dynamic>{
|
||||||
'signalLastSignedPreKeyUpdated': instance.signalLastSignedPreKeyUpdated
|
'signalLastSignedPreKeyUpdated': instance.signalLastSignedPreKeyUpdated
|
||||||
?.toIso8601String(),
|
?.toIso8601String(),
|
||||||
'allowErrorTrackingViaSentry': instance.allowErrorTrackingViaSentry,
|
'allowErrorTrackingViaSentry': instance.allowErrorTrackingViaSentry,
|
||||||
|
'screenLockEnabled': instance.screenLockEnabled,
|
||||||
'currentPreKeyIndexStart': instance.currentPreKeyIndexStart,
|
'currentPreKeyIndexStart': instance.currentPreKeyIndexStart,
|
||||||
'currentSignedPreKeyIndexStart': instance.currentSignedPreKeyIndexStart,
|
'currentSignedPreKeyIndexStart': instance.currentSignedPreKeyIndexStart,
|
||||||
'lastChangeLogHash': instance.lastChangeLogHash,
|
'lastChangeLogHash': instance.lastChangeLogHash,
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:collection';
|
import 'dart:collection';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
|
|
@ -14,13 +15,13 @@ import 'package:twonly/src/model/memory_item.model.dart';
|
||||||
import 'package:twonly/src/services/api/messages.dart';
|
import 'package:twonly/src/services/api/messages.dart';
|
||||||
import 'package:twonly/src/services/notifications/background.notifications.dart';
|
import 'package:twonly/src/services/notifications/background.notifications.dart';
|
||||||
import 'package:twonly/src/utils/misc.dart';
|
import 'package:twonly/src/utils/misc.dart';
|
||||||
|
import 'package:twonly/src/views/chats/chat_messages_components/blink.component.dart';
|
||||||
import 'package:twonly/src/views/chats/chat_messages_components/chat_group_action.dart';
|
import 'package:twonly/src/views/chats/chat_messages_components/chat_group_action.dart';
|
||||||
import 'package:twonly/src/views/chats/chat_messages_components/chat_list_entry.dart';
|
import 'package:twonly/src/views/chats/chat_messages_components/chat_list_entry.dart';
|
||||||
import 'package:twonly/src/views/chats/chat_messages_components/entries/chat_date_chip.dart';
|
import 'package:twonly/src/views/chats/chat_messages_components/entries/chat_date_chip.dart';
|
||||||
import 'package:twonly/src/views/chats/chat_messages_components/message_input.dart';
|
import 'package:twonly/src/views/chats/chat_messages_components/message_input.dart';
|
||||||
import 'package:twonly/src/views/chats/chat_messages_components/response_container.dart';
|
import 'package:twonly/src/views/chats/chat_messages_components/response_container.dart';
|
||||||
import 'package:twonly/src/views/components/avatar_icon.component.dart';
|
import 'package:twonly/src/views/components/avatar_icon.component.dart';
|
||||||
import 'package:twonly/src/views/chats/chat_messages_components/blink.component.dart';
|
|
||||||
import 'package:twonly/src/views/components/flame.dart';
|
import 'package:twonly/src/views/components/flame.dart';
|
||||||
import 'package:twonly/src/views/components/verified_shield.dart';
|
import 'package:twonly/src/views/components/verified_shield.dart';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,10 +17,10 @@ import 'package:twonly/src/views/chats/chat_messages_components/entries/chat_con
|
||||||
import 'package:twonly/src/views/chats/chat_messages_components/entries/chat_flame_restored.entry.dart';
|
import 'package:twonly/src/views/chats/chat_messages_components/entries/chat_flame_restored.entry.dart';
|
||||||
import 'package:twonly/src/views/chats/chat_messages_components/entries/chat_media_entry.dart';
|
import 'package:twonly/src/views/chats/chat_messages_components/entries/chat_media_entry.dart';
|
||||||
import 'package:twonly/src/views/chats/chat_messages_components/entries/chat_text_entry.dart';
|
import 'package:twonly/src/views/chats/chat_messages_components/entries/chat_text_entry.dart';
|
||||||
import 'package:twonly/src/views/chats/chat_messages_components/entries/chat_unkown.entry.dart';
|
import 'package:twonly/src/views/chats/chat_messages_components/entries/chat_unknown.entry.dart';
|
||||||
import 'package:twonly/src/views/chats/chat_messages_components/entries/common.dart';
|
import 'package:twonly/src/views/chats/chat_messages_components/entries/common.dart';
|
||||||
import 'package:twonly/src/views/chats/chat_messages_components/message_reply_drag.dart';
|
|
||||||
import 'package:twonly/src/views/chats/chat_messages_components/message_context_menu.dart';
|
import 'package:twonly/src/views/chats/chat_messages_components/message_context_menu.dart';
|
||||||
|
import 'package:twonly/src/views/chats/chat_messages_components/message_reply_drag.dart';
|
||||||
import 'package:twonly/src/views/chats/chat_messages_components/response_container.dart';
|
import 'package:twonly/src/views/chats/chat_messages_components/response_container.dart';
|
||||||
import 'package:twonly/src/views/components/avatar_icon.component.dart';
|
import 'package:twonly/src/views/components/avatar_icon.component.dart';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ class _SlidingResponseWidgetState extends State<MessageReplyDrag> {
|
||||||
_animatedScale = 1.3;
|
_animatedScale = 1.3;
|
||||||
});
|
});
|
||||||
|
|
||||||
await Future.delayed(Duration(milliseconds: 50));
|
await Future.delayed(const Duration(milliseconds: 50));
|
||||||
|
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
setState(() {
|
setState(() {
|
||||||
|
|
|
||||||
|
|
@ -190,7 +190,7 @@ class _MessageSendStateIconState extends State<MessageSendStateIcon> {
|
||||||
hasLoader = true;
|
hasLoader = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (message.mediaStored) {
|
if (message.mediaStored && message.openedAt != null) {
|
||||||
icon = FaIcon(FontAwesomeIcons.floppyDisk, size: 12, color: color);
|
icon = FaIcon(FontAwesomeIcons.floppyDisk, size: 12, color: color);
|
||||||
text = context.lang.messageStoredInGallery;
|
text = context.lang.messageStoredInGallery;
|
||||||
}
|
}
|
||||||
|
|
@ -275,7 +275,6 @@ class _MessageSendStateIconState extends State<MessageSendStateIcon> {
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
// Log.info("DISPLAY REACTION");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (widget.group != null &&
|
if (widget.group != null &&
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ import 'package:go_router/go_router.dart';
|
||||||
import 'package:twonly/globals.dart';
|
import 'package:twonly/globals.dart';
|
||||||
import 'package:twonly/src/constants/routes.keys.dart';
|
import 'package:twonly/src/constants/routes.keys.dart';
|
||||||
import 'package:twonly/src/utils/misc.dart';
|
import 'package:twonly/src/utils/misc.dart';
|
||||||
|
import 'package:twonly/src/utils/storage.dart';
|
||||||
|
|
||||||
class PrivacyView extends StatefulWidget {
|
class PrivacyView extends StatefulWidget {
|
||||||
const PrivacyView({super.key});
|
const PrivacyView({super.key});
|
||||||
|
|
@ -17,6 +18,20 @@ class _PrivacyViewState extends State<PrivacyView> {
|
||||||
super.initState();
|
super.initState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> toggleAuthRequirementOnStartup() async {
|
||||||
|
final isAuth = await authenticateUser(
|
||||||
|
gUser.screenLockEnabled
|
||||||
|
? context.lang.settingsScreenLockAuthMessageDisable
|
||||||
|
: context.lang.settingsScreenLockAuthMessageEnable,
|
||||||
|
);
|
||||||
|
if (!isAuth) return;
|
||||||
|
await updateUserdata((u) {
|
||||||
|
u.screenLockEnabled = !u.screenLockEnabled;
|
||||||
|
return u;
|
||||||
|
});
|
||||||
|
setState(() {});
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
|
|
@ -43,6 +58,15 @@ class _PrivacyViewState extends State<PrivacyView> {
|
||||||
),
|
),
|
||||||
onTap: () => context.push(Routes.settingsPrivacyBlockUsers),
|
onTap: () => context.push(Routes.settingsPrivacyBlockUsers),
|
||||||
),
|
),
|
||||||
|
ListTile(
|
||||||
|
title: Text(context.lang.settingsScreenLock),
|
||||||
|
subtitle: Text(context.lang.settingsScreenLockSubtitle),
|
||||||
|
onTap: toggleAuthRequirementOnStartup,
|
||||||
|
trailing: Switch(
|
||||||
|
value: gUser.screenLockEnabled,
|
||||||
|
onChanged: (a) => toggleAuthRequirementOnStartup(),
|
||||||
|
),
|
||||||
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
title: Text(context.lang.contactVerifyNumberTitle),
|
title: Text(context.lang.contactVerifyNumberTitle),
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
|
|
|
||||||
81
lib/src/views/unlock_twonly.view.dart
Normal file
81
lib/src/views/unlock_twonly.view.dart
Normal file
|
|
@ -0,0 +1,81 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||||
|
import 'package:twonly/src/utils/misc.dart';
|
||||||
|
|
||||||
|
class UnlockTwonlyView extends StatefulWidget {
|
||||||
|
const UnlockTwonlyView({required this.callbackOnSuccess, super.key});
|
||||||
|
|
||||||
|
final void Function() callbackOnSuccess;
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<UnlockTwonlyView> createState() => _UnlockTwonlyViewState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _UnlockTwonlyViewState extends State<UnlockTwonlyView> {
|
||||||
|
Future<void> _unlockTwonly() async {
|
||||||
|
final isAuth = await authenticateUser(context.lang.unlockTwonly);
|
||||||
|
if (isAuth) {
|
||||||
|
widget.callbackOnSuccess();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
|
// _unlockTwonly();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
body: SafeArea(
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
|
children: [
|
||||||
|
const Spacer(),
|
||||||
|
|
||||||
|
const Icon(
|
||||||
|
FontAwesomeIcons.lock,
|
||||||
|
size: 40,
|
||||||
|
),
|
||||||
|
const SizedBox(height: 24),
|
||||||
|
|
||||||
|
Text(
|
||||||
|
context.lang.unlockTwonly,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: const TextStyle(fontSize: 24),
|
||||||
|
),
|
||||||
|
|
||||||
|
const Spacer(),
|
||||||
|
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.all(30),
|
||||||
|
child: Text(
|
||||||
|
context.lang.unlockTwonlyDesc,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 14,
|
||||||
|
color: Colors.grey,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
|
||||||
|
Center(
|
||||||
|
child: FilledButton(
|
||||||
|
onPressed: _unlockTwonly,
|
||||||
|
child: Text(context.lang.unlockTwonlyTryAgain),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 24),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue