From 19a366dcab9dc94bc0bca9a19d9f8665dfa0fec4 Mon Sep 17 00:00:00 2001 From: Christien Rioux Date: Tue, 6 Aug 2024 10:29:03 -0700 Subject: [PATCH] contacts ui cleanup --- assets/i18n/en.json | 11 ++++--- .../cubits/single_contact_messages_cubit.dart | 1 - lib/contacts/views/contact_item_widget.dart | 13 +++++++-- lib/contacts/views/contacts_browser.dart | 8 ++--- lib/contacts/views/contacts_dialog.dart | 29 +++++++++++++++---- lib/contacts/views/edit_contact_form.dart | 25 ++++++++-------- .../views/empty_contact_list_widget.dart | 12 ++++---- lib/theme/views/styled_alert.dart | 8 ++--- lib/theme/views/widget_helpers.dart | 16 ++++++++++ 9 files changed, 84 insertions(+), 39 deletions(-) diff --git a/assets/i18n/en.json b/assets/i18n/en.json index 22f5840..aa4d16e 100644 --- a/assets/i18n/en.json +++ b/assets/i18n/en.json @@ -86,10 +86,12 @@ "button": { "ok": "Ok", "cancel": "Cancel", + "edit": "Edit", "delete": "Delete", "accept": "Accept", "reject": "Reject", "finish": "Finish", + "close": "Close", "yes": "Yes", "no": "No", "waiting_for_network": "Waiting For Network" @@ -120,12 +122,13 @@ "contacts": "Contacts", "edit_contact": "Edit Contact", "invitations": "Invitations", - "no_contact_selected": "No contact selected", - "new_chat": "New Chat" + "no_contact_selected": "Double-click a contact to edit it", + "new_chat": "Open Chat", + "close_contact": "Close Contact" }, "contact_list": { "contacts": "Contacts", - "invite_people": "Invite people to VeilidChat", + "invite_people": "No contacts\n\nPress 'Create Invitation' to invite a contact to VeilidChat", "search": "Search contacts", "invitation": "Invitation", "loading_contacts": "Loading contacts..." @@ -134,7 +137,7 @@ "form_name": "Name", "form_pronouns": "Pronouns", "form_about": "About", - "form_status": "Current Status", + "form_status": "Status", "form_nickname": "Nickname", "form_notes": "Notes", "form_fingerprint": "Fingerprint", diff --git a/lib/chat/cubits/single_contact_messages_cubit.dart b/lib/chat/cubits/single_contact_messages_cubit.dart index 187a556..b4e77db 100644 --- a/lib/chat/cubits/single_contact_messages_cubit.dart +++ b/lib/chat/cubits/single_contact_messages_cubit.dart @@ -2,7 +2,6 @@ import 'dart:async'; import 'package:async_tools/async_tools.dart'; import 'package:fast_immutable_collections/fast_immutable_collections.dart'; -import 'package:flutter/foundation.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:veilid_support/veilid_support.dart'; diff --git a/lib/contacts/views/contact_item_widget.dart b/lib/contacts/views/contact_item_widget.dart index 46b658a..4cb874d 100644 --- a/lib/contacts/views/contact_item_widget.dart +++ b/lib/contacts/views/contact_item_widget.dart @@ -5,7 +5,6 @@ import '../../proto/proto.dart' as proto; import '../../theme/theme.dart'; const _kOnTap = 'onTap'; -const _kOnDelete = 'onDelete'; class ContactItemWidget extends StatelessWidget { const ContactItemWidget( @@ -70,13 +69,23 @@ class ContactItemWidget extends StatelessWidget { await _onTap(_contact); }), endActions: [ + if (_onDoubleTap != null) + SliderTileAction( + icon: Icons.edit, + label: translate('button.edit'), + actionScale: ScaleKind.secondary, + onPressed: (_context) => + singleFuture((this, _kOnTap), () async { + await _onDoubleTap(_contact); + }), + ), if (_onDelete != null) SliderTileAction( icon: Icons.delete, label: translate('button.delete'), actionScale: ScaleKind.tertiary, onPressed: (_context) => - singleFuture((this, _kOnDelete), () async { + singleFuture((this, _kOnTap), () async { await _onDelete(_contact); }), ), diff --git a/lib/contacts/views/contacts_browser.dart b/lib/contacts/views/contacts_browser.dart index 2eea880..89cea88 100644 --- a/lib/contacts/views/contacts_browser.dart +++ b/lib/contacts/views/contacts_browser.dart @@ -191,13 +191,13 @@ class _ContactsBrowserState extends State //final scaleConfig = theme.extension()!; final cilState = context.watch().state; - final cilBusy = cilState.busy; + //final cilBusy = cilState.busy; final contactInvitationRecordList = cilState.state.asData?.value.map((x) => x.value).toIList() ?? const IListConst([]); final ciState = context.watch().state; - final ciBusy = ciState.busy; + //final ciBusy = ciState.busy; final contactList = ciState.state.asData?.value.map((x) => x.value).toIList(); @@ -243,8 +243,8 @@ class _ContactsBrowserState extends State selected: widget.selectedContactRecordKey == contact.localConversationRecordKey.toVeilid(), disabled: false, - onTap: _onTapContact, - onDoubleTap: _onStartChat, + onDoubleTap: _onTapContact, + onTap: _onStartChat, onDelete: _onDeleteContact) .paddingLTRB(0, 4, 0, 0); case ContactsBrowserElementKind.invitation: diff --git a/lib/contacts/views/contacts_dialog.dart b/lib/contacts/views/contacts_dialog.dart index f994148..8d65338 100644 --- a/lib/contacts/views/contacts_dialog.dart +++ b/lib/contacts/views/contacts_dialog.dart @@ -75,12 +75,29 @@ class _ContactsDialogState extends State { : null, actions: [ if (_selectedContact != null) - IconButton( - icon: const Icon(Icons.chat_bubble), - tooltip: translate('contacts_dialog.new_chat'), - onPressed: () async { - await onChatStarted(_selectedContact!); - }) + Column(mainAxisSize: MainAxisSize.min, children: [ + IconButton( + icon: const Icon(Icons.chat_bubble), + tooltip: translate('contacts_dialog.new_chat'), + onPressed: () async { + await onChatStarted(_selectedContact!); + }), + Text(translate('contacts_dialog.new_chat'), + style: theme.textTheme.labelSmall! + .copyWith(color: scale.primaryScale.borderText)), + ]).paddingLTRB(8, 0, 8, 0), + if (enableSplit && _selectedContact != null) + Column(mainAxisSize: MainAxisSize.min, children: [ + IconButton( + icon: const Icon(Icons.close), + tooltip: translate('contacts_dialog.close_contact'), + onPressed: () async { + await onContactSelected(null); + }), + Text(translate('contacts_dialog.close_contact'), + style: theme.textTheme.labelSmall! + .copyWith(color: scale.primaryScale.borderText)), + ]).paddingLTRB(8, 0, 8, 0), ]), body: LayoutBuilder(builder: (context, constraint) { final maxWidth = constraint.maxWidth; diff --git a/lib/contacts/views/edit_contact_form.dart b/lib/contacts/views/edit_contact_form.dart index 0e8acc1..e515f14 100644 --- a/lib/contacts/views/edit_contact_form.dart +++ b/lib/contacts/views/edit_contact_form.dart @@ -67,6 +67,7 @@ class _EditContactFormState extends State { return FormBuilder( key: widget.formKey, child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, children: [ AvatarWidget( name: widget.contact.profile.name, @@ -79,53 +80,53 @@ class _EditContactFormState extends State { ).paddingLTRB(0, 0, 0, 16), SelectableText(widget.contact.profile.name, style: textTheme.headlineMedium) - .decoratorLabel( + .noEditDecoratorLabel( context, translate('contact_form.form_name'), scale: scale.secondaryScale, ) - .paddingSymmetric(vertical: 8), + .paddingSymmetric(vertical: 4), SelectableText(widget.contact.profile.pronouns, style: textTheme.headlineSmall) - .decoratorLabel( + .noEditDecoratorLabel( context, translate('contact_form.form_pronouns'), scale: scale.secondaryScale, ) - .paddingSymmetric(vertical: 8), - Row(children: [ + .paddingSymmetric(vertical: 4), + Row(mainAxisSize: MainAxisSize.min, children: [ _availabilityWidget(context, widget.contact.profile.availability), SelectableText(widget.contact.profile.status, style: textTheme.bodyMedium) .paddingSymmetric(horizontal: 8) ]) - .decoratorLabel( + .noEditDecoratorLabel( context, translate('contact_form.form_status'), scale: scale.secondaryScale, ) - .paddingSymmetric(vertical: 8), + .paddingSymmetric(vertical: 4), SelectableText(widget.contact.profile.about, minLines: 1, maxLines: 8, style: textTheme.bodyMedium) - .decoratorLabel( + .noEditDecoratorLabel( context, translate('contact_form.form_about'), scale: scale.secondaryScale, ) - .paddingSymmetric(vertical: 8), + .paddingSymmetric(vertical: 4), SelectableText( widget.contact.identityPublicKey.value.toVeilid().toString(), style: textTheme.labelMedium! .copyWith(fontFamily: 'Source Code Pro')) - .decoratorLabel( + .noEditDecoratorLabel( context, translate('contact_form.form_fingerprint'), scale: scale.secondaryScale, ) - .paddingSymmetric(vertical: 8), + .paddingSymmetric(vertical: 4), Divider(color: border).paddingLTRB(8, 0, 8, 8), FormBuilderTextField( - autofocus: true, + //autofocus: true, name: EditContactForm.formFieldNickname, initialValue: widget.contact.nickname, decoration: InputDecoration( diff --git a/lib/contacts/views/empty_contact_list_widget.dart b/lib/contacts/views/empty_contact_list_widget.dart index d787da3..2563a1d 100644 --- a/lib/contacts/views/empty_contact_list_widget.dart +++ b/lib/contacts/views/empty_contact_list_widget.dart @@ -1,4 +1,3 @@ -import 'package:awesome_extensions/awesome_extensions.dart'; import 'package:flutter/material.dart'; import 'package:flutter_translate/flutter_translate.dart'; @@ -22,14 +21,15 @@ class EmptyContactListWidget extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.stretch, mainAxisAlignment: MainAxisAlignment.center, children: [ - Icon( - Icons.person_add_sharp, - color: scale.primaryScale.subtleBorder, - size: 48, - ), + // Icon( + // Icons.person_add_sharp, + // color: scale.primaryScale.subtleBorder, + // size: 48, + // ), Text( textAlign: TextAlign.center, translate('contact_list.invite_people'), + //maxLines: 3, style: textTheme.bodyMedium?.copyWith( color: scale.primaryScale.subtleBorder, ), diff --git a/lib/theme/views/styled_alert.dart b/lib/theme/views/styled_alert.dart index 23b9e9e..39fa6f2 100644 --- a/lib/theme/views/styled_alert.dart +++ b/lib/theme/views/styled_alert.dart @@ -94,7 +94,7 @@ Future showErrorModal( {required BuildContext context, required String title, required String text}) async { - final theme = Theme.of(context); + // final theme = Theme.of(context); // final scale = theme.extension()!; // final scaleConfig = theme.extension()!; @@ -144,7 +144,7 @@ Future showWarningModal( {required BuildContext context, required String title, required String text}) async { - final theme = Theme.of(context); + // final theme = Theme.of(context); // final scale = theme.extension()!; // final scaleConfig = theme.extension()!; @@ -183,7 +183,7 @@ Future showWarningWidgetModal( {required BuildContext context, required String title, required Widget child}) async { - final theme = Theme.of(context); + // final theme = Theme.of(context); // final scale = theme.extension()!; // final scaleConfig = theme.extension()!; @@ -222,7 +222,7 @@ Future showConfirmModal( {required BuildContext context, required String title, required String text}) async { - final theme = Theme.of(context); + // final theme = Theme.of(context); // final scale = theme.extension()!; // final scaleConfig = theme.extension()!; diff --git a/lib/theme/views/widget_helpers.dart b/lib/theme/views/widget_helpers.dart index 8404e72..970e065 100644 --- a/lib/theme/views/widget_helpers.dart +++ b/lib/theme/views/widget_helpers.dart @@ -109,6 +109,22 @@ extension LabelExt on Widget { ), child: this); } + + Widget noEditDecoratorLabel(BuildContext context, String label, + {ScaleColor? scale}) { + final theme = Theme.of(context); + final scaleScheme = theme.extension()!; + // final scaleConfig = theme.extension()!; + scale = scale ?? scaleScheme.primaryScale; + + return Wrap(crossAxisAlignment: WrapCrossAlignment.center, children: [ + Text( + '$label:', + style: theme.textTheme.titleLarge!.copyWith(color: scale.border), + ).paddingLTRB(0, 0, 8, 8), + this + ]); + } } Widget buildProgressIndicator() => Builder(builder: (context) {