mirror of
https://github.com/cypherstack/stack_wallet.git
synced 2025-01-11 05:04:35 +00:00
wip: new contact emoji selection and crypto selection
This commit is contained in:
parent
9df0569bb1
commit
9417d78c81
1 changed files with 501 additions and 357 deletions
|
@ -15,15 +15,17 @@ import 'package:stackwallet/utilities/clipboard_interface.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/custom_buttons/blue_text_button.dart';
|
import 'package:stackwallet/widgets/custom_buttons/blue_text_button.dart';
|
||||||
|
import 'package:stackwallet/widgets/desktop/desktop_dialog.dart';
|
||||||
|
import 'package:stackwallet/widgets/desktop/desktop_dialog_close_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 AddAddressBookEntryView extends ConsumerStatefulWidget {
|
class AddAddressBookEntryView extends ConsumerStatefulWidget {
|
||||||
const AddAddressBookEntryView({
|
const AddAddressBookEntryView({
|
||||||
Key? key,
|
Key? key,
|
||||||
|
@ -108,395 +110,537 @@ class _AddAddressBookEntryViewState
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
debugPrint("BUILD: $runtimeType");
|
debugPrint("BUILD: $runtimeType");
|
||||||
|
|
||||||
return Scaffold(
|
final isDesktop = Util.isDesktop;
|
||||||
backgroundColor: Theme.of(context).extension<StackColors>()!.background,
|
return ConditionalParent(
|
||||||
appBar: AppBar(
|
condition: !isDesktop,
|
||||||
leading: AppBarBackButton(
|
builder: (child) {
|
||||||
onPressed: () async {
|
return Scaffold(
|
||||||
if (FocusScope.of(context).hasFocus) {
|
backgroundColor:
|
||||||
FocusScope.of(context).unfocus();
|
Theme.of(context).extension<StackColors>()!.background,
|
||||||
await Future<void>.delayed(const Duration(milliseconds: 75));
|
appBar: AppBar(
|
||||||
}
|
leading: AppBarBackButton(
|
||||||
if (mounted) {
|
onPressed: () async {
|
||||||
Navigator.of(context).pop();
|
if (FocusScope.of(context).hasFocus) {
|
||||||
}
|
FocusScope.of(context).unfocus();
|
||||||
},
|
await Future<void>.delayed(
|
||||||
),
|
const Duration(milliseconds: 75));
|
||||||
title: Text(
|
}
|
||||||
"New contact",
|
if (mounted) {
|
||||||
style: STextStyles.navBarTitle(context),
|
Navigator.of(context).pop();
|
||||||
),
|
}
|
||||||
actions: [
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.only(
|
|
||||||
top: 10,
|
|
||||||
bottom: 10,
|
|
||||||
right: 10,
|
|
||||||
),
|
|
||||||
child: AspectRatio(
|
|
||||||
aspectRatio: 1,
|
|
||||||
child: AppBarIconButton(
|
|
||||||
key: const Key("addAddressBookEntryFavoriteButtonKey"),
|
|
||||||
size: 36,
|
|
||||||
shadows: const [],
|
|
||||||
color: Theme.of(context).extension<StackColors>()!.background,
|
|
||||||
icon: SvgPicture.asset(
|
|
||||||
Assets.svg.star,
|
|
||||||
color: _isFavorite
|
|
||||||
? Theme.of(context)
|
|
||||||
.extension<StackColors>()!
|
|
||||||
.favoriteStarActive
|
|
||||||
: Theme.of(context)
|
|
||||||
.extension<StackColors>()!
|
|
||||||
.favoriteStarInactive,
|
|
||||||
width: 20,
|
|
||||||
height: 20,
|
|
||||||
),
|
|
||||||
onPressed: () {
|
|
||||||
setState(() {
|
|
||||||
_isFavorite = !_isFavorite;
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
title: Text(
|
||||||
),
|
"New contact",
|
||||||
],
|
style: STextStyles.navBarTitle(context),
|
||||||
),
|
|
||||||
body: LayoutBuilder(
|
|
||||||
builder: (context, constraint) {
|
|
||||||
return Padding(
|
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 12),
|
|
||||||
child: SingleChildScrollView(
|
|
||||||
controller: scrollController,
|
|
||||||
padding: const EdgeInsets.only(
|
|
||||||
// top: 8,
|
|
||||||
left: 4,
|
|
||||||
right: 4,
|
|
||||||
bottom: 16,
|
|
||||||
),
|
),
|
||||||
child: ConstrainedBox(
|
actions: [
|
||||||
constraints: BoxConstraints(
|
Padding(
|
||||||
// subtract top and bottom padding set in parent
|
padding: const EdgeInsets.only(
|
||||||
minHeight: constraint.maxHeight - 16, // - 8,
|
top: 10,
|
||||||
),
|
bottom: 10,
|
||||||
child: IntrinsicHeight(
|
right: 10,
|
||||||
child: Column(
|
),
|
||||||
children: [
|
child: AspectRatio(
|
||||||
const SizedBox(
|
aspectRatio: 1,
|
||||||
height: 4,
|
child: AppBarIconButton(
|
||||||
|
key: const Key("addAddressBookEntryFavoriteButtonKey"),
|
||||||
|
size: 36,
|
||||||
|
shadows: const [],
|
||||||
|
color: Theme.of(context)
|
||||||
|
.extension<StackColors>()!
|
||||||
|
.background,
|
||||||
|
icon: SvgPicture.asset(
|
||||||
|
Assets.svg.star,
|
||||||
|
color: _isFavorite
|
||||||
|
? Theme.of(context)
|
||||||
|
.extension<StackColors>()!
|
||||||
|
.favoriteStarActive
|
||||||
|
: Theme.of(context)
|
||||||
|
.extension<StackColors>()!
|
||||||
|
.favoriteStarInactive,
|
||||||
|
width: 20,
|
||||||
|
height: 20,
|
||||||
),
|
),
|
||||||
GestureDetector(
|
onPressed: () {
|
||||||
onTap: () {
|
setState(() {
|
||||||
if (_selectedEmoji != null) {
|
_isFavorite = !_isFavorite;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
body: child);
|
||||||
|
},
|
||||||
|
child: ConditionalParent(
|
||||||
|
condition: isDesktop,
|
||||||
|
builder: (child) {
|
||||||
|
return Column(
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.all(32),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
"New contact",
|
||||||
|
style: STextStyles.desktopH3(context),
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
),
|
||||||
|
const SizedBox(width: 10),
|
||||||
|
AppBarIconButton(
|
||||||
|
key:
|
||||||
|
const Key("addAddressBookEntryFavoriteButtonKey"),
|
||||||
|
size: 36,
|
||||||
|
shadows: const [],
|
||||||
|
color: Theme.of(context)
|
||||||
|
.extension<StackColors>()!
|
||||||
|
.background,
|
||||||
|
icon: SvgPicture.asset(
|
||||||
|
Assets.svg.star,
|
||||||
|
color: _isFavorite
|
||||||
|
? Theme.of(context)
|
||||||
|
.extension<StackColors>()!
|
||||||
|
.favoriteStarActive
|
||||||
|
: Theme.of(context)
|
||||||
|
.extension<StackColors>()!
|
||||||
|
.favoriteStarInactive,
|
||||||
|
width: 20,
|
||||||
|
height: 20,
|
||||||
|
),
|
||||||
|
onPressed: () {
|
||||||
setState(() {
|
setState(() {
|
||||||
_selectedEmoji = null;
|
_isFavorite = !_isFavorite;
|
||||||
});
|
});
|
||||||
return;
|
},
|
||||||
}
|
),
|
||||||
showModalBottomSheet<dynamic>(
|
],
|
||||||
backgroundColor: Colors.transparent,
|
),
|
||||||
context: context,
|
),
|
||||||
shape: const RoundedRectangleBorder(
|
const DesktopDialogCloseButton(),
|
||||||
borderRadius: BorderRadius.vertical(
|
],
|
||||||
top: Radius.circular(20),
|
),
|
||||||
),
|
Expanded(child: child),
|
||||||
),
|
],
|
||||||
builder: (_) => const EmojiSelectSheet(),
|
);
|
||||||
).then((value) {
|
},
|
||||||
if (value is Emoji) {
|
child: LayoutBuilder(
|
||||||
|
builder: (context, constraint) {
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 12),
|
||||||
|
child: SingleChildScrollView(
|
||||||
|
controller: scrollController,
|
||||||
|
padding: const EdgeInsets.only(
|
||||||
|
// top: 8,
|
||||||
|
left: 4,
|
||||||
|
right: 4,
|
||||||
|
bottom: 16,
|
||||||
|
),
|
||||||
|
child: ConstrainedBox(
|
||||||
|
constraints: BoxConstraints(
|
||||||
|
// subtract top and bottom padding set in parent
|
||||||
|
minHeight: constraint.maxHeight - 16, // - 8,
|
||||||
|
),
|
||||||
|
child: IntrinsicHeight(
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
const SizedBox(
|
||||||
|
height: 4,
|
||||||
|
),
|
||||||
|
GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
if (_selectedEmoji != null) {
|
||||||
setState(() {
|
setState(() {
|
||||||
_selectedEmoji = value;
|
_selectedEmoji = null;
|
||||||
});
|
});
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
});
|
|
||||||
},
|
///TODO if desktop make dialog
|
||||||
child: SizedBox(
|
!isDesktop
|
||||||
height: 48,
|
? showModalBottomSheet<dynamic>(
|
||||||
width: 48,
|
backgroundColor: Colors.transparent,
|
||||||
child: Stack(
|
context: context,
|
||||||
children: [
|
shape: const RoundedRectangleBorder(
|
||||||
Container(
|
borderRadius: BorderRadius.vertical(
|
||||||
height: 48,
|
top: Radius.circular(20),
|
||||||
width: 48,
|
),
|
||||||
decoration: BoxDecoration(
|
),
|
||||||
borderRadius: BorderRadius.circular(24),
|
builder: (_) => const EmojiSelectSheet(),
|
||||||
color: Theme.of(context)
|
).then((value) {
|
||||||
.extension<StackColors>()!
|
if (value is Emoji) {
|
||||||
.textFieldActiveBG,
|
setState(() {
|
||||||
),
|
_selectedEmoji = value;
|
||||||
child: Center(
|
});
|
||||||
child: _selectedEmoji == null
|
}
|
||||||
? SvgPicture.asset(
|
})
|
||||||
Assets.svg.user,
|
: showDialog<dynamic>(
|
||||||
height: 24,
|
context: context,
|
||||||
width: 24,
|
builder: (context) {
|
||||||
)
|
return DesktopDialog(
|
||||||
: Text(
|
maxHeight: 700,
|
||||||
_selectedEmoji!.char,
|
maxWidth: 700,
|
||||||
style:
|
child: Column(
|
||||||
STextStyles.pageTitleH1(context),
|
children: [
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding:
|
||||||
|
const EdgeInsets.all(32),
|
||||||
|
child: Text(
|
||||||
|
"Select emoji",
|
||||||
|
style:
|
||||||
|
STextStyles.desktopH3(
|
||||||
|
context),
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: LayoutBuilder(
|
||||||
|
builder:
|
||||||
|
(context, constraints) {
|
||||||
|
return SingleChildScrollView(
|
||||||
|
scrollDirection:
|
||||||
|
Axis.vertical,
|
||||||
|
child: ConstrainedBox(
|
||||||
|
constraints:
|
||||||
|
BoxConstraints(
|
||||||
|
minHeight: constraints
|
||||||
|
.maxHeight,
|
||||||
|
minWidth: constraints
|
||||||
|
.maxWidth,
|
||||||
|
),
|
||||||
|
child: IntrinsicHeight(
|
||||||
|
child: Column(
|
||||||
|
children: const [
|
||||||
|
Padding(
|
||||||
|
padding: EdgeInsets
|
||||||
|
.symmetric(
|
||||||
|
horizontal:
|
||||||
|
32),
|
||||||
|
// child:
|
||||||
|
// EmojiSelectSheet(),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
),
|
);
|
||||||
),
|
}).then((value) {
|
||||||
Align(
|
if (value is Emoji) {
|
||||||
alignment: Alignment.bottomRight,
|
setState(() {
|
||||||
child: Container(
|
_selectedEmoji = value;
|
||||||
height: 14,
|
});
|
||||||
width: 14,
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
child: SizedBox(
|
||||||
|
height: 48,
|
||||||
|
width: 48,
|
||||||
|
child: Stack(
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
height: 48,
|
||||||
|
width: 48,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
borderRadius: BorderRadius.circular(14),
|
borderRadius: BorderRadius.circular(24),
|
||||||
color: Theme.of(context)
|
color: Theme.of(context)
|
||||||
.extension<StackColors>()!
|
.extension<StackColors>()!
|
||||||
.accentColorDark),
|
.textFieldActiveBG,
|
||||||
|
),
|
||||||
child: Center(
|
child: Center(
|
||||||
child: _selectedEmoji == null
|
child: _selectedEmoji == null
|
||||||
? SvgPicture.asset(
|
? SvgPicture.asset(
|
||||||
Assets.svg.plus,
|
Assets.svg.user,
|
||||||
color: Theme.of(context)
|
height: 24,
|
||||||
.extension<StackColors>()!
|
width: 24,
|
||||||
.textWhite,
|
|
||||||
width: 12,
|
|
||||||
height: 12,
|
|
||||||
)
|
)
|
||||||
: SvgPicture.asset(
|
: Text(
|
||||||
Assets.svg.thickX,
|
_selectedEmoji!.char,
|
||||||
color: Theme.of(context)
|
style: STextStyles.pageTitleH1(
|
||||||
.extension<StackColors>()!
|
context),
|
||||||
.textWhite,
|
|
||||||
width: 8,
|
|
||||||
height: 8,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
)
|
Align(
|
||||||
],
|
alignment: Alignment.bottomRight,
|
||||||
),
|
child: Container(
|
||||||
),
|
height: 14,
|
||||||
),
|
width: 14,
|
||||||
const SizedBox(
|
decoration: BoxDecoration(
|
||||||
height: 8,
|
borderRadius: BorderRadius.circular(14),
|
||||||
),
|
color: Theme.of(context)
|
||||||
ClipRRect(
|
.extension<StackColors>()!
|
||||||
borderRadius: BorderRadius.circular(
|
.accentColorDark),
|
||||||
Constants.size.circularBorderRadius,
|
child: Center(
|
||||||
),
|
child: _selectedEmoji == null
|
||||||
child: TextField(
|
? SvgPicture.asset(
|
||||||
autocorrect: Util.isDesktop ? false : true,
|
Assets.svg.plus,
|
||||||
enableSuggestions: Util.isDesktop ? false : true,
|
color: Theme.of(context)
|
||||||
controller: nameController,
|
.extension<StackColors>()!
|
||||||
focusNode: nameFocusNode,
|
.textWhite,
|
||||||
style: STextStyles.field(context),
|
width: 12,
|
||||||
decoration: standardInputDecoration(
|
height: 12,
|
||||||
"Enter contact name",
|
)
|
||||||
nameFocusNode,
|
: SvgPicture.asset(
|
||||||
context,
|
Assets.svg.thickX,
|
||||||
).copyWith(
|
color: Theme.of(context)
|
||||||
suffixIcon: ref
|
.extension<StackColors>()!
|
||||||
.read(contactNameIsNotEmptyStateProvider
|
.textWhite,
|
||||||
.state)
|
width: 8,
|
||||||
.state
|
height: 8,
|
||||||
? Padding(
|
),
|
||||||
padding: const EdgeInsets.only(right: 0),
|
|
||||||
child: UnconstrainedBox(
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
TextFieldIconButton(
|
|
||||||
child: const XIcon(),
|
|
||||||
onTap: () async {
|
|
||||||
setState(() {
|
|
||||||
nameController.text = "";
|
|
||||||
});
|
|
||||||
},
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
)
|
),
|
||||||
: null,
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
onChanged: (newValue) {
|
|
||||||
ref
|
|
||||||
.read(contactNameIsNotEmptyStateProvider.state)
|
|
||||||
.state = newValue.isNotEmpty;
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
),
|
|
||||||
if (forms.length <= 1)
|
|
||||||
const SizedBox(
|
const SizedBox(
|
||||||
height: 8,
|
height: 8,
|
||||||
),
|
),
|
||||||
if (forms.length <= 1) forms[0],
|
ClipRRect(
|
||||||
if (forms.length > 1)
|
borderRadius: BorderRadius.circular(
|
||||||
for (int i = 0; i < forms.length; i++)
|
Constants.size.circularBorderRadius,
|
||||||
Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
const SizedBox(
|
|
||||||
height: 12,
|
|
||||||
),
|
|
||||||
Row(
|
|
||||||
mainAxisAlignment:
|
|
||||||
MainAxisAlignment.spaceBetween,
|
|
||||||
children: [
|
|
||||||
Text(
|
|
||||||
"Address ${i + 1}",
|
|
||||||
style: STextStyles.smallMed12(context),
|
|
||||||
),
|
|
||||||
BlueTextButton(
|
|
||||||
onTap: () {
|
|
||||||
_removeForm(forms[i].id);
|
|
||||||
},
|
|
||||||
text: "Remove",
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
const SizedBox(
|
|
||||||
height: 8,
|
|
||||||
),
|
|
||||||
forms[i],
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
const SizedBox(
|
child: TextField(
|
||||||
height: 16,
|
autocorrect: Util.isDesktop ? false : true,
|
||||||
),
|
enableSuggestions: Util.isDesktop ? false : true,
|
||||||
BlueTextButton(
|
controller: nameController,
|
||||||
onTap: () {
|
focusNode: nameFocusNode,
|
||||||
_addForm();
|
style: STextStyles.field(context),
|
||||||
scrollController.animateTo(
|
decoration: standardInputDecoration(
|
||||||
scrollController.position.maxScrollExtent + 500,
|
"Enter contact name",
|
||||||
duration: const Duration(milliseconds: 500),
|
nameFocusNode,
|
||||||
curve: Curves.easeInOut,
|
context,
|
||||||
);
|
).copyWith(
|
||||||
},
|
suffixIcon: ref
|
||||||
text: "+ Add another address",
|
.read(contactNameIsNotEmptyStateProvider
|
||||||
),
|
.state)
|
||||||
// GestureDetector(
|
.state
|
||||||
//
|
? Padding(
|
||||||
// child: Text(
|
padding: const EdgeInsets.only(right: 0),
|
||||||
// "+ Add another address",
|
child: UnconstrainedBox(
|
||||||
// style: STextStyles.largeMedium14(context),
|
child: Row(
|
||||||
// ),
|
children: [
|
||||||
// ),
|
TextFieldIconButton(
|
||||||
const SizedBox(
|
child: const XIcon(),
|
||||||
height: 16,
|
onTap: () async {
|
||||||
),
|
setState(() {
|
||||||
const Spacer(),
|
nameController.text = "";
|
||||||
Row(
|
});
|
||||||
children: [
|
},
|
||||||
Expanded(
|
),
|
||||||
child: TextButton(
|
],
|
||||||
style: Theme.of(context)
|
),
|
||||||
.extension<StackColors>()!
|
),
|
||||||
.getSecondaryEnabledButtonColor(context),
|
)
|
||||||
child: Text(
|
: null,
|
||||||
"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();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
|
onChanged: (newValue) {
|
||||||
|
ref
|
||||||
|
.read(
|
||||||
|
contactNameIsNotEmptyStateProvider.state)
|
||||||
|
.state = newValue.isNotEmpty;
|
||||||
|
},
|
||||||
),
|
),
|
||||||
|
),
|
||||||
|
if (forms.length <= 1)
|
||||||
const SizedBox(
|
const SizedBox(
|
||||||
width: 16,
|
height: 8,
|
||||||
),
|
),
|
||||||
Expanded(
|
if (forms.length <= 1) forms[0],
|
||||||
child: Builder(
|
if (forms.length > 1)
|
||||||
builder: (context) {
|
for (int i = 0; i < forms.length; i++)
|
||||||
bool nameExists = ref
|
Column(
|
||||||
.watch(contactNameIsNotEmptyStateProvider
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
.state)
|
children: [
|
||||||
.state;
|
const SizedBox(
|
||||||
|
height: 12,
|
||||||
bool validForms = ref.watch(
|
),
|
||||||
validContactStateProvider(forms
|
Row(
|
||||||
.map((e) => e.id)
|
mainAxisAlignment:
|
||||||
.toList(growable: false)));
|
MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
bool shouldEnableSave =
|
Text(
|
||||||
validForms && nameExists;
|
"Address ${i + 1}",
|
||||||
|
style: STextStyles.smallMed12(context),
|
||||||
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 =
|
|
||||||
[];
|
|
||||||
for (int i = 0;
|
|
||||||
i < forms.length;
|
|
||||||
i++) {
|
|
||||||
entries.add(ref
|
|
||||||
.read(addressEntryDataProvider(
|
|
||||||
forms[i].id))
|
|
||||||
.buildAddressEntry());
|
|
||||||
}
|
|
||||||
Contact contact = Contact(
|
|
||||||
emojiChar: _selectedEmoji?.char,
|
|
||||||
name: nameController.text,
|
|
||||||
addresses: entries,
|
|
||||||
isFavorite: _isFavorite,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (await ref
|
|
||||||
.read(addressBookServiceProvider)
|
|
||||||
.addContact(contact)) {
|
|
||||||
if (mounted) {
|
|
||||||
Navigator.of(context).pop();
|
|
||||||
}
|
|
||||||
// TODO show success notification
|
|
||||||
} else {
|
|
||||||
// TODO show error notification
|
|
||||||
}
|
|
||||||
}
|
|
||||||
: null,
|
|
||||||
child: Text(
|
|
||||||
"Save",
|
|
||||||
style: STextStyles.button(context).copyWith(
|
|
||||||
color: shouldEnableSave
|
|
||||||
? Theme.of(context)
|
|
||||||
.extension<StackColors>()!
|
|
||||||
.buttonTextPrimary
|
|
||||||
: Theme.of(context)
|
|
||||||
.extension<StackColors>()!
|
|
||||||
.buttonTextPrimaryDisabled,
|
|
||||||
),
|
),
|
||||||
),
|
BlueTextButton(
|
||||||
);
|
onTap: () {
|
||||||
},
|
_removeForm(forms[i].id);
|
||||||
|
},
|
||||||
|
text: "Remove",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const SizedBox(
|
||||||
|
height: 8,
|
||||||
|
),
|
||||||
|
forms[i],
|
||||||
|
],
|
||||||
),
|
),
|
||||||
),
|
const SizedBox(
|
||||||
],
|
height: 16,
|
||||||
),
|
),
|
||||||
],
|
BlueTextButton(
|
||||||
|
onTap: () {
|
||||||
|
_addForm();
|
||||||
|
scrollController.animateTo(
|
||||||
|
scrollController.position.maxScrollExtent + 500,
|
||||||
|
duration: const Duration(milliseconds: 500),
|
||||||
|
curve: Curves.easeInOut,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
text: "+ Add another address",
|
||||||
|
),
|
||||||
|
// GestureDetector(
|
||||||
|
//
|
||||||
|
// child: Text(
|
||||||
|
// "+ Add another address",
|
||||||
|
// style: STextStyles.largeMedium14(context),
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
const SizedBox(
|
||||||
|
height: 16,
|
||||||
|
),
|
||||||
|
const Spacer(),
|
||||||
|
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 nameExists = ref
|
||||||
|
.watch(contactNameIsNotEmptyStateProvider
|
||||||
|
.state)
|
||||||
|
.state;
|
||||||
|
|
||||||
|
bool validForms = ref.watch(
|
||||||
|
validContactStateProvider(forms
|
||||||
|
.map((e) => e.id)
|
||||||
|
.toList(growable: false)));
|
||||||
|
|
||||||
|
bool shouldEnableSave =
|
||||||
|
validForms && nameExists;
|
||||||
|
|
||||||
|
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 =
|
||||||
|
[];
|
||||||
|
for (int i = 0;
|
||||||
|
i < forms.length;
|
||||||
|
i++) {
|
||||||
|
entries.add(ref
|
||||||
|
.read(
|
||||||
|
addressEntryDataProvider(
|
||||||
|
forms[i].id))
|
||||||
|
.buildAddressEntry());
|
||||||
|
}
|
||||||
|
Contact contact = Contact(
|
||||||
|
emojiChar: _selectedEmoji?.char,
|
||||||
|
name: nameController.text,
|
||||||
|
addresses: entries,
|
||||||
|
isFavorite: _isFavorite,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (await ref
|
||||||
|
.read(
|
||||||
|
addressBookServiceProvider)
|
||||||
|
.addContact(contact)) {
|
||||||
|
if (mounted) {
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
}
|
||||||
|
// TODO show success notification
|
||||||
|
} else {
|
||||||
|
// TODO show error notification
|
||||||
|
}
|
||||||
|
}
|
||||||
|
: null,
|
||||||
|
child: Text(
|
||||||
|
"Save",
|
||||||
|
style:
|
||||||
|
STextStyles.button(context).copyWith(
|
||||||
|
color: shouldEnableSave
|
||||||
|
? Theme.of(context)
|
||||||
|
.extension<StackColors>()!
|
||||||
|
.buttonTextPrimary
|
||||||
|
: Theme.of(context)
|
||||||
|
.extension<StackColors>()!
|
||||||
|
.buttonTextPrimaryDisabled,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
);
|
||||||
);
|
},
|
||||||
},
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue