veilidchat/lib/contact_invitation/views/create_invitation_dialog.dart

241 lines
7.8 KiB
Dart
Raw Normal View History

2023-08-03 00:49:48 -04:00
import 'dart:async';
2023-09-23 22:32:27 -04:00
import 'dart:math';
2023-08-03 00:49:48 -04:00
2023-08-02 21:09:28 -04:00
import 'package:awesome_extensions/awesome_extensions.dart';
2023-08-03 00:49:48 -04:00
import 'package:flutter/foundation.dart';
2023-08-02 21:09:28 -04:00
import 'package:flutter/material.dart';
2023-08-05 01:00:46 -04:00
import 'package:flutter/services.dart';
2024-01-29 22:38:19 -05:00
import 'package:flutter_bloc/flutter_bloc.dart';
2023-08-02 21:09:28 -04:00
import 'package:flutter_translate/flutter_translate.dart';
2024-01-09 20:58:27 -05:00
import 'package:veilid_support/veilid_support.dart';
2023-08-02 21:09:28 -04:00
2024-01-09 20:58:27 -05:00
import '../../account_manager/account_manager.dart';
import '../../theme/theme.dart';
2024-01-09 20:58:27 -05:00
import '../../tools/tools.dart';
2024-01-30 14:14:11 -05:00
import '../contact_invitation.dart';
2023-08-02 21:09:28 -04:00
2024-04-05 22:03:04 -04:00
class CreateInvitationDialog extends StatefulWidget {
const CreateInvitationDialog._({required this.modalContext});
2023-08-02 21:09:28 -04:00
@override
2024-04-05 22:03:04 -04:00
CreateInvitationDialogState createState() => CreateInvitationDialogState();
2023-09-23 12:56:54 -04:00
static Future<void> show(BuildContext context) async {
2024-04-05 22:03:04 -04:00
await StyledDialog.show<void>(
2023-09-23 12:56:54 -04:00
context: context,
2024-04-05 22:03:04 -04:00
title: translate('create_invitation_dialog.title'),
child: CreateInvitationDialog._(modalContext: context));
2024-02-14 21:33:15 -05:00
}
final BuildContext modalContext;
@override
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
properties
.add(DiagnosticsProperty<BuildContext>('modalContext', modalContext));
2023-09-23 12:56:54 -04:00
}
2023-08-02 21:09:28 -04:00
}
2024-04-05 22:03:04 -04:00
class CreateInvitationDialogState extends State<CreateInvitationDialog> {
2023-08-03 00:49:48 -04:00
final _messageTextController = TextEditingController(
2024-04-05 22:03:04 -04:00
text: translate('create_invitation_dialog.connect_with_me'));
2023-08-02 21:09:28 -04:00
EncryptionKeyType _encryptionKeyType = EncryptionKeyType.none;
String _encryptionKey = '';
2023-08-03 00:49:48 -04:00
Timestamp? _expiration;
2023-08-02 21:09:28 -04:00
@override
void initState() {
super.initState();
}
Future<void> _onNoneEncryptionSelected(bool selected) async {
setState(() {
if (selected) {
_encryptionKeyType = EncryptionKeyType.none;
}
});
}
Future<void> _onPinEncryptionSelected(bool selected) async {
2024-04-05 22:03:04 -04:00
final description = translate('create_invitation_dialog.pin_description');
2023-08-02 21:09:28 -04:00
final pin = await showDialog<String>(
context: context,
2023-09-26 22:32:13 -04:00
builder: (context) =>
EnterPinDialog(reenter: false, description: description));
2023-08-02 21:09:28 -04:00
if (pin == null) {
return;
}
2024-02-29 14:37:50 -05:00
if (!mounted) {
2023-08-02 21:09:28 -04:00
return;
}
final matchpin = await showDialog<String>(
context: context,
builder: (context) => EnterPinDialog(
2023-09-26 22:32:13 -04:00
reenter: true,
2023-08-02 21:09:28 -04:00
description: description,
));
if (matchpin == null) {
return;
} else if (pin == matchpin) {
setState(() {
_encryptionKeyType = EncryptionKeyType.pin;
_encryptionKey = pin;
});
} else {
2024-02-29 14:37:50 -05:00
if (!mounted) {
2023-08-02 21:09:28 -04:00
return;
}
showErrorToast(
2024-04-05 22:03:04 -04:00
context, translate('create_invitation_dialog.pin_does_not_match'));
2023-08-02 21:09:28 -04:00
setState(() {
_encryptionKeyType = EncryptionKeyType.none;
_encryptionKey = '';
});
}
}
Future<void> _onPasswordEncryptionSelected(bool selected) async {
2024-04-05 22:03:04 -04:00
final description =
translate('create_invitation_dialog.password_description');
2023-09-26 22:32:13 -04:00
final password = await showDialog<String>(
context: context,
builder: (context) => EnterPasswordDialog(description: description));
if (password == null) {
return;
}
2024-02-29 14:37:50 -05:00
if (!mounted) {
2023-09-26 22:32:13 -04:00
return;
}
final matchpass = await showDialog<String>(
context: context,
builder: (context) => EnterPasswordDialog(
matchPass: password,
description: description,
));
if (matchpass == null) {
return;
} else if (password == matchpass) {
setState(() {
2023-08-02 21:09:28 -04:00
_encryptionKeyType = EncryptionKeyType.password;
2023-09-26 22:32:13 -04:00
_encryptionKey = password;
});
} else {
2024-02-29 14:37:50 -05:00
if (!mounted) {
2023-09-26 22:32:13 -04:00
return;
2023-08-02 21:09:28 -04:00
}
2024-04-05 22:03:04 -04:00
showErrorToast(context,
translate('create_invitation_dialog.password_does_not_match'));
2023-09-26 22:32:13 -04:00
setState(() {
_encryptionKeyType = EncryptionKeyType.none;
_encryptionKey = '';
});
}
2023-08-02 21:09:28 -04:00
}
Future<void> _onGenerateButtonPressed() async {
2023-08-03 00:49:48 -04:00
final navigator = Navigator.of(context);
// Start generation
2024-01-30 14:14:11 -05:00
final contactInvitationListCubit =
2024-02-14 21:33:15 -05:00
widget.modalContext.read<ContactInvitationListCubit>();
2024-01-29 22:38:19 -05:00
2024-01-30 14:14:11 -05:00
final generator = contactInvitationListCubit.createInvitation(
2023-08-03 00:49:48 -04:00
encryptionKeyType: _encryptionKeyType,
encryptionKey: _encryptionKey,
2023-08-04 01:00:38 -04:00
message: _messageTextController.text,
2023-08-03 00:49:48 -04:00
expiration: _expiration);
2024-02-29 14:37:50 -05:00
2024-04-05 22:03:04 -04:00
await ContactInvitationDisplayDialog.show(
2023-08-02 21:09:28 -04:00
context: context,
2024-04-05 22:03:04 -04:00
message: _messageTextController.text,
create: (context) => InvitationGeneratorCubit(generator));
2024-02-29 14:37:50 -05:00
2023-08-03 00:49:48 -04:00
navigator.pop();
2023-08-02 21:09:28 -04:00
}
@override
// ignore: prefer_expression_function_bodies
Widget build(BuildContext context) {
2023-09-23 22:19:53 -04:00
final windowSize = MediaQuery.of(context).size;
2023-09-23 22:32:27 -04:00
final maxDialogWidth = min(windowSize.width - 64.0, 800.0 - 64.0);
final maxDialogHeight = windowSize.height - 64.0;
2023-09-23 22:19:53 -04:00
2023-08-02 21:09:28 -04:00
final theme = Theme.of(context);
//final scale = theme.extension<ScaleScheme>()!;
final textTheme = theme.textTheme;
2023-09-23 22:19:53 -04:00
return ConstrainedBox(
constraints:
BoxConstraints(maxHeight: maxDialogHeight, maxWidth: maxDialogWidth),
2023-08-02 21:09:28 -04:00
child: SingleChildScrollView(
padding: const EdgeInsets.all(8),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Text(
2024-04-05 22:03:04 -04:00
translate('create_invitation_dialog.message_to_contact'),
2023-08-02 21:09:28 -04:00
).paddingAll(8),
TextField(
2023-08-03 00:49:48 -04:00
controller: _messageTextController,
2023-08-05 01:00:46 -04:00
inputFormatters: [
2023-08-09 02:33:31 -04:00
LengthLimitingTextInputFormatter(128),
2023-08-05 01:00:46 -04:00
],
2023-08-02 21:09:28 -04:00
decoration: InputDecoration(
2024-04-10 16:13:08 -04:00
//border: const OutlineInputBorder(),
2024-04-05 22:03:04 -04:00
hintText:
translate('create_invitation_dialog.enter_message_hint'),
labelText: translate('create_invitation_dialog.message')),
2023-08-02 21:09:28 -04:00
).paddingAll(8),
const SizedBox(height: 10),
2024-04-05 22:03:04 -04:00
Text(translate('create_invitation_dialog.protect_this_invitation'),
2023-08-02 21:09:28 -04:00
style: textTheme.labelLarge)
.paddingAll(8),
Wrap(spacing: 5, children: [
ChoiceChip(
2024-04-05 22:03:04 -04:00
label: Text(translate('create_invitation_dialog.unlocked')),
2023-08-02 21:09:28 -04:00
selected: _encryptionKeyType == EncryptionKeyType.none,
onSelected: _onNoneEncryptionSelected,
),
ChoiceChip(
2024-04-05 22:03:04 -04:00
label: Text(translate('create_invitation_dialog.pin')),
2023-08-02 21:09:28 -04:00
selected: _encryptionKeyType == EncryptionKeyType.pin,
onSelected: _onPinEncryptionSelected,
),
ChoiceChip(
2024-04-05 22:03:04 -04:00
label: Text(translate('create_invitation_dialog.password')),
2023-08-02 21:09:28 -04:00
selected: _encryptionKeyType == EncryptionKeyType.password,
onSelected: _onPasswordEncryptionSelected,
)
]).paddingAll(8),
Container(
width: double.infinity,
height: 60,
padding: const EdgeInsets.all(8),
child: ElevatedButton(
onPressed: _onGenerateButtonPressed,
child: Text(
2024-04-05 22:03:04 -04:00
translate('create_invitation_dialog.generate'),
2023-08-02 21:09:28 -04:00
),
),
),
2024-04-05 22:03:04 -04:00
Text(translate('create_invitation_dialog.note')).paddingAll(8),
2023-08-02 21:09:28 -04:00
Text(
2024-04-05 22:03:04 -04:00
translate('create_invitation_dialog.note_text'),
2023-08-02 21:09:28 -04:00
style: Theme.of(context).textTheme.bodySmall,
).paddingAll(8),
],
),
),
);
}
2023-08-03 00:49:48 -04:00
@override
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
properties.add(DiagnosticsProperty<TextEditingController>(
'messageTextController', _messageTextController));
}
2023-08-02 21:09:28 -04:00
}