diff --git a/assets/svg/chevron-up.svg b/assets/svg/chevron-up.svg
new file mode 100644
index 000000000..630f8df69
--- /dev/null
+++ b/assets/svg/chevron-up.svg
@@ -0,0 +1,3 @@
+
diff --git a/lib/pages_desktop_specific/home/settings_menu/advanced_settings.dart b/lib/pages_desktop_specific/home/advanced_settings/advanced_settings.dart
similarity index 60%
rename from lib/pages_desktop_specific/home/settings_menu/advanced_settings.dart
rename to lib/pages_desktop_specific/home/advanced_settings/advanced_settings.dart
index e55326527..7361d9773 100644
--- a/lib/pages_desktop_specific/home/settings_menu/advanced_settings.dart
+++ b/lib/pages_desktop_specific/home/advanced_settings/advanced_settings.dart
@@ -1,17 +1,14 @@
import 'package:flutter/material.dart';
-import 'package:flutter/src/widgets/framework.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_svg/svg.dart';
-import 'package:stackwallet/pages/stack_privacy_calls.dart';
+import 'package:stackwallet/pages_desktop_specific/home/advanced_settings/stack_privacy_dialog.dart';
+import 'package:stackwallet/providers/global/prefs_provider.dart';
import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/utilities/theme/stack_colors.dart';
+import 'package:stackwallet/widgets/custom_buttons/draggable_switch_button.dart';
import 'package:stackwallet/widgets/rounded_white_container.dart';
-import '../../../pages/settings_views/global_settings_view/advanced_views/debug_view.dart';
-import '../../../providers/global/prefs_provider.dart';
-import '../../../widgets/custom_buttons/draggable_switch_button.dart';
-
class AdvancedSettings extends ConsumerStatefulWidget {
const AdvancedSettings({Key? key}) : super(key: key);
@@ -109,63 +106,69 @@ class _AdvancedSettings extends ConsumerState {
),
/// TODO: Make a dialog popup
- Padding(
- padding: const EdgeInsets.all(10),
- child: Row(
- mainAxisAlignment: MainAxisAlignment.spaceBetween,
- children: [
- Column(
- crossAxisAlignment: CrossAxisAlignment.start,
- children: [
- Text(
- "Stack Experience",
- style:
- STextStyles.desktopTextExtraSmall(context)
- .copyWith(
- color: Theme.of(context)
- .extension()!
- .textDark),
- textAlign: TextAlign.left,
- ),
- Text(
- "Easy Crypto",
- style: STextStyles.desktopTextExtraExtraSmall(
- context),
- ),
- ],
- ),
- const StackPrivacyButton(),
- ],
- ),
- ),
- const Padding(
- padding: EdgeInsets.all(10.0),
- child: Divider(
- thickness: 0.5,
- ),
- ),
-
- /// TODO: Make a dialog popup
- Padding(
- padding: const EdgeInsets.all(10),
- child: Row(
- mainAxisAlignment: MainAxisAlignment.spaceBetween,
- children: [
- Text(
- "Debug info",
- style: STextStyles.desktopTextExtraSmall(context)
- .copyWith(
- color: Theme.of(context)
- .extension()!
- .textDark),
- textAlign: TextAlign.left,
- ),
- ShowLogsButton(),
- ],
- ),
- ),
+ Consumer(builder: (_, ref, __) {
+ final externalCalls = ref.watch(
+ prefsChangeNotifierProvider
+ .select((value) => value.externalCalls),
+ );
+ return Padding(
+ padding: const EdgeInsets.all(10),
+ child: Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: [
+ Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Text(
+ "Stack Experience",
+ style:
+ STextStyles.desktopTextExtraSmall(context)
+ .copyWith(
+ color: Theme.of(context)
+ .extension()!
+ .textDark),
+ textAlign: TextAlign.left,
+ ),
+ Text(
+ externalCalls ? "Easy crypto" : "Incognito",
+ style: STextStyles.desktopTextExtraExtraSmall(
+ context),
+ ),
+ ],
+ ),
+ const StackPrivacyButton(),
+ ],
+ ),
+ );
+ }),
],
),
+ const Padding(
+ padding: EdgeInsets.all(10.0),
+ child: Divider(
+ thickness: 0.5,
+ ),
+ ),
+
+ /// TODO: Make a dialog popup
+ Padding(
+ padding: const EdgeInsets.all(10),
+ child: Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: [
+ Text(
+ "Debug info",
+ style: STextStyles.desktopTextExtraSmall(context)
+ .copyWith(
+ color: Theme.of(context)
+ .extension()!
+ .textDark),
+ textAlign: TextAlign.left,
+ ),
+ const ShowLogsButton(),
+ ],
+ ),
+ ),
],
),
),
@@ -181,6 +184,17 @@ class StackPrivacyButton extends ConsumerWidget {
}) : super(key: key);
@override
Widget build(BuildContext context, WidgetRef ref) {
+ Future changePrivacySettings() async {
+ await showDialog(
+ context: context,
+ useSafeArea: false,
+ barrierDismissible: true,
+ builder: (context) {
+ return const StackPrivacyDialog();
+ },
+ );
+ }
+
return SizedBox(
width: 84,
height: 37,
@@ -189,10 +203,11 @@ class StackPrivacyButton extends ConsumerWidget {
.extension()!
.getPrimaryEnabledButtonColor(context),
onPressed: () {
- Navigator.of(context).pushNamed(
- StackPrivacyCalls.routeName,
- arguments: false,
- );
+ // Navigator.of(context).pushNamed(
+ // StackPrivacyCalls.routeName,
+ // arguments: false,
+ // );
+ changePrivacySettings();
},
child: Text(
"Change",
@@ -208,6 +223,18 @@ class ShowLogsButton extends ConsumerWidget {
const ShowLogsButton({
Key? key,
}) : super(key: key);
+
+ Future viewDebugLogs() async {
+ // await showDialog(
+ // context: context,
+ // useSafeArea: false,
+ // barrierDismissible: true,
+ // builder: (context) {
+ // return const DebugInfoDialog();
+ // },
+ // );
+ }
+
@override
Widget build(BuildContext context, WidgetRef ref) {
return SizedBox(
@@ -218,7 +245,8 @@ class ShowLogsButton extends ConsumerWidget {
.extension()!
.getPrimaryEnabledButtonColor(context),
onPressed: () {
- Navigator.of(context).pushNamed(DebugView.routeName);
+ //
+ viewDebugLogs();
},
child: Text(
"Show logs",
diff --git a/lib/pages_desktop_specific/home/advanced_settings/debug_info_dialog.dart b/lib/pages_desktop_specific/home/advanced_settings/debug_info_dialog.dart
new file mode 100644
index 000000000..e69de29bb
diff --git a/lib/pages_desktop_specific/home/advanced_settings/stack_privacy_dialog.dart b/lib/pages_desktop_specific/home/advanced_settings/stack_privacy_dialog.dart
new file mode 100644
index 000000000..8e385fd37
--- /dev/null
+++ b/lib/pages_desktop_specific/home/advanced_settings/stack_privacy_dialog.dart
@@ -0,0 +1,437 @@
+import 'dart:async';
+
+import 'package:flutter/material.dart';
+import 'package:flutter_riverpod/flutter_riverpod.dart';
+import 'package:flutter_svg/svg.dart';
+import 'package:stackwallet/utilities/text_styles.dart';
+import 'package:stackwallet/widgets/desktop/desktop_dialog.dart';
+import 'package:stackwallet/widgets/desktop/desktop_dialog_close_button.dart';
+import 'package:stackwallet/widgets/desktop/primary_button.dart';
+import 'package:stackwallet/widgets/desktop/secondary_button.dart';
+
+import '../../../hive/db.dart';
+import '../../../providers/global/prefs_provider.dart';
+import '../../../providers/global/price_provider.dart';
+import '../../../services/exchange/exchange_data_loading_service.dart';
+import '../../../utilities/assets.dart';
+import '../../../utilities/constants.dart';
+import '../../../utilities/theme/stack_colors.dart';
+import '../../../utilities/util.dart';
+import '../../../widgets/rounded_white_container.dart';
+
+class StackPrivacyDialog extends ConsumerStatefulWidget {
+ const StackPrivacyDialog({Key? key}) : super(key: key);
+
+ @override
+ ConsumerState createState() => _StackPrivacyDialog();
+}
+
+class _StackPrivacyDialog extends ConsumerState {
+ late final bool isDesktop;
+ late bool isEasy;
+ late bool infoToggle;
+
+ @override
+ void initState() {
+ isDesktop = Util.isDesktop;
+ isEasy = ref.read(prefsChangeNotifierProvider).externalCalls;
+ infoToggle = isEasy;
+ super.initState();
+ }
+
+ @override
+ void dispose() {
+ super.dispose();
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return DesktopDialog(
+ maxHeight: 650,
+ maxWidth: 600,
+ child: Column(
+ children: [
+ Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: [
+ Padding(
+ padding: const EdgeInsets.all(32),
+ child: Text(
+ "Choose Your Stack Experience",
+ style: STextStyles.desktopH3(context),
+ textAlign: TextAlign.center,
+ ),
+ ),
+ const DesktopDialogCloseButton(),
+ ],
+ ),
+ const SizedBox(
+ height: 35,
+ ),
+ Padding(
+ padding: EdgeInsets.symmetric(horizontal: 32),
+ child: PrivacyToggle(
+ externalCallsEnabled: isEasy,
+ onChanged: (externalCalls) {
+ isEasy = externalCalls;
+ setState(() {
+ infoToggle = isEasy;
+ });
+ },
+ ),
+ ),
+ Padding(
+ padding: const EdgeInsets.all(32.0),
+ child: RoundedWhiteContainer(
+ borderColor: Theme.of(context)
+ .extension()!
+ .textFieldDefaultBG,
+ child: Center(
+ child: RichText(
+ textAlign: TextAlign.left,
+ text: TextSpan(
+ style: isDesktop
+ ? STextStyles.desktopTextExtraExtraSmall(context)
+ : STextStyles.label(context).copyWith(
+ fontSize: 12.0,
+ ),
+ children: infoToggle
+ ? [
+ const TextSpan(
+ text:
+ "Exchange data preloaded for a seamless experience."),
+ const TextSpan(
+ text:
+ "\n\nCoinGecko enabled: (24 hour price change shown in-app, total wallet value shown in USD or other currency)."),
+ TextSpan(
+ text: "\n\nRecommended for most crypto users.",
+ style: isDesktop
+ ? STextStyles.desktopTextExtraExtraSmall600(
+ context)
+ : TextStyle(
+ color: Theme.of(context)
+ .extension()!
+ .textDark,
+ fontWeight: FontWeight.w600,
+ ),
+ ),
+ ]
+ : [
+ const TextSpan(
+ text:
+ "Exchange data not preloaded (slower experience)."),
+ const TextSpan(
+ text:
+ "\n\nCoinGecko disabled (price changes not shown, no wallet value shown in other currencies)."),
+ TextSpan(
+ text:
+ "\n\nRecommended for the privacy conscious.",
+ style: isDesktop
+ ? STextStyles.desktopTextExtraExtraSmall600(
+ context)
+ : TextStyle(
+ color: Theme.of(context)
+ .extension()!
+ .textDark,
+ fontWeight: FontWeight.w600,
+ ),
+ ),
+ ],
+ ),
+ ),
+ ),
+ ),
+ ),
+ // const Spacer(),
+ Padding(
+ padding: const EdgeInsets.symmetric(horizontal: 32),
+ child: Row(
+ children: [
+ Expanded(
+ child: SecondaryButton(
+ label: "Cancel",
+ onPressed: () {},
+ ),
+ ),
+ const SizedBox(
+ width: 16,
+ ),
+ Expanded(
+ child: PrimaryButton(
+ label: "Save",
+ onPressed: () {
+ ref.read(prefsChangeNotifierProvider).externalCalls =
+ isEasy;
+
+ DB.instance
+ .put(
+ boxName: DB.boxNamePrefs,
+ key: "externalCalls",
+ value: isEasy)
+ .then((_) {
+ if (isEasy) {
+ unawaited(ExchangeDataLoadingService().loadAll(ref));
+ ref
+ .read(priceAnd24hChangeNotifierProvider)
+ .start(true);
+ }
+ });
+ if (isDesktop) {
+ Navigator.pop(context);
+ }
+ },
+ ),
+ )
+ ],
+ ),
+ ),
+ ],
+ ),
+ );
+ }
+}
+
+class PrivacyToggle extends StatefulWidget {
+ const PrivacyToggle({
+ Key? key,
+ required this.externalCallsEnabled,
+ this.onChanged,
+ }) : super(key: key);
+
+ final bool externalCallsEnabled;
+ final void Function(bool)? onChanged;
+
+ @override
+ State createState() => _PrivacyToggleState();
+}
+
+class _PrivacyToggleState extends State {
+ late bool externalCallsEnabled;
+
+ late final bool isDesktop;
+
+ @override
+ void initState() {
+ isDesktop = Util.isDesktop;
+ // initial toggle state
+ externalCallsEnabled = widget.externalCallsEnabled;
+ super.initState();
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return Row(
+ children: [
+ Expanded(
+ child: RawMaterialButton(
+ elevation: 0,
+ hoverElevation: 0,
+ fillColor: Theme.of(context).extension()!.popupBG,
+ shape: RoundedRectangleBorder(
+ side: !externalCallsEnabled
+ ? BorderSide.none
+ : BorderSide(
+ color: Theme.of(context)
+ .extension()!
+ .infoItemIcons,
+ width: 2,
+ ),
+ borderRadius: BorderRadius.circular(
+ Constants.size.circularBorderRadius * 2,
+ ),
+ ),
+ onPressed: () {
+ setState(() {
+ // update toggle state
+ externalCallsEnabled = true;
+ });
+ // call callback with newly set value
+ widget.onChanged?.call(externalCallsEnabled);
+ },
+ child: Padding(
+ padding: const EdgeInsets.all(
+ 12,
+ ),
+ child: Stack(
+ children: [
+ Column(
+ crossAxisAlignment: CrossAxisAlignment.stretch,
+ children: [
+ if (isDesktop)
+ const SizedBox(
+ height: 10,
+ ),
+ SvgPicture.asset(
+ Assets.svg.personaEasy,
+ width: 120,
+ height: 120,
+ ),
+ if (isDesktop)
+ const SizedBox(
+ height: 12,
+ ),
+ Center(
+ child: Text(
+ "Easy Crypto",
+ style: isDesktop
+ ? STextStyles.desktopTextSmall(context)
+ : STextStyles.label700(context),
+ ),
+ ),
+ Center(
+ child: Text(
+ "Recommended",
+ style: isDesktop
+ ? STextStyles.desktopTextExtraExtraSmall(context)
+ : STextStyles.label(context),
+ ),
+ ),
+ if (isDesktop)
+ const SizedBox(
+ height: 12,
+ ),
+ ],
+ ),
+ if (externalCallsEnabled)
+ Positioned(
+ top: 4,
+ right: 4,
+ child: SvgPicture.asset(
+ Assets.svg.checkCircle,
+ width: 20,
+ height: 20,
+ color: Theme.of(context)
+ .extension()!
+ .infoItemIcons,
+ ),
+ ),
+ if (!externalCallsEnabled)
+ Positioned(
+ top: 4,
+ right: 4,
+ child: Container(
+ width: 20,
+ height: 20,
+ decoration: BoxDecoration(
+ borderRadius: BorderRadius.circular(1000),
+ color: Theme.of(context)
+ .extension()!
+ .textFieldDefaultBG,
+ ),
+ ),
+ ),
+ ],
+ ),
+ ),
+ ),
+ ),
+ const SizedBox(
+ width: 16,
+ ),
+ Expanded(
+ child: RawMaterialButton(
+ elevation: 0,
+ hoverElevation: 0,
+ fillColor: Theme.of(context).extension()!.popupBG,
+ shape: RoundedRectangleBorder(
+ side: externalCallsEnabled
+ ? BorderSide.none
+ : BorderSide(
+ color: Theme.of(context)
+ .extension()!
+ .infoItemIcons,
+ width: 2,
+ ),
+ borderRadius: BorderRadius.circular(
+ Constants.size.circularBorderRadius * 2,
+ ),
+ ),
+ onPressed: () {
+ setState(() {
+ // update toggle state
+ externalCallsEnabled = false;
+ });
+ // call callback with newly set value
+ widget.onChanged?.call(externalCallsEnabled);
+ },
+ child: Padding(
+ padding: const EdgeInsets.all(
+ 12,
+ ),
+ child: Stack(
+ children: [
+ Column(
+ crossAxisAlignment: CrossAxisAlignment.stretch,
+ children: [
+ if (isDesktop)
+ const SizedBox(
+ height: 10,
+ ),
+ SvgPicture.asset(
+ Assets.svg.personaIncognito,
+ width: 120,
+ height: 120,
+ ),
+ if (isDesktop)
+ const SizedBox(
+ height: 12,
+ ),
+ Center(
+ child: Text(
+ "Incognito",
+ style: isDesktop
+ ? STextStyles.desktopTextSmall(context)
+ : STextStyles.label700(context),
+ ),
+ ),
+ Center(
+ child: Text(
+ "Privacy conscious",
+ style: isDesktop
+ ? STextStyles.desktopTextExtraExtraSmall(context)
+ : STextStyles.label(context),
+ ),
+ ),
+ if (isDesktop)
+ const SizedBox(
+ height: 12,
+ ),
+ ],
+ ),
+ if (!externalCallsEnabled)
+ Positioned(
+ top: 4,
+ right: 4,
+ child: SvgPicture.asset(
+ Assets.svg.checkCircle,
+ width: 20,
+ height: 20,
+ color: Theme.of(context)
+ .extension()!
+ .infoItemIcons,
+ ),
+ ),
+ if (externalCallsEnabled)
+ Positioned(
+ top: 4,
+ right: 4,
+ child: Container(
+ width: 20,
+ height: 20,
+ decoration: BoxDecoration(
+ borderRadius: BorderRadius.circular(1000),
+ color: Theme.of(context)
+ .extension()!
+ .textFieldDefaultBG,
+ ),
+ ),
+ ),
+ ],
+ ),
+ ),
+ ),
+ ),
+ ],
+ );
+ }
+}
diff --git a/lib/pages_desktop_specific/home/desktop_settings_view.dart b/lib/pages_desktop_specific/home/desktop_settings_view.dart
index 719a37a3a..34cb07f27 100644
--- a/lib/pages_desktop_specific/home/desktop_settings_view.dart
+++ b/lib/pages_desktop_specific/home/desktop_settings_view.dart
@@ -1,6 +1,6 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
-import 'package:stackwallet/pages_desktop_specific/home/settings_menu/advanced_settings.dart';
+import 'package:stackwallet/pages_desktop_specific/home/advanced_settings/advanced_settings.dart';
import 'package:stackwallet/pages_desktop_specific/home/settings_menu/appearance_settings.dart';
import 'package:stackwallet/pages_desktop_specific/home/settings_menu/backup_and_restore/backup_and_restore_settings.dart';
import 'package:stackwallet/pages_desktop_specific/home/settings_menu/currency_settings.dart';
diff --git a/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/address_book_address_chooser/address_book_address_chooser.dart b/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/address_book_address_chooser/address_book_address_chooser.dart
index 372c86e2f..9f309a08e 100644
--- a/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/address_book_address_chooser/address_book_address_chooser.dart
+++ b/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/address_book_address_chooser/address_book_address_chooser.dart
@@ -1,10 +1,18 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
+import 'package:flutter_svg/flutter_svg.dart';
import 'package:stackwallet/models/contact.dart';
import 'package:stackwallet/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/address_book_address_chooser/sub_widgets/contact_list_item.dart';
import 'package:stackwallet/providers/global/address_book_service_provider.dart';
+import 'package:stackwallet/utilities/assets.dart';
+import 'package:stackwallet/utilities/constants.dart';
import 'package:stackwallet/utilities/enums/coin_enum.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/icon_widgets/x_icon.dart';
+import 'package:stackwallet/widgets/stack_text_field.dart';
+import 'package:stackwallet/widgets/textfield_icon_button.dart';
class AddressBookAddressChooser extends StatefulWidget {
const AddressBookAddressChooser({
@@ -20,6 +28,12 @@ class AddressBookAddressChooser extends StatefulWidget {
}
class _AddressBookAddressChooserState extends State {
+ late final bool isDesktop;
+ late final TextEditingController _searchController;
+ late final FocusNode searchFieldFocusNode;
+
+ String _searchTerm = "";
+
int _compareContactFavorite(Contact a, Contact b) {
if (a.isFavorite && b.isFavorite) {
return 0;
@@ -43,29 +57,128 @@ class _AddressBookAddressChooserState extends State {
return favorites;
}
- List filter(List contacts) {
+ List filter(List contacts, String searchTerm) {
if (widget.coin != null) {
contacts.removeWhere(
(e) => e.addresses.where((a) => a.coin == widget.coin!).isEmpty);
}
+ contacts.retainWhere((e) => _matches(searchTerm, e));
+
if (contacts.length < 2) {
return contacts;
}
+ // redundant due to pullOutFavorites?
contacts.sort(_compareContactFavorite);
- // TODO: other filtering?
-
return contacts;
}
+ bool _matches(String term, Contact contact) {
+ final text = term.toLowerCase();
+ if (contact.name.toLowerCase().contains(text)) {
+ return true;
+ }
+ for (int i = 0; i < contact.addresses.length; i++) {
+ if (contact.addresses[i].label.toLowerCase().contains(text) ||
+ contact.addresses[i].coin.name.toLowerCase().contains(text) ||
+ contact.addresses[i].coin.prettyName.toLowerCase().contains(text) ||
+ contact.addresses[i].coin.ticker.toLowerCase().contains(text) ||
+ contact.addresses[i].address.toLowerCase().contains(text)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @override
+ void initState() {
+ isDesktop = Util.isDesktop;
+ searchFieldFocusNode = FocusNode();
+ _searchController = TextEditingController();
+ super.initState();
+ }
+
+ @override
+ void dispose() {
+ _searchController.dispose();
+ searchFieldFocusNode.dispose();
+ super.dispose();
+ }
+
@override
Widget build(BuildContext context) {
return Column(
children: [
// search field
- const TextField(),
+ Padding(
+ padding: const EdgeInsets.symmetric(
+ horizontal: 32,
+ ),
+ child: ClipRRect(
+ borderRadius: BorderRadius.circular(
+ Constants.size.circularBorderRadius,
+ ),
+ child: TextField(
+ autocorrect: !isDesktop,
+ enableSuggestions: !isDesktop,
+ controller: _searchController,
+ focusNode: searchFieldFocusNode,
+ onChanged: (value) {
+ setState(() {
+ _searchTerm = value;
+ });
+ },
+ style: isDesktop
+ ? STextStyles.desktopTextExtraSmall(context).copyWith(
+ color: Theme.of(context)
+ .extension()!
+ .textFieldActiveText,
+ height: 1.8,
+ )
+ : STextStyles.field(context),
+ decoration: standardInputDecoration(
+ "Search",
+ searchFieldFocusNode,
+ context,
+ desktopMed: isDesktop,
+ ).copyWith(
+ prefixIcon: Padding(
+ padding: EdgeInsets.symmetric(
+ horizontal: isDesktop ? 12 : 10,
+ vertical: isDesktop ? 18 : 16,
+ ),
+ child: SvgPicture.asset(
+ Assets.svg.search,
+ width: isDesktop ? 20 : 16,
+ height: isDesktop ? 20 : 16,
+ ),
+ ),
+ suffixIcon: _searchController.text.isNotEmpty
+ ? Padding(
+ padding: const EdgeInsets.only(right: 0),
+ child: UnconstrainedBox(
+ child: Row(
+ children: [
+ TextFieldIconButton(
+ child: const XIcon(),
+ onTap: () async {
+ setState(() {
+ _searchController.text = "";
+ _searchTerm = "";
+ });
+ },
+ ),
+ ],
+ ),
+ ),
+ )
+ : null,
+ ),
+ ),
+ ),
+ ),
const SizedBox(
height: 16,
),
@@ -83,7 +196,7 @@ class _AddressBookAddressChooserState extends State {
.select((value) => value.contacts))
.toList();
- contacts = filter(contacts);
+ contacts = filter(contacts, _searchTerm);
final favorites = pullOutFavorites(contacts);
@@ -96,6 +209,8 @@ class _AddressBookAddressChooserState extends State {
itemBuilder: (context, index) {
if (index == 0) {
return Padding(
+ key: const Key(
+ "addressBookCAddressChooserFavoritesHeaderItemKey"),
padding: const EdgeInsets.only(
bottom: 10,
),
@@ -108,12 +223,14 @@ class _AddressBookAddressChooserState extends State {
} else if (index <= favorites.length) {
final id = favorites[index - 1].id;
return ContactListItem(
- key: Key("contactCard_${id}_key"),
+ key: Key("contactContactListItem_${id}_key"),
contactId: id,
filterByCoin: widget.coin,
);
} else if (index == favorites.length + 1) {
return Padding(
+ key: const Key(
+ "addressBookCAddressChooserAllContactsHeaderItemKey"),
padding: const EdgeInsets.symmetric(
vertical: 10,
),
@@ -126,7 +243,7 @@ class _AddressBookAddressChooserState extends State {
} else {
final id = contacts[index - favorites.length - 1].id;
return ContactListItem(
- key: Key("contactCard_${id}_key"),
+ key: Key("contactContactListItem_${id}_key"),
contactId: id,
filterByCoin: widget.coin,
);
diff --git a/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/address_book_address_chooser/sub_widgets/contact_list_item.dart b/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/address_book_address_chooser/sub_widgets/contact_list_item.dart
index 593ae2bc4..e030f9882 100644
--- a/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/address_book_address_chooser/sub_widgets/contact_list_item.dart
+++ b/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/address_book_address_chooser/sub_widgets/contact_list_item.dart
@@ -10,7 +10,7 @@ import 'package:stackwallet/widgets/expandable.dart';
import 'package:stackwallet/widgets/rounded_white_container.dart';
import 'package:stackwallet/widgets/wallet_info_row/sub_widgets/wallet_info_row_coin_icon.dart';
-class ContactListItem extends ConsumerWidget {
+class ContactListItem extends ConsumerStatefulWidget {
const ContactListItem({
Key? key,
required this.contactId,
@@ -21,7 +21,24 @@ class ContactListItem extends ConsumerWidget {
final Coin? filterByCoin;
@override
- Widget build(BuildContext context, WidgetRef ref) {
+ ConsumerState createState() => _ContactListItemState();
+}
+
+class _ContactListItemState extends ConsumerState {
+ late final String contactId;
+ late final Coin? filterByCoin;
+
+ ExpandableState _state = ExpandableState.collapsed;
+
+ @override
+ void initState() {
+ contactId = widget.contactId;
+ filterByCoin = widget.filterByCoin;
+ super.initState();
+ }
+
+ @override
+ Widget build(BuildContext context) {
final contact = ref.watch(addressBookServiceProvider
.select((value) => value.getContactById(contactId)));
@@ -29,6 +46,11 @@ class ContactListItem extends ConsumerWidget {
padding: const EdgeInsets.all(0),
borderColor: Theme.of(context).extension()!.background,
child: Expandable(
+ onExpandChanged: (state) {
+ setState(() {
+ _state = state;
+ });
+ },
header: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 20,
@@ -36,6 +58,7 @@ class ContactListItem extends ConsumerWidget {
),
child: AddressBookCard(
contactId: contactId,
+ indicatorDown: _state == ExpandableState.expanded,
),
),
body: Column(
diff --git a/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/desktop_send.dart b/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/desktop_send.dart
index 26f2f806c..710bc8685 100644
--- a/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/desktop_send.dart
+++ b/lib/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/desktop_send.dart
@@ -1190,8 +1190,32 @@ class _DesktopSendState extends ConsumerState {
builder: (context) => DesktopDialog(
maxWidth: 696,
maxHeight: 600,
- child: AddressBookAddressChooser(
- coin: coin,
+ child: Column(
+ mainAxisSize: MainAxisSize.min,
+ children: [
+ Row(
+ mainAxisAlignment:
+ MainAxisAlignment.spaceBetween,
+ children: [
+ Padding(
+ padding: const EdgeInsets.only(
+ left: 32,
+ ),
+ child: Text(
+ "Address book",
+ style:
+ STextStyles.desktopH3(context),
+ ),
+ ),
+ const DesktopDialogCloseButton(),
+ ],
+ ),
+ Expanded(
+ child: AddressBookAddressChooser(
+ coin: coin,
+ ),
+ ),
+ ],
),
),
);
diff --git a/lib/route_generator.dart b/lib/route_generator.dart
index 136dc7a34..613e0d509 100644
--- a/lib/route_generator.dart
+++ b/lib/route_generator.dart
@@ -85,13 +85,13 @@ import 'package:stackwallet/pages/wallet_view/transaction_views/transaction_sear
import 'package:stackwallet/pages/wallet_view/wallet_view.dart';
import 'package:stackwallet/pages/wallets_view/wallets_view.dart';
import 'package:stackwallet/pages_desktop_specific/create_password/create_password_view.dart';
+import 'package:stackwallet/pages_desktop_specific/home/advanced_settings/advanced_settings.dart';
import 'package:stackwallet/pages_desktop_specific/home/desktop_home_view.dart';
import 'package:stackwallet/pages_desktop_specific/home/desktop_settings_view.dart';
import 'package:stackwallet/pages_desktop_specific/home/my_stack_view/my_stack_view.dart';
import 'package:stackwallet/pages_desktop_specific/home/my_stack_view/wallet_view/desktop_wallet_view.dart';
import 'package:stackwallet/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/qr_code_desktop_popup_content.dart';
import 'package:stackwallet/pages_desktop_specific/home/my_stack_view/wallet_view/sub_widgets/wallet_keys_desktop_popup.dart';
-import 'package:stackwallet/pages_desktop_specific/home/settings_menu/advanced_settings.dart';
import 'package:stackwallet/pages_desktop_specific/home/settings_menu/appearance_settings.dart';
import 'package:stackwallet/pages_desktop_specific/home/settings_menu/backup_and_restore/backup_and_restore_settings.dart';
import 'package:stackwallet/pages_desktop_specific/home/settings_menu/currency_settings.dart';
diff --git a/lib/utilities/assets.dart b/lib/utilities/assets.dart
index 432ebbec9..78535c19b 100644
--- a/lib/utilities/assets.dart
+++ b/lib/utilities/assets.dart
@@ -96,6 +96,7 @@ class _SVG {
String get qrcode => "assets/svg/qrcode1.svg";
String get ellipsis => "assets/svg/gear-3.svg";
String get chevronDown => "assets/svg/chevron-down.svg";
+ String get chevronUp => "assets/svg/chevron-up.svg";
String get swap => "assets/svg/swap.svg";
String get downloadFolder => "assets/svg/folder-down.svg";
String get lock => "assets/svg/lock-keyhole.svg";
diff --git a/lib/widgets/address_book_card.dart b/lib/widgets/address_book_card.dart
index 6a51edbad..cebcf166f 100644
--- a/lib/widgets/address_book_card.dart
+++ b/lib/widgets/address_book_card.dart
@@ -13,9 +13,14 @@ import 'package:stackwallet/widgets/conditional_parent.dart';
import 'package:stackwallet/widgets/rounded_white_container.dart';
class AddressBookCard extends ConsumerStatefulWidget {
- const AddressBookCard({Key? key, required this.contactId}) : super(key: key);
+ const AddressBookCard({
+ Key? key,
+ required this.contactId,
+ this.indicatorDown,
+ }) : super(key: key);
final String contactId;
+ final bool? indicatorDown;
@override
ConsumerState createState() => _AddressBookCardState();
@@ -122,7 +127,17 @@ class _AddressBookCardState extends ConsumerState {
style: STextStyles.label(context),
),
],
- )
+ ),
+ if (isDesktop) const Spacer(),
+ if (isDesktop)
+ SvgPicture.asset(
+ widget.indicatorDown == true
+ ? Assets.svg.chevronDown
+ : Assets.svg.chevronUp,
+ width: 10,
+ height: 5,
+ color: Theme.of(context).extension()!.textSubtitle2,
+ ),
],
),
builder: (child) => RoundedWhiteContainer(
diff --git a/lib/widgets/transaction_card.dart b/lib/widgets/transaction_card.dart
index 8867e34f6..15dcf2b4d 100644
--- a/lib/widgets/transaction_card.dart
+++ b/lib/widgets/transaction_card.dart
@@ -102,15 +102,13 @@ class _TransactionCardState extends ConsumerState {
.select((value) => value.getPrice(coin)))
.item1;
- late final String prefix;
+ String prefix = "";
if (Util.isDesktop) {
if (_transaction.txType == "Sent") {
prefix = "-";
} else if (_transaction.txType == "Received") {
prefix = "+";
}
- } else {
- prefix = "";
}
return Material(
diff --git a/pubspec.yaml b/pubspec.yaml
index 7bd53de06..29d25cb84 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -232,6 +232,7 @@ flutter:
- assets/svg/gear-3.svg
- assets/svg/swap.svg
- assets/svg/chevron-down.svg
+ - assets/svg/chevron-up.svg
- assets/svg/lock-keyhole.svg
- assets/svg/rotate-exclamation.svg
- assets/svg/folder-down.svg
diff --git a/test/widget_tests/address_book_card_test.dart b/test/widget_tests/address_book_card_test.dart
index 8c8c44abd..07b1387df 100644
--- a/test/widget_tests/address_book_card_test.dart
+++ b/test/widget_tests/address_book_card_test.dart
@@ -1,6 +1,22 @@
+import 'dart:io';
+
+import 'package:flutter/material.dart';
+import 'package:flutter_riverpod/flutter_riverpod.dart';
+import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/annotations.dart';
import 'package:mockito/mockito.dart';
+import 'package:stackwallet/models/contact.dart';
+import 'package:stackwallet/models/contact_address_entry.dart';
+import 'package:stackwallet/pages/address_book_views/subviews/contact_popup.dart';
+import 'package:stackwallet/providers/global/address_book_service_provider.dart';
import 'package:stackwallet/services/address_book_service.dart';
+import 'package:stackwallet/utilities/enums/coin_enum.dart';
+import 'package:stackwallet/utilities/theme/light_colors.dart';
+import 'package:stackwallet/utilities/theme/stack_colors.dart';
+import 'package:stackwallet/utilities/util.dart';
+import 'package:stackwallet/widgets/address_book_card.dart';
+
+import 'address_book_card_test.mocks.dart';
class MockedFunctions extends Mock {
void showDialog();
@@ -8,46 +24,53 @@ class MockedFunctions extends Mock {
@GenerateMocks([AddressBookService])
void main() {
- // testWidgets('test returns Contact Address Entry', (widgetTester) async {
- // final service = MockAddressBookService();
- //
- // when(service.getContactById("default"))
- // .thenAnswer((realInvocation) => Contact(
- // name: "John Doe",
- // addresses: [
- // const ContactAddressEntry(
- // coin: Coin.bitcoincash,
- // address: "some bch address",
- // label: "Bills")
- // ],
- // isFavorite: true));
- //
- // await widgetTester.pumpWidget(
- // ProviderScope(
- // overrides: [
- // addressBookServiceProvider.overrideWithValue(
- // service,
- // ),
- // ],
- // child: MaterialApp(
- // theme: ThemeData(
- // extensions: [
- // StackColors.fromStackColorTheme(
- // LightColors(),
- // ),
- // ],
- // ),
- // home: const AddressBookCard(
- // contactId: "default",
- // ),
- // ),
- // ),
- // );
- //
- // expect(find.text("John Doe"), findsOneWidget);
- // expect(find.text("BCH"), findsOneWidget);
- // expect(find.text(Coin.bitcoincash.ticker), findsOneWidget);
- //
- // await widgetTester.tap(find.byType(RawMaterialButton));
- // });
+ testWidgets('test returns Contact Address Entry', (widgetTester) async {
+ final service = MockAddressBookService();
+
+ when(service.getContactById("default")).thenAnswer(
+ (realInvocation) => Contact(
+ name: "John Doe",
+ addresses: [
+ const ContactAddressEntry(
+ coin: Coin.bitcoincash,
+ address: "some bch address",
+ label: "Bills")
+ ],
+ isFavorite: true,
+ ),
+ );
+
+ await widgetTester.pumpWidget(
+ ProviderScope(
+ overrides: [
+ addressBookServiceProvider.overrideWithValue(
+ service,
+ ),
+ ],
+ child: MaterialApp(
+ theme: ThemeData(
+ extensions: [
+ StackColors.fromStackColorTheme(
+ LightColors(),
+ ),
+ ],
+ ),
+ home: const AddressBookCard(
+ contactId: "default",
+ ),
+ ),
+ ),
+ );
+
+ expect(find.text("John Doe"), findsOneWidget);
+ expect(find.text("BCH"), findsOneWidget);
+ expect(find.text(Coin.bitcoincash.ticker), findsOneWidget);
+
+ if (Platform.isIOS || Platform.isAndroid) {
+ await widgetTester.tap(find.byType(RawMaterialButton));
+ expect(find.byType(ContactPopUp), findsOneWidget);
+ } else if (Util.isDesktop) {
+ expect(find.byType(RawMaterialButton), findsNothing);
+ }
+ });
}
diff --git a/test/widget_tests/transaction_card_test.dart b/test/widget_tests/transaction_card_test.dart
index 6c36fce8d..f28c5f81d 100644
--- a/test/widget_tests/transaction_card_test.dart
+++ b/test/widget_tests/transaction_card_test.dart
@@ -1,4 +1,14 @@
+import 'package:decimal/decimal.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_feather_icons/flutter_feather_icons.dart';
+import 'package:flutter_riverpod/flutter_riverpod.dart';
+import 'package:flutter_test/flutter_test.dart';
+import 'package:mockingjay/mockingjay.dart' as mockingjay;
import 'package:mockito/annotations.dart';
+import 'package:mockito/mockito.dart';
+import 'package:stackwallet/models/models.dart';
+import 'package:stackwallet/pages/wallet_view/transaction_views/transaction_details_view.dart';
+import 'package:stackwallet/providers/providers.dart';
import 'package:stackwallet/services/coins/coin_service.dart';
import 'package:stackwallet/services/coins/firo/firo_wallet.dart';
import 'package:stackwallet/services/coins/manager.dart';
@@ -6,7 +16,15 @@ import 'package:stackwallet/services/locale_service.dart';
import 'package:stackwallet/services/notes_service.dart';
import 'package:stackwallet/services/price_service.dart';
import 'package:stackwallet/services/wallets.dart';
+import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/prefs.dart';
+import 'package:stackwallet/utilities/theme/light_colors.dart';
+import 'package:stackwallet/utilities/theme/stack_colors.dart';
+import 'package:stackwallet/utilities/util.dart';
+import 'package:stackwallet/widgets/transaction_card.dart';
+import 'package:tuple/tuple.dart';
+
+import 'transaction_card_test.mocks.dart';
@GenerateMocks([
Wallets,
@@ -19,362 +37,370 @@ import 'package:stackwallet/utilities/prefs.dart';
NotesService
], customMocks: [])
void main() {
- // TestWidgetsFlutterBinding.ensureInitialized();
- // testWidgets("Sent confirmed tx displays correctly", (tester) async {
- // final mockManager = MockManager();
- // final mockLocaleService = MockLocaleService();
- // final wallets = MockWallets();
- // final mockPrefs = MockPrefs();
- // final mockPriceService = MockPriceService();
- //
- // final tx = Transaction(
- // txid: "some txid",
- // confirmedStatus: true,
- // timestamp: 1648595998,
- // txType: "Sent",
- // amount: 100000000,
- // aliens: [],
- // worthNow: "0.01",
- // worthAtBlockTimestamp: "0.01",
- // fees: 3794,
- // inputSize: 1,
- // outputSize: 1,
- // inputs: [],
- // outputs: [],
- // address: "",
- // height: 450123,
- // subType: "",
- // confirmations: 10,
- // isCancelled: false);
- //
- // final CoinServiceAPI wallet = MockFiroWallet();
- //
- // when(wallet.coin.ticker).thenAnswer((_) => "FIRO");
- // when(mockLocaleService.locale).thenAnswer((_) => "en_US");
- // when(mockPrefs.currency).thenAnswer((_) => "USD");
- // when(mockPrefs.externalCalls).thenAnswer((_) => true);
- // when(mockPriceService.getPrice(Coin.firo))
- // .thenAnswer((realInvocation) => Tuple2(Decimal.ten, 0.00));
- //
- // when(wallet.coin).thenAnswer((_) => Coin.firo);
- //
- // when(wallets.getManager("wallet-id"))
- // .thenAnswer((realInvocation) => Manager(wallet));
- // //
- // await tester.pumpWidget(
- // ProviderScope(
- // overrides: [
- // walletsChangeNotifierProvider.overrideWithValue(wallets),
- // localeServiceChangeNotifierProvider
- // .overrideWithValue(mockLocaleService),
- // prefsChangeNotifierProvider.overrideWithValue(mockPrefs),
- // priceAnd24hChangeNotifierProvider.overrideWithValue(mockPriceService)
- // ],
- // child: MaterialApp(
- // theme: ThemeData(
- // extensions: [
- // StackColors.fromStackColorTheme(
- // LightColors(),
- // ),
- // ],
- // ),
- // home: TransactionCard(transaction: tx, walletId: "wallet-id"),
- // ),
- // ),
- // );
- //
- // //
- // final title = find.text("Sent");
- // // final price1 = find.text("0.00 USD");
- // final amount = find.text("1.00000000 FIRO");
- //
- // final icon = find.byIcon(FeatherIcons.arrowUp);
- //
- // expect(title, findsOneWidget);
- // // expect(price1, findsOneWidget);
- // expect(amount, findsOneWidget);
- // // expect(icon, findsOneWidget);
- // //
- // await tester.pumpAndSettle(Duration(seconds: 2));
- // //
- // // final price2 = find.text("\$10.00");
- // // expect(price2, findsOneWidget);
- // //
- // // verify(mockManager.addListener(any)).called(1);
- // verify(mockLocaleService.addListener(any)).called(1);
- //
- // verify(mockPrefs.currency).called(1);
- // verify(mockPriceService.getPrice(Coin.firo)).called(1);
- // verify(wallet.coin.ticker).called(1);
- //
- // verify(mockLocaleService.locale).called(1);
- //
- // verifyNoMoreInteractions(mockManager);
- // verifyNoMoreInteractions(mockLocaleService);
- // });
- //
- // testWidgets("Anonymized confirmed tx displays correctly", (tester) async {
- // final mockManager = MockManager();
- // final mockLocaleService = MockLocaleService();
- // final wallets = MockWallets();
- // final mockPrefs = MockPrefs();
- // final mockPriceService = MockPriceService();
- //
- // final tx = Transaction(
- // txid: "some txid",
- // confirmedStatus: true,
- // timestamp: 1648595998,
- // txType: "Anonymized",
- // amount: 100000000,
- // aliens: [],
- // worthNow: "0.01",
- // worthAtBlockTimestamp: "0.01",
- // fees: 3794,
- // inputSize: 1,
- // outputSize: 1,
- // inputs: [],
- // outputs: [],
- // address: "",
- // height: 450123,
- // subType: "mint",
- // confirmations: 10,
- // isCancelled: false);
- //
- // final CoinServiceAPI wallet = MockFiroWallet();
- //
- // when(wallet.coin.ticker).thenAnswer((_) => "FIRO");
- // when(mockLocaleService.locale).thenAnswer((_) => "en_US");
- // when(mockPrefs.currency).thenAnswer((_) => "USD");
- // when(mockPrefs.externalCalls).thenAnswer((_) => true);
- // when(mockPriceService.getPrice(Coin.firo))
- // .thenAnswer((realInvocation) => Tuple2(Decimal.ten, 0.00));
- //
- // when(wallet.coin).thenAnswer((_) => Coin.firo);
- //
- // when(wallets.getManager("wallet-id"))
- // .thenAnswer((realInvocation) => Manager(wallet));
- // //
- // await tester.pumpWidget(
- // ProviderScope(
- // overrides: [
- // walletsChangeNotifierProvider.overrideWithValue(wallets),
- // localeServiceChangeNotifierProvider
- // .overrideWithValue(mockLocaleService),
- // prefsChangeNotifierProvider.overrideWithValue(mockPrefs),
- // priceAnd24hChangeNotifierProvider.overrideWithValue(mockPriceService)
- // ],
- // child: MaterialApp(
- // theme: ThemeData(
- // extensions: [
- // StackColors.fromStackColorTheme(
- // LightColors(),
- // ),
- // ],
- // ),
- // home: TransactionCard(transaction: tx, walletId: "wallet-id"),
- // ),
- // ),
- // );
- //
- // //
- // final title = find.text("Anonymized");
- // // final price1 = find.text("0.00 USD");
- // final amount = find.text("1.00000000 FIRO");
- //
- // final icon = find.byIcon(FeatherIcons.arrowUp);
- //
- // expect(title, findsOneWidget);
- // // expect(price1, findsOneWidget);
- // expect(amount, findsOneWidget);
- // // expect(icon, findsOneWidget);
- // //
- // await tester.pumpAndSettle(Duration(seconds: 2));
- // //
- // // final price2 = find.text("\$10.00");
- // // expect(price2, findsOneWidget);
- // //
- // // verify(mockManager.addListener(any)).called(1);
- // verify(mockLocaleService.addListener(any)).called(1);
- //
- // verify(mockPrefs.currency).called(1);
- // verify(mockPriceService.getPrice(Coin.firo)).called(1);
- // verify(wallet.coin.ticker).called(1);
- //
- // verify(mockLocaleService.locale).called(1);
- //
- // verifyNoMoreInteractions(mockManager);
- // verifyNoMoreInteractions(mockLocaleService);
- // });
- //
- // testWidgets("Received unconfirmed tx displays correctly", (tester) async {
- // final mockManager = MockManager();
- // final mockLocaleService = MockLocaleService();
- // final wallets = MockWallets();
- // final mockPrefs = MockPrefs();
- // final mockPriceService = MockPriceService();
- //
- // final tx = Transaction(
- // txid: "some txid",
- // confirmedStatus: false,
- // timestamp: 1648595998,
- // txType: "Received",
- // amount: 100000000,
- // aliens: [],
- // worthNow: "0.01",
- // worthAtBlockTimestamp: "0.01",
- // fees: 3794,
- // inputSize: 1,
- // outputSize: 1,
- // inputs: [],
- // outputs: [],
- // address: "",
- // height: 0,
- // subType: "",
- // confirmations: 0,
- // );
- //
- // final CoinServiceAPI wallet = MockFiroWallet();
- //
- // when(wallet.coin.ticker).thenAnswer((_) => "FIRO");
- // when(mockLocaleService.locale).thenAnswer((_) => "en_US");
- // when(mockPrefs.currency).thenAnswer((_) => "USD");
- // when(mockPrefs.externalCalls).thenAnswer((_) => true);
- // when(mockPriceService.getPrice(Coin.firo))
- // .thenAnswer((realInvocation) => Tuple2(Decimal.ten, 0.00));
- //
- // when(wallet.coin).thenAnswer((_) => Coin.firo);
- //
- // when(wallets.getManager("wallet-id"))
- // .thenAnswer((realInvocation) => Manager(wallet));
- //
- // await tester.pumpWidget(
- // ProviderScope(
- // overrides: [
- // walletsChangeNotifierProvider.overrideWithValue(wallets),
- // localeServiceChangeNotifierProvider
- // .overrideWithValue(mockLocaleService),
- // prefsChangeNotifierProvider.overrideWithValue(mockPrefs),
- // priceAnd24hChangeNotifierProvider.overrideWithValue(mockPriceService)
- // ],
- // child: MaterialApp(
- // theme: ThemeData(
- // extensions: [
- // StackColors.fromStackColorTheme(
- // LightColors(),
- // ),
- // ],
- // ),
- // home: TransactionCard(transaction: tx, walletId: "wallet-id"),
- // ),
- // ),
- // );
- //
- // final title = find.text("Receiving");
- // final amount = find.text("1.00000000 FIRO");
- //
- // expect(title, findsOneWidget);
- // expect(amount, findsOneWidget);
- //
- // await tester.pumpAndSettle(Duration(seconds: 2));
- //
- // verify(mockLocaleService.addListener(any)).called(1);
- //
- // verify(mockPrefs.currency).called(1);
- // verify(mockPriceService.getPrice(Coin.firo)).called(1);
- // verify(wallet.coin.ticker).called(1);
- //
- // verify(mockLocaleService.locale).called(1);
- //
- // verifyNoMoreInteractions(mockManager);
- // verifyNoMoreInteractions(mockLocaleService);
- // });
- //
- // testWidgets("Tap gesture", (tester) async {
- // final mockManager = MockManager();
- // final mockLocaleService = MockLocaleService();
- // final wallets = MockWallets();
- // final mockPrefs = MockPrefs();
- // final mockPriceService = MockPriceService();
- // final navigator = mockingjay.MockNavigator();
- //
- // final tx = Transaction(
- // txid: "some txid",
- // confirmedStatus: false,
- // timestamp: 1648595998,
- // txType: "Received",
- // amount: 100000000,
- // aliens: [],
- // worthNow: "0.01",
- // worthAtBlockTimestamp: "0.01",
- // fees: 3794,
- // inputSize: 1,
- // outputSize: 1,
- // inputs: [],
- // outputs: [],
- // address: "",
- // height: 250,
- // subType: "",
- // confirmations: 10,
- // );
- //
- // final CoinServiceAPI wallet = MockFiroWallet();
- //
- // when(wallet.coin.ticker).thenAnswer((_) => "FIRO");
- // when(mockLocaleService.locale).thenAnswer((_) => "en_US");
- // when(mockPrefs.currency).thenAnswer((_) => "USD");
- // when(mockPrefs.externalCalls).thenAnswer((_) => true);
- // when(mockPriceService.getPrice(Coin.firo))
- // .thenAnswer((realInvocation) => Tuple2(Decimal.ten, 0.00));
- //
- // when(wallet.coin).thenAnswer((_) => Coin.firo);
- //
- // when(wallets.getManager("wallet id"))
- // .thenAnswer((realInvocation) => Manager(wallet));
- //
- // mockingjay
- // .when(() => navigator.pushNamed("/transactionDetails",
- // arguments: Tuple3(tx, Coin.firo, "wallet id")))
- // .thenAnswer((_) async => {});
- //
- // await tester.pumpWidget(
- // ProviderScope(
- // overrides: [
- // walletsChangeNotifierProvider.overrideWithValue(wallets),
- // localeServiceChangeNotifierProvider
- // .overrideWithValue(mockLocaleService),
- // prefsChangeNotifierProvider.overrideWithValue(mockPrefs),
- // priceAnd24hChangeNotifierProvider.overrideWithValue(mockPriceService)
- // ],
- // child: MaterialApp(
- // theme: ThemeData(
- // extensions: [
- // StackColors.fromStackColorTheme(LightColors()),
- // ],
- // ),
- // home: mockingjay.MockNavigatorProvider(
- // navigator: navigator,
- // child: TransactionCard(transaction: tx, walletId: "wallet id")),
- // ),
- // ),
- // );
- //
- // expect(find.byType(GestureDetector), findsOneWidget);
- //
- // await tester.tap(find.byType(GestureDetector));
- // await tester.pump();
- //
- // verify(mockLocaleService.addListener(any)).called(1);
- //
- // verify(mockPrefs.currency).called(1);
- // verify(mockLocaleService.locale).called(1);
- // verify(wallet.coin.ticker).called(1);
- //
- // verifyNoMoreInteractions(wallet);
- // verifyNoMoreInteractions(mockLocaleService);
- //
- // mockingjay
- // .verify(() => navigator.pushNamed("/transactionDetails",
- // arguments: Tuple3(tx, Coin.firo, "wallet id")))
- // .called(1);
- // });
+ TestWidgetsFlutterBinding.ensureInitialized();
+ testWidgets("Sent confirmed tx displays correctly", (tester) async {
+ final mockManager = MockManager();
+ final mockLocaleService = MockLocaleService();
+ final wallets = MockWallets();
+ final mockPrefs = MockPrefs();
+ final mockPriceService = MockPriceService();
+
+ final tx = Transaction(
+ txid: "some txid",
+ confirmedStatus: true,
+ timestamp: 1648595998,
+ txType: "Sent",
+ amount: 100000000,
+ aliens: [],
+ worthNow: "0.01",
+ worthAtBlockTimestamp: "0.01",
+ fees: 3794,
+ inputSize: 1,
+ outputSize: 1,
+ inputs: [],
+ outputs: [],
+ address: "",
+ height: 450123,
+ subType: "",
+ confirmations: 10,
+ isCancelled: false);
+
+ final CoinServiceAPI wallet = MockFiroWallet();
+
+ when(wallet.coin.ticker).thenAnswer((_) => "FIRO");
+ when(mockLocaleService.locale).thenAnswer((_) => "en_US");
+ when(mockPrefs.currency).thenAnswer((_) => "USD");
+ when(mockPrefs.externalCalls).thenAnswer((_) => true);
+ when(mockPriceService.getPrice(Coin.firo))
+ .thenAnswer((realInvocation) => Tuple2(Decimal.ten, 0.00));
+
+ when(wallet.coin).thenAnswer((_) => Coin.firo);
+
+ when(wallets.getManager("wallet-id"))
+ .thenAnswer((realInvocation) => Manager(wallet));
+ //
+ await tester.pumpWidget(
+ ProviderScope(
+ overrides: [
+ walletsChangeNotifierProvider.overrideWithValue(wallets),
+ localeServiceChangeNotifierProvider
+ .overrideWithValue(mockLocaleService),
+ prefsChangeNotifierProvider.overrideWithValue(mockPrefs),
+ priceAnd24hChangeNotifierProvider.overrideWithValue(mockPriceService)
+ ],
+ child: MaterialApp(
+ theme: ThemeData(
+ extensions: [
+ StackColors.fromStackColorTheme(
+ LightColors(),
+ ),
+ ],
+ ),
+ home: TransactionCard(transaction: tx, walletId: "wallet-id"),
+ ),
+ ),
+ );
+
+ //
+ final title = find.text("Sent");
+ // final price1 = find.text("0.00 USD");
+ final amount = Util.isDesktop
+ ? find.text("-1.00000000 FIRO")
+ : find.text("1.00000000 FIRO");
+
+ final icon = find.byIcon(FeatherIcons.arrowUp);
+
+ expect(title, findsOneWidget);
+ // expect(price1, findsOneWidget);
+ expect(amount, findsOneWidget);
+ // expect(icon, findsOneWidget);
+ //
+ await tester.pumpAndSettle(const Duration(seconds: 2));
+ //
+ // final price2 = find.text("\$10.00");
+ // expect(price2, findsOneWidget);
+ //
+ // verify(mockManager.addListener(any)).called(1);
+ verify(mockLocaleService.addListener(any)).called(1);
+
+ verify(mockPrefs.currency).called(1);
+ verify(mockPriceService.getPrice(Coin.firo)).called(1);
+ verify(wallet.coin.ticker).called(1);
+
+ verify(mockLocaleService.locale).called(1);
+
+ verifyNoMoreInteractions(mockManager);
+ verifyNoMoreInteractions(mockLocaleService);
+ });
+
+ testWidgets("Anonymized confirmed tx displays correctly", (tester) async {
+ final mockManager = MockManager();
+ final mockLocaleService = MockLocaleService();
+ final wallets = MockWallets();
+ final mockPrefs = MockPrefs();
+ final mockPriceService = MockPriceService();
+
+ final tx = Transaction(
+ txid: "some txid",
+ confirmedStatus: true,
+ timestamp: 1648595998,
+ txType: "Anonymized",
+ amount: 100000000,
+ aliens: [],
+ worthNow: "0.01",
+ worthAtBlockTimestamp: "0.01",
+ fees: 3794,
+ inputSize: 1,
+ outputSize: 1,
+ inputs: [],
+ outputs: [],
+ address: "",
+ height: 450123,
+ subType: "mint",
+ confirmations: 10,
+ isCancelled: false);
+
+ final CoinServiceAPI wallet = MockFiroWallet();
+
+ when(wallet.coin.ticker).thenAnswer((_) => "FIRO");
+ when(mockLocaleService.locale).thenAnswer((_) => "en_US");
+ when(mockPrefs.currency).thenAnswer((_) => "USD");
+ when(mockPrefs.externalCalls).thenAnswer((_) => true);
+ when(mockPriceService.getPrice(Coin.firo))
+ .thenAnswer((realInvocation) => Tuple2(Decimal.ten, 0.00));
+
+ when(wallet.coin).thenAnswer((_) => Coin.firo);
+
+ when(wallets.getManager("wallet-id"))
+ .thenAnswer((realInvocation) => Manager(wallet));
+ //
+ await tester.pumpWidget(
+ ProviderScope(
+ overrides: [
+ walletsChangeNotifierProvider.overrideWithValue(wallets),
+ localeServiceChangeNotifierProvider
+ .overrideWithValue(mockLocaleService),
+ prefsChangeNotifierProvider.overrideWithValue(mockPrefs),
+ priceAnd24hChangeNotifierProvider.overrideWithValue(mockPriceService)
+ ],
+ child: MaterialApp(
+ theme: ThemeData(
+ extensions: [
+ StackColors.fromStackColorTheme(
+ LightColors(),
+ ),
+ ],
+ ),
+ home: TransactionCard(transaction: tx, walletId: "wallet-id"),
+ ),
+ ),
+ );
+
+ //
+ final title = find.text("Anonymized");
+ // final price1 = find.text("0.00 USD");
+ final amount = find.text("1.00000000 FIRO");
+
+ final icon = find.byIcon(FeatherIcons.arrowUp);
+
+ expect(title, findsOneWidget);
+ // expect(price1, findsOneWidget);
+ expect(amount, findsOneWidget);
+ // expect(icon, findsOneWidget);
+ //
+ await tester.pumpAndSettle(const Duration(seconds: 2));
+ //
+ // final price2 = find.text("\$10.00");
+ // expect(price2, findsOneWidget);
+ //
+ // verify(mockManager.addListener(any)).called(1);
+ verify(mockLocaleService.addListener(any)).called(1);
+
+ verify(mockPrefs.currency).called(1);
+ verify(mockPriceService.getPrice(Coin.firo)).called(1);
+ verify(wallet.coin.ticker).called(1);
+
+ verify(mockLocaleService.locale).called(1);
+
+ verifyNoMoreInteractions(mockManager);
+ verifyNoMoreInteractions(mockLocaleService);
+ });
+
+ testWidgets("Received unconfirmed tx displays correctly", (tester) async {
+ final mockManager = MockManager();
+ final mockLocaleService = MockLocaleService();
+ final wallets = MockWallets();
+ final mockPrefs = MockPrefs();
+ final mockPriceService = MockPriceService();
+
+ final tx = Transaction(
+ txid: "some txid",
+ confirmedStatus: false,
+ timestamp: 1648595998,
+ txType: "Received",
+ amount: 100000000,
+ aliens: [],
+ worthNow: "0.01",
+ worthAtBlockTimestamp: "0.01",
+ fees: 3794,
+ inputSize: 1,
+ outputSize: 1,
+ inputs: [],
+ outputs: [],
+ address: "",
+ height: 0,
+ subType: "",
+ confirmations: 0,
+ );
+
+ final CoinServiceAPI wallet = MockFiroWallet();
+
+ when(wallet.coin.ticker).thenAnswer((_) => "FIRO");
+ when(mockLocaleService.locale).thenAnswer((_) => "en_US");
+ when(mockPrefs.currency).thenAnswer((_) => "USD");
+ when(mockPrefs.externalCalls).thenAnswer((_) => true);
+ when(mockPriceService.getPrice(Coin.firo))
+ .thenAnswer((realInvocation) => Tuple2(Decimal.ten, 0.00));
+
+ when(wallet.coin).thenAnswer((_) => Coin.firo);
+
+ when(wallets.getManager("wallet-id"))
+ .thenAnswer((realInvocation) => Manager(wallet));
+
+ await tester.pumpWidget(
+ ProviderScope(
+ overrides: [
+ walletsChangeNotifierProvider.overrideWithValue(wallets),
+ localeServiceChangeNotifierProvider
+ .overrideWithValue(mockLocaleService),
+ prefsChangeNotifierProvider.overrideWithValue(mockPrefs),
+ priceAnd24hChangeNotifierProvider.overrideWithValue(mockPriceService)
+ ],
+ child: MaterialApp(
+ theme: ThemeData(
+ extensions: [
+ StackColors.fromStackColorTheme(
+ LightColors(),
+ ),
+ ],
+ ),
+ home: TransactionCard(transaction: tx, walletId: "wallet-id"),
+ ),
+ ),
+ );
+
+ final title = find.text("Receiving");
+ final amount = Util.isDesktop
+ ? find.text("+1.00000000 FIRO")
+ : find.text("1.00000000 FIRO");
+
+ expect(title, findsOneWidget);
+ expect(amount, findsOneWidget);
+
+ await tester.pumpAndSettle(const Duration(seconds: 2));
+
+ verify(mockLocaleService.addListener(any)).called(1);
+
+ verify(mockPrefs.currency).called(1);
+ verify(mockPriceService.getPrice(Coin.firo)).called(1);
+ verify(wallet.coin.ticker).called(1);
+
+ verify(mockLocaleService.locale).called(1);
+
+ verifyNoMoreInteractions(mockManager);
+ verifyNoMoreInteractions(mockLocaleService);
+ });
+
+ testWidgets("Tap gesture", (tester) async {
+ final mockManager = MockManager();
+ final mockLocaleService = MockLocaleService();
+ final wallets = MockWallets();
+ final mockPrefs = MockPrefs();
+ final mockPriceService = MockPriceService();
+ final navigator = mockingjay.MockNavigator();
+
+ final tx = Transaction(
+ txid: "some txid",
+ confirmedStatus: false,
+ timestamp: 1648595998,
+ txType: "Received",
+ amount: 100000000,
+ aliens: [],
+ worthNow: "0.01",
+ worthAtBlockTimestamp: "0.01",
+ fees: 3794,
+ inputSize: 1,
+ outputSize: 1,
+ inputs: [],
+ outputs: [],
+ address: "",
+ height: 250,
+ subType: "",
+ confirmations: 10,
+ );
+
+ final CoinServiceAPI wallet = MockFiroWallet();
+
+ when(wallet.coin.ticker).thenAnswer((_) => "FIRO");
+ when(mockLocaleService.locale).thenAnswer((_) => "en_US");
+ when(mockPrefs.currency).thenAnswer((_) => "USD");
+ when(mockPrefs.externalCalls).thenAnswer((_) => true);
+ when(mockPriceService.getPrice(Coin.firo))
+ .thenAnswer((realInvocation) => Tuple2(Decimal.ten, 0.00));
+
+ when(wallet.coin).thenAnswer((_) => Coin.firo);
+
+ when(wallets.getManager("wallet id"))
+ .thenAnswer((realInvocation) => Manager(wallet));
+
+ mockingjay
+ .when(() => navigator.pushNamed("/transactionDetails",
+ arguments: Tuple3(tx, Coin.firo, "wallet id")))
+ .thenAnswer((_) async => {});
+
+ await tester.pumpWidget(
+ ProviderScope(
+ overrides: [
+ walletsChangeNotifierProvider.overrideWithValue(wallets),
+ localeServiceChangeNotifierProvider
+ .overrideWithValue(mockLocaleService),
+ prefsChangeNotifierProvider.overrideWithValue(mockPrefs),
+ priceAnd24hChangeNotifierProvider.overrideWithValue(mockPriceService)
+ ],
+ child: MaterialApp(
+ theme: ThemeData(
+ extensions: [
+ StackColors.fromStackColorTheme(LightColors()),
+ ],
+ ),
+ home: mockingjay.MockNavigatorProvider(
+ navigator: navigator,
+ child: TransactionCard(transaction: tx, walletId: "wallet id")),
+ ),
+ ),
+ );
+
+ expect(find.byType(GestureDetector), findsOneWidget);
+
+ await tester.tap(find.byType(GestureDetector));
+ await tester.pump();
+
+ verify(mockLocaleService.addListener(any)).called(1);
+
+ verify(mockPrefs.currency).called(2);
+ verify(mockLocaleService.locale).called(4);
+ verify(wallet.coin.ticker).called(1);
+
+ verifyNoMoreInteractions(wallet);
+ verifyNoMoreInteractions(mockLocaleService);
+
+ if (Util.isDesktop) {
+ expect(find.byType(TransactionDetailsView), findsOneWidget);
+ } else {
+ mockingjay
+ .verify(() => navigator.pushNamed("/transactionDetails",
+ arguments: Tuple3(tx, Coin.firo, "wallet id")))
+ .called(1);
+ }
+ });
}