desktop edit contact address entry

This commit is contained in:
julian 2022-11-17 16:47:50 -06:00
parent 318758f768
commit cd19d776ae
2 changed files with 268 additions and 227 deletions

View file

@ -12,7 +12,11 @@ import 'package:stackwallet/utilities/barcode_scanner_interface.dart';
import 'package:stackwallet/utilities/clipboard_interface.dart';
import 'package:stackwallet/utilities/text_styles.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/desktop/primary_button.dart';
import 'package:stackwallet/widgets/desktop/secondary_button.dart';
class EditContactAddressView extends ConsumerStatefulWidget {
const EditContactAddressView({
@ -44,6 +48,42 @@ class _EditContactAddressViewState
late final BarcodeScannerInterface barcodeScanner;
late final ClipboardInterface clipboard;
Future<void> save(Contact contact) async {
if (FocusScope.of(context).hasFocus) {
FocusScope.of(context).unfocus();
await Future<void>.delayed(
const Duration(milliseconds: 75),
);
}
List<ContactAddressEntry> entries = contact.addresses.toList();
final entry = entries.firstWhere(
(e) =>
e.label == addressEntry.label &&
e.address == addressEntry.address &&
e.coin == addressEntry.coin,
);
final index = entries.indexOf(entry);
entries.remove(entry);
ContactAddressEntry editedEntry =
ref.read(addressEntryDataProvider(0)).buildAddressEntry();
entries.insert(index, editedEntry);
Contact editedContact = contact.copyWith(addresses: entries);
if (await ref.read(addressBookServiceProvider).editContact(editedContact)) {
if (mounted) {
Navigator.of(context).pop();
}
// TODO show success notification
} else {
// TODO show error notification
}
}
@override
void initState() {
contactId = widget.contactId;
@ -59,236 +99,181 @@ class _EditContactAddressViewState
final contact = ref.watch(addressBookServiceProvider
.select((value) => value.getContactById(contactId)));
return Scaffold(
backgroundColor: Theme.of(context).extension<StackColors>()!.background,
appBar: AppBar(
leading: AppBarBackButton(
onPressed: () async {
if (FocusScope.of(context).hasFocus) {
FocusScope.of(context).unfocus();
await Future<void>.delayed(const Duration(milliseconds: 75));
}
if (mounted) {
Navigator.of(context).pop();
}
},
final bool isDesktop = Util.isDesktop;
return ConditionalParent(
condition: !isDesktop,
builder: (child) => Scaffold(
backgroundColor: Theme.of(context).extension<StackColors>()!.background,
appBar: AppBar(
leading: AppBarBackButton(
onPressed: () async {
if (FocusScope.of(context).hasFocus) {
FocusScope.of(context).unfocus();
await Future<void>.delayed(const Duration(milliseconds: 75));
}
if (mounted) {
Navigator.of(context).pop();
}
},
),
title: Text(
"Edit address",
style: STextStyles.navBarTitle(context),
),
),
title: Text(
"Edit address",
style: STextStyles.navBarTitle(context),
),
),
body: LayoutBuilder(
builder: (context, constraints) {
return Padding(
padding: const EdgeInsets.only(
left: 12,
top: 12,
right: 12,
),
child: SingleChildScrollView(
child: ConstrainedBox(
constraints: BoxConstraints(
minHeight: constraints.maxHeight - 24,
),
child: IntrinsicHeight(
child: Padding(
padding: const EdgeInsets.all(4),
child: Column(
children: [
Row(
children: [
Container(
height: 48,
width: 48,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(24),
color: Theme.of(context)
.extension<StackColors>()!
.textFieldActiveBG,
),
child: Center(
child: contact.emojiChar == null
? SvgPicture.asset(
Assets.svg.user,
height: 24,
width: 24,
)
: Text(
contact.emojiChar!,
style: STextStyles.pageTitleH1(context),
),
),
),
const SizedBox(
width: 16,
),
Expanded(
child: FittedBox(
fit: BoxFit.scaleDown,
child: Text(
contact.name,
style: STextStyles.pageTitleH2(context),
),
),
),
],
),
const SizedBox(
height: 16,
),
NewContactAddressEntryForm(
id: 0,
barcodeScanner: barcodeScanner,
clipboard: clipboard,
),
const SizedBox(
height: 24,
),
GestureDetector(
onTap: () async {
// delete address
final _addresses = contact.addresses;
final entry = _addresses.firstWhere(
(e) =>
e.label == addressEntry.label &&
e.address == addressEntry.address &&
e.coin == addressEntry.coin,
);
_addresses.remove(entry);
Contact editedContact =
contact.copyWith(addresses: _addresses);
if (await ref
.read(addressBookServiceProvider)
.editContact(editedContact)) {
Navigator.of(context).pop();
// TODO show success notification
} else {
// TODO show error notification
}
},
child: Text(
"Delete address",
style: STextStyles.link(context),
),
),
const Spacer(),
const SizedBox(
height: 16,
),
Row(
children: [
Expanded(
child: TextButton(
style: Theme.of(context)
.extension<StackColors>()!
.getSecondaryEnabledButtonColor(context),
child: Text(
"Cancel",
style: STextStyles.button(context).copyWith(
color: Theme.of(context)
.extension<StackColors>()!
.accentColorDark),
),
onPressed: () async {
if (FocusScope.of(context).hasFocus) {
FocusScope.of(context).unfocus();
await Future<void>.delayed(
const Duration(milliseconds: 75));
}
if (mounted) {
Navigator.of(context).pop();
}
},
),
),
const SizedBox(
width: 16,
),
Expanded(
child: Builder(
builder: (context) {
bool shouldEnableSave =
ref.watch(validContactStateProvider([0]));
return TextButton(
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();
await Future<void>.delayed(
const Duration(
milliseconds: 75),
);
}
List<ContactAddressEntry> entries =
contact.addresses.toList();
final entry = entries.firstWhere(
(e) =>
e.label ==
addressEntry.label &&
e.address ==
addressEntry.address &&
e.coin == addressEntry.coin,
);
final index =
entries.indexOf(entry);
entries.remove(entry);
ContactAddressEntry editedEntry = ref
.read(
addressEntryDataProvider(0))
.buildAddressEntry();
entries.insert(index, editedEntry);
Contact editedContact = contact
.copyWith(addresses: entries);
if (await ref
.read(
addressBookServiceProvider)
.editContact(editedContact)) {
if (mounted) {
Navigator.of(context).pop();
}
// TODO show success notification
} else {
// TODO show error notification
}
}
: null,
child: Text(
"Save",
style: STextStyles.button(context),
),
);
},
),
),
],
),
],
body: LayoutBuilder(
builder: (context, constraints) {
return Padding(
padding: const EdgeInsets.only(
left: 12,
top: 12,
right: 12,
),
child: SingleChildScrollView(
child: ConstrainedBox(
constraints: BoxConstraints(
minHeight: constraints.maxHeight - 24,
),
child: IntrinsicHeight(
child: Padding(
padding: const EdgeInsets.all(4),
child: child,
),
),
),
),
);
},
),
),
child: Column(
children: [
Row(
children: [
Container(
height: 48,
width: 48,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(24),
color: Theme.of(context)
.extension<StackColors>()!
.textFieldActiveBG,
),
child: Center(
child: contact.emojiChar == null
? SvgPicture.asset(
Assets.svg.user,
height: 24,
width: 24,
)
: Text(
contact.emojiChar!,
style: STextStyles.pageTitleH1(context),
),
),
),
const SizedBox(
width: 16,
),
if (isDesktop)
Text(
contact.name,
style: STextStyles.pageTitleH2(context),
),
if (!isDesktop)
Expanded(
child: FittedBox(
fit: BoxFit.scaleDown,
child: Text(
contact.name,
style: STextStyles.pageTitleH2(context),
),
),
),
],
),
const SizedBox(
height: 16,
),
NewContactAddressEntryForm(
id: 0,
barcodeScanner: barcodeScanner,
clipboard: clipboard,
),
const SizedBox(
height: 24,
),
ConditionalParent(
condition: isDesktop,
builder: (child) => MouseRegion(
cursor: SystemMouseCursors.click,
child: child,
),
);
},
child: GestureDetector(
onTap: () async {
// delete address
final _addresses = contact.addresses;
final entry = _addresses.firstWhere(
(e) =>
e.label == addressEntry.label &&
e.address == addressEntry.address &&
e.coin == addressEntry.coin,
);
_addresses.remove(entry);
Contact editedContact = contact.copyWith(addresses: _addresses);
if (await ref
.read(addressBookServiceProvider)
.editContact(editedContact)) {
Navigator.of(context).pop();
// TODO show success notification
} else {
// TODO show error notification
}
},
child: Text(
"Delete address",
style: STextStyles.link(context),
),
),
),
const Spacer(),
const SizedBox(
height: 16,
),
Row(
children: [
Expanded(
child: SecondaryButton(
label: "Cancel",
buttonHeight: isDesktop ? ButtonHeight.l : null,
onPressed: () async {
if (!isDesktop && FocusScope.of(context).hasFocus) {
FocusScope.of(context).unfocus();
await Future<void>.delayed(
const Duration(milliseconds: 75));
}
if (mounted) {
Navigator.of(context).pop();
}
},
),
),
const SizedBox(
width: 16,
),
Expanded(
child: PrimaryButton(
label: "Save",
enabled: ref.watch(validContactStateProvider([0])),
onPressed: () => save(contact),
buttonHeight: isDesktop ? ButtonHeight.l : null,
),
),
],
),
],
),
);
}

View file

@ -1,15 +1,20 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:stackwallet/models/contact_address_entry.dart';
import 'package:stackwallet/notifications/show_flush_bar.dart';
import 'package:stackwallet/pages/address_book_views/subviews/edit_contact_address_view.dart';
import 'package:stackwallet/providers/ui/address_book_providers/address_entry_data_provider.dart';
import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/clipboard_interface.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/enums/flush_bar_type.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/utilities/theme/stack_colors.dart';
import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
import 'package:stackwallet/widgets/custom_buttons/blue_text_button.dart';
import 'package:stackwallet/widgets/desktop/desktop_dialog.dart';
class DesktopAddressCard extends StatelessWidget {
const DesktopAddressCard({
@ -80,9 +85,60 @@ class DesktopAddressCard extends StatelessWidget {
width: 16,
),
if (contactId != "default")
BlueTextButton(
text: "Edit",
onTap: () {},
Consumer(
builder: (context, ref, child) {
return BlueTextButton(
text: "Edit",
onTap: () async {
ref.read(addressEntryDataProvider(0)).address =
entry.address;
ref.read(addressEntryDataProvider(0)).addressLabel =
entry.label;
ref.read(addressEntryDataProvider(0)).coin =
entry.coin;
await showDialog<void>(
context: context,
builder: (context) => DesktopDialog(
maxWidth: 580,
maxHeight: 566,
child: Column(
children: [
Row(
children: [
const SizedBox(
width: 8,
),
const AppBarBackButton(
isCompact: true,
),
Text(
"Edit address",
style: STextStyles.desktopH3(context),
),
],
),
Expanded(
child: Padding(
padding: const EdgeInsets.only(
top: 20,
left: 32,
right: 32,
bottom: 32,
),
child: EditContactAddressView(
contactId: contactId,
addressEntry: entry,
),
),
),
],
),
),
);
},
);
},
),
],
)