This commit is contained in:
Christien Rioux 2024-01-30 14:14:11 -05:00
parent 1e6b9f4a43
commit 4a8958a868
7 changed files with 104 additions and 138 deletions

View File

@ -10,7 +10,6 @@ import '../../../layout/default_app_bar.dart';
import '../../../tools/tools.dart';
import '../../../veilid_processor/veilid_processor.dart';
import '../../account_manager.dart';
import '../../models/models.dart';
class NewAccountPage extends StatefulWidget {
const NewAccountPage({super.key});

View File

@ -1,25 +1,24 @@
import 'package:awesome_extensions/awesome_extensions.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import '../../proto/proto.dart' as proto;
import '../../theme/theme.dart';
import '../../tools/tools.dart';
import '../cubit/cubit.dart';
class ProfileWidget extends StatelessWidget {
const ProfileWidget({
required proto.Profile profile,
super.key,
});
}) : _profile = profile;
//
final proto.Profile _profile;
//
@override
// ignore: prefer_expression_function_bodies
Widget build(BuildContext context) {
final accountData = context.watch<AccountRecordCubit>().state.data;
if (accountData == null) {
return waitingPage(context);
}
final account = accountData.value;
final theme = Theme.of(context);
final scale = theme.extension<ScaleScheme>()!;
final textTheme = theme.textTheme;
@ -31,12 +30,12 @@ class ProfileWidget extends StatelessWidget {
RoundedRectangleBorder(borderRadius: BorderRadius.circular(16))),
child: Column(children: [
Text(
account.profile.name,
_profile.name,
style: textTheme.headlineSmall,
textAlign: TextAlign.left,
).paddingAll(4),
if (account.profile.pronouns.isNotEmpty)
Text(account.profile.pronouns, style: textTheme.bodyMedium)
if (_profile.pronouns.isNotEmpty)
Text(_profile.pronouns, style: textTheme.bodyMedium)
.paddingLTRB(4, 0, 4, 4),
]),
);

View File

@ -10,7 +10,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../../old_to_refactor/proto/proto.dart' as proto;
import '../../old_to_refactor/providers/account.dart';
import '../../old_to_refactor/providers/chat.dart';
import '../../old_to_refactor/providers/conversation.dart';
import '../../contacts/models/conversation.dart';
import '../../old_to_refactor/tools/tools.dart';
import '../../old_to_refactor/veilid_init.dart';
import '../../old_to_refactor/veilid_support/veilid_support.dart';

View File

@ -26,6 +26,8 @@ class ValidContactInvitation {
_contactIdentityMaster = contactIdentityMaster,
_writer = writer;
proto.Profile get remoteProfile => _contactRequestPrivate.profile;
Future<AcceptedContact?> accept() async {
final pool = DHTRecordPool.instance;
try {

View File

@ -3,10 +3,12 @@ import 'dart:async';
import 'package:awesome_extensions/awesome_extensions.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_translate/flutter_translate.dart';
import '../../account_manager/account_manager.dart';
import '../../tools/tools.dart';
import '../contact_invitation.dart';
class InviteDialog extends StatefulWidget {
const InviteDialog(
@ -66,22 +68,14 @@ class InviteDialogState extends State<InviteDialog> {
Future<void> _onAccept() async {
final navigator = Navigator.of(context);
final activeAccountInfo = context.read<ActiveAccountInfo>();
setState(() {
_isAccepting = true;
});
final activeAccountInfo = await ref.read(fetchActiveAccountProvider.future);
if (activeAccountInfo == null) {
setState(() {
_isAccepting = false;
});
navigator.pop();
return;
}
final validInvitation = _validInvitation;
if (validInvitation != null) {
final acceptedContact =
await acceptContactInvitation(activeAccountInfo, validInvitation);
final acceptedContact = await validInvitation.accept();
if (acceptedContact != null) {
// initiator when accept is received will create
// contact in the case of a 'note to self'
@ -91,7 +85,7 @@ class InviteDialogState extends State<InviteDialog> {
if (!isSelf) {
await createContact(
activeAccountInfo: activeAccountInfo,
profile: acceptedContact.profile,
profile: acceptedContact.remoteProfile,
remoteIdentity: acceptedContact.remoteIdentity,
remoteConversationRecordKey:
acceptedContact.remoteConversationRecordKey,
@ -99,9 +93,6 @@ class InviteDialogState extends State<InviteDialog> {
acceptedContact.localConversationRecordKey,
);
}
ref
..invalidate(fetchContactInvitationRecordsProvider)
..invalidate(fetchContactListProvider);
} else {
if (context.mounted) {
showErrorToast(context, 'invite_dialog.failed_to_accept');
@ -120,17 +111,9 @@ class InviteDialogState extends State<InviteDialog> {
setState(() {
_isAccepting = true;
});
final activeAccountInfo = await ref.read(fetchActiveAccountProvider.future);
if (activeAccountInfo == null) {
setState(() {
_isAccepting = false;
});
navigator.pop();
return;
}
final validInvitation = _validInvitation;
if (validInvitation != null) {
if (await rejectContactInvitation(activeAccountInfo, validInvitation)) {
if (await validInvitation.reject()) {
// do nothing right now
} else {
if (context.mounted) {
@ -148,67 +131,56 @@ class InviteDialogState extends State<InviteDialog> {
required Uint8List inviteData,
}) async {
try {
final activeAccountInfo =
await ref.read(fetchActiveAccountProvider.future);
if (activeAccountInfo == null) {
setState(() {
_isValidating = false;
_validInvitation = null;
});
return;
}
final contactInvitationRecords =
await ref.read(fetchContactInvitationRecordsProvider.future);
final contactInvitationListCubit =
context.read<ContactInvitationListCubit>();
setState(() {
_isValidating = true;
_validInvitation = null;
});
final validatedContactInvitation = await validateContactInvitation(
activeAccountInfo: activeAccountInfo,
contactInvitationRecords: contactInvitationRecords,
inviteData: inviteData,
getEncryptionKeyCallback:
(cs, encryptionKeyType, encryptedSecret) async {
String encryptionKey;
switch (encryptionKeyType) {
case EncryptionKeyType.none:
encryptionKey = '';
case EncryptionKeyType.pin:
final description =
translate('invite_dialog.protected_with_pin');
if (!context.mounted) {
return null;
final validatedContactInvitation =
await contactInvitationListCubit.validateInvitation(
inviteData: inviteData,
getEncryptionKeyCallback:
(cs, encryptionKeyType, encryptedSecret) async {
String encryptionKey;
switch (encryptionKeyType) {
case EncryptionKeyType.none:
encryptionKey = '';
case EncryptionKeyType.pin:
final description =
translate('invite_dialog.protected_with_pin');
if (!context.mounted) {
return null;
}
final pin = await showDialog<String>(
context: context,
builder: (context) => EnterPinDialog(
reenter: false, description: description));
if (pin == null) {
return null;
}
encryptionKey = pin;
case EncryptionKeyType.password:
final description =
translate('invite_dialog.protected_with_password');
if (!context.mounted) {
return null;
}
final password = await showDialog<String>(
context: context,
builder: (context) =>
EnterPasswordDialog(description: description));
if (password == null) {
return null;
}
encryptionKey = password;
}
final pin = await showDialog<String>(
context: context,
builder: (context) => EnterPinDialog(
reenter: false, description: description));
if (pin == null) {
return null;
}
encryptionKey = pin;
case EncryptionKeyType.password:
final description =
translate('invite_dialog.protected_with_password');
if (!context.mounted) {
return null;
}
final password = await showDialog<String>(
context: context,
builder: (context) =>
EnterPasswordDialog(description: description));
if (password == null) {
return null;
}
encryptionKey = password;
}
return decryptSecretFromBytes(
secretBytes: encryptedSecret,
cryptoKind: cs.kind(),
encryptionKeyType: encryptionKeyType,
encryptionKey: encryptionKey);
});
return encryptionKeyType.decryptSecretFromBytes(
secretBytes: encryptedSecret,
cryptoKind: cs.kind(),
encryptionKey: encryptionKey);
});
// Check if validation was cancelled
if (validatedContactInvitation == null) {
@ -297,14 +269,11 @@ class InviteDialogState extends State<InviteDialog> {
if (_validInvitation != null && !_isValidating)
Column(children: [
Container(
constraints: const BoxConstraints(maxHeight: 64),
width: double.infinity,
child: ProfileWidget(
name: _validInvitation!
.contactRequestPrivate.profile.name,
pronouns: _validInvitation!
.contactRequestPrivate.profile.pronouns,
)).paddingLTRB(0, 0, 0, 8),
constraints: const BoxConstraints(maxHeight: 64),
width: double.infinity,
child: ProfileWidget(
profile: _validInvitation!.remoteProfile))
.paddingLTRB(0, 0, 0, 8),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [

View File

@ -11,7 +11,7 @@ import 'package:veilid_support/veilid_support.dart';
import '../../account_manager/account_manager.dart';
import '../../tools/tools.dart';
import 'contact_invitation_display.dart';
import '../contact_invitation.dart';
class SendInviteDialog extends StatefulWidget {
const SendInviteDialog({super.key});
@ -130,17 +130,11 @@ class SendInviteDialogState extends State<SendInviteDialog> {
Future<void> _onGenerateButtonPressed() async {
final navigator = Navigator.of(context);
xxx continue here
// Start generation
final activeAccountInfo = context.read<ActiveAccountInfo>();
final contactInvitationListCubit =
context.read<ContactInvitationListCubit>();
if (activeAccountInfo == null) {
navigator.pop();
return;
}
final generator = ContactInvitationRespositoryxxx.createContactInvitation(
activeAccountInfo: activeAccountInfo,
final generator = contactInvitationListCubit.createInvitation(
encryptionKeyType: _encryptionKeyType,
encryptionKey: _encryptionKey,
message: _messageTextController.text,
@ -152,14 +146,12 @@ xxx continue here
await showDialog<void>(
context: context,
builder: (context) => ContactInvitationDisplayDialog(
name: activeAccountInfo.localAccount.name,
message: _messageTextController.text,
generator: generator,
));
// if (ret == null) {
// return;
// }
ref.invalidate(fetchContactInvitationRecordsProvider);
navigator.pop();
}

View File

@ -34,37 +34,42 @@ class HomeAccountReadyState extends State<HomeAccountReady>
return const Center(child: Text('unlock account'));
}
Widget buildUserPanel(BuildContext context) {
final theme = Theme.of(context);
final scale = theme.extension<ScaleScheme>()!;
Widget buildUserPanel() => Builder(builder: (context) {
final account = context.watch<AccountRecordCubit>().state;
final theme = Theme.of(context);
final scale = theme.extension<ScaleScheme>()!;
return Column(children: <Widget>[
Row(children: [
IconButton(
icon: const Icon(Icons.settings),
color: scale.secondaryScale.text,
constraints: const BoxConstraints.expand(height: 64, width: 64),
style: ButtonStyle(
backgroundColor:
MaterialStateProperty.all(scale.secondaryScale.border),
shape: MaterialStateProperty.all(const RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(16))))),
tooltip: translate('app_bar.settings_tooltip'),
onPressed: () async {
context.go('/home/settings');
}).paddingLTRB(0, 0, 8, 0),
const ProfileWidget().expanded(),
]).paddingAll(8),
const MainPager().expanded()
]);
}
return Column(children: <Widget>[
Row(children: [
IconButton(
icon: const Icon(Icons.settings),
color: scale.secondaryScale.text,
constraints: const BoxConstraints.expand(height: 64, width: 64),
style: ButtonStyle(
backgroundColor:
MaterialStateProperty.all(scale.secondaryScale.border),
shape: MaterialStateProperty.all(
const RoundedRectangleBorder(
borderRadius:
BorderRadius.all(Radius.circular(16))))),
tooltip: translate('app_bar.settings_tooltip'),
onPressed: () async {
context.go('/home/settings');
}).paddingLTRB(0, 0, 8, 0),
asyncValueBuilder(account,
(_, account) => ProfileWidget(profile: account.profile))
.expanded(),
]).paddingAll(8),
const MainPager().expanded()
]);
});
Widget buildPhone(BuildContext context) =>
Material(color: Colors.transparent, child: buildUserPanel(context));
Material(color: Colors.transparent, child: buildUserPanel());
Widget buildTabletLeftPane(BuildContext context) => Builder(
builder: (context) =>
Material(color: Colors.transparent, child: buildUserPanel(context)));
Material(color: Colors.transparent, child: buildUserPanel()));
Widget buildTabletRightPane(BuildContext context) => buildChatComponent();