mirror of
https://github.com/twonlyapp/twonly-app.git
synced 2026-07-20 22:54:08 +00:00
pop until contact view after sucessfull verification
Some checks are pending
Flutter analyze & test / flutter_analyze_and_test (push) Waiting to run
Some checks are pending
Flutter analyze & test / flutter_analyze_and_test (push) Waiting to run
This commit is contained in:
parent
bb8f33e9d6
commit
6284345b57
4 changed files with 99 additions and 58 deletions
|
|
@ -3,6 +3,7 @@ import 'dart:typed_data';
|
||||||
|
|
||||||
import 'package:collection/collection.dart';
|
import 'package:collection/collection.dart';
|
||||||
import 'package:cryptography_plus/cryptography_plus.dart';
|
import 'package:cryptography_plus/cryptography_plus.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
import 'package:twonly/locator.dart';
|
import 'package:twonly/locator.dart';
|
||||||
import 'package:twonly/src/database/daos/contacts.dao.dart';
|
import 'package:twonly/src/database/daos/contacts.dao.dart';
|
||||||
import 'package:twonly/src/database/tables/contacts.table.dart';
|
import 'package:twonly/src/database/tables/contacts.table.dart';
|
||||||
|
|
@ -17,6 +18,24 @@ import 'package:twonly/src/utils/misc.dart';
|
||||||
import 'package:twonly/src/visual/components/verification_success_dialog.comp.dart';
|
import 'package:twonly/src/visual/components/verification_success_dialog.comp.dart';
|
||||||
|
|
||||||
class KeyVerificationService {
|
class KeyVerificationService {
|
||||||
|
static final StreamController<void> _verificationSuccessCloseController =
|
||||||
|
StreamController<void>.broadcast();
|
||||||
|
|
||||||
|
static Stream<void> get onVerificationSuccessClose =>
|
||||||
|
_verificationSuccessCloseController.stream;
|
||||||
|
|
||||||
|
static void notifyVerificationSuccessClose() {
|
||||||
|
_verificationSuccessCloseController.add(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void closeVerificationFlows(BuildContext context) {
|
||||||
|
Navigator.popUntil(context, (route) {
|
||||||
|
final name = route.settings.name;
|
||||||
|
if (name == null) return false;
|
||||||
|
return !name.contains('qr_scanner') && !name.contains('verifybadge');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
static Future<List<int>> getNewSecretVerificationToken() async {
|
static Future<List<int>> getNewSecretVerificationToken() async {
|
||||||
final token = getRandomUint8List(16);
|
final token = getRandomUint8List(16);
|
||||||
await twonlyDB.keyVerificationDao.insertVerificationToken(token);
|
await twonlyDB.keyVerificationDao.insertVerificationToken(token);
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,11 @@
|
||||||
|
import 'dart:async';
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:qr_flutter/qr_flutter.dart';
|
import 'package:qr_flutter/qr_flutter.dart';
|
||||||
import 'package:twonly/src/database/daos/contacts.dao.dart';
|
import 'package:twonly/src/database/daos/contacts.dao.dart';
|
||||||
import 'package:twonly/src/database/twonly.db.dart';
|
import 'package:twonly/src/database/twonly.db.dart';
|
||||||
|
import 'package:twonly/src/services/key_verification.service.dart';
|
||||||
import 'package:twonly/src/utils/avatars.dart';
|
import 'package:twonly/src/utils/avatars.dart';
|
||||||
import 'package:twonly/src/utils/misc.dart';
|
import 'package:twonly/src/utils/misc.dart';
|
||||||
import 'package:twonly/src/utils/qr.utils.dart';
|
import 'package:twonly/src/utils/qr.utils.dart';
|
||||||
|
|
@ -22,59 +24,73 @@ class ProfileQrCodeComp extends StatefulWidget {
|
||||||
BuildContext context, {
|
BuildContext context, {
|
||||||
Contact? contact,
|
Contact? contact,
|
||||||
bool openToVerify = false,
|
bool openToVerify = false,
|
||||||
}) {
|
}) async {
|
||||||
return showModalBottomSheet(
|
StreamSubscription<void>? subscription;
|
||||||
context: context,
|
|
||||||
isScrollControlled: true,
|
if (openToVerify) {
|
||||||
backgroundColor: Colors.transparent,
|
subscription = KeyVerificationService.onVerificationSuccessClose.listen((_) {
|
||||||
builder: (context) {
|
if (context.mounted) {
|
||||||
return Container(
|
KeyVerificationService.closeVerificationFlows(context);
|
||||||
decoration: BoxDecoration(
|
}
|
||||||
color: context.color.surface,
|
});
|
||||||
borderRadius: const BorderRadius.vertical(
|
}
|
||||||
top: Radius.circular(24),
|
|
||||||
|
try {
|
||||||
|
await showModalBottomSheet<void>(
|
||||||
|
context: context,
|
||||||
|
isScrollControlled: true,
|
||||||
|
backgroundColor: Colors.transparent,
|
||||||
|
builder: (context) {
|
||||||
|
return Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: context.color.surface,
|
||||||
|
borderRadius: const BorderRadius.vertical(
|
||||||
|
top: Radius.circular(24),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
padding: const EdgeInsets.symmetric(vertical: 24, horizontal: 20),
|
||||||
padding: const EdgeInsets.symmetric(vertical: 24, horizontal: 20),
|
child: Column(
|
||||||
child: Column(
|
mainAxisSize: MainAxisSize.min,
|
||||||
mainAxisSize: MainAxisSize.min,
|
children: [
|
||||||
children: [
|
const SizedBox(width: double.infinity),
|
||||||
const SizedBox(width: double.infinity),
|
Container(
|
||||||
Container(
|
width: 40,
|
||||||
width: 40,
|
height: 4,
|
||||||
height: 4,
|
decoration: BoxDecoration(
|
||||||
decoration: BoxDecoration(
|
color: context.color.onSurface.withValues(alpha: 0.2),
|
||||||
color: context.color.onSurface.withValues(alpha: 0.2),
|
borderRadius: BorderRadius.circular(2),
|
||||||
borderRadius: BorderRadius.circular(2),
|
),
|
||||||
),
|
),
|
||||||
),
|
const SizedBox(height: 24),
|
||||||
const SizedBox(height: 24),
|
Text(
|
||||||
Text(
|
openToVerify
|
||||||
openToVerify
|
? (contact != null
|
||||||
? (contact != null
|
? context.lang.letUserScanQrCode(
|
||||||
? context.lang.letUserScanQrCode(
|
getContactDisplayName(contact),
|
||||||
getContactDisplayName(contact),
|
)
|
||||||
)
|
: context.lang.letFriendScanQrToVerify)
|
||||||
: context.lang.letFriendScanQrToVerify)
|
: (contact != null
|
||||||
: (contact != null
|
? context.lang.letUserScanQrCode(
|
||||||
? context.lang.letUserScanQrCode(
|
getContactDisplayName(contact),
|
||||||
getContactDisplayName(contact),
|
)
|
||||||
)
|
: context.lang.addContactQrSheetSubtext),
|
||||||
: context.lang.addContactQrSheetSubtext),
|
style: TextStyle(
|
||||||
style: TextStyle(
|
fontSize: 14,
|
||||||
fontSize: 14,
|
color: context.color.onSurface.withValues(alpha: 0.6),
|
||||||
color: context.color.onSurface.withValues(alpha: 0.6),
|
),
|
||||||
|
textAlign: TextAlign.center,
|
||||||
),
|
),
|
||||||
textAlign: TextAlign.center,
|
const SizedBox(height: 24),
|
||||||
),
|
const ProfileQrCodeComp(),
|
||||||
const SizedBox(height: 24),
|
const SizedBox(height: 34),
|
||||||
const ProfileQrCodeComp(),
|
],
|
||||||
const SizedBox(height: 34),
|
),
|
||||||
],
|
);
|
||||||
),
|
},
|
||||||
);
|
);
|
||||||
},
|
} finally {
|
||||||
);
|
await subscription?.cancel();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:twonly/src/database/daos/contacts.dao.dart';
|
import 'package:twonly/src/database/daos/contacts.dao.dart';
|
||||||
import 'package:twonly/src/database/twonly.db.dart';
|
import 'package:twonly/src/database/twonly.db.dart';
|
||||||
|
import 'package:twonly/src/services/key_verification.service.dart';
|
||||||
import 'package:twonly/src/utils/misc.dart';
|
import 'package:twonly/src/utils/misc.dart';
|
||||||
import 'package:twonly/src/visual/components/avatar_icon.comp.dart';
|
import 'package:twonly/src/visual/components/avatar_icon.comp.dart';
|
||||||
import 'package:twonly/src/visual/components/verification_success_animation.comp.dart';
|
import 'package:twonly/src/visual/components/verification_success_animation.comp.dart';
|
||||||
|
|
@ -18,11 +19,16 @@ class VerificationSuccessDialog extends StatelessWidget {
|
||||||
final String? message;
|
final String? message;
|
||||||
|
|
||||||
/// Utility method to easily present this dialog.
|
/// Utility method to easily present this dialog.
|
||||||
static Future<void> show(BuildContext context, Contact contact, {String? message}) {
|
static Future<void> show(
|
||||||
|
BuildContext context,
|
||||||
|
Contact contact, {
|
||||||
|
String? message,
|
||||||
|
}) {
|
||||||
return showDialog<void>(
|
return showDialog<void>(
|
||||||
context: context,
|
context: context,
|
||||||
barrierDismissible: false,
|
barrierDismissible: false,
|
||||||
builder: (context) => VerificationSuccessDialog(contact: contact, message: message),
|
builder: (context) =>
|
||||||
|
VerificationSuccessDialog(contact: contact, message: message),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -75,7 +81,10 @@ class VerificationSuccessDialog extends StatelessWidget {
|
||||||
),
|
),
|
||||||
const SizedBox(height: 28),
|
const SizedBox(height: 28),
|
||||||
MyButton(
|
MyButton(
|
||||||
onPressed: () => Navigator.pop(context),
|
onPressed: () {
|
||||||
|
KeyVerificationService.notifyVerificationSuccessClose();
|
||||||
|
Navigator.pop(context);
|
||||||
|
},
|
||||||
child: Text(context.lang.close),
|
child: Text(context.lang.close),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ import 'package:flutter/material.dart';
|
||||||
import 'package:permission_handler/permission_handler.dart';
|
import 'package:permission_handler/permission_handler.dart';
|
||||||
import 'package:twonly/src/database/daos/contacts.dao.dart';
|
import 'package:twonly/src/database/daos/contacts.dao.dart';
|
||||||
import 'package:twonly/src/database/twonly.db.dart';
|
import 'package:twonly/src/database/twonly.db.dart';
|
||||||
|
import 'package:twonly/src/services/key_verification.service.dart';
|
||||||
import 'package:twonly/src/utils/misc.dart';
|
import 'package:twonly/src/utils/misc.dart';
|
||||||
import 'package:twonly/src/visual/views/camera/camera_preview_components/camera_preview.dart';
|
import 'package:twonly/src/visual/views/camera/camera_preview_components/camera_preview.dart';
|
||||||
import 'package:twonly/src/visual/views/camera/camera_preview_components/camera_preview_controller_view.dart';
|
import 'package:twonly/src/visual/views/camera/camera_preview_components/camera_preview_controller_view.dart';
|
||||||
|
|
@ -34,11 +35,7 @@ class QrCodeScannerViewState extends State<QrCodeScannerView> {
|
||||||
if (widget.openToVerify && widget.contact != null) {
|
if (widget.openToVerify && widget.contact != null) {
|
||||||
_mainCameraController.onVerificationSuccessDismissed = (contact) {
|
_mainCameraController.onVerificationSuccessDismissed = (contact) {
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
Navigator.popUntil(context, (route) {
|
KeyVerificationService.closeVerificationFlows(context);
|
||||||
final name = route.settings.name;
|
|
||||||
if (name == null) return true;
|
|
||||||
return !name.contains('qr_scanner') && !name.contains('verifybadge');
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue