chore: Nicer verification dialog

This commit is contained in:
Krille Fear 2022-12-26 18:30:18 +01:00
parent b1699cfa16
commit 94b19cf6a6

View File

@ -1,7 +1,6 @@
import 'dart:convert'; import 'dart:convert';
import 'dart:ui'; import 'dart:ui';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
@ -11,25 +10,15 @@ import 'package:future_loading_dialog/future_loading_dialog.dart';
import 'package:matrix/encryption.dart'; import 'package:matrix/encryption.dart';
import 'package:matrix/matrix.dart'; import 'package:matrix/matrix.dart';
import 'package:fluffychat/utils/platform_infos.dart';
import 'package:fluffychat/widgets/avatar.dart'; import 'package:fluffychat/widgets/avatar.dart';
import '../../utils/beautify_string_extension.dart';
import '../../widgets/adaptive_flat_button.dart';
class KeyVerificationDialog extends StatefulWidget { class KeyVerificationDialog extends StatefulWidget {
Future<void> show(BuildContext context) => PlatformInfos.isCupertinoStyle Future<void> show(BuildContext context) => showModalBottomSheet(
? showCupertinoDialog( context: context,
context: context, builder: (context) => this,
barrierDismissible: true, useRootNavigator: true,
builder: (context) => this, isDismissible: false,
useRootNavigator: false, );
)
: showDialog(
context: context,
barrierDismissible: true,
builder: (context) => this,
useRootNavigator: false,
);
final KeyVerification request; final KeyVerification request;
@ -152,12 +141,16 @@ class KeyVerificationPageState extends State<KeyVerificationDialog> {
], ],
), ),
); );
buttons.add(AdaptiveFlatButton( buttons.add(TextButton(
label: L10n.of(context)!.submit, child: Text(
L10n.of(context)!.submit,
),
onPressed: () => checkInput(textEditingController.text), onPressed: () => checkInput(textEditingController.text),
)); ));
buttons.add(AdaptiveFlatButton( buttons.add(TextButton(
label: L10n.of(context)!.skip, child: Text(
L10n.of(context)!.skip,
),
onPressed: () => widget.request.openSSSS(skip: true), onPressed: () => widget.request.openSSSS(skip: true),
)); ));
break; break;
@ -166,102 +159,78 @@ class KeyVerificationPageState extends State<KeyVerificationDialog> {
body = Column( body = Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
Row(children: [
if (!PlatformInfos.isCupertinoStyle)
Avatar(mxContent: user?.avatarUrl, name: displayName),
const SizedBox(width: 12),
Expanded(
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: PlatformInfos.isCupertinoStyle
? CrossAxisAlignment.center
: CrossAxisAlignment.start,
children: [
Text(
displayName,
style: const TextStyle(fontSize: 16),
),
Text(
'${widget.request.userId} - ${widget.request.deviceId}',
style: const TextStyle(
fontWeight: FontWeight.w300,
fontSize: 14,
),
),
],
),
),
]),
const SizedBox(height: 16), const SizedBox(height: 16),
Image.asset('assets/verification.png', fit: BoxFit.contain), Avatar(
mxContent: user?.avatarUrl,
name: displayName,
size: Avatar.defaultSize * 2,
),
const SizedBox(height: 16), const SizedBox(height: 16),
Text( Text(
L10n.of(context)!.askVerificationRequest(displayName), L10n.of(context)!.askVerificationRequest(displayName),
) )
], ],
); );
buttons.add(AdaptiveFlatButton( buttons.add(TextButton.icon(
label: L10n.of(context)!.reject, icon: const Icon(Icons.close),
textColor: Colors.red, style: TextButton.styleFrom(foregroundColor: Colors.red),
label: Text(L10n.of(context)!.reject),
onPressed: () => widget.request onPressed: () => widget.request
.rejectVerification() .rejectVerification()
.then((_) => Navigator.of(context, rootNavigator: false).pop()), .then((_) => Navigator.of(context, rootNavigator: false).pop()),
)); ));
buttons.add(AdaptiveFlatButton( buttons.add(TextButton.icon(
label: L10n.of(context)!.accept, icon: const Icon(Icons.check),
label: Text(L10n.of(context)!.accept),
onPressed: () => widget.request.acceptVerification(), onPressed: () => widget.request.acceptVerification(),
)); ));
break; break;
case KeyVerificationState.waitingAccept: case KeyVerificationState.waitingAccept:
body = Column( body = Center(
mainAxisSize: MainAxisSize.min, child: Column(
children: <Widget>[ children: <Widget>[
Image.asset('assets/verification.png', fit: BoxFit.contain), Stack(
const SizedBox(height: 16), alignment: Alignment.center,
const CircularProgressIndicator.adaptive(strokeWidth: 2), children: [
const SizedBox(height: 16), Avatar(
Text( mxContent: user?.avatarUrl,
L10n.of(context)!.waitingPartnerAcceptRequest, name: displayName,
textAlign: TextAlign.center, ),
), const SizedBox(
], width: Avatar.defaultSize + 2,
height: Avatar.defaultSize + 2,
child: CircularProgressIndicator(strokeWidth: 2),
),
],
),
const SizedBox(height: 16),
Text(
L10n.of(context)!.waitingPartnerAcceptRequest,
textAlign: TextAlign.center,
),
],
),
); );
final key = widget.request.client.userDeviceKeys[widget.request.userId]
?.deviceKeys[widget.request.deviceId];
if (key != null) {
buttons.add(AdaptiveFlatButton(
label: L10n.of(context)!.verifyManual,
onPressed: () async {
final result = await showOkCancelAlertDialog(
useRootNavigator: false,
context: context,
title: L10n.of(context)!.verifyManual,
message: key.ed25519Key?.beautified ?? 'Key not found',
);
if (result == OkCancelResult.ok) {
await key.setVerified(true);
}
await widget.request.cancel();
Navigator.of(context, rootNavigator: false).pop();
},
));
}
break; break;
case KeyVerificationState.askSas: case KeyVerificationState.askSas:
TextSpan compareWidget; TextSpan compareWidget;
// maybe add a button to switch between the two and only determine default // maybe add a button to switch between the two and only determine default
// view for if "emoji" is a present sasType or not? // view for if "emoji" is a present sasType or not?
String compareText;
if (widget.request.sasTypes.contains('emoji')) { if (widget.request.sasTypes.contains('emoji')) {
compareText = L10n.of(context)!.compareEmojiMatch; title = Text(
L10n.of(context)!.compareEmojiMatch,
maxLines: 2,
style: const TextStyle(fontSize: 16),
);
compareWidget = TextSpan( compareWidget = TextSpan(
children: widget.request.sasEmojis children: widget.request.sasEmojis
.map((e) => WidgetSpan(child: _Emoji(e, sasEmoji))) .map((e) => WidgetSpan(child: _Emoji(e, sasEmoji)))
.toList(), .toList(),
); );
} else { } else {
compareText = L10n.of(context)!.compareNumbersMatch; title = Text(L10n.of(context)!.compareNumbersMatch);
final numbers = widget.request.sasNumbers; final numbers = widget.request.sasNumbers;
final numbstr = '${numbers[0]}-${numbers[1]}-${numbers[2]}'; final numbstr = '${numbers[0]}-${numbers[1]}-${numbers[2]}';
compareWidget = compareWidget =
@ -270,27 +239,23 @@ class KeyVerificationPageState extends State<KeyVerificationDialog> {
body = Column( body = Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: <Widget>[ children: <Widget>[
Center(
child: Text(
compareText,
style: const TextStyle(fontSize: 16),
textAlign: TextAlign.center,
),
),
const SizedBox(height: 10),
Text.rich( Text.rich(
compareWidget, compareWidget,
textAlign: TextAlign.center, textAlign: TextAlign.center,
), ),
], ],
); );
buttons.add(AdaptiveFlatButton( buttons.add(TextButton.icon(
textColor: Colors.red, icon: const Icon(Icons.close),
label: L10n.of(context)!.theyDontMatch, style: TextButton.styleFrom(
foregroundColor: Colors.red,
),
label: Text(L10n.of(context)!.theyDontMatch),
onPressed: () => widget.request.rejectSas(), onPressed: () => widget.request.rejectSas(),
)); ));
buttons.add(AdaptiveFlatButton( buttons.add(TextButton.icon(
label: L10n.of(context)!.theyMatch, icon: const Icon(Icons.check_outlined),
label: Text(L10n.of(context)!.theyMatch),
onPressed: () => widget.request.acceptSas(), onPressed: () => widget.request.acceptSas(),
)); ));
break; break;
@ -315,7 +280,7 @@ class KeyVerificationPageState extends State<KeyVerificationDialog> {
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: <Widget>[ children: <Widget>[
const Icon(Icons.check_circle_outlined, const Icon(Icons.check_circle_outlined,
color: Colors.green, size: 200.0), color: Colors.green, size: 128.0),
const SizedBox(height: 10), const SizedBox(height: 10),
Text( Text(
L10n.of(context)!.verifySuccess, L10n.of(context)!.verifySuccess,
@ -323,8 +288,10 @@ class KeyVerificationPageState extends State<KeyVerificationDialog> {
), ),
], ],
); );
buttons.add(AdaptiveFlatButton( buttons.add(TextButton(
label: L10n.of(context)!.close, child: Text(
L10n.of(context)!.close,
),
onPressed: () => Navigator.of(context, rootNavigator: false).pop(), onPressed: () => Navigator.of(context, rootNavigator: false).pop(),
)); ));
break; break;
@ -332,7 +299,7 @@ class KeyVerificationPageState extends State<KeyVerificationDialog> {
body = Column( body = Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: <Widget>[ children: <Widget>[
const Icon(Icons.cancel, color: Colors.red, size: 200.0), const Icon(Icons.cancel, color: Colors.red, size: 128.0),
const SizedBox(height: 10), const SizedBox(height: 10),
Text( Text(
'Error ${widget.request.canceledCode}: ${widget.request.canceledReason}', 'Error ${widget.request.canceledCode}: ${widget.request.canceledReason}',
@ -340,33 +307,32 @@ class KeyVerificationPageState extends State<KeyVerificationDialog> {
), ),
], ],
); );
buttons.add(AdaptiveFlatButton( buttons.add(TextButton(
label: L10n.of(context)!.close, child: Text(
L10n.of(context)!.close,
),
onPressed: () => Navigator.of(context, rootNavigator: false).pop(), onPressed: () => Navigator.of(context, rootNavigator: false).pop(),
)); ));
break; break;
} }
final content = SingleChildScrollView( return Scaffold(
scrollDirection: Axis.vertical, appBar: AppBar(
child: Column( leading: const CloseButton(),
mainAxisSize: MainAxisSize.min,
children: [
const SizedBox(height: 16),
body,
],
),
);
if (PlatformInfos.isCupertinoStyle) {
return CupertinoAlertDialog(
title: title, title: title,
content: content, ),
actions: buttons, body: ListView(
); padding: const EdgeInsets.all(12.0),
} children: [body],
return AlertDialog( ),
title: title, bottomNavigationBar: SafeArea(
content: content, child: Padding(
actions: buttons, padding: const EdgeInsets.all(12.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: buttons,
),
),
),
); );
} }
} }