mirror of
https://gitlab.com/veilid/veilidchat.git
synced 2024-10-01 06:55:46 -04:00
ui improvements for invitations
This commit is contained in:
parent
d962f98786
commit
01c6490ec4
@ -122,7 +122,9 @@
|
|||||||
},
|
},
|
||||||
"create_invitation_dialog": {
|
"create_invitation_dialog": {
|
||||||
"title": "Create Contact Invitation",
|
"title": "Create Contact Invitation",
|
||||||
"connect_with_me": "Connect with me on VeilidChat!",
|
"me": "me",
|
||||||
|
"fingerprint": "Fingerprint:",
|
||||||
|
"connect_with_me": "Connect with {name} on VeilidChat!",
|
||||||
"enter_message_hint": "Enter message for contact (optional)",
|
"enter_message_hint": "Enter message for contact (optional)",
|
||||||
"message_to_contact": "Message to send with invitation (not encrypted)",
|
"message_to_contact": "Message to send with invitation (not encrypted)",
|
||||||
"generate": "Generate Invitation",
|
"generate": "Generate Invitation",
|
||||||
@ -148,6 +150,7 @@
|
|||||||
"failed_to_reject": "Failed to reject contact invitation",
|
"failed_to_reject": "Failed to reject contact invitation",
|
||||||
"invalid_invitation": "Invalid invitation",
|
"invalid_invitation": "Invalid invitation",
|
||||||
"try_again_online": "Invitation could not be reached, try again when online",
|
"try_again_online": "Invitation could not be reached, try again when online",
|
||||||
|
"key_not_found": "Invitation could not be found, it may not be on the network yet",
|
||||||
"protected_with_pin": "Contact invitation is protected with a PIN",
|
"protected_with_pin": "Contact invitation is protected with a PIN",
|
||||||
"protected_with_password": "Contact invitation is protected with a password",
|
"protected_with_password": "Contact invitation is protected with a password",
|
||||||
"invalid_pin": "Invalid PIN",
|
"invalid_pin": "Invalid PIN",
|
||||||
@ -155,7 +158,7 @@
|
|||||||
},
|
},
|
||||||
"waiting_invitation": {
|
"waiting_invitation": {
|
||||||
"accepted": "Contact invitation accepted from {name}",
|
"accepted": "Contact invitation accepted from {name}",
|
||||||
"reject": "Contact invitation was rejected"
|
"rejected": "Contact invitation was rejected"
|
||||||
},
|
},
|
||||||
"paste_invitation_dialog": {
|
"paste_invitation_dialog": {
|
||||||
"title": "Paste Contact Invite",
|
"title": "Paste Contact Invite",
|
||||||
@ -225,6 +228,10 @@
|
|||||||
"in_app": "In-app",
|
"in_app": "In-app",
|
||||||
"push": "Push",
|
"push": "Push",
|
||||||
"in_app_or_push": "In-app or Push",
|
"in_app_or_push": "In-app or Push",
|
||||||
|
"notifications": "Notifications",
|
||||||
|
"event": "Event",
|
||||||
|
"sound": "Sound",
|
||||||
|
"delivery": "Delivery",
|
||||||
"enable_badge": "Enable icon 'badge' bubble",
|
"enable_badge": "Enable icon 'badge' bubble",
|
||||||
"enable_notifications": "Enable notifications",
|
"enable_notifications": "Enable notifications",
|
||||||
"message_notification_content": "Message notification content",
|
"message_notification_content": "Message notification content",
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
|
import 'package:async_tools/async_tools.dart';
|
||||||
import 'package:bloc_advanced_tools/bloc_advanced_tools.dart';
|
import 'package:bloc_advanced_tools/bloc_advanced_tools.dart';
|
||||||
import 'package:fast_immutable_collections/fast_immutable_collections.dart';
|
import 'package:fast_immutable_collections/fast_immutable_collections.dart';
|
||||||
import 'package:fixnum/fixnum.dart';
|
import 'package:fixnum/fixnum.dart';
|
||||||
@ -214,9 +215,11 @@ class ContactInvitationListCubit
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<ValidContactInvitation?> validateInvitation(
|
Future<ValidContactInvitation?> validateInvitation({
|
||||||
{required Uint8List inviteData,
|
required Uint8List inviteData,
|
||||||
required GetEncryptionKeyCallback getEncryptionKeyCallback}) async {
|
required GetEncryptionKeyCallback getEncryptionKeyCallback,
|
||||||
|
required CancelRequest cancelRequest,
|
||||||
|
}) async {
|
||||||
final pool = DHTRecordPool.instance;
|
final pool = DHTRecordPool.instance;
|
||||||
|
|
||||||
// Get contact request inbox from invitation
|
// Get contact request inbox from invitation
|
||||||
@ -245,15 +248,18 @@ class ContactInvitationListCubit
|
|||||||
contactRequestInboxKey) !=
|
contactRequestInboxKey) !=
|
||||||
-1;
|
-1;
|
||||||
|
|
||||||
await (await pool.openRecordRead(contactRequestInboxKey,
|
await (await pool
|
||||||
debugName: 'ContactInvitationListCubit::validateInvitation::'
|
.openRecordRead(contactRequestInboxKey,
|
||||||
'ContactRequestInbox',
|
debugName: 'ContactInvitationListCubit::validateInvitation::'
|
||||||
parent: pool.getParentRecordKey(contactRequestInboxKey) ??
|
'ContactRequestInbox',
|
||||||
_accountInfo.accountRecordKey))
|
parent: pool.getParentRecordKey(contactRequestInboxKey) ??
|
||||||
|
_accountInfo.accountRecordKey)
|
||||||
|
.withCancel(cancelRequest))
|
||||||
.maybeDeleteScope(!isSelf, (contactRequestInbox) async {
|
.maybeDeleteScope(!isSelf, (contactRequestInbox) async {
|
||||||
//
|
//
|
||||||
final contactRequest = await contactRequestInbox
|
final contactRequest = await contactRequestInbox
|
||||||
.getProtobuf(proto.ContactRequest.fromBuffer);
|
.getProtobuf(proto.ContactRequest.fromBuffer)
|
||||||
|
.withCancel(cancelRequest);
|
||||||
|
|
||||||
final cs = await pool.veilid.getCryptoSystem(contactRequestInboxKey.kind);
|
final cs = await pool.veilid.getCryptoSystem(contactRequestInboxKey.kind);
|
||||||
|
|
||||||
@ -281,7 +287,8 @@ class ContactInvitationListCubit
|
|||||||
|
|
||||||
// Fetch the account master
|
// Fetch the account master
|
||||||
final contactSuperIdentity = await SuperIdentity.open(
|
final contactSuperIdentity = await SuperIdentity.open(
|
||||||
superRecordKey: contactSuperIdentityRecordKey);
|
superRecordKey: contactSuperIdentityRecordKey)
|
||||||
|
.withCancel(cancelRequest);
|
||||||
|
|
||||||
// Verify
|
// Verify
|
||||||
final idcs = await contactSuperIdentity.currentInstance.cryptoSystem;
|
final idcs = await contactSuperIdentity.currentInstance.cryptoSystem;
|
||||||
|
@ -11,6 +11,7 @@ import 'package:provider/provider.dart';
|
|||||||
import 'package:qr_flutter/qr_flutter.dart';
|
import 'package:qr_flutter/qr_flutter.dart';
|
||||||
import 'package:veilid_support/veilid_support.dart';
|
import 'package:veilid_support/veilid_support.dart';
|
||||||
|
|
||||||
|
import '../../account_manager/account_manager.dart';
|
||||||
import '../../notifications/notifications.dart';
|
import '../../notifications/notifications.dart';
|
||||||
import '../../proto/proto.dart' as proto;
|
import '../../proto/proto.dart' as proto;
|
||||||
import '../../theme/theme.dart';
|
import '../../theme/theme.dart';
|
||||||
@ -20,17 +21,20 @@ class ContactInvitationDisplayDialog extends StatelessWidget {
|
|||||||
const ContactInvitationDisplayDialog._({
|
const ContactInvitationDisplayDialog._({
|
||||||
required this.locator,
|
required this.locator,
|
||||||
required this.message,
|
required this.message,
|
||||||
|
required this.fingerprint,
|
||||||
});
|
});
|
||||||
|
|
||||||
final Locator locator;
|
final Locator locator;
|
||||||
final String message;
|
final String message;
|
||||||
|
final String fingerprint;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
|
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
|
||||||
super.debugFillProperties(properties);
|
super.debugFillProperties(properties);
|
||||||
properties
|
properties
|
||||||
..add(StringProperty('message', message))
|
..add(StringProperty('message', message))
|
||||||
..add(DiagnosticsProperty<Locator>('locator', locator));
|
..add(DiagnosticsProperty<Locator>('locator', locator))
|
||||||
|
..add(StringProperty('fingerprint', fingerprint));
|
||||||
}
|
}
|
||||||
|
|
||||||
String makeTextInvite(String message, Uint8List data) {
|
String makeTextInvite(String message, Uint8List data) {
|
||||||
@ -38,10 +42,12 @@ class ContactInvitationDisplayDialog extends StatelessWidget {
|
|||||||
base64UrlNoPadEncode(data), '\n', 40,
|
base64UrlNoPadEncode(data), '\n', 40,
|
||||||
repeat: true);
|
repeat: true);
|
||||||
final msg = message.isNotEmpty ? '$message\n' : '';
|
final msg = message.isNotEmpty ? '$message\n' : '';
|
||||||
|
|
||||||
return '$msg'
|
return '$msg'
|
||||||
'--- BEGIN VEILIDCHAT CONTACT INVITE ----\n'
|
'--- BEGIN VEILIDCHAT CONTACT INVITE ----\n'
|
||||||
'$invite\n'
|
'$invite\n'
|
||||||
'---- END VEILIDCHAT CONTACT INVITE -----\n';
|
'---- END VEILIDCHAT CONTACT INVITE -----\n'
|
||||||
|
'Fingerprint:\n$fingerprint\n';
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -97,18 +103,27 @@ class ContactInvitationDisplayDialog extends StatelessWidget {
|
|||||||
.copyWith(color: Colors.black)))
|
.copyWith(color: Colors.black)))
|
||||||
.paddingAll(8),
|
.paddingAll(8),
|
||||||
FittedBox(
|
FittedBox(
|
||||||
child: QrImageView.withQr(
|
child: QrImageView.withQr(
|
||||||
size: 300,
|
size: 300,
|
||||||
qr: QrCode.fromUint8List(
|
qr: QrCode.fromUint8List(
|
||||||
data: data.$1,
|
data: data.$1,
|
||||||
errorCorrectLevel:
|
errorCorrectLevel:
|
||||||
QrErrorCorrectLevel.L)))
|
QrErrorCorrectLevel.L)),
|
||||||
.expanded(),
|
).expanded(),
|
||||||
Text(message,
|
Text(message,
|
||||||
softWrap: true,
|
softWrap: true,
|
||||||
style: textTheme.labelLarge!
|
style: textTheme.labelLarge!
|
||||||
.copyWith(color: Colors.black))
|
.copyWith(color: Colors.black))
|
||||||
.paddingAll(8),
|
.paddingAll(8),
|
||||||
|
Text(
|
||||||
|
'${translate('create_invitation_dialog.fingerprint')}\n'
|
||||||
|
'$fingerprint',
|
||||||
|
softWrap: true,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: textTheme.labelSmall!.copyWith(
|
||||||
|
color: Colors.black,
|
||||||
|
fontFamily: 'Source Code Pro'))
|
||||||
|
.paddingAll(2),
|
||||||
ElevatedButton.icon(
|
ElevatedButton.icon(
|
||||||
icon: const Icon(Icons.copy),
|
icon: const Icon(Icons.copy),
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
@ -129,11 +144,15 @@ class ContactInvitationDisplayDialog extends StatelessWidget {
|
|||||||
error: errorPage)))));
|
error: errorPage)))));
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future<void> show(
|
static Future<void> show({
|
||||||
{required BuildContext context,
|
required BuildContext context,
|
||||||
required Locator locator,
|
required Locator locator,
|
||||||
required InvitationGeneratorCubit Function(BuildContext) create,
|
required InvitationGeneratorCubit Function(BuildContext) create,
|
||||||
required String message}) async {
|
required String message,
|
||||||
|
}) async {
|
||||||
|
final fingerprint =
|
||||||
|
locator<AccountInfoCubit>().state.identityPublicKey.toString();
|
||||||
|
|
||||||
await showPopControlDialog<void>(
|
await showPopControlDialog<void>(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (context) => BlocProvider(
|
builder: (context) => BlocProvider(
|
||||||
@ -141,6 +160,7 @@ class ContactInvitationDisplayDialog extends StatelessWidget {
|
|||||||
child: ContactInvitationDisplayDialog._(
|
child: ContactInvitationDisplayDialog._(
|
||||||
locator: locator,
|
locator: locator,
|
||||||
message: message,
|
message: message,
|
||||||
|
fingerprint: fingerprint,
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -37,8 +37,7 @@ class CreateInvitationDialog extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class CreateInvitationDialogState extends State<CreateInvitationDialog> {
|
class CreateInvitationDialogState extends State<CreateInvitationDialog> {
|
||||||
final _messageTextController = TextEditingController(
|
late final TextEditingController _messageTextController;
|
||||||
text: translate('create_invitation_dialog.connect_with_me'));
|
|
||||||
|
|
||||||
EncryptionKeyType _encryptionKeyType = EncryptionKeyType.none;
|
EncryptionKeyType _encryptionKeyType = EncryptionKeyType.none;
|
||||||
String _encryptionKey = '';
|
String _encryptionKey = '';
|
||||||
@ -46,6 +45,12 @@ class CreateInvitationDialogState extends State<CreateInvitationDialog> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
|
final accountInfo = widget.locator<AccountRecordCubit>().state;
|
||||||
|
final name = accountInfo.asData?.value.profile.name ??
|
||||||
|
translate('create_invitation_dialog.me');
|
||||||
|
_messageTextController = TextEditingController(
|
||||||
|
text: translate('create_invitation_dialog.connect_with_me',
|
||||||
|
args: {'name': name}));
|
||||||
super.initState();
|
super.initState();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -152,13 +157,13 @@ class CreateInvitationDialogState extends State<CreateInvitationDialog> {
|
|||||||
message: _messageTextController.text,
|
message: _messageTextController.text,
|
||||||
expiration: _expiration);
|
expiration: _expiration);
|
||||||
|
|
||||||
|
navigator.pop();
|
||||||
|
|
||||||
await ContactInvitationDisplayDialog.show(
|
await ContactInvitationDisplayDialog.show(
|
||||||
context: context,
|
context: context,
|
||||||
locator: widget.locator,
|
locator: widget.locator,
|
||||||
message: _messageTextController.text,
|
message: _messageTextController.text,
|
||||||
create: (context) => InvitationGeneratorCubit(generator));
|
create: (context) => InvitationGeneratorCubit(generator));
|
||||||
|
|
||||||
navigator.pop();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
|
import 'package:async_tools/async_tools.dart';
|
||||||
import 'package:awesome_extensions/awesome_extensions.dart';
|
import 'package:awesome_extensions/awesome_extensions.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
@ -61,17 +62,19 @@ class InvitationDialog extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class InvitationDialogState extends State<InvitationDialog> {
|
class InvitationDialogState extends State<InvitationDialog> {
|
||||||
ValidContactInvitation? _validInvitation;
|
|
||||||
bool _isValidating = false;
|
|
||||||
bool _isAccepting = false;
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool get isValidating => _isValidating;
|
Future<void> _onCancel() async {
|
||||||
bool get isAccepting => _isAccepting;
|
final navigator = Navigator.of(context);
|
||||||
|
_cancelRequest.cancel();
|
||||||
|
setState(() {
|
||||||
|
_isAccepting = false;
|
||||||
|
});
|
||||||
|
navigator.pop();
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> _onAccept() async {
|
Future<void> _onAccept() async {
|
||||||
final navigator = Navigator.of(context);
|
final navigator = Navigator.of(context);
|
||||||
@ -153,6 +156,7 @@ class InvitationDialogState extends State<InvitationDialog> {
|
|||||||
final validatedContactInvitation =
|
final validatedContactInvitation =
|
||||||
await contactInvitationListCubit.validateInvitation(
|
await contactInvitationListCubit.validateInvitation(
|
||||||
inviteData: inviteData,
|
inviteData: inviteData,
|
||||||
|
cancelRequest: _cancelRequest,
|
||||||
getEncryptionKeyCallback:
|
getEncryptionKeyCallback:
|
||||||
(cs, encryptionKeyType, encryptedSecret) async {
|
(cs, encryptionKeyType, encryptedSecret) async {
|
||||||
String encryptionKey;
|
String encryptionKey;
|
||||||
@ -234,6 +238,9 @@ class InvitationDialogState extends State<InvitationDialog> {
|
|||||||
late final String errorText;
|
late final String errorText;
|
||||||
if (e is VeilidAPIExceptionTryAgain) {
|
if (e is VeilidAPIExceptionTryAgain) {
|
||||||
errorText = translate('invitation_dialog.try_again_online');
|
errorText = translate('invitation_dialog.try_again_online');
|
||||||
|
}
|
||||||
|
if (e is VeilidAPIExceptionKeyNotFound) {
|
||||||
|
errorText = translate('invitation_dialog.key_not_found');
|
||||||
} else {
|
} else {
|
||||||
errorText = translate('invitation_dialog.invalid_invitation');
|
errorText = translate('invitation_dialog.invalid_invitation');
|
||||||
}
|
}
|
||||||
@ -245,6 +252,12 @@ class InvitationDialogState extends State<InvitationDialog> {
|
|||||||
_validInvitation = null;
|
_validInvitation = null;
|
||||||
widget.onValidationFailed();
|
widget.onValidationFailed();
|
||||||
});
|
});
|
||||||
|
} on CancelException {
|
||||||
|
setState(() {
|
||||||
|
_isValidating = false;
|
||||||
|
_validInvitation = null;
|
||||||
|
widget.onValidationCancelled();
|
||||||
|
});
|
||||||
} on Exception catch (e) {
|
} on Exception catch (e) {
|
||||||
log.debug('exception: $e', e);
|
log.debug('exception: $e', e);
|
||||||
setState(() {
|
setState(() {
|
||||||
@ -264,6 +277,11 @@ class InvitationDialogState extends State<InvitationDialog> {
|
|||||||
Text(translate('invitation_dialog.validating'))
|
Text(translate('invitation_dialog.validating'))
|
||||||
.paddingLTRB(0, 0, 0, 16),
|
.paddingLTRB(0, 0, 0, 16),
|
||||||
buildProgressIndicator().paddingAll(16),
|
buildProgressIndicator().paddingAll(16),
|
||||||
|
ElevatedButton.icon(
|
||||||
|
icon: const Icon(Icons.cancel),
|
||||||
|
label: Text(translate('button.cancel')),
|
||||||
|
onPressed: _onCancel,
|
||||||
|
).paddingAll(16),
|
||||||
]).toCenter(),
|
]).toCenter(),
|
||||||
if (_validInvitation == null &&
|
if (_validInvitation == null &&
|
||||||
!_isValidating &&
|
!_isValidating &&
|
||||||
@ -315,13 +333,25 @@ class InvitationDialogState extends State<InvitationDialog> {
|
|||||||
child: Column(
|
child: Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: _isAccepting
|
children: _isAccepting
|
||||||
? [buildProgressIndicator().paddingAll(16)]
|
? [
|
||||||
|
buildProgressIndicator().paddingAll(16),
|
||||||
|
]
|
||||||
: _buildPreAccept()),
|
: _buildPreAccept()),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
return PopControl(dismissible: dismissible, child: dialog);
|
return PopControl(dismissible: dismissible, child: dialog);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
ValidContactInvitation? _validInvitation;
|
||||||
|
bool _isValidating = false;
|
||||||
|
bool _isAccepting = false;
|
||||||
|
final _cancelRequest = CancelRequest();
|
||||||
|
|
||||||
|
bool get isValidating => _isValidating;
|
||||||
|
bool get isAccepting => _isAccepting;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
|
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
|
||||||
super.debugFillProperties(properties);
|
super.debugFillProperties(properties);
|
||||||
|
@ -52,7 +52,11 @@ Widget buildSettingsPageNotificationPreferences(
|
|||||||
out.add(DropdownMenuItem(
|
out.add(DropdownMenuItem(
|
||||||
value: x.$1,
|
value: x.$1,
|
||||||
enabled: x.$2,
|
enabled: x.$2,
|
||||||
child: Text(x.$3, style: textTheme.labelSmall)));
|
child: Text(
|
||||||
|
x.$3,
|
||||||
|
style: textTheme.labelSmall,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
)));
|
||||||
}
|
}
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
@ -71,7 +75,11 @@ Widget buildSettingsPageNotificationPreferences(
|
|||||||
out.add(DropdownMenuItem(
|
out.add(DropdownMenuItem(
|
||||||
value: x.$1,
|
value: x.$1,
|
||||||
enabled: x.$2,
|
enabled: x.$2,
|
||||||
child: Text(x.$3, style: textTheme.labelSmall)));
|
child: Text(
|
||||||
|
x.$3,
|
||||||
|
style: textTheme.labelSmall,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
)));
|
||||||
}
|
}
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
@ -100,17 +108,23 @@ Widget buildSettingsPageNotificationPreferences(
|
|||||||
out.add(DropdownMenuItem(
|
out.add(DropdownMenuItem(
|
||||||
value: x.$1,
|
value: x.$1,
|
||||||
enabled: x.$2,
|
enabled: x.$2,
|
||||||
child: Text(x.$3, style: textTheme.labelSmall)));
|
child: Text(
|
||||||
|
x.$3,
|
||||||
|
style: textTheme.labelSmall,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
)));
|
||||||
}
|
}
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
return DecoratedBox(
|
return InputDecorator(
|
||||||
decoration: ShapeDecoration(
|
decoration: InputDecoration(
|
||||||
shape: RoundedRectangleBorder(
|
labelText: translate('settings_page.notifications'),
|
||||||
side: BorderSide(width: 2, color: scale.primaryScale.border),
|
border: OutlineInputBorder(
|
||||||
borderRadius:
|
borderRadius: BorderRadius.circular(8 * scaleConfig.borderRadiusScale),
|
||||||
BorderRadius.circular(8 * scaleConfig.borderRadiusScale))),
|
borderSide: BorderSide(width: 2, color: scale.primaryScale.border),
|
||||||
|
),
|
||||||
|
),
|
||||||
child: Column(mainAxisSize: MainAxisSize.min, children: [
|
child: Column(mainAxisSize: MainAxisSize.min, children: [
|
||||||
// Display Beta Warning
|
// Display Beta Warning
|
||||||
FormBuilderCheckbox(
|
FormBuilderCheckbox(
|
||||||
@ -175,12 +189,35 @@ Widget buildSettingsPageNotificationPreferences(
|
|||||||
await updatePreferences(newNotificationsPreference);
|
await updatePreferences(newNotificationsPreference);
|
||||||
},
|
},
|
||||||
items: messageNotificationContentItems(),
|
items: messageNotificationContentItems(),
|
||||||
).paddingAll(8),
|
).paddingLTRB(0, 4, 0, 4),
|
||||||
|
|
||||||
// Notifications
|
// Notifications
|
||||||
Table(
|
Table(
|
||||||
defaultVerticalAlignment: TableCellVerticalAlignment.middle,
|
defaultVerticalAlignment: TableCellVerticalAlignment.middle,
|
||||||
children: [
|
children: [
|
||||||
|
TableRow(children: [
|
||||||
|
Text(translate('settings_page.event'),
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: textTheme.titleMedium!.copyWith(
|
||||||
|
color: scale.primaryScale.border,
|
||||||
|
decorationColor: scale.primaryScale.border,
|
||||||
|
decoration: TextDecoration.underline))
|
||||||
|
.paddingAll(8),
|
||||||
|
Text(translate('settings_page.delivery'),
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: textTheme.titleMedium!.copyWith(
|
||||||
|
color: scale.primaryScale.border,
|
||||||
|
decorationColor: scale.primaryScale.border,
|
||||||
|
decoration: TextDecoration.underline))
|
||||||
|
.paddingAll(8),
|
||||||
|
Text(translate('settings_page.sound'),
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: textTheme.titleMedium!.copyWith(
|
||||||
|
color: scale.primaryScale.border,
|
||||||
|
decorationColor: scale.primaryScale.border,
|
||||||
|
decoration: TextDecoration.underline))
|
||||||
|
.paddingAll(8),
|
||||||
|
]),
|
||||||
TableRow(children: [
|
TableRow(children: [
|
||||||
// Invitation accepted
|
// Invitation accepted
|
||||||
Text(
|
Text(
|
||||||
@ -216,7 +253,7 @@ Widget buildSettingsPageNotificationPreferences(
|
|||||||
await updatePreferences(newNotificationsPreference);
|
await updatePreferences(newNotificationsPreference);
|
||||||
},
|
},
|
||||||
items: soundEffectItems(),
|
items: soundEffectItems(),
|
||||||
).paddingAll(4)
|
).paddingLTRB(4, 4, 0, 4)
|
||||||
]),
|
]),
|
||||||
// Message received
|
// Message received
|
||||||
TableRow(children: [
|
TableRow(children: [
|
||||||
@ -253,7 +290,7 @@ Widget buildSettingsPageNotificationPreferences(
|
|||||||
await updatePreferences(newNotificationsPreference);
|
await updatePreferences(newNotificationsPreference);
|
||||||
},
|
},
|
||||||
items: soundEffectItems(),
|
items: soundEffectItems(),
|
||||||
).paddingAll(4)
|
).paddingLTRB(4, 4, 0, 4)
|
||||||
]),
|
]),
|
||||||
|
|
||||||
// Message sent
|
// Message sent
|
||||||
@ -277,9 +314,9 @@ Widget buildSettingsPageNotificationPreferences(
|
|||||||
await updatePreferences(newNotificationsPreference);
|
await updatePreferences(newNotificationsPreference);
|
||||||
},
|
},
|
||||||
items: soundEffectItems(),
|
items: soundEffectItems(),
|
||||||
).paddingAll(4)
|
).paddingLTRB(4, 4, 0, 4)
|
||||||
]),
|
]),
|
||||||
]).paddingAll(8)
|
])
|
||||||
]).paddingAll(8),
|
]).paddingAll(8),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -36,10 +36,9 @@ packages:
|
|||||||
async_tools:
|
async_tools:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: async_tools
|
path: "../../../dart_async_tools"
|
||||||
sha256: "375da1e5b51974a9e84469b7630f36d1361fb53d3fcc818a5a0121ab51fe0343"
|
relative: true
|
||||||
url: "https://pub.dev"
|
source: path
|
||||||
source: hosted
|
|
||||||
version: "0.1.4"
|
version: "0.1.4"
|
||||||
bloc:
|
bloc:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
@ -52,10 +51,9 @@ packages:
|
|||||||
bloc_advanced_tools:
|
bloc_advanced_tools:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: bloc_advanced_tools
|
path: "../../../bloc_advanced_tools"
|
||||||
sha256: "0599d860eb096c5b12457c60bdf7f66bfcb7171bc94ccf2c7c752b6a716a79f9"
|
relative: true
|
||||||
url: "https://pub.dev"
|
source: path
|
||||||
source: hosted
|
|
||||||
version: "0.1.4"
|
version: "0.1.4"
|
||||||
boolean_selector:
|
boolean_selector:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
|
@ -26,11 +26,11 @@ dependencies:
|
|||||||
# veilid: ^0.0.1
|
# veilid: ^0.0.1
|
||||||
path: ../../../veilid/veilid-flutter
|
path: ../../../veilid/veilid-flutter
|
||||||
|
|
||||||
# dependency_overrides:
|
dependency_overrides:
|
||||||
# async_tools:
|
async_tools:
|
||||||
# path: ../../../dart_async_tools
|
path: ../../../dart_async_tools
|
||||||
# bloc_advanced_tools:
|
bloc_advanced_tools:
|
||||||
# path: ../../../bloc_advanced_tools
|
path: ../../../bloc_advanced_tools
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
build_runner: ^2.4.10
|
build_runner: ^2.4.10
|
||||||
|
14
pubspec.lock
14
pubspec.lock
@ -84,10 +84,9 @@ packages:
|
|||||||
async_tools:
|
async_tools:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: async_tools
|
path: "../dart_async_tools"
|
||||||
sha256: "375da1e5b51974a9e84469b7630f36d1361fb53d3fcc818a5a0121ab51fe0343"
|
relative: true
|
||||||
url: "https://pub.dev"
|
source: path
|
||||||
source: hosted
|
|
||||||
version: "0.1.4"
|
version: "0.1.4"
|
||||||
awesome_extensions:
|
awesome_extensions:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
@ -140,10 +139,9 @@ packages:
|
|||||||
bloc_advanced_tools:
|
bloc_advanced_tools:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: bloc_advanced_tools
|
path: "../bloc_advanced_tools"
|
||||||
sha256: "0599d860eb096c5b12457c60bdf7f66bfcb7171bc94ccf2c7c752b6a716a79f9"
|
relative: true
|
||||||
url: "https://pub.dev"
|
source: path
|
||||||
source: hosted
|
|
||||||
version: "0.1.4"
|
version: "0.1.4"
|
||||||
blurry_modal_progress_hud:
|
blurry_modal_progress_hud:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
|
10
pubspec.yaml
10
pubspec.yaml
@ -107,11 +107,11 @@ dependencies:
|
|||||||
xterm: ^4.0.0
|
xterm: ^4.0.0
|
||||||
zxing2: ^0.2.3
|
zxing2: ^0.2.3
|
||||||
|
|
||||||
# dependency_overrides:
|
dependency_overrides:
|
||||||
# async_tools:
|
async_tools:
|
||||||
# path: ../dart_async_tools
|
path: ../dart_async_tools
|
||||||
# bloc_advanced_tools:
|
bloc_advanced_tools:
|
||||||
# path: ../bloc_advanced_tools
|
path: ../bloc_advanced_tools
|
||||||
# flutter_chat_ui:
|
# flutter_chat_ui:
|
||||||
# path: ../flutter_chat_ui
|
# path: ../flutter_chat_ui
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user