desktop edit contact

This commit is contained in:
julian 2022-11-18 09:54:26 -06:00
parent 07f229f2a0
commit d4b7ec0f17
2 changed files with 462 additions and 366 deletions

View file

@ -1,3 +1,5 @@
import 'dart:async';
import 'package:emojis/emoji.dart'; import 'package:emojis/emoji.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
@ -7,14 +9,17 @@ import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/constants.dart'; import 'package:stackwallet/utilities/constants.dart';
import 'package:stackwallet/utilities/text_styles.dart'; import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/utilities/theme/stack_colors.dart'; import 'package:stackwallet/utilities/theme/stack_colors.dart';
import 'package:stackwallet/utilities/util.dart';
import 'package:stackwallet/widgets/conditional_parent.dart';
import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart'; import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
import 'package:stackwallet/widgets/desktop/desktop_dialog.dart';
import 'package:stackwallet/widgets/desktop/primary_button.dart';
import 'package:stackwallet/widgets/desktop/secondary_button.dart';
import 'package:stackwallet/widgets/emoji_select_sheet.dart'; import 'package:stackwallet/widgets/emoji_select_sheet.dart';
import 'package:stackwallet/widgets/icon_widgets/x_icon.dart'; import 'package:stackwallet/widgets/icon_widgets/x_icon.dart';
import 'package:stackwallet/widgets/stack_text_field.dart'; import 'package:stackwallet/widgets/stack_text_field.dart';
import 'package:stackwallet/widgets/textfield_icon_button.dart'; import 'package:stackwallet/widgets/textfield_icon_button.dart';
import 'package:stackwallet/utilities/util.dart';
class EditContactNameEmojiView extends ConsumerStatefulWidget { class EditContactNameEmojiView extends ConsumerStatefulWidget {
const EditContactNameEmojiView({ const EditContactNameEmojiView({
Key? key, Key? key,
@ -69,7 +74,12 @@ class _EditContactNameEmojiViewState
final contact = ref.watch(addressBookServiceProvider final contact = ref.watch(addressBookServiceProvider
.select((value) => value.getContactById(contactId))); .select((value) => value.getContactById(contactId)));
return Scaffold( final isDesktop = Util.isDesktop;
final double emojiSize = isDesktop ? 56 : 48;
return ConditionalParent(
condition: !isDesktop,
builder: (child) => Scaffold(
backgroundColor: Theme.of(context).extension<StackColors>()!.background, backgroundColor: Theme.of(context).extension<StackColors>()!.background,
appBar: AppBar( appBar: AppBar(
leading: AppBarBackButton( leading: AppBarBackButton(
@ -104,7 +114,19 @@ class _EditContactNameEmojiViewState
child: IntrinsicHeight( child: IntrinsicHeight(
child: Padding( child: Padding(
padding: const EdgeInsets.all(4), padding: const EdgeInsets.all(4),
child: child,
),
),
),
),
);
},
),
),
child: Column( child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
GestureDetector( GestureDetector(
onTap: () { onTap: () {
@ -114,6 +136,32 @@ class _EditContactNameEmojiViewState
}); });
return; return;
} }
if (isDesktop) {
showDialog<dynamic>(
barrierColor: Colors.transparent,
context: context,
builder: (context) {
return const DesktopDialog(
maxHeight: 700,
maxWidth: 600,
child: Padding(
padding: EdgeInsets.only(
left: 32,
right: 20,
top: 32,
bottom: 32,
),
child: EmojiSelectSheet(),
),
);
}).then((value) {
if (value is Emoji) {
setState(() {
_selectedEmoji = value;
});
}
});
} else {
showModalBottomSheet<dynamic>( showModalBottomSheet<dynamic>(
backgroundColor: Colors.transparent, backgroundColor: Colors.transparent,
context: context, context: context,
@ -130,17 +178,18 @@ class _EditContactNameEmojiViewState
}); });
} }
}); });
}
}, },
child: SizedBox( child: SizedBox(
height: 48, height: emojiSize,
width: 48, width: emojiSize,
child: Stack( child: Stack(
children: [ children: [
Container( Container(
height: 48, height: emojiSize,
width: 48, width: emojiSize,
decoration: BoxDecoration( decoration: BoxDecoration(
borderRadius: BorderRadius.circular(24), borderRadius: BorderRadius.circular(emojiSize / 2),
color: Theme.of(context) color: Theme.of(context)
.extension<StackColors>()! .extension<StackColors>()!
.textFieldActiveBG, .textFieldActiveBG,
@ -149,13 +198,14 @@ class _EditContactNameEmojiViewState
child: _selectedEmoji == null child: _selectedEmoji == null
? SvgPicture.asset( ? SvgPicture.asset(
Assets.svg.user, Assets.svg.user,
height: 24, height: emojiSize / 2,
width: 24, width: emojiSize / 2,
) )
: Text( : Text(
_selectedEmoji!.char, _selectedEmoji!.char,
style: STextStyles.pageTitleH1( style: isDesktop
context), ? STextStyles.desktopH3(context)
: STextStyles.pageTitleH1(context),
), ),
), ),
), ),
@ -194,9 +244,58 @@ class _EditContactNameEmojiViewState
), ),
), ),
), ),
if (isDesktop)
const SizedBox(
width: 8,
),
if (isDesktop)
Expanded(
child: ClipRRect(
borderRadius: BorderRadius.circular(
Constants.size.circularBorderRadius,
),
child: TextField(
autocorrect: Util.isDesktop ? false : true,
enableSuggestions: Util.isDesktop ? false : true,
controller: nameController,
focusNode: nameFocusNode,
style: STextStyles.field(context),
onChanged: (_) => setState(() {}),
decoration: standardInputDecoration(
"Enter contact name",
nameFocusNode,
context,
).copyWith(
suffixIcon: nameController.text.isNotEmpty
? Padding(
padding: const EdgeInsets.only(right: 0),
child: UnconstrainedBox(
child: Row(
children: [
TextFieldIconButton(
child: const XIcon(),
onTap: () async {
setState(() {
nameController.text = "";
});
},
),
],
),
),
)
: null,
),
),
),
),
],
),
if (!isDesktop)
const SizedBox( const SizedBox(
height: 8, height: 8,
), ),
if (!isDesktop)
ClipRRect( ClipRRect(
borderRadius: BorderRadius.circular( borderRadius: BorderRadius.circular(
Constants.size.circularBorderRadius, Constants.size.circularBorderRadius,
@ -242,19 +341,11 @@ class _EditContactNameEmojiViewState
Row( Row(
children: [ children: [
Expanded( Expanded(
child: TextButton( child: SecondaryButton(
style: Theme.of(context) label: "Cancel",
.extension<StackColors>()! buttonHeight: isDesktop ? ButtonHeight.l : null,
.getSecondaryEnabledButtonColor(context),
child: Text(
"Cancel",
style: STextStyles.button(context).copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.accentColorDark),
),
onPressed: () async { onPressed: () async {
if (FocusScope.of(context).hasFocus) { if (!isDesktop && FocusScope.of(context).hasFocus) {
FocusScope.of(context).unfocus(); FocusScope.of(context).unfocus();
await Future<void>.delayed( await Future<void>.delayed(
const Duration(milliseconds: 75)); const Duration(milliseconds: 75));
@ -269,55 +360,31 @@ class _EditContactNameEmojiViewState
width: 16, width: 16,
), ),
Expanded( Expanded(
child: Builder( child: PrimaryButton(
builder: (context) { label: "Save",
bool shouldEnableSave = enabled: nameController.text.isNotEmpty,
nameController.text.isNotEmpty; buttonHeight: isDesktop ? ButtonHeight.l : null,
onPressed: () async {
return TextButton( if (!isDesktop && FocusScope.of(context).hasFocus) {
style: shouldEnableSave
? Theme.of(context)
.extension<StackColors>()!
.getPrimaryEnabledButtonColor(
context)
: Theme.of(context)
.extension<StackColors>()!
.getPrimaryDisabledButtonColor(
context),
onPressed: shouldEnableSave
? () async {
if (FocusScope.of(context)
.hasFocus) {
FocusScope.of(context).unfocus(); FocusScope.of(context).unfocus();
await Future<void>.delayed( await Future<void>.delayed(
const Duration( const Duration(milliseconds: 75),
milliseconds: 75),
); );
} }
final editedContact = final editedContact = contact.copyWith(
contact.copyWith(
shouldCopyEmojiWithNull: true, shouldCopyEmojiWithNull: true,
name: nameController.text, name: nameController.text,
emojiChar: _selectedEmoji == null emojiChar:
? null _selectedEmoji == null ? null : _selectedEmoji!.char,
: _selectedEmoji!.char,
); );
ref unawaited(
.read( ref.read(addressBookServiceProvider).editContact(
addressBookServiceProvider)
.editContact(
editedContact, editedContact,
),
); );
if (mounted) { if (mounted) {
Navigator.of(context).pop(); Navigator.of(context).pop();
} }
}
: null,
child: Text(
"Save",
style: STextStyles.button(context),
),
);
}, },
), ),
), ),
@ -325,13 +392,6 @@ class _EditContactNameEmojiViewState
) )
], ],
), ),
),
),
),
),
);
},
),
); );
} }
} }

View file

@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_svg/flutter_svg.dart'; import 'package:flutter_svg/flutter_svg.dart';
import 'package:stackwallet/notifications/show_flush_bar.dart'; import 'package:stackwallet/notifications/show_flush_bar.dart';
import 'package:stackwallet/pages/address_book_views/subviews/edit_contact_name_emoji_view.dart';
import 'package:stackwallet/providers/global/address_book_service_provider.dart'; import 'package:stackwallet/providers/global/address_book_service_provider.dart';
import 'package:stackwallet/utilities/assets.dart'; import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/text_styles.dart'; import 'package:stackwallet/utilities/text_styles.dart';
@ -28,6 +29,147 @@ class _DesktopContactOptionsMenuPopupState
bool hoveredOnPencil = false; bool hoveredOnPencil = false;
bool hoveredOnTrash = false; bool hoveredOnTrash = false;
void editContact() {
// pop context menu
Navigator.of(context).pop();
showDialog<dynamic>(
context: context,
useSafeArea: true,
barrierDismissible: true,
builder: (_) => DesktopDialog(
maxWidth: 580,
maxHeight: 400,
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Padding(
padding: const EdgeInsets.only(
left: 32,
),
child: Text(
"Edit contact",
style: STextStyles.desktopH3(context),
),
),
const DesktopDialogCloseButton(),
],
),
Expanded(
child: Padding(
padding: const EdgeInsets.only(
top: 16,
left: 32,
right: 32,
bottom: 32,
),
child: EditContactNameEmojiView(
contactId: widget.contactId,
),
),
),
],
),
),
);
}
void attemptDeleteContact() {
final contact =
ref.read(addressBookServiceProvider).getContactById(widget.contactId);
// pop context menu
Navigator.of(context).pop();
showDialog<dynamic>(
context: context,
useSafeArea: true,
barrierDismissible: true,
builder: (_) => DesktopDialog(
maxWidth: 500,
maxHeight: 400,
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Padding(
padding: const EdgeInsets.only(
left: 32,
),
child: Text(
"Delete ${contact.name}?",
style: STextStyles.desktopH3(context),
),
),
const DesktopDialogCloseButton(),
],
),
Expanded(
child: Padding(
padding: const EdgeInsets.only(
left: 32,
right: 32,
bottom: 32,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Spacer(
flex: 1,
),
Text(
"Contact will be deleted permanently!",
style: STextStyles.desktopTextSmall(context),
),
const Spacer(
flex: 2,
),
Row(
children: [
Expanded(
child: SecondaryButton(
label: "Cancel",
onPressed: Navigator.of(context).pop,
buttonHeight: ButtonHeight.l,
),
),
const SizedBox(
width: 16,
),
Expanded(
child: Consumer(
builder: (context, ref, __) => PrimaryButton(
label: "Delete",
buttonHeight: ButtonHeight.l,
onPressed: () {
ref
.read(addressBookServiceProvider)
.removeContact(contact.id);
Navigator.of(context).pop();
showFloatingFlushBar(
type: FlushBarType.success,
message: "${contact.name} deleted",
context: context,
);
},
),
),
),
],
)
],
),
),
),
],
),
),
);
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Stack( return Stack(
@ -148,9 +290,7 @@ class _DesktopContactOptionsMenuPopupState
1000, 1000,
), ),
), ),
onPressed: () { onPressed: editContact,
print("should go to edit");
},
child: Padding( child: Padding(
padding: const EdgeInsets.symmetric( padding: const EdgeInsets.symmetric(
horizontal: 25, horizontal: 25,
@ -213,111 +353,7 @@ class _DesktopContactOptionsMenuPopupState
1000, 1000,
), ),
), ),
onPressed: () { onPressed: attemptDeleteContact,
final contact = ref
.read(addressBookServiceProvider)
.getContactById(widget.contactId);
// pop context menu
Navigator.of(context).pop();
showDialog<dynamic>(
context: context,
useSafeArea: true,
barrierDismissible: true,
builder: (_) => DesktopDialog(
maxWidth: 500,
maxHeight: 300,
child: Column(
children: [
Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
Padding(
padding: const EdgeInsets.only(
left: 32,
),
child: Text(
"Delete ${contact.name}?",
style: STextStyles.desktopH3(context),
),
),
const DesktopDialogCloseButton(),
],
),
Expanded(
child: Padding(
padding: const EdgeInsets.only(
left: 32,
right: 32,
bottom: 32,
),
child: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
const Spacer(
flex: 1,
),
Text(
"Contact will be deleted permanently!",
style: STextStyles.desktopTextSmall(
context),
),
const Spacer(
flex: 2,
),
Row(
children: [
Expanded(
child: SecondaryButton(
label: "Cancel",
onPressed:
Navigator.of(context).pop,
buttonHeight: ButtonHeight.l,
),
),
const SizedBox(
width: 16,
),
Expanded(
child: Consumer(
builder: (context, ref, __) =>
PrimaryButton(
label: "Delete",
buttonHeight:
ButtonHeight.l,
onPressed: () {
ref
.read(
addressBookServiceProvider)
.removeContact(
contact.id);
Navigator.of(context)
.pop();
showFloatingFlushBar(
type: FlushBarType
.success,
message:
"${contact.name} deleted",
context: context,
);
},
),
),
),
],
)
],
),
),
),
],
),
),
);
},
child: Padding( child: Padding(
padding: const EdgeInsets.symmetric( padding: const EdgeInsets.symmetric(
horizontal: 25, horizontal: 25,