> allOffsets,
) {
writer.writeString(offsets[0], object.addressString);
- writer.writeString(offsets[1], object.value);
- writer.writeString(offsets[2], object.walletId);
+ writer.writeStringList(offsets[1], object.tags);
+ writer.writeString(offsets[2], object.value);
+ writer.writeString(offsets[3], object.walletId);
}
AddressLabel _addressLabelDeserialize(
@@ -110,8 +128,9 @@ AddressLabel _addressLabelDeserialize(
) {
final object = AddressLabel(
addressString: reader.readString(offsets[0]),
- value: reader.readString(offsets[1]),
- walletId: reader.readString(offsets[2]),
+ tags: reader.readStringList(offsets[1]),
+ value: reader.readString(offsets[2]),
+ walletId: reader.readString(offsets[3]),
);
object.id = id;
return object;
@@ -127,9 +146,11 @@ P _addressLabelDeserializeProp(
case 0:
return (reader.readString(offset)) as P;
case 1:
- return (reader.readString(offset)) as P;
+ return (reader.readStringList(offset)) as P;
case 2:
return (reader.readString(offset)) as P;
+ case 3:
+ return (reader.readString(offset)) as P;
default:
throw IsarError('Unknown property with id $propertyId');
}
@@ -649,6 +670,248 @@ extension AddressLabelQueryFilter
});
}
+ QueryBuilder tagsIsNull() {
+ return QueryBuilder.apply(this, (query) {
+ return query.addFilterCondition(const FilterCondition.isNull(
+ property: r'tags',
+ ));
+ });
+ }
+
+ QueryBuilder
+ tagsIsNotNull() {
+ return QueryBuilder.apply(this, (query) {
+ return query.addFilterCondition(const FilterCondition.isNotNull(
+ property: r'tags',
+ ));
+ });
+ }
+
+ QueryBuilder
+ tagsElementEqualTo(
+ String value, {
+ bool caseSensitive = true,
+ }) {
+ return QueryBuilder.apply(this, (query) {
+ return query.addFilterCondition(FilterCondition.equalTo(
+ property: r'tags',
+ value: value,
+ caseSensitive: caseSensitive,
+ ));
+ });
+ }
+
+ QueryBuilder
+ tagsElementGreaterThan(
+ String value, {
+ bool include = false,
+ bool caseSensitive = true,
+ }) {
+ return QueryBuilder.apply(this, (query) {
+ return query.addFilterCondition(FilterCondition.greaterThan(
+ include: include,
+ property: r'tags',
+ value: value,
+ caseSensitive: caseSensitive,
+ ));
+ });
+ }
+
+ QueryBuilder
+ tagsElementLessThan(
+ String value, {
+ bool include = false,
+ bool caseSensitive = true,
+ }) {
+ return QueryBuilder.apply(this, (query) {
+ return query.addFilterCondition(FilterCondition.lessThan(
+ include: include,
+ property: r'tags',
+ value: value,
+ caseSensitive: caseSensitive,
+ ));
+ });
+ }
+
+ QueryBuilder
+ tagsElementBetween(
+ String lower,
+ String upper, {
+ bool includeLower = true,
+ bool includeUpper = true,
+ bool caseSensitive = true,
+ }) {
+ return QueryBuilder.apply(this, (query) {
+ return query.addFilterCondition(FilterCondition.between(
+ property: r'tags',
+ lower: lower,
+ includeLower: includeLower,
+ upper: upper,
+ includeUpper: includeUpper,
+ caseSensitive: caseSensitive,
+ ));
+ });
+ }
+
+ QueryBuilder
+ tagsElementStartsWith(
+ String value, {
+ bool caseSensitive = true,
+ }) {
+ return QueryBuilder.apply(this, (query) {
+ return query.addFilterCondition(FilterCondition.startsWith(
+ property: r'tags',
+ value: value,
+ caseSensitive: caseSensitive,
+ ));
+ });
+ }
+
+ QueryBuilder
+ tagsElementEndsWith(
+ String value, {
+ bool caseSensitive = true,
+ }) {
+ return QueryBuilder.apply(this, (query) {
+ return query.addFilterCondition(FilterCondition.endsWith(
+ property: r'tags',
+ value: value,
+ caseSensitive: caseSensitive,
+ ));
+ });
+ }
+
+ QueryBuilder
+ tagsElementContains(String value, {bool caseSensitive = true}) {
+ return QueryBuilder.apply(this, (query) {
+ return query.addFilterCondition(FilterCondition.contains(
+ property: r'tags',
+ value: value,
+ caseSensitive: caseSensitive,
+ ));
+ });
+ }
+
+ QueryBuilder
+ tagsElementMatches(String pattern, {bool caseSensitive = true}) {
+ return QueryBuilder.apply(this, (query) {
+ return query.addFilterCondition(FilterCondition.matches(
+ property: r'tags',
+ wildcard: pattern,
+ caseSensitive: caseSensitive,
+ ));
+ });
+ }
+
+ QueryBuilder
+ tagsElementIsEmpty() {
+ return QueryBuilder.apply(this, (query) {
+ return query.addFilterCondition(FilterCondition.equalTo(
+ property: r'tags',
+ value: '',
+ ));
+ });
+ }
+
+ QueryBuilder
+ tagsElementIsNotEmpty() {
+ return QueryBuilder.apply(this, (query) {
+ return query.addFilterCondition(FilterCondition.greaterThan(
+ property: r'tags',
+ value: '',
+ ));
+ });
+ }
+
+ QueryBuilder
+ tagsLengthEqualTo(int length) {
+ return QueryBuilder.apply(this, (query) {
+ return query.listLength(
+ r'tags',
+ length,
+ true,
+ length,
+ true,
+ );
+ });
+ }
+
+ QueryBuilder
+ tagsIsEmpty() {
+ return QueryBuilder.apply(this, (query) {
+ return query.listLength(
+ r'tags',
+ 0,
+ true,
+ 0,
+ true,
+ );
+ });
+ }
+
+ QueryBuilder
+ tagsIsNotEmpty() {
+ return QueryBuilder.apply(this, (query) {
+ return query.listLength(
+ r'tags',
+ 0,
+ false,
+ 999999,
+ true,
+ );
+ });
+ }
+
+ QueryBuilder
+ tagsLengthLessThan(
+ int length, {
+ bool include = false,
+ }) {
+ return QueryBuilder.apply(this, (query) {
+ return query.listLength(
+ r'tags',
+ 0,
+ true,
+ length,
+ include,
+ );
+ });
+ }
+
+ QueryBuilder
+ tagsLengthGreaterThan(
+ int length, {
+ bool include = false,
+ }) {
+ return QueryBuilder.apply(this, (query) {
+ return query.listLength(
+ r'tags',
+ length,
+ include,
+ 999999,
+ true,
+ );
+ });
+ }
+
+ QueryBuilder
+ tagsLengthBetween(
+ int lower,
+ int upper, {
+ bool includeLower = true,
+ bool includeUpper = true,
+ }) {
+ return QueryBuilder.apply(this, (query) {
+ return query.listLength(
+ r'tags',
+ lower,
+ includeLower,
+ upper,
+ includeUpper,
+ );
+ });
+ }
+
QueryBuilder valueEqualTo(
String value, {
bool caseSensitive = true,
@@ -1028,6 +1291,12 @@ extension AddressLabelQueryWhereDistinct
});
}
+ QueryBuilder distinctByTags() {
+ return QueryBuilder.apply(this, (query) {
+ return query.addDistinctBy(r'tags');
+ });
+ }
+
QueryBuilder distinctByValue(
{bool caseSensitive = true}) {
return QueryBuilder.apply(this, (query) {
@@ -1057,6 +1326,12 @@ extension AddressLabelQueryProperty
});
}
+ QueryBuilder?, QQueryOperations> tagsProperty() {
+ return QueryBuilder.apply(this, (query) {
+ return query.addPropertyName(r'tags');
+ });
+ }
+
QueryBuilder valueProperty() {
return QueryBuilder.apply(this, (query) {
return query.addPropertyName(r'value');
diff --git a/lib/models/isar/models/blockchain_data/address.dart b/lib/models/isar/models/blockchain_data/address.dart
index 0d29f28a7..770af4a6b 100644
--- a/lib/models/isar/models/blockchain_data/address.dart
+++ b/lib/models/isar/models/blockchain_data/address.dart
@@ -122,7 +122,26 @@ enum AddressType {
cryptonote,
mimbleWimble,
unknown,
- nonWallet,
+ nonWallet;
+
+ String get readableName {
+ switch (this) {
+ case AddressType.p2pkh:
+ return "Legacy";
+ case AddressType.p2sh:
+ return "Wrapped segwit";
+ case AddressType.p2wpkh:
+ return "Segwit";
+ case AddressType.cryptonote:
+ return "Cryptonote";
+ case AddressType.mimbleWimble:
+ return "Mimble Wimble";
+ case AddressType.unknown:
+ return "Unknown";
+ case AddressType.nonWallet:
+ return "Non wallet/unknown";
+ }
+ }
}
// do not modify
@@ -133,7 +152,26 @@ enum AddressSubType {
paynymSend,
paynymReceive,
unknown,
- nonWallet,
+ nonWallet;
+
+ String get prettyName {
+ switch (this) {
+ case AddressSubType.receiving:
+ return "Receiving";
+ case AddressSubType.change:
+ return "Change";
+ case AddressSubType.paynymNotification:
+ return "PayNym Notification";
+ case AddressSubType.paynymSend:
+ return "PayNym Send";
+ case AddressSubType.paynymReceive:
+ return "PayNym Receiving";
+ case AddressSubType.unknown:
+ return "Unknown";
+ case AddressSubType.nonWallet:
+ return "Non wallet/unknown";
+ }
+ }
}
@Embedded(inheritance: false)
diff --git a/lib/pages/add_wallet_views/create_or_restore_wallet_view/create_or_restore_wallet_view.dart b/lib/pages/add_wallet_views/create_or_restore_wallet_view/create_or_restore_wallet_view.dart
index 85d5beb74..38880f076 100644
--- a/lib/pages/add_wallet_views/create_or_restore_wallet_view/create_or_restore_wallet_view.dart
+++ b/lib/pages/add_wallet_views/create_or_restore_wallet_view/create_or_restore_wallet_view.dart
@@ -5,6 +5,7 @@ import 'package:stackwallet/pages/add_wallet_views/create_or_restore_wallet_view
import 'package:stackwallet/pages/add_wallet_views/create_or_restore_wallet_view/sub_widgets/create_wallet_button_group.dart';
import 'package:stackwallet/pages_desktop_specific/my_stack_view/exit_to_my_stack_button.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
+import 'package:stackwallet/utilities/theme/color_theme.dart';
import 'package:stackwallet/utilities/theme/stack_colors.dart';
import 'package:stackwallet/utilities/util.dart';
import 'package:stackwallet/widgets/background.dart';
@@ -81,6 +82,11 @@ class CreateOrRestoreWalletView extends StatelessWidget {
),
);
} else {
+ final isChans = Theme.of(context).extension()!.themeType ==
+ ThemeType.chan ||
+ Theme.of(context).extension()!.themeType ==
+ ThemeType.darkChans;
+
return Background(
child: Scaffold(
backgroundColor:
@@ -95,42 +101,59 @@ class CreateOrRestoreWalletView extends StatelessWidget {
body: SafeArea(
child: Container(
color: Theme.of(context).extension()!.background,
- child: Padding(
- padding: const EdgeInsets.all(16),
- child: Column(
- crossAxisAlignment: CrossAxisAlignment.stretch,
- children: [
- CoinImage(
- coin: coin,
- width: isDesktop
- ? 324
- : MediaQuery.of(context).size.width / 1.6,
- height: isDesktop
- ? null
- : MediaQuery.of(context).size.width / 1.6,
+ child: LayoutBuilder(
+ builder: (context, constraints) {
+ return SingleChildScrollView(
+ child: ConstrainedBox(
+ constraints: BoxConstraints(
+ minHeight: constraints.maxHeight,
+ ),
+ child: IntrinsicHeight(
+ child: Padding(
+ padding: const EdgeInsets.all(16),
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.stretch,
+ children: [
+ if (!isChans)
+ const Spacer(
+ flex: 2,
+ ),
+ CoinImage(
+ coin: coin,
+ width: isDesktop
+ ? 324
+ : MediaQuery.of(context).size.width / 1.6,
+ height: isDesktop
+ ? null
+ : MediaQuery.of(context).size.width / 1.6,
+ ),
+ const Spacer(
+ flex: 2,
+ ),
+ CreateRestoreWalletTitle(
+ coin: coin,
+ isDesktop: isDesktop,
+ ),
+ const SizedBox(
+ height: 8,
+ ),
+ CreateRestoreWalletSubTitle(
+ isDesktop: isDesktop,
+ ),
+ const Spacer(
+ flex: 5,
+ ),
+ CreateWalletButtonGroup(
+ coin: coin,
+ isDesktop: isDesktop,
+ ),
+ ],
+ ),
+ ),
+ ),
),
- const Spacer(
- flex: 2,
- ),
- CreateRestoreWalletTitle(
- coin: coin,
- isDesktop: isDesktop,
- ),
- const SizedBox(
- height: 8,
- ),
- CreateRestoreWalletSubTitle(
- isDesktop: isDesktop,
- ),
- const Spacer(
- flex: 5,
- ),
- CreateWalletButtonGroup(
- coin: coin,
- isDesktop: isDesktop,
- ),
- ],
- ),
+ );
+ },
),
),
),
diff --git a/lib/pages/add_wallet_views/create_or_restore_wallet_view/sub_widgets/coin_image.dart b/lib/pages/add_wallet_views/create_or_restore_wallet_view/sub_widgets/coin_image.dart
index fb282d9ca..4b8a18005 100644
--- a/lib/pages/add_wallet_views/create_or_restore_wallet_view/sub_widgets/coin_image.dart
+++ b/lib/pages/add_wallet_views/create_or_restore_wallet_view/sub_widgets/coin_image.dart
@@ -6,6 +6,8 @@ import 'package:stackwallet/utilities/enums/coin_enum.dart';
import 'package:stackwallet/utilities/theme/color_theme.dart';
import 'package:stackwallet/utilities/theme/stack_colors.dart';
+import '../../../../utilities/util.dart';
+
class CoinImage extends ConsumerWidget {
const CoinImage({
Key? key,
@@ -20,11 +22,17 @@ class CoinImage extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
- if (Theme.of(context).extension()!.themeType ==
- ThemeType.chan) {
+ final isChans = Theme.of(context).extension()!.themeType ==
+ ThemeType.chan ||
+ Theme.of(context).extension()!.themeType ==
+ ThemeType.darkChans;
+
+ final isDesktop = Util.isDesktop;
+
+ if (isChans) {
return SizedBox(
- width: width,
- height: height,
+ width: isDesktop ? width : MediaQuery.of(context).size.width,
+ height: isDesktop ? height : MediaQuery.of(context).size.width,
child: Image(
image: AssetImage(
Assets.gif.plain(coin),
diff --git a/lib/pages/coin_control/utxo_details_view.dart b/lib/pages/coin_control/utxo_details_view.dart
index e4b31c63d..c08b856c8 100644
--- a/lib/pages/coin_control/utxo_details_view.dart
+++ b/lib/pages/coin_control/utxo_details_view.dart
@@ -111,6 +111,10 @@ class _UtxoDetailsViewState extends ConsumerState {
Navigator.of(context).pop(_popWithRefresh ? "refresh" : null);
},
),
+ title: Text(
+ "Output details",
+ style: STextStyles.navBarTitle(context),
+ ),
),
body: SafeArea(
child: LayoutBuilder(
diff --git a/lib/pages/generic/single_field_edit_view.dart b/lib/pages/generic/single_field_edit_view.dart
index c1049b006..5735a7754 100644
--- a/lib/pages/generic/single_field_edit_view.dart
+++ b/lib/pages/generic/single_field_edit_view.dart
@@ -196,7 +196,11 @@ class _SingleFieldEditViewState extends State {
}
},
),
- )
+ ),
+ if (!isDesktop)
+ const SizedBox(
+ height: 16,
+ ),
],
),
);
diff --git a/lib/pages/loading_view.dart b/lib/pages/loading_view.dart
index 6c4b611ee..2da507847 100644
--- a/lib/pages/loading_view.dart
+++ b/lib/pages/loading_view.dart
@@ -16,6 +16,12 @@ class LoadingView extends StatelessWidget {
Widget build(BuildContext context) {
final size = MediaQuery.of(context).size;
final width = min(size.width, size.height) * 0.5;
+
+ final isChan = Theme.of(context).extension()!.themeType ==
+ ThemeType.chan ||
+ Theme.of(context).extension()!.themeType ==
+ ThemeType.darkChans;
+
return Background(
child: Scaffold(
backgroundColor: Theme.of(context).extension()!.background,
@@ -35,11 +41,17 @@ class LoadingView extends StatelessWidget {
),
child: SizedBox(
width: width,
- child: Lottie.asset(
- Assets.lottie.test2,
- animate: true,
- repeat: true,
- ),
+ child: isChan
+ ? Image(
+ image: AssetImage(
+ Assets.gif.stacyPlain,
+ ),
+ )
+ : Lottie.asset(
+ Assets.lottie.test2,
+ animate: true,
+ repeat: true,
+ ),
),
),
// child: Image(
diff --git a/lib/pages/receive_view/addresses/address_card.dart b/lib/pages/receive_view/addresses/address_card.dart
index 0bc922e9c..fdf3201d1 100644
--- a/lib/pages/receive_view/addresses/address_card.dart
+++ b/lib/pages/receive_view/addresses/address_card.dart
@@ -1,21 +1,13 @@
import 'dart:async';
import 'package:flutter/material.dart';
-import 'package:flutter/services.dart';
import 'package:isar/isar.dart';
import 'package:stackwallet/db/main_db.dart';
import 'package:stackwallet/models/isar/models/isar_models.dart';
-import 'package:stackwallet/notifications/show_flush_bar.dart';
-import 'package:stackwallet/pages/receive_view/addresses/address_qr_popup.dart';
-import 'package:stackwallet/pages/receive_view/addresses/edit_address_label_view.dart';
+import 'package:stackwallet/pages/receive_view/addresses/address_tag.dart';
import 'package:stackwallet/utilities/clipboard_interface.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/widgets/custom_buttons/blue_text_button.dart';
-import 'package:stackwallet/widgets/desktop/secondary_button.dart';
-import 'package:stackwallet/widgets/icon_widgets/copy_icon.dart';
-import 'package:stackwallet/widgets/icon_widgets/qrcode_icon.dart';
import 'package:stackwallet/widgets/rounded_white_container.dart';
class AddressCard extends StatefulWidget {
@@ -24,6 +16,7 @@ class AddressCard extends StatefulWidget {
required this.addressId,
required this.walletId,
required this.coin,
+ this.onPressed,
this.clipboard = const ClipboardWrapper(),
}) : super(key: key);
@@ -31,6 +24,7 @@ class AddressCard extends StatefulWidget {
final String walletId;
final Coin coin;
final ClipboardInterface clipboard;
+ final VoidCallback? onPressed;
@override
State createState() => _AddressCardState();
@@ -56,6 +50,11 @@ class _AddressCardState extends State {
walletId: widget.walletId,
addressString: address.value,
value: "",
+ tags: address.subType == AddressSubType.receiving
+ ? ["receiving"]
+ : address.subType == AddressSubType.change
+ ? ["change"]
+ : null,
);
id = MainDB.instance.putAddressLabelSync(label!);
}
@@ -67,106 +66,126 @@ class _AddressCardState extends State {
@override
Widget build(BuildContext context) {
return RoundedWhiteContainer(
+ onPressed: widget.onPressed,
child: StreamBuilder(
- stream: stream,
- builder: (context, snapshot) {
- if (snapshot.hasData) {
- label = snapshot.data!;
- }
+ stream: stream,
+ builder: (context, snapshot) {
+ if (snapshot.hasData) {
+ label = snapshot.data!;
+ }
- return Column(
- children: [
- Row(
- mainAxisAlignment: MainAxisAlignment.spaceBetween,
- children: [
- Text(
- label!.value,
- style: STextStyles.itemSubtitle(context),
- ),
- CustomTextButton(
- text: "Edit label",
- textSize: 14,
- onTap: () {
- Navigator.of(context).pushNamed(
- EditAddressLabelView.routeName,
- arguments: label!.id,
- );
- },
- ),
- ],
+ return Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ if (label!.value.isNotEmpty)
+ Text(
+ label!.value,
+ style: STextStyles.itemSubtitle(context),
+ textAlign: TextAlign.left,
),
+ // Row(
+ // mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ // children: [
+ //
+ // CustomTextButton(
+ // text: "Edit label",
+ // textSize: 14,
+ // onTap: () {
+ // Navigator.of(context).pushNamed(
+ // EditAddressLabelView.routeName,
+ // arguments: label!.id,
+ // );
+ // },
+ // ),
+ // ],
+ // ),
+ if (label!.value.isNotEmpty)
const SizedBox(
height: 8,
),
- Row(
- children: [
- Expanded(
- child: SelectableText(
- address.value,
- style: STextStyles.itemSubtitle12(context),
- ),
- )
- ],
- ),
- const SizedBox(
- height: 10,
- ),
- Row(
- children: [
- Expanded(
- child: SecondaryButton(
- label: "Copy address",
- icon: CopyIcon(
- color: Theme.of(context)
- .extension()!
- .buttonTextSecondary,
+ Row(
+ children: [
+ Expanded(
+ child: Text(
+ address.value,
+ style: STextStyles.itemSubtitle12(context),
+ ),
+ ),
+ ],
+ ),
+ const SizedBox(
+ height: 10,
+ ),
+
+ if (label!.tags != null && label!.tags!.isNotEmpty)
+ Wrap(
+ spacing: 10,
+ runSpacing: 10,
+ children: label!.tags!
+ .map(
+ (e) => AddressTag(
+ tag: e,
),
- onPressed: () async {
- await widget.clipboard.setData(
- ClipboardData(
- text: address.value,
- ),
- );
- if (mounted) {
- unawaited(
- showFloatingFlushBar(
- type: FlushBarType.info,
- message: "Copied to clipboard",
- context: context,
- ),
- );
- }
- },
- ),
- ),
- const SizedBox(
- width: 12,
- ),
- Expanded(
- child: SecondaryButton(
- label: "Show QR Code",
- icon: QrCodeIcon(
- color: Theme.of(context)
- .extension()!
- .buttonTextSecondary,
- ),
- onPressed: () {
- showDialog(
- context: context,
- builder: (context) => AddressQrPopup(
- addressString: address.value,
- coin: widget.coin,
- clipboard: widget.clipboard,
- ),
- );
- },
- ),
- ),
- ],
- )
- ],
- );
- }),
+ )
+ .toList(),
+ ),
+ // Row(
+ // children: [
+ // Expanded(
+ // child: SecondaryButton(
+ // label: "Copy address",
+ // icon: CopyIcon(
+ // color: Theme.of(context)
+ // .extension()!
+ // .buttonTextSecondary,
+ // ),
+ // onPressed: () async {
+ // await widget.clipboard.setData(
+ // ClipboardData(
+ // text: address.value,
+ // ),
+ // );
+ // if (mounted) {
+ // unawaited(
+ // showFloatingFlushBar(
+ // type: FlushBarType.info,
+ // message: "Copied to clipboard",
+ // context: context,
+ // ),
+ // );
+ // }
+ // },
+ // ),
+ // ),
+ // const SizedBox(
+ // width: 12,
+ // ),
+ // Expanded(
+ // child: SecondaryButton(
+ // label: "Show QR Code",
+ // icon: QrCodeIcon(
+ // color: Theme.of(context)
+ // .extension()!
+ // .buttonTextSecondary,
+ // ),
+ // onPressed: () {
+ // showDialog(
+ // context: context,
+ // builder: (context) => AddressQrPopup(
+ // addressString: address.value,
+ // coin: widget.coin,
+ // clipboard: widget.clipboard,
+ // ),
+ // );
+ // },
+ // ),
+ // ),
+ // ],
+ // )
+ ],
+ );
+ },
+ ),
);
}
}
diff --git a/lib/pages/receive_view/addresses/address_details_view.dart b/lib/pages/receive_view/addresses/address_details_view.dart
new file mode 100644
index 000000000..1ddf2f666
--- /dev/null
+++ b/lib/pages/receive_view/addresses/address_details_view.dart
@@ -0,0 +1,350 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_riverpod/flutter_riverpod.dart';
+import 'package:isar/isar.dart';
+import 'package:qr_flutter/qr_flutter.dart';
+import 'package:stackwallet/db/main_db.dart';
+import 'package:stackwallet/models/isar/models/isar_models.dart';
+import 'package:stackwallet/pages/receive_view/addresses/address_tag.dart';
+import 'package:stackwallet/pages/wallet_view/sub_widgets/no_transactions_found.dart';
+import 'package:stackwallet/providers/global/wallets_provider.dart';
+import 'package:stackwallet/utilities/address_utils.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/background.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/simple_copy_button.dart';
+import 'package:stackwallet/widgets/custom_buttons/simple_edit_button.dart';
+import 'package:stackwallet/widgets/rounded_white_container.dart';
+import 'package:stackwallet/widgets/transaction_card.dart';
+
+class AddressDetailsView extends ConsumerStatefulWidget {
+ const AddressDetailsView({
+ Key? key,
+ required this.addressId,
+ required this.walletId,
+ }) : super(key: key);
+
+ static const String routeName = "/addressDetailsView";
+
+ final Id addressId;
+ final String walletId;
+
+ @override
+ ConsumerState createState() => _AddressDetailsViewState();
+}
+
+class _AddressDetailsViewState extends ConsumerState {
+ final _qrKey = GlobalKey();
+ final isDesktop = Util.isDesktop;
+
+ late Stream stream;
+ late final Address address;
+
+ AddressLabel? label;
+
+ @override
+ void initState() {
+ address = MainDB.instance.isar.addresses
+ .where()
+ .idEqualTo(widget.addressId)
+ .findFirstSync()!;
+
+ label = MainDB.instance.getAddressLabelSync(widget.walletId, address.value);
+ Id? id = label?.id;
+ if (id == null) {
+ label = AddressLabel(
+ walletId: widget.walletId,
+ addressString: address.value,
+ value: "",
+ tags: address.subType == AddressSubType.receiving
+ ? ["receiving"]
+ : address.subType == AddressSubType.change
+ ? ["change"]
+ : null,
+ );
+ id = MainDB.instance.putAddressLabelSync(label!);
+ }
+ stream = MainDB.instance.watchAddressLabel(id: id);
+
+ super.initState();
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ final coin = ref.watch(walletsChangeNotifierProvider
+ .select((value) => value.getManager(widget.walletId).coin));
+ final query = MainDB.instance
+ .getTransactions(widget.walletId)
+ .filter()
+ .address((q) => q.valueEqualTo(address.value));
+
+ return ConditionalParent(
+ condition: !isDesktop,
+ builder: (child) => Background(
+ child: Scaffold(
+ backgroundColor:
+ Theme.of(context).extension()!.background,
+ appBar: AppBar(
+ backgroundColor:
+ Theme.of(context).extension()!.backgroundAppBar,
+ leading: AppBarBackButton(
+ onPressed: () {
+ Navigator.of(context).pop();
+ },
+ ),
+ titleSpacing: 0,
+ title: Text(
+ "Wallet addresses",
+ style: STextStyles.navBarTitle(context),
+ ),
+ ),
+ body: SafeArea(
+ child: LayoutBuilder(
+ builder: (builderContext, constraints) {
+ return SingleChildScrollView(
+ child: ConstrainedBox(
+ constraints: BoxConstraints(
+ minHeight: constraints.maxHeight,
+ ),
+ child: Padding(
+ padding: const EdgeInsets.all(16),
+ child: child,
+ ),
+ ),
+ );
+ },
+ ),
+ ),
+ ),
+ ),
+ child: StreamBuilder(
+ stream: stream,
+ builder: (context, snapshot) {
+ if (snapshot.hasData) {
+ label = snapshot.data!;
+ }
+
+ return Column(
+ crossAxisAlignment: CrossAxisAlignment.stretch,
+ children: [
+ Center(
+ child: RepaintBoundary(
+ key: _qrKey,
+ child: QrImage(
+ data: AddressUtils.buildUriString(
+ coin,
+ address.value,
+ {},
+ ),
+ size: 220,
+ backgroundColor:
+ Theme.of(context).extension()!.background,
+ foregroundColor: Theme.of(context)
+ .extension()!
+ .accentColorDark,
+ ),
+ ),
+ ),
+ const SizedBox(
+ height: 16,
+ ),
+ _Item(
+ title: "Address",
+ data: address.value,
+ button: SimpleCopyButton(
+ data: address.value,
+ ),
+ ),
+ const SizedBox(
+ height: 12,
+ ),
+ _Item(
+ title: "Label",
+ data: label!.value,
+ button: SimpleEditButton(
+ editValue: label!.value,
+ editLabel: 'label',
+ onValueChanged: (value) {
+ MainDB.instance.putAddressLabel(
+ label!.copyWith(
+ label: value,
+ ),
+ );
+ },
+ ),
+ ),
+ const SizedBox(
+ height: 12,
+ ),
+ _Tags(
+ tags: label!.tags,
+ ),
+ if (address.derivationPath != null)
+ const SizedBox(
+ height: 12,
+ ),
+ if (address.derivationPath != null)
+ _Item(
+ title: "Derivation path",
+ data: address.derivationPath!.value,
+ button: Container(),
+ ),
+ const SizedBox(
+ height: 12,
+ ),
+ _Item(
+ title: "Type",
+ data: address.type.readableName,
+ button: Container(),
+ ),
+ const SizedBox(
+ height: 12,
+ ),
+ _Item(
+ title: "Sub type",
+ data: address.subType.prettyName,
+ button: Container(),
+ ),
+ const SizedBox(
+ height: 20,
+ ),
+ Text(
+ "Transactions",
+ textAlign: TextAlign.left,
+ style: STextStyles.itemSubtitle(context).copyWith(
+ color: Theme.of(context).extension()!.textDark3,
+ ),
+ ),
+ const SizedBox(
+ height: 12,
+ ),
+ if (query.countSync() == 0) const NoTransActionsFound(),
+ if (query.countSync() > 0)
+ RoundedWhiteContainer(
+ padding: EdgeInsets.zero,
+ child: Column(
+ mainAxisSize: MainAxisSize.min,
+ children: query
+ .findAllSync()
+ .map((e) => TransactionCard(
+ transaction: e, walletId: widget.walletId))
+ .toList(),
+ ),
+ ),
+ ],
+ );
+ },
+ ),
+ );
+ }
+}
+
+class _Tags extends StatelessWidget {
+ const _Tags({
+ Key? key,
+ required this.tags,
+ }) : super(key: key);
+
+ final List? tags;
+
+ @override
+ Widget build(BuildContext context) {
+ return RoundedWhiteContainer(
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: [
+ Text(
+ "Tags",
+ style: STextStyles.itemSubtitle(context),
+ ),
+ Container(),
+ // SimpleEditButton(
+ // onPressedOverride: () {
+ // // TODO edit tags
+ // },
+ // ),
+ ],
+ ),
+ const SizedBox(
+ height: 8,
+ ),
+ tags != null && tags!.isNotEmpty
+ ? Wrap(
+ spacing: 10,
+ runSpacing: 10,
+ children: tags!
+ .map(
+ (e) => AddressTag(
+ tag: e,
+ ),
+ )
+ .toList(),
+ )
+ : Text(
+ "Tags will appear here",
+ style: STextStyles.w500_14(context).copyWith(
+ color: Theme.of(context)
+ .extension()!
+ .textSubtitle3,
+ ),
+ ),
+ ],
+ ),
+ );
+ }
+}
+
+class _Item extends StatelessWidget {
+ const _Item({
+ Key? key,
+ required this.title,
+ required this.data,
+ required this.button,
+ }) : super(key: key);
+
+ final String title;
+ final String data;
+ final Widget button;
+
+ @override
+ Widget build(BuildContext context) {
+ return RoundedWhiteContainer(
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: [
+ Text(
+ title,
+ style: STextStyles.itemSubtitle(context),
+ ),
+ button,
+ ],
+ ),
+ const SizedBox(
+ height: 5,
+ ),
+ data.isNotEmpty
+ ? SelectableText(
+ data,
+ style: STextStyles.w500_14(context),
+ )
+ : Text(
+ "$title will appear here",
+ style: STextStyles.w500_14(context).copyWith(
+ color: Theme.of(context)
+ .extension()!
+ .textSubtitle3,
+ ),
+ ),
+ ],
+ ),
+ );
+ }
+}
diff --git a/lib/pages/receive_view/addresses/address_tag.dart b/lib/pages/receive_view/addresses/address_tag.dart
new file mode 100644
index 000000000..df03dc405
--- /dev/null
+++ b/lib/pages/receive_view/addresses/address_tag.dart
@@ -0,0 +1,26 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_native_splash/cli_commands.dart';
+import 'package:stackwallet/utilities/text_styles.dart';
+import 'package:stackwallet/widgets/rounded_container.dart';
+
+class AddressTag extends StatelessWidget {
+ const AddressTag({Key? key, required this.tag}) : super(key: key);
+
+ final String tag;
+
+ @override
+ Widget build(BuildContext context) {
+ return RoundedContainer(
+ radiusMultiplier: 0.5,
+ padding: const EdgeInsets.symmetric(
+ vertical: 5,
+ horizontal: 7,
+ ),
+ color: Colors.black,
+ child: Text(
+ tag.capitalize(),
+ style: STextStyles.w500_14(context),
+ ),
+ );
+ }
+}
diff --git a/lib/pages/receive_view/addresses/wallet_addresses_view.dart b/lib/pages/receive_view/addresses/wallet_addresses_view.dart
index aec8f24c3..aa0948528 100644
--- a/lib/pages/receive_view/addresses/wallet_addresses_view.dart
+++ b/lib/pages/receive_view/addresses/wallet_addresses_view.dart
@@ -1,9 +1,11 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
+import 'package:flutter_svg/svg.dart';
import 'package:isar/isar.dart';
import 'package:stackwallet/db/main_db.dart';
import 'package:stackwallet/models/isar/models/isar_models.dart';
import 'package:stackwallet/pages/receive_view/addresses/address_card.dart';
+import 'package:stackwallet/pages/receive_view/addresses/address_details_view.dart';
import 'package:stackwallet/providers/global/wallets_provider.dart';
import 'package:stackwallet/utilities/constants.dart';
import 'package:stackwallet/utilities/text_styles.dart';
@@ -13,7 +15,12 @@ import 'package:stackwallet/widgets/background.dart';
import 'package:stackwallet/widgets/conditional_parent.dart';
import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
import 'package:stackwallet/widgets/loading_indicator.dart';
-import 'package:stackwallet/widgets/toggle.dart';
+import 'package:stackwallet/widgets/stack_text_field.dart';
+import 'package:tuple/tuple.dart';
+
+import '../../../utilities/assets.dart';
+import '../../../widgets/icon_widgets/x_icon.dart';
+import '../../../widgets/textfield_icon_button.dart';
class WalletAddressesView extends ConsumerStatefulWidget {
const WalletAddressesView({
@@ -33,7 +40,88 @@ class WalletAddressesView extends ConsumerStatefulWidget {
class _WalletAddressesViewState extends ConsumerState {
final bool isDesktop = Util.isDesktop;
- bool _showChange = false;
+ String _searchString = "";
+
+ late final TextEditingController _searchController;
+ final searchFieldFocusNode = FocusNode();
+
+ Future> _search(String term) async {
+ if (term.isEmpty) {
+ return MainDB.instance
+ .getAddresses(widget.walletId)
+ .filter()
+ .group((q) => q
+ .subTypeEqualTo(AddressSubType.change)
+ .or()
+ .subTypeEqualTo(AddressSubType.receiving)
+ .or()
+ .subTypeEqualTo(AddressSubType.paynymReceive)
+ .or()
+ .subTypeEqualTo(AddressSubType.paynymNotification))
+ .and()
+ .not()
+ .typeEqualTo(AddressType.nonWallet)
+ .sortByDerivationIndex()
+ .idProperty()
+ .findAll();
+ }
+
+ final labels = await MainDB.instance
+ .getAddressLabels(widget.walletId)
+ .filter()
+ .group(
+ (q) => q
+ .valueContains(term, caseSensitive: false)
+ .or()
+ .addressStringContains(term, caseSensitive: false)
+ .or()
+ .group(
+ (q) => q
+ .tagsIsNotNull()
+ .and()
+ .tagsElementContains(term, caseSensitive: false),
+ ),
+ )
+ .findAll();
+
+ if (labels.isEmpty) {
+ return [];
+ }
+
+ return MainDB.instance
+ .getAddresses(widget.walletId)
+ .filter()
+ .anyOf(
+ labels, (q, e) => q.valueEqualTo(e.addressString))
+ .group((q) => q
+ .subTypeEqualTo(AddressSubType.change)
+ .or()
+ .subTypeEqualTo(AddressSubType.receiving)
+ .or()
+ .subTypeEqualTo(AddressSubType.paynymReceive)
+ .or()
+ .subTypeEqualTo(AddressSubType.paynymNotification))
+ .and()
+ .not()
+ .typeEqualTo(AddressType.nonWallet)
+ .sortByDerivationIndex()
+ .idProperty()
+ .findAll();
+ }
+
+ @override
+ void initState() {
+ _searchController = TextEditingController();
+
+ super.initState();
+ }
+
+ @override
+ void dispose() {
+ _searchController.dispose();
+ searchFieldFocusNode.dispose();
+ super.dispose();
+ }
@override
Widget build(BuildContext context) {
@@ -68,26 +156,66 @@ class _WalletAddressesViewState extends ConsumerState {
child: Column(
children: [
SizedBox(
- height: isDesktop ? 56 : 48,
width: isDesktop ? 490 : null,
- child: Toggle(
- key: UniqueKey(),
- onColor: Theme.of(context).extension()!.popupBG,
- onText: "Receiving",
- offColor: Theme.of(context)
- .extension()!
- .textFieldDefaultBG,
- offText: "Change",
- isOn: _showChange,
- onValueChanged: (value) {
- setState(() {
- _showChange = value;
- });
- },
- decoration: BoxDecoration(
- color: Colors.transparent,
- borderRadius: BorderRadius.circular(
- Constants.size.circularBorderRadius,
+ child: ClipRRect(
+ borderRadius: BorderRadius.circular(
+ Constants.size.circularBorderRadius,
+ ),
+ child: TextField(
+ autocorrect: !isDesktop,
+ enableSuggestions: !isDesktop,
+ controller: _searchController,
+ focusNode: searchFieldFocusNode,
+ onChanged: (value) {
+ setState(() {
+ _searchString = 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 = "";
+ _searchString = "";
+ });
+ },
+ ),
+ ],
+ ),
+ ),
+ )
+ : null,
),
),
),
@@ -97,23 +225,7 @@ class _WalletAddressesViewState extends ConsumerState {
),
Expanded(
child: FutureBuilder(
- future: MainDB.instance
- .getAddresses(widget.walletId)
- .filter()
- .group(
- (q) => _showChange
- ? q.subTypeEqualTo(AddressSubType.change)
- : q
- .subTypeEqualTo(AddressSubType.receiving)
- .or()
- .subTypeEqualTo(AddressSubType.paynymReceive),
- )
- .and()
- .not()
- .typeEqualTo(AddressType.nonWallet)
- .sortByDerivationIndex()
- .idProperty()
- .findAll(),
+ future: _search(_searchString),
builder: (context, AsyncSnapshot> snapshot) {
if (snapshot.connectionState == ConnectionState.done &&
snapshot.data != null) {
@@ -127,6 +239,15 @@ class _WalletAddressesViewState extends ConsumerState {
walletId: widget.walletId,
addressId: snapshot.data![index],
coin: coin,
+ onPressed: () {
+ Navigator.of(context).pushNamed(
+ AddressDetailsView.routeName,
+ arguments: Tuple2(
+ snapshot.data![index],
+ widget.walletId,
+ ),
+ );
+ },
),
);
} else {
diff --git a/lib/pages/send_view/send_view.dart b/lib/pages/send_view/send_view.dart
index c7c63bac7..508b9d6cc 100644
--- a/lib/pages/send_view/send_view.dart
+++ b/lib/pages/send_view/send_view.dart
@@ -588,7 +588,7 @@ class _SendViewState extends ConsumerState {
cryptoAmountController.text = _data!.amount!.toString();
}
sendToController.text = _data!.contactLabel;
- _address = _data!.address;
+ _address = _data!.address.trim();
_addressToggleFlag = true;
}
@@ -689,7 +689,7 @@ class _SendViewState extends ConsumerState {
// add listener for epic cash to strip http:// and https:// prefixes if the address also ocntains an @ symbol (indicating an epicbox address)
if (coin == Coin.epicCash) {
sendToController.addListener(() {
- _address = sendToController.text;
+ _address = sendToController.text.trim();
if (_address != null && _address!.isNotEmpty) {
_address = _address!.trim();
@@ -956,7 +956,7 @@ class _SendViewState extends ConsumerState {
selectAll: false,
),
onChanged: (newValue) {
- _address = newValue;
+ _address = newValue.trim();
_updatePreviewButtonState(
_address, _amountToSend);
@@ -1032,8 +1032,8 @@ class _SendViewState extends ConsumerState {
content);
}
sendToController.text =
- content;
- _address = content;
+ content.trim();
+ _address = content.trim();
_updatePreviewButtonState(
_address,
@@ -1112,8 +1112,9 @@ class _SendViewState extends ConsumerState {
coin.uriScheme) {
// auto fill address
_address =
- results["address"] ??
- "";
+ (results["address"] ??
+ "")
+ .trim();
sendToController.text =
_address!;
@@ -1168,8 +1169,9 @@ class _SendViewState extends ConsumerState {
.getManager(walletId)
.validateAddress(qrResult
.rawContent)) {
- _address =
- qrResult.rawContent;
+ _address = qrResult
+ .rawContent
+ .trim();
sendToController.text =
_address ?? "";
diff --git a/lib/pages/send_view/sub_widgets/building_transaction_dialog.dart b/lib/pages/send_view/sub_widgets/building_transaction_dialog.dart
index 6915493d5..8bd800cad 100644
--- a/lib/pages/send_view/sub_widgets/building_transaction_dialog.dart
+++ b/lib/pages/send_view/sub_widgets/building_transaction_dialog.dart
@@ -57,6 +57,11 @@ class _RestoringDialogState extends State
@override
Widget build(BuildContext context) {
+ final isChans = Theme.of(context).extension()!.themeType ==
+ ThemeType.chan ||
+ Theme.of(context).extension()!.themeType ==
+ ThemeType.darkChans;
+
if (Util.isDesktop) {
return Column(
mainAxisSize: MainAxisSize.min,
@@ -68,15 +73,13 @@ class _RestoringDialogState extends State
const SizedBox(
height: 40,
),
- if (Theme.of(context).extension()!.themeType ==
- ThemeType.chan)
+ if (isChans)
Image(
image: AssetImage(
Assets.gif.kiss(widget.coin),
),
),
- if (Theme.of(context).extension()!.themeType !=
- ThemeType.chan)
+ if (!isChans)
RotationTransition(
turns: _spinAnimation,
child: SvgPicture.asset(
@@ -104,8 +107,7 @@ class _RestoringDialogState extends State
onWillPop: () async {
return false;
},
- child: Theme.of(context).extension()!.themeType ==
- ThemeType.chan
+ child: isChans
? StackDialogBase(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
diff --git a/lib/pages/send_view/sub_widgets/sending_transaction_dialog.dart b/lib/pages/send_view/sub_widgets/sending_transaction_dialog.dart
index 3d9928c34..7c318a517 100644
--- a/lib/pages/send_view/sub_widgets/sending_transaction_dialog.dart
+++ b/lib/pages/send_view/sub_widgets/sending_transaction_dialog.dart
@@ -51,6 +51,11 @@ class _RestoringDialogState extends State
@override
Widget build(BuildContext context) {
+ final isChans = Theme.of(context).extension()!.themeType ==
+ ThemeType.chan ||
+ Theme.of(context).extension()!.themeType ==
+ ThemeType.darkChans;
+
if (Util.isDesktop) {
return DesktopDialog(
child: Padding(
@@ -65,8 +70,7 @@ class _RestoringDialogState extends State
const SizedBox(
height: 40,
),
- Theme.of(context).extension()!.themeType ==
- ThemeType.chan
+ isChans
? Image(
image: AssetImage(
Assets.gif.kiss(widget.coin),
@@ -92,8 +96,7 @@ class _RestoringDialogState extends State
onWillPop: () async {
return false;
},
- child: Theme.of(context).extension()!.themeType ==
- ThemeType.chan
+ child: isChans
? StackDialogBase(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
diff --git a/lib/pages/settings_views/global_settings_view/appearance_settings_view.dart b/lib/pages/settings_views/global_settings_view/appearance_settings_view.dart
index 04642b98f..981ddc69c 100644
--- a/lib/pages/settings_views/global_settings_view/appearance_settings_view.dart
+++ b/lib/pages/settings_views/global_settings_view/appearance_settings_view.dart
@@ -1,6 +1,6 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
-import 'package:stackwallet/hive/db.dart';
+import 'package:flutter_svg/flutter_svg.dart';
import 'package:stackwallet/providers/providers.dart';
import 'package:stackwallet/providers/ui/color_theme_provider.dart';
import 'package:stackwallet/utilities/assets.dart';
@@ -11,7 +11,10 @@ import 'package:stackwallet/utilities/theme/stack_colors.dart';
import 'package:stackwallet/widgets/background.dart';
import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
import 'package:stackwallet/widgets/custom_buttons/draggable_switch_button.dart';
+import 'package:stackwallet/widgets/expandable.dart';
+import 'package:stackwallet/widgets/rounded_container.dart';
import 'package:stackwallet/widgets/rounded_white_container.dart';
+import 'package:tuple/tuple.dart';
class AppearanceSettingsView extends ConsumerWidget {
const AppearanceSettingsView({Key? key}) : super(key: key);
@@ -101,43 +104,56 @@ class AppearanceSettingsView extends ConsumerWidget {
const SizedBox(
height: 10,
),
- RoundedWhiteContainer(
- padding: const EdgeInsets.all(0),
- child: RawMaterialButton(
- // splashColor: Theme.of(context).extension()!.highlight,
+ const SystemBrightnessToggle(),
+ if (!ref.watch(
+ prefsChangeNotifierProvider
+ .select((value) => value.enableSystemBrightness),
+ ))
+ const SizedBox(
+ height: 10,
+ ),
+ if (!ref.watch(
+ prefsChangeNotifierProvider
+ .select((value) => value.enableSystemBrightness),
+ ))
+ RoundedWhiteContainer(
padding: const EdgeInsets.all(0),
- materialTapTargetSize:
- MaterialTapTargetSize.shrinkWrap,
- shape: RoundedRectangleBorder(
- borderRadius: BorderRadius.circular(
- Constants.size.circularBorderRadius,
+ child: RawMaterialButton(
+ // splashColor: Theme.of(context).extension()!.highlight,
+ padding: const EdgeInsets.all(0),
+ materialTapTargetSize:
+ MaterialTapTargetSize.shrinkWrap,
+ shape: RoundedRectangleBorder(
+ borderRadius: BorderRadius.circular(
+ Constants.size.circularBorderRadius,
+ ),
),
- ),
- onPressed: null,
- child: Padding(
- padding: const EdgeInsets.all(12),
- child: Row(
- children: [
- Column(
- crossAxisAlignment:
- CrossAxisAlignment.start,
- children: [
- Text(
- "Choose Theme",
- style: STextStyles.titleBold12(context),
- textAlign: TextAlign.left,
- ),
- const Padding(
- padding: EdgeInsets.all(10),
- child: ThemeOptionsView(),
- ),
- ],
- ),
- ],
+ onPressed: null,
+ child: Padding(
+ padding: const EdgeInsets.all(12),
+ child: Row(
+ children: [
+ Column(
+ crossAxisAlignment:
+ CrossAxisAlignment.start,
+ children: [
+ Text(
+ "Choose Theme",
+ style:
+ STextStyles.titleBold12(context),
+ textAlign: TextAlign.left,
+ ),
+ const Padding(
+ padding: EdgeInsets.all(10),
+ child: ThemeOptionsView(),
+ ),
+ ],
+ ),
+ ],
+ ),
),
),
),
- ),
],
),
),
@@ -151,6 +167,238 @@ class AppearanceSettingsView extends ConsumerWidget {
}
}
+class SystemBrightnessToggle extends ConsumerStatefulWidget {
+ const SystemBrightnessToggle({Key? key}) : super(key: key);
+
+ @override
+ ConsumerState createState() =>
+ _SystemBrightnessToggleState();
+}
+
+class _SystemBrightnessToggleState
+ extends ConsumerState {
+ final controller = ExpandableController();
+
+ void _toggle(bool enable) {
+ ref.read(prefsChangeNotifierProvider).enableSystemBrightness = enable;
+
+ if (enable && controller.state == ExpandableState.collapsed) {
+ controller.toggle?.call();
+ } else if (!enable && controller.state == ExpandableState.expanded) {
+ controller.toggle?.call();
+ }
+
+ if (enable) {
+ final ThemeType type;
+ switch (MediaQuery.of(context).platformBrightness) {
+ case Brightness.dark:
+ type = ref
+ .read(prefsChangeNotifierProvider.notifier)
+ .systemBrightnessDarkTheme;
+ break;
+ case Brightness.light:
+ type = ref
+ .read(prefsChangeNotifierProvider.notifier)
+ .systemBrightnessLightTheme;
+ break;
+ }
+ ref.read(colorThemeProvider.notifier).state =
+ StackColors.fromStackColorTheme(
+ type.colorTheme,
+ );
+ } else {
+ ref.read(prefsChangeNotifierProvider.notifier).theme =
+ ref.read(colorThemeProvider.notifier).state.themeType;
+ }
+ }
+
+ @override
+ void initState() {
+ if (ref.read(prefsChangeNotifierProvider).enableSystemBrightness) {
+ WidgetsBinding.instance.addPostFrameCallback((_) {
+ controller.toggle?.call();
+ });
+ }
+ super.initState();
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ final enable = ref.watch(
+ prefsChangeNotifierProvider
+ .select((value) => value.enableSystemBrightness),
+ );
+
+ return RoundedWhiteContainer(
+ child: Expandable(
+ controller: controller,
+ expandOverride: () {
+ _toggle(
+ !ref.read(prefsChangeNotifierProvider).enableSystemBrightness);
+ },
+ header: RawMaterialButton(
+ splashColor: Theme.of(context).extension()!.highlight,
+ materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
+ shape: RoundedRectangleBorder(
+ borderRadius: BorderRadius.circular(
+ Constants.size.circularBorderRadius,
+ ),
+ ),
+ onPressed: null,
+ child: Padding(
+ padding: const EdgeInsets.symmetric(vertical: 8),
+ child: Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: [
+ Text(
+ "System brightness",
+ style: STextStyles.titleBold12(context),
+ textAlign: TextAlign.left,
+ ),
+ SizedBox(
+ key: Key("${enable}enableSystemBrightnessToggleKey"),
+ height: 20,
+ width: 40,
+ child: DraggableSwitchButton(
+ isOn: enable,
+ onValueChanged: _toggle,
+ ),
+ )
+ ],
+ ),
+ ),
+ ),
+ body: Column(
+ children: [
+ RoundedContainer(
+ color: Colors.transparent,
+ padding: EdgeInsets.zero,
+ onPressed: () async {
+ final result = await Navigator.of(context).pushNamed(
+ SystemBrightnessThemeSelectionView.routeName,
+ arguments: Tuple2(
+ "light",
+ ref
+ .read(prefsChangeNotifierProvider)
+ .systemBrightnessLightTheme),
+ );
+ if (result is ThemeType) {
+ ref
+ .read(prefsChangeNotifierProvider)
+ .systemBrightnessLightTheme = result;
+ if (ref
+ .read(prefsChangeNotifierProvider)
+ .enableSystemBrightness) {
+ if (mounted &&
+ MediaQuery.of(context).platformBrightness ==
+ Brightness.light) {
+ ref.read(colorThemeProvider.notifier).state =
+ StackColors.fromStackColorTheme(result.colorTheme);
+ }
+ }
+ }
+ },
+ child: Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: [
+ Padding(
+ padding: const EdgeInsets.all(8.0),
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Text(
+ "Light theme",
+ style: STextStyles.itemSubtitle(context),
+ ),
+ const SizedBox(
+ height: 2,
+ ),
+ Text(
+ ref
+ .watch(
+ prefsChangeNotifierProvider.select((value) =>
+ value.systemBrightnessLightTheme),
+ )
+ .prettyName,
+ style: STextStyles.itemSubtitle12(context),
+ ),
+ ],
+ ),
+ ),
+ SvgPicture.asset(
+ Assets.svg.chevronRight,
+ color: Theme.of(context).extension()!.textDark,
+ ),
+ ],
+ ),
+ ),
+ RoundedContainer(
+ color: Colors.transparent,
+ padding: EdgeInsets.zero,
+ onPressed: () async {
+ final result = await Navigator.of(context).pushNamed(
+ SystemBrightnessThemeSelectionView.routeName,
+ arguments: Tuple2(
+ "dark",
+ ref
+ .read(prefsChangeNotifierProvider)
+ .systemBrightnessDarkTheme),
+ );
+ if (result is ThemeType) {
+ ref
+ .read(prefsChangeNotifierProvider)
+ .systemBrightnessDarkTheme = result;
+ if (ref
+ .read(prefsChangeNotifierProvider)
+ .enableSystemBrightness) {
+ if (mounted &&
+ MediaQuery.of(context).platformBrightness ==
+ Brightness.dark) {
+ ref.read(colorThemeProvider.notifier).state =
+ StackColors.fromStackColorTheme(result.colorTheme);
+ }
+ }
+ }
+ },
+ child: Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: [
+ Padding(
+ padding: const EdgeInsets.all(8.0),
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Text(
+ "Dark theme",
+ style: STextStyles.itemSubtitle(context),
+ ),
+ const SizedBox(
+ height: 2,
+ ),
+ Text(
+ ref.watch(
+ prefsChangeNotifierProvider.select((value) =>
+ value.systemBrightnessDarkTheme.prettyName),
+ ),
+ style: STextStyles.itemSubtitle12(context),
+ ),
+ ],
+ ),
+ ),
+ SvgPicture.asset(
+ Assets.svg.chevronRight,
+ color: Theme.of(context).extension()!.textDark,
+ ),
+ ],
+ ),
+ )
+ ],
+ ),
+ ),
+ );
+ }
+}
+
class ThemeOptionsView extends ConsumerWidget {
const ThemeOptionsView({Key? key}) : super(key: key);
@@ -165,12 +413,9 @@ class ThemeOptionsView extends ConsumerWidget {
)
: ThemeOption(
onPressed: () {
- DB.instance.put(
- boxName: DB.boxNameTheme,
- key: "colorScheme",
- value: ThemeType.values[i ~/ 2].name,
- );
- ref.read(colorThemeProvider.state).state =
+ ref.read(prefsChangeNotifierProvider.notifier).theme =
+ ThemeType.values[i ~/ 2];
+ ref.read(colorThemeProvider.notifier).state =
StackColors.fromStackColorTheme(
ThemeType.values[i ~/ 2].colorTheme,
);
@@ -178,12 +423,9 @@ class ThemeOptionsView extends ConsumerWidget {
},
onChanged: (newValue) {
if (newValue == ThemeType.values[i ~/ 2]) {
- DB.instance.put(
- boxName: DB.boxNameTheme,
- key: "colorScheme",
- value: ThemeType.values[i ~/ 2].name,
- );
- ref.read(colorThemeProvider.state).state =
+ ref.read(prefsChangeNotifierProvider.notifier).theme =
+ ThemeType.values[i ~/ 2];
+ ref.read(colorThemeProvider.notifier).state =
StackColors.fromStackColorTheme(
ThemeType.values[i ~/ 2].colorTheme,
);
@@ -263,3 +505,124 @@ class ThemeOption extends StatelessWidget {
);
}
}
+
+class SystemBrightnessThemeSelectionView extends StatelessWidget {
+ const SystemBrightnessThemeSelectionView({
+ Key? key,
+ required this.brightness,
+ required this.current,
+ }) : super(key: key);
+
+ final String brightness;
+ final ThemeType current;
+
+ static const String routeName = "/chooseSystemTheme";
+
+ @override
+ Widget build(BuildContext context) {
+ return Background(
+ child: Scaffold(
+ backgroundColor: Theme.of(context).extension()!.background,
+ appBar: AppBar(
+ leading: AppBarBackButton(
+ onPressed: () async {
+ Navigator.of(context).pop();
+ },
+ ),
+ title: Text(
+ "Choose $brightness theme",
+ style: STextStyles.navBarTitle(context),
+ ),
+ ),
+ body: Padding(
+ padding: const EdgeInsets.all(16),
+ child: LayoutBuilder(
+ builder: (context, constraints) {
+ return SingleChildScrollView(
+ child: ConstrainedBox(
+ constraints: BoxConstraints(
+ minHeight: constraints.maxHeight,
+ ),
+ child: IntrinsicHeight(
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.stretch,
+ children: [
+ RoundedWhiteContainer(
+ padding: const EdgeInsets.all(0),
+ child: RawMaterialButton(
+ // splashColor: Theme.of(context).extension()!.highlight,
+ padding: const EdgeInsets.all(0),
+ materialTapTargetSize:
+ MaterialTapTargetSize.shrinkWrap,
+ shape: RoundedRectangleBorder(
+ borderRadius: BorderRadius.circular(
+ Constants.size.circularBorderRadius,
+ ),
+ ),
+ onPressed: null,
+ child: Padding(
+ padding: const EdgeInsets.all(12),
+ child: Row(
+ children: [
+ Column(
+ crossAxisAlignment:
+ CrossAxisAlignment.start,
+ children: [
+ Padding(
+ padding: const EdgeInsets.all(10),
+ child: Column(
+ children: [
+ for (int i = 0;
+ i <
+ (2 *
+ ThemeType.values
+ .length) -
+ 1;
+ i++)
+ (i % 2 == 1)
+ ? const SizedBox(
+ height: 10,
+ )
+ : ThemeOption(
+ onPressed: () {
+ Navigator.of(context)
+ .pop(ThemeType
+ .values[
+ i ~/ 2]);
+ },
+ onChanged: (newValue) {
+ if (newValue ==
+ ThemeType.values[
+ i ~/ 2]) {
+ Navigator.of(context)
+ .pop(ThemeType
+ .values[
+ i ~/ 2]);
+ }
+ },
+ value: ThemeType
+ .values[i ~/ 2],
+ groupValue: current,
+ ),
+ ],
+ ),
+ ),
+ ],
+ ),
+ ],
+ ),
+ ),
+ ),
+ ),
+ ],
+ ),
+ ),
+ ),
+ );
+ },
+ ),
+ ),
+ ),
+ );
+ }
+}
diff --git a/lib/pages/settings_views/global_settings_view/startup_preferences/startup_preferences_view.dart b/lib/pages/settings_views/global_settings_view/startup_preferences/startup_preferences_view.dart
index 186b9b293..c6e26c4b8 100644
--- a/lib/pages/settings_views/global_settings_view/startup_preferences/startup_preferences_view.dart
+++ b/lib/pages/settings_views/global_settings_view/startup_preferences/startup_preferences_view.dart
@@ -1,7 +1,9 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
+import 'package:flutter_svg/flutter_svg.dart';
import 'package:stackwallet/pages/settings_views/global_settings_view/startup_preferences/startup_wallet_selection_view.dart';
-import 'package:stackwallet/providers/global/prefs_provider.dart';
+import 'package:stackwallet/providers/providers.dart';
+import 'package:stackwallet/utilities/assets.dart';
import 'package:stackwallet/utilities/constants.dart';
import 'package:stackwallet/utilities/text_styles.dart';
import 'package:stackwallet/utilities/theme/stack_colors.dart';
@@ -21,6 +23,31 @@ class StartupPreferencesView extends ConsumerStatefulWidget {
class _StartupPreferencesViewState
extends ConsumerState {
+ bool safe = true;
+
+ @override
+ void initState() {
+ final possibleWalletId =
+ ref.read(prefsChangeNotifierProvider).startupWalletId;
+
+ // check if wallet exists (hasn't been deleted or otherwise missing)
+ if (possibleWalletId != null) {
+ try {
+ ref.read(walletsChangeNotifierProvider).getManager(possibleWalletId);
+ } catch (_) {
+ safe = false;
+ WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
+ ref.read(prefsChangeNotifierProvider).startupWalletId = null;
+ setState(() {
+ safe = true;
+ });
+ });
+ }
+ }
+
+ super.initState();
+ }
+
@override
Widget build(BuildContext context) {
return Background(
@@ -195,13 +222,73 @@ class _StartupPreferencesViewState
context),
textAlign: TextAlign.left,
),
- Text(
- "Select a specific wallet to load into on startup",
- style:
- STextStyles.itemSubtitle(
- context),
- textAlign: TextAlign.left,
- ),
+ (safe &&
+ ref.watch(
+ prefsChangeNotifierProvider
+ .select((value) =>
+ value
+ .startupWalletId),
+ ) !=
+ null)
+ ? Padding(
+ padding:
+ const EdgeInsets
+ .only(top: 12),
+ child: Row(
+ children: [
+ SvgPicture.asset(
+ Assets.svg
+ .iconFor(
+ coin: ref
+ .watch(
+ walletsChangeNotifierProvider
+ .select(
+ (value) =>
+ value.getManager(
+ ref.watch(
+ prefsChangeNotifierProvider.select((value) =>
+ value.startupWalletId!),
+ ),
+ ),
+ ),
+ )
+ .coin,
+ ),
+ ),
+ const SizedBox(
+ width: 10,
+ ),
+ Text(
+ ref
+ .watch(
+ walletsChangeNotifierProvider
+ .select(
+ (value) =>
+ value
+ .getManager(
+ ref.watch(
+ prefsChangeNotifierProvider.select((value) =>
+ value.startupWalletId!),
+ ),
+ ),
+ ),
+ )
+ .walletName,
+ style: STextStyles
+ .itemSubtitle(
+ context),
+ ),
+ ],
+ ),
+ )
+ : Text(
+ "Select a specific wallet to load into on startup",
+ style: STextStyles
+ .itemSubtitle(
+ context),
+ textAlign:
+ TextAlign.left,
+ ),
],
),
),
diff --git a/lib/pages_desktop_specific/settings/settings_menu/appearance_settings.dart b/lib/pages_desktop_specific/settings/settings_menu/appearance_settings.dart
index a23ad962a..f10d91555 100644
--- a/lib/pages_desktop_specific/settings/settings_menu/appearance_settings.dart
+++ b/lib/pages_desktop_specific/settings/settings_menu/appearance_settings.dart
@@ -1,7 +1,6 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_svg/svg.dart';
-import 'package:stackwallet/hive/db.dart';
import 'package:stackwallet/providers/global/prefs_provider.dart';
import 'package:stackwallet/providers/ui/color_theme_provider.dart';
import 'package:stackwallet/utilities/assets.dart';
@@ -112,6 +111,44 @@ class _AppearanceOptionSettings
],
),
),
+ // const Padding(
+ // padding: EdgeInsets.all(10.0),
+ // child: Divider(
+ // thickness: 0.5,
+ // ),
+ // ),
+ // Padding(
+ // padding: const EdgeInsets.all(10.0),
+ // child: Row(
+ // mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ // children: [
+ // Text(
+ // "System brightness",
+ // style: STextStyles.desktopTextExtraSmall(context)
+ // .copyWith(
+ // color: Theme.of(context)
+ // .extension()!
+ // .textDark),
+ // textAlign: TextAlign.left,
+ // ),
+ // SizedBox(
+ // height: 20,
+ // width: 40,
+ // child: DraggableSwitchButton(
+ // isOn: ref.watch(
+ // prefsChangeNotifierProvider.select(
+ // (value) => value.enableSystemBrightness),
+ // ),
+ // onValueChanged: (newValue) {
+ // ref
+ // .read(prefsChangeNotifierProvider)
+ // .enableSystemBrightness = newValue;
+ // },
+ // ),
+ // )
+ // ],
+ // ),
+ // ),
const Padding(
padding: EdgeInsets.all(10.0),
child: Divider(
@@ -166,6 +203,8 @@ class _ThemeToggle extends ConsumerState {
return Assets.svg.themeLight;
case ThemeType.dark:
return Assets.svg.themeDark;
+ case ThemeType.darkChans:
+ return Assets.svg.themeDarkChan;
case ThemeType.oceanBreeze:
return Assets.svg.themeOcean;
case ThemeType.oledBlack:
@@ -192,14 +231,12 @@ class _ThemeToggle extends ConsumerState {
cursor: SystemMouseCursors.click,
child: GestureDetector(
onTap: () {
- if (ref.read(colorThemeProvider.state).state.themeType !=
+ if (ref.read(colorThemeProvider.notifier).state.themeType !=
ThemeType.values[i]) {
- DB.instance.put(
- boxName: DB.boxNameTheme,
- key: "colorScheme",
- value: ThemeType.values[i].name,
- );
- ref.read(colorThemeProvider.state).state =
+ ref.read(prefsChangeNotifierProvider.notifier).theme =
+ ThemeType.values[i];
+
+ ref.read(colorThemeProvider.notifier).state =
StackColors.fromStackColorTheme(
ThemeType.values[i].colorTheme);
}
@@ -215,7 +252,7 @@ class _ThemeToggle extends ConsumerState {
border: Border.all(
width: 2.5,
color: ref
- .read(colorThemeProvider.state)
+ .read(colorThemeProvider.notifier)
.state
.themeType ==
ThemeType.values[i]
diff --git a/lib/route_generator.dart b/lib/route_generator.dart
index 64fd1e010..524639e54 100644
--- a/lib/route_generator.dart
+++ b/lib/route_generator.dart
@@ -48,6 +48,7 @@ import 'package:stackwallet/pages/paynym/add_new_paynym_follow_view.dart';
import 'package:stackwallet/pages/paynym/paynym_claim_view.dart';
import 'package:stackwallet/pages/paynym/paynym_home_view.dart';
import 'package:stackwallet/pages/pinpad_views/create_pin_view.dart';
+import 'package:stackwallet/pages/receive_view/addresses/address_details_view.dart';
import 'package:stackwallet/pages/receive_view/addresses/edit_address_label_view.dart';
import 'package:stackwallet/pages/receive_view/addresses/wallet_addresses_view.dart';
import 'package:stackwallet/pages/receive_view/generate_receiving_uri_qr_code_view.dart';
@@ -133,6 +134,7 @@ import 'package:stackwallet/services/event_bus/events/global/node_connection_sta
import 'package:stackwallet/services/event_bus/events/global/wallet_sync_status_changed_event.dart';
import 'package:stackwallet/utilities/enums/add_wallet_type_enum.dart';
import 'package:stackwallet/utilities/enums/coin_enum.dart';
+import 'package:stackwallet/utilities/theme/color_theme.dart';
import 'package:tuple/tuple.dart';
class RouteGenerator {
@@ -640,6 +642,21 @@ class RouteGenerator {
}
return _routeError("${settings.name} invalid args: ${args.toString()}");
+ case SystemBrightnessThemeSelectionView.routeName:
+ if (args is Tuple2) {
+ return getRoute(
+ shouldUseMaterialRoute: useMaterialPageRoute,
+ builder: (_) => SystemBrightnessThemeSelectionView(
+ brightness: args.item1,
+ current: args.item2,
+ ),
+ settings: RouteSettings(
+ name: settings.name,
+ ),
+ );
+ }
+ return _routeError("${settings.name} invalid args: ${args.toString()}");
+
case WalletNetworkSettingsView.routeName:
if (args is Tuple3) {
return getRoute(
@@ -912,6 +929,21 @@ class RouteGenerator {
}
return _routeError("${settings.name} invalid args: ${args.toString()}");
+ case AddressDetailsView.routeName:
+ if (args is Tuple2) {
+ return getRoute(
+ shouldUseMaterialRoute: useMaterialPageRoute,
+ builder: (_) => AddressDetailsView(
+ walletId: args.item2,
+ addressId: args.item1,
+ ),
+ settings: RouteSettings(
+ name: settings.name,
+ ),
+ );
+ }
+ return _routeError("${settings.name} invalid args: ${args.toString()}");
+
case SendView.routeName:
if (args is Tuple2) {
return getRoute(
diff --git a/lib/services/coins/bitcoin/bitcoin_wallet.dart b/lib/services/coins/bitcoin/bitcoin_wallet.dart
index acbfb16f2..3a9175d70 100644
--- a/lib/services/coins/bitcoin/bitcoin_wallet.dart
+++ b/lib/services/coins/bitcoin/bitcoin_wallet.dart
@@ -1842,6 +1842,7 @@ class BitcoinWallet extends CoinServiceAPI
bool shouldBlock = false;
String? blockReason;
+ String? label;
if (storedTx?.subType ==
isar_models.TransactionSubType.bip47Notification) {
@@ -1849,10 +1850,11 @@ class BitcoinWallet extends CoinServiceAPI
shouldBlock = true;
blockReason = "Incoming paynym notification transaction.";
} else if (storedTx?.type == isar_models.TransactionType.outgoing) {
- shouldBlock = true;
+ shouldBlock = false;
blockReason = "Paynym notification change output. Incautious "
"handling of change outputs from notification transactions "
"may cause unintended loss of privacy.";
+ label = blockReason;
}
}
@@ -1875,7 +1877,7 @@ class BitcoinWallet extends CoinServiceAPI
txid: txn["txid"] as String,
vout: vout,
value: jsonUTXO["value"] as int,
- name: "",
+ name: label ?? "",
isBlocked: shouldBlock,
blockedReason: blockReason,
isCoinbase: txn["is_coinbase"] as bool? ?? false,
diff --git a/lib/services/coins/dogecoin/dogecoin_wallet.dart b/lib/services/coins/dogecoin/dogecoin_wallet.dart
index 240d303e9..8fb892609 100644
--- a/lib/services/coins/dogecoin/dogecoin_wallet.dart
+++ b/lib/services/coins/dogecoin/dogecoin_wallet.dart
@@ -1587,6 +1587,7 @@ class DogecoinWallet extends CoinServiceAPI
bool shouldBlock = false;
String? blockReason;
+ String? label;
if (storedTx?.subType ==
isar_models.TransactionSubType.bip47Notification) {
@@ -1594,10 +1595,11 @@ class DogecoinWallet extends CoinServiceAPI
shouldBlock = true;
blockReason = "Incoming paynym notification transaction.";
} else if (storedTx?.type == isar_models.TransactionType.outgoing) {
- shouldBlock = true;
+ shouldBlock = false;
blockReason = "Paynym notification change output. Incautious "
"handling of change outputs from notification transactions "
"may cause unintended loss of privacy.";
+ label = blockReason;
}
}
@@ -1620,7 +1622,7 @@ class DogecoinWallet extends CoinServiceAPI
txid: txn["txid"] as String,
vout: vout,
value: jsonUTXO["value"] as int,
- name: "",
+ name: label ?? "",
isBlocked: shouldBlock,
blockedReason: blockReason,
isCoinbase: txn["is_coinbase"] as bool? ?? false,
diff --git a/lib/utilities/assets.dart b/lib/utilities/assets.dart
index 25c434fa0..c54e75baf 100644
--- a/lib/utilities/assets.dart
+++ b/lib/utilities/assets.dart
@@ -27,6 +27,7 @@ abstract class Assets {
if (Util.isDesktop) {
assets.add(svg.themeChan);
+ assets.add(svg.themeDarkChan);
}
final futures = assets.map(
@@ -71,6 +72,7 @@ class _BUY {
switch (Theme.of(context).extension()!.themeType) {
case ThemeType.dark:
case ThemeType.oledBlack:
+ case ThemeType.darkChans:
return "assets/svg/buy/Simplex-Nuvei-Logo-light.svg";
case ThemeType.fruitSorbet:
@@ -102,6 +104,9 @@ class _SVG {
// chan theme uses all the same assets as the light theme
case ThemeType.chan:
return "assets/svg/themed/${ThemeType.light.name}";
+ case ThemeType.darkChans:
+ return "assets/svg/themed/${ThemeType.dark.name}";
+
default:
return "assets/svg/themed/${Theme.of(context).extension()!.themeType.name}";
}
@@ -115,6 +120,7 @@ class _SVG {
case ThemeType.chan:
case ThemeType.dark:
case ThemeType.oledBlack:
+ case ThemeType.darkChans:
return null;
case ThemeType.oceanBreeze:
@@ -163,6 +169,7 @@ class _SVG {
String get themeLight => "assets/svg/light-mode.svg";
String get themeDark => "assets/svg/dark-theme.svg";
String get themeChan => "assets/svg/chanstheme.svg";
+ String get themeDarkChan => "assets/svg/darkChansTheme.svg";
String get circleSliders => "assets/svg/configuration.svg";
String get circlePlus => "assets/svg/plus-circle.svg";
@@ -394,6 +401,8 @@ class _ANIMATIONS {
class _GIF {
const _GIF();
+ String get stacyPlain => "assets/gif/stacy-plain.gif";
+
String plain(Coin coin) {
return "assets/gif/coins/${coin.mainNetVersion.name}/plain.gif";
}
diff --git a/lib/utilities/constants.dart b/lib/utilities/constants.dart
index 19516c5b9..55569a6d3 100644
--- a/lib/utilities/constants.dart
+++ b/lib/utilities/constants.dart
@@ -41,7 +41,7 @@ abstract class Constants {
// Enable Logger.print statements
static const bool disableLogger = false;
- static const int currentHiveDbVersion = 5;
+ static const int currentHiveDbVersion = 7;
static const int rescanV1 = 1;
diff --git a/lib/utilities/db_version_migration.dart b/lib/utilities/db_version_migration.dart
index 67e76ef29..aaa40b45a 100644
--- a/lib/utilities/db_version_migration.dart
+++ b/lib/utilities/db_version_migration.dart
@@ -1,9 +1,11 @@
import 'package:hive/hive.dart';
+import 'package:isar/isar.dart';
import 'package:stackwallet/db/main_db.dart';
import 'package:stackwallet/electrumx_rpc/electrumx.dart';
import 'package:stackwallet/hive/db.dart';
import 'package:stackwallet/models/exchange/change_now/exchange_transaction.dart';
import 'package:stackwallet/models/exchange/response_objects/trade.dart';
+import 'package:stackwallet/models/isar/models/blockchain_data/address.dart';
import 'package:stackwallet/models/isar/models/isar_models.dart' as isar_models;
import 'package:stackwallet/models/models.dart';
import 'package:stackwallet/models/node_model.dart';
@@ -185,6 +187,97 @@ class DbVersionMigrator with WalletDB {
// try to continue migrating
return await migrate(5, secureStore: secureStore);
+ case 5:
+ // migrate
+ await Hive.openBox("theme");
+ await Hive.openBox(DB.boxNamePrefs);
+
+ final themeName =
+ DB.instance.get(boxName: "theme", key: "colorScheme")
+ as String? ??
+ "light";
+
+ await DB.instance.put(
+ boxName: DB.boxNamePrefs, key: "theme", value: themeName);
+
+ // update version
+ await DB.instance.put(
+ boxName: DB.boxNameDBInfo, key: "hive_data_version", value: 6);
+
+ // try to continue migrating
+ return await migrate(6, secureStore: secureStore);
+
+ case 6:
+ // migrate
+ await MainDB.instance.initMainDB();
+ final count = await MainDB.instance.isar.addresses.count();
+ // add change/receiving tags to address labels
+ for (var i = 0; i < count; i += 50) {
+ final addresses = await MainDB.instance.isar.addresses
+ .where()
+ .offset(i)
+ .limit(50)
+ .findAll();
+
+ final List labels = [];
+ for (final address in addresses) {
+ List? tags;
+ switch (address.subType) {
+ case AddressSubType.receiving:
+ tags = ["receiving"];
+ break;
+ case AddressSubType.change:
+ tags = ["change"];
+ break;
+ case AddressSubType.paynymNotification:
+ tags = ["paynym notification"];
+ break;
+ case AddressSubType.paynymSend:
+ break;
+ case AddressSubType.paynymReceive:
+ tags = ["paynym receiving"];
+ break;
+ case AddressSubType.unknown:
+ break;
+ case AddressSubType.nonWallet:
+ break;
+ }
+
+ // update/create label if tags is not empty
+ if (tags != null) {
+ isar_models.AddressLabel? label = await MainDB
+ .instance.isar.addressLabels
+ .where()
+ .addressStringWalletIdEqualTo(address.value, address.walletId)
+ .findFirst();
+ if (label == null) {
+ label = isar_models.AddressLabel(
+ walletId: address.walletId,
+ value: "",
+ addressString: address.value,
+ tags: tags,
+ );
+ } else if (label.tags == null) {
+ label = label.copyWith(tags: tags);
+ }
+ labels.add(label);
+ }
+ }
+
+ if (labels.isNotEmpty) {
+ await MainDB.instance.isar.writeTxn(() async {
+ await MainDB.instance.isar.addressLabels.putAll(labels);
+ });
+ }
+ }
+
+ // update version
+ await DB.instance.put(
+ boxName: DB.boxNameDBInfo, key: "hive_data_version", value: 7);
+
+ // try to continue migrating
+ return await migrate(7, secureStore: secureStore);
+
default:
// finally return
return;
diff --git a/lib/utilities/delete_everything.dart b/lib/utilities/delete_everything.dart
index 497cd71f4..f9a33dbaf 100644
--- a/lib/utilities/delete_everything.dart
+++ b/lib/utilities/delete_everything.dart
@@ -21,7 +21,7 @@ Future deleteEverything() async {
.deleteBoxFromDisk(boxName: DB.boxNameWalletsToDeleteOnStart);
await DB.instance.deleteBoxFromDisk(boxName: DB.boxNamePriceCache);
await DB.instance.deleteBoxFromDisk(boxName: DB.boxNameDBInfo);
- await DB.instance.deleteBoxFromDisk(boxName: DB.boxNameTheme);
+ await DB.instance.deleteBoxFromDisk(boxName: "theme");
return true;
} catch (e, s) {
Logging.instance.log("$e $s", level: LogLevel.Error);
diff --git a/lib/utilities/prefs.dart b/lib/utilities/prefs.dart
index 5fcbfc64a..25388c6ff 100644
--- a/lib/utilities/prefs.dart
+++ b/lib/utilities/prefs.dart
@@ -4,6 +4,7 @@ import 'package:stackwallet/utilities/constants.dart';
import 'package:stackwallet/utilities/enums/backup_frequency_type.dart';
import 'package:stackwallet/utilities/enums/languages_enum.dart';
import 'package:stackwallet/utilities/enums/sync_type_enum.dart';
+import 'package:stackwallet/utilities/theme/color_theme.dart';
import 'package:uuid/uuid.dart';
class Prefs extends ChangeNotifier {
@@ -41,6 +42,10 @@ class Prefs extends ChangeNotifier {
_userId = await _getUserId();
_signupEpoch = await _getSignupEpoch();
_enableCoinControl = await _getEnableCoinControl();
+ _enableSystemBrightness = await _getEnableSystemBrightness();
+ _theme = await _getTheme();
+ _systemBrightnessLightTheme = await _getSystemBrightnessLightTheme();
+ _systemBrightnessDarkTheme = await _getSystemBrightnessDarkTheme();
_initialized = true;
}
@@ -669,4 +674,96 @@ class Prefs extends ChangeNotifier {
boxName: DB.boxNamePrefs, key: "enableCoinControl") as bool? ??
false;
}
+
+ // follow system brightness
+
+ bool _enableSystemBrightness = false;
+
+ bool get enableSystemBrightness => _enableSystemBrightness;
+
+ set enableSystemBrightness(bool enableSystemBrightness) {
+ if (_enableSystemBrightness != enableSystemBrightness) {
+ DB.instance.put(
+ boxName: DB.boxNamePrefs,
+ key: "enableSystemBrightness",
+ value: enableSystemBrightness);
+ _enableSystemBrightness = enableSystemBrightness;
+ notifyListeners();
+ }
+ }
+
+ Future _getEnableSystemBrightness() async {
+ return await DB.instance.get(
+ boxName: DB.boxNamePrefs, key: "enableSystemBrightness") as bool? ??
+ false;
+ }
+
+ // system brightness light theme name
+
+ ThemeType _theme = ThemeType.light;
+
+ ThemeType get theme => _theme;
+
+ set theme(ThemeType theme) {
+ if (this.theme != theme) {
+ DB.instance.put(
+ boxName: DB.boxNamePrefs, key: "theme", value: theme.name);
+ _theme = theme;
+ notifyListeners();
+ }
+ }
+
+ Future _getTheme() async {
+ return ThemeTypeExt.fromName(await DB.instance
+ .get(boxName: DB.boxNamePrefs, key: "theme") as String? ??
+ ThemeType.light.name);
+ }
+
+ // system brightness light theme name
+
+ ThemeType _systemBrightnessLightTheme = ThemeType.light;
+
+ ThemeType get systemBrightnessLightTheme => _systemBrightnessLightTheme;
+
+ set systemBrightnessLightTheme(ThemeType systemBrightnessLightTheme) {
+ if (this.systemBrightnessLightTheme != systemBrightnessLightTheme) {
+ DB.instance.put(
+ boxName: DB.boxNamePrefs,
+ key: "systemBrightnessLightTheme",
+ value: systemBrightnessLightTheme.name);
+ _systemBrightnessLightTheme = systemBrightnessLightTheme;
+ notifyListeners();
+ }
+ }
+
+ Future _getSystemBrightnessLightTheme() async {
+ return ThemeTypeExt.fromName(await DB.instance.get(
+ boxName: DB.boxNamePrefs,
+ key: "systemBrightnessLightTheme") as String? ??
+ ThemeType.light.name);
+ }
+
+ // system brightness dark theme name
+
+ ThemeType _systemBrightnessDarkTheme = ThemeType.dark;
+
+ ThemeType get systemBrightnessDarkTheme => _systemBrightnessDarkTheme;
+
+ set systemBrightnessDarkTheme(ThemeType systemBrightnessDarkTheme) {
+ if (this.systemBrightnessDarkTheme != systemBrightnessDarkTheme) {
+ DB.instance.put(
+ boxName: DB.boxNamePrefs,
+ key: "systemBrightnessDarkTheme",
+ value: systemBrightnessDarkTheme.name);
+ _systemBrightnessDarkTheme = systemBrightnessDarkTheme;
+ notifyListeners();
+ }
+ }
+
+ Future _getSystemBrightnessDarkTheme() async {
+ return ThemeTypeExt.fromName(await DB.instance.get(
+ boxName: DB.boxNamePrefs,
+ key: "systemBrightnessDarkTheme") as String? ??
+ ThemeType.dark.name);
+ }
}
diff --git a/lib/utilities/theme/color_theme.dart b/lib/utilities/theme/color_theme.dart
index f04a81932..fb7306de2 100644
--- a/lib/utilities/theme/color_theme.dart
+++ b/lib/utilities/theme/color_theme.dart
@@ -6,6 +6,7 @@ import 'package:stackwallet/utilities/theme/fruit_sorbet_colors.dart';
import 'package:stackwallet/utilities/theme/light_colors.dart';
import 'package:stackwallet/utilities/theme/ocean_breeze_colors.dart';
import 'package:stackwallet/utilities/theme/oled_black_colors.dart';
+import 'package:stackwallet/utilities/theme/oled_chans_colors.dart';
import 'chan_colors.dart';
@@ -16,12 +17,36 @@ enum ThemeType {
oledBlack,
fruitSorbet,
forest,
- chan;
+ chan,
+ darkChans;
}
// adjust this file
extension ThemeTypeExt on ThemeType {
+ static ThemeType fromName(String name) {
+ switch (name) {
+ case "light":
+ return ThemeType.light;
+ case "chan":
+ return ThemeType.chan;
+ case "dark":
+ return ThemeType.dark;
+ case "oceanBreeze":
+ return ThemeType.oceanBreeze;
+ case "oledBlack":
+ return ThemeType.oledBlack;
+ case "fruitSorbet":
+ return ThemeType.fruitSorbet;
+ case "forest":
+ return ThemeType.forest;
+ case "darkChans":
+ return ThemeType.darkChans;
+ default:
+ throw ArgumentError("Invalid theme name");
+ }
+ }
+
StackColorTheme get colorTheme {
switch (this) {
case ThemeType.light:
@@ -38,6 +63,8 @@ extension ThemeTypeExt on ThemeType {
return FruitSorbetColors();
case ThemeType.forest:
return ForestColors();
+ case ThemeType.darkChans:
+ return DarkChansColors();
}
}
@@ -57,6 +84,8 @@ extension ThemeTypeExt on ThemeType {
return "Fruit Sorbet";
case ThemeType.forest:
return "Forest";
+ case ThemeType.darkChans:
+ return "Dark Chans";
}
}
}
diff --git a/lib/utilities/theme/oled_black_colors.dart b/lib/utilities/theme/oled_black_colors.dart
index 71d4b2361..4f273eeff 100644
--- a/lib/utilities/theme/oled_black_colors.dart
+++ b/lib/utilities/theme/oled_black_colors.dart
@@ -326,7 +326,7 @@ class OledBlackColors extends StackColorTheme {
Color get textConfirmTotalAmount =>
textFieldSuccessLabel; //const Color(0xFF144D35);
@override
- Color get textSelectedWordTableItem => const Color(0xFF143D8E);
+ Color get textSelectedWordTableItem => const Color(0xFFF26822);
//rate type toggle
@override
diff --git a/lib/utilities/theme/oled_chans_colors.dart b/lib/utilities/theme/oled_chans_colors.dart
new file mode 100644
index 000000000..83600d5d5
--- /dev/null
+++ b/lib/utilities/theme/oled_chans_colors.dart
@@ -0,0 +1,351 @@
+import 'package:flutter/material.dart';
+import 'package:stackwallet/utilities/theme/color_theme.dart';
+
+class DarkChansColors extends StackColorTheme {
+ @override
+ ThemeType get themeType => ThemeType.darkChans;
+ @override
+ Brightness get brightness => Brightness.dark;
+
+ @override
+ Color get background => const Color(0xFF2A2D34);
+ @override
+ Color get backgroundAppBar => background;
+ @override
+ Gradient? get gradientBackground => null;
+
+ @override
+ Color get overlay => const Color(0xFF111215);
+
+ @override
+ Color get accentColorBlue => const Color(0xFF4C86E9);
+ @override
+ Color get accentColorGreen => const Color(0xFF4CC0A0);
+ @override
+ Color get accentColorYellow => const Color(0xFFF7D65D);
+ @override
+ Color get accentColorRed => const Color(0xFFD34E50);
+ @override
+ Color get accentColorOrange => const Color(0xFFFEA68D);
+ @override
+ Color get accentColorDark => const Color(0xFFF3F3F3);
+
+ @override
+ Color get shadow => const Color(0x0F2D3132);
+
+ @override
+ Color get textDark => const Color(0xFFF3F3F3);
+ @override
+ Color get textDark2 => const Color(0xFFDBDBDB);
+ @override
+ Color get textDark3 => const Color(0xFFEEEFF1);
+ @override
+ Color get textSubtitle1 => const Color(0xFF9E9E9E);
+ @override
+ Color get textSubtitle2 => const Color(0xFF969696);
+ @override
+ Color get textSubtitle3 => const Color(0xFFA9ACAC);
+ @override
+ Color get textSubtitle4 => const Color(0xFF8E9192);
+ @override
+ Color get textSubtitle5 => const Color(0xFF747778);
+ @override
+ Color get textSubtitle6 => const Color(0xFF414141);
+ @override
+ Color get textWhite => const Color(0xFF232323);
+ @override
+ Color get textFavoriteCard => const Color(0xFF232323);
+ @override
+ Color get textError => const Color(0xFFF37475);
+ @override
+ Color get textRestore => overlay;
+
+ // button background
+ @override
+ Color get buttonBackPrimary => const Color(0xFF4C86E9);
+ @override
+ Color get buttonBackSecondary => const Color(0xFF444E5C);
+ @override
+ Color get buttonBackPrimaryDisabled => const Color(0xFF38517C);
+ @override
+ Color get buttonBackSecondaryDisabled => const Color(0xFF3B3F46);
+ @override
+ Color get buttonBackBorder => const Color(0xFF4C86E9);
+ @override
+ Color get buttonBackBorderDisabled => const Color(0xFF314265);
+ @override
+ Color get buttonBackBorderSecondary => buttonBackSecondary;
+ @override
+ Color get buttonBackBorderSecondaryDisabled => buttonBackSecondaryDisabled;
+
+ @override
+ Color get numberBackDefault => const Color(0xFF484B51);
+ @override
+ Color get numpadBackDefault => const Color(0xFF4C86E9);
+ @override
+ Color get bottomNavBack => const Color(0xFF3E4148);
+
+ // button text/element
+ @override
+ Color get buttonTextPrimary => const Color(0xFFFFFFFF);
+ @override
+ Color get buttonTextSecondary => const Color(0xFFFFFFFF);
+ @override
+ Color get buttonTextPrimaryDisabled => const Color(0xFFFFFFFF);
+ @override
+ Color get buttonTextSecondaryDisabled => const Color(0xFF6A6C71);
+ @override
+ Color get buttonTextBorder => const Color(0xFF4C86E9);
+ @override
+ Color get buttonTextDisabled => const Color(0xFF314265);
+ @override
+ Color get buttonTextBorderless => const Color(0xFF4C86E9);
+ @override
+ Color get buttonTextBorderlessDisabled => const Color(0xFFB6B6B6);
+ @override
+ Color get numberTextDefault => const Color(0xFFFFFFFF);
+ @override
+ Color get numpadTextDefault => const Color(0xFFFFFFFF);
+ @override
+ Color get bottomNavText => const Color(0xFFFFFFFF);
+ @override
+ Color get customTextButtonEnabledText => buttonTextBorderless;
+ @override
+ Color get customTextButtonDisabledText => textSubtitle1;
+
+ // switch
+ @override
+ Color get switchBGOn => const Color(0xFF4C86E9);
+ @override
+ Color get switchBGOff => const Color(0xFFC1D9FF);
+ @override
+ Color get switchBGDisabled => const Color(0xFFB5B7BA);
+ @override
+ Color get switchCircleOn => const Color(0xFFC9DDFF);
+ @override
+ Color get switchCircleOff => const Color(0xFFFFFFFF);
+ @override
+ Color get switchCircleDisabled => const Color(0xFFFFFFFF);
+
+ // step indicator background
+ @override
+ Color get stepIndicatorBGCheck => const Color(0xFF4C86E9);
+ @override
+ Color get stepIndicatorBGNumber => const Color(0xFF4C86E9);
+ @override
+ Color get stepIndicatorBGInactive => const Color(0xFF3B3F46);
+ @override
+ Color get stepIndicatorBGLines => const Color(0xFF4C86E9);
+ @override
+ Color get stepIndicatorBGLinesInactive => const Color(0xFF3B3F46);
+ @override
+ Color get stepIndicatorIconText => const Color(0xFFFFFFFF);
+ @override
+ Color get stepIndicatorIconNumber => const Color(0xFFFFFFFF);
+ @override
+ Color get stepIndicatorIconInactive => const Color(0xFF747474);
+
+ // checkbox
+ @override
+ Color get checkboxBGChecked => const Color(0xFF4C86E9);
+ @override
+ Color get checkboxBorderEmpty => const Color(0xFF8E9192);
+ @override
+ Color get checkboxBGDisabled => const Color(0xFFADC7EC);
+ @override
+ Color get checkboxIconChecked => const Color(0xFFFFFFFF);
+ @override
+ Color get checkboxIconDisabled => const Color(0xFFFFFFFF);
+ @override
+ Color get checkboxTextLabel => const Color(0xFFFFFFFF);
+
+ // snack bar
+ @override
+ Color get snackBarBackSuccess => const Color(0xFF8EF5C3);
+ @override
+ Color get snackBarBackError => const Color(0xFFFFB4A9);
+ @override
+ Color get snackBarBackInfo => const Color(0xFFB4C4FF);
+ @override
+ Color get snackBarTextSuccess => const Color(0xFF003921);
+ @override
+ Color get snackBarTextError => const Color(0xFF690001);
+ @override
+ Color get snackBarTextInfo => const Color(0xFF00297A);
+
+ // icons
+ @override
+ Color get bottomNavIconBack => const Color(0xFF7F8185);
+ @override
+ Color get bottomNavIconIcon => const Color(0xFFFFFFFF);
+
+ @override
+ Color get topNavIconPrimary => const Color(0xFFFFFFFF);
+ @override
+ Color get topNavIconGreen => const Color(0xFF4CC0A0);
+ @override
+ Color get topNavIconYellow => const Color(0xFFF7D65D);
+ @override
+ Color get topNavIconRed => const Color(0xFFD34E50);
+
+ @override
+ Color get settingsIconBack => const Color(0xFFE0E3E3);
+ @override
+ Color get settingsIconIcon => const Color(0xFF232323);
+ @override
+ Color get settingsIconBack2 => const Color(0xFF94D6C4);
+ @override
+ Color get settingsIconElement => const Color(0xFF00A578);
+
+ // text field
+ @override
+ Color get textFieldActiveBG => const Color(0xFF4C5360);
+ @override
+ Color get textFieldDefaultBG => const Color(0xFF444953);
+ @override
+ Color get textFieldErrorBG => const Color(0xFFFFB4A9);
+ @override
+ Color get textFieldSuccessBG => const Color(0xFF8EF5C3);
+ @override
+ Color get textFieldErrorBorder => textFieldErrorBG;
+ @override
+ Color get textFieldSuccessBorder => textFieldSuccessBG;
+
+ @override
+ Color get textFieldActiveSearchIconLeft => const Color(0xFFA9ACAC);
+ @override
+ Color get textFieldDefaultSearchIconLeft => const Color(0xFFA9ACAC);
+ @override
+ Color get textFieldErrorSearchIconLeft => const Color(0xFF690001);
+ @override
+ Color get textFieldSuccessSearchIconLeft => const Color(0xFF003921);
+
+ @override
+ Color get textFieldActiveText => const Color(0xFFFFFFFF);
+ @override
+ Color get textFieldDefaultText => const Color(0xFFA9ACAC);
+ @override
+ Color get textFieldErrorText => const Color(0xFF000000);
+ @override
+ Color get textFieldSuccessText => const Color(0xFF000000);
+
+ @override
+ Color get textFieldActiveLabel => const Color(0xFFA9ACAC);
+ @override
+ Color get textFieldErrorLabel => const Color(0xFF690001);
+ @override
+ Color get textFieldSuccessLabel => const Color(0xFF003921);
+
+ @override
+ Color get textFieldActiveSearchIconRight => const Color(0xFFC4C7C7);
+ @override
+ Color get textFieldDefaultSearchIconRight => const Color(0xFF747778);
+ @override
+ Color get textFieldErrorSearchIconRight => const Color(0xFF690001);
+ @override
+ Color get textFieldSuccessSearchIconRight => const Color(0xFF003921);
+
+ // settings item level2
+ @override
+ Color get settingsItem2ActiveBG => const Color(0xFF484B51);
+ @override
+ Color get settingsItem2ActiveText => const Color(0xFFFFFFFF);
+ @override
+ Color get settingsItem2ActiveSub => const Color(0xFF9E9E9E);
+
+ // radio buttons
+ @override
+ Color get radioButtonIconBorder => const Color(0xFF4C86E9);
+ @override
+ Color get radioButtonIconBorderDisabled => const Color(0xFF9E9E9E);
+ @override
+ Color get radioButtonBorderEnabled => const Color(0xFF4C86E9);
+ @override
+ Color get radioButtonBorderDisabled => const Color(0xFFCDCDCD);
+ @override
+ Color get radioButtonIconCircle => const Color(0xFF9E9E9E);
+ @override
+ Color get radioButtonIconEnabled => const Color(0xFF4C86E9);
+ @override
+ Color get radioButtonTextEnabled => const Color(0xFF44464E);
+ @override
+ Color get radioButtonTextDisabled => const Color(0xFF44464E);
+ @override
+ Color get radioButtonLabelEnabled => const Color(0xFF8E9192);
+ @override
+ Color get radioButtonLabelDisabled => const Color(0xFF8E9192);
+
+ // info text
+ @override
+ Color get infoItemBG => const Color(0xFF333942);
+ @override
+ Color get infoItemLabel => const Color(0xFF9E9E9E);
+ @override
+ Color get infoItemText => const Color(0xFFFFFFFF);
+ @override
+ Color get infoItemIcons => const Color(0xFF4C86E9);
+
+ // popup
+ @override
+ Color get popupBG => const Color(0xFF333942);
+
+ // currency list
+ @override
+ Color get currencyListItemBG => const Color(0xFF484B51);
+
+ // bottom nav
+ @override
+ Color get stackWalletBG => const Color(0xFF35383D);
+ @override
+ Color get stackWalletMid => const Color(0xFF292D34);
+ @override
+ Color get stackWalletBottom => const Color(0xFFFFFFFF);
+ @override
+ Color get bottomNavShadow => const Color(0xFF282E33);
+
+ @override
+ Color get favoriteStarActive => accentColorYellow;
+ @override
+ Color get favoriteStarInactive => textSubtitle2;
+
+ @override
+ Color get splash => const Color(0x358E9192);
+ @override
+ Color get highlight => const Color(0x44A9ACAC);
+ @override
+ Color get warningForeground => snackBarTextError;
+ @override
+ Color get warningBackground => const Color(0xFFFFB4A9);
+ @override
+ Color get loadingOverlayTextColor => const Color(0xFFF7F7F7);
+ @override
+ Color get myStackContactIconBG => const Color(0x88747778);
+ @override
+ Color get textConfirmTotalAmount => const Color(0xFF003921);
+ @override
+ Color get textSelectedWordTableItem => const Color(0xFF00297A);
+
+ //rate type toggle
+ @override
+ Color get rateTypeToggleColorOn => textFieldDefaultBG;
+ @override
+ Color get rateTypeToggleColorOff => popupBG;
+ @override
+ Color get rateTypeToggleDesktopColorOn => textFieldDefaultBG;
+ @override
+ Color get rateTypeToggleDesktopColorOff => buttonBackSecondary;
+
+ @override
+ BoxShadow get standardBoxShadow => BoxShadow(
+ color: shadow,
+ spreadRadius: 3,
+ blurRadius: 4,
+ );
+
+ @override
+ BoxShadow? get homeViewButtonBarBoxShadow => BoxShadow(
+ color: shadow,
+ spreadRadius: 3,
+ blurRadius: 4,
+ );
+}
diff --git a/lib/widgets/custom_buttons/simple_edit_button.dart b/lib/widgets/custom_buttons/simple_edit_button.dart
index 931de7aa4..3bebeb4d0 100644
--- a/lib/widgets/custom_buttons/simple_edit_button.dart
+++ b/lib/widgets/custom_buttons/simple_edit_button.dart
@@ -13,14 +13,23 @@ import '../icon_widgets/pencil_icon.dart';
class SimpleEditButton extends StatelessWidget {
const SimpleEditButton({
Key? key,
- required this.editValue,
- required this.editLabel,
- required this.onValueChanged,
- }) : super(key: key);
+ this.editValue,
+ this.editLabel,
+ this.onValueChanged,
+ this.onPressedOverride,
+ }) : assert(
+ (editLabel != null && editValue != null && onValueChanged != null) ||
+ (editLabel == null &&
+ editValue == null &&
+ onValueChanged == null &&
+ onPressedOverride != null),
+ ),
+ super(key: key);
- final String editValue;
- final String editLabel;
- final void Function(String) onValueChanged;
+ final String? editValue;
+ final String? editLabel;
+ final void Function(String)? onValueChanged;
+ final VoidCallback? onPressedOverride;
@override
Widget build(BuildContext context) {
@@ -36,24 +45,25 @@ class SimpleEditButton extends StatelessWidget {
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(6),
),
- onPressed: () async {
- final result = await showDialog(
- context: context,
- builder: (context) {
- return DesktopDialog(
- maxWidth: 580,
- maxHeight: 360,
- child: SingleFieldEditView(
- initialValue: editValue,
- label: editLabel,
- ),
+ onPressed: onPressedOverride ??
+ () async {
+ final result = await showDialog(
+ context: context,
+ builder: (context) {
+ return DesktopDialog(
+ maxWidth: 580,
+ maxHeight: 360,
+ child: SingleFieldEditView(
+ initialValue: editValue!,
+ label: editLabel!,
+ ),
+ );
+ },
);
+ if (result is String && result != editValue!) {
+ onValueChanged?.call(result);
+ }
},
- );
- if (result is String && result != editValue) {
- onValueChanged(result);
- }
- },
child: Padding(
padding: const EdgeInsets.all(5),
child: PencilIcon(
@@ -66,18 +76,19 @@ class SimpleEditButton extends StatelessWidget {
);
} else {
return GestureDetector(
- onTap: () async {
- final result = await Navigator.of(context).pushNamed(
- SingleFieldEditView.routeName,
- arguments: Tuple2(
- editValue,
- editLabel,
- ),
- );
- if (result is String && result != editValue) {
- onValueChanged(result);
- }
- },
+ onTap: onPressedOverride ??
+ () async {
+ final result = await Navigator.of(context).pushNamed(
+ SingleFieldEditView.routeName,
+ arguments: Tuple2(
+ editValue!,
+ editLabel!,
+ ),
+ );
+ if (result is String && result != editValue!) {
+ onValueChanged?.call(result);
+ }
+ },
child: Row(
children: [
SvgPicture.asset(
diff --git a/lib/widgets/rounded_white_container.dart b/lib/widgets/rounded_white_container.dart
index 2ade9b729..8208d69ca 100644
--- a/lib/widgets/rounded_white_container.dart
+++ b/lib/widgets/rounded_white_container.dart
@@ -12,6 +12,7 @@ class RoundedWhiteContainer extends StatelessWidget {
this.height,
this.borderColor,
this.boxShadow,
+ this.onPressed,
}) : super(key: key);
final Widget? child;
@@ -21,6 +22,7 @@ class RoundedWhiteContainer extends StatelessWidget {
final double? height;
final Color? borderColor;
final List? boxShadow;
+ final VoidCallback? onPressed;
@override
Widget build(BuildContext context) {
@@ -32,6 +34,7 @@ class RoundedWhiteContainer extends StatelessWidget {
height: height,
borderColor: borderColor,
boxShadow: boxShadow,
+ onPressed: onPressed,
child: child,
);
}
diff --git a/pubspec.yaml b/pubspec.yaml
index 44a19578b..4d1213b83 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -336,6 +336,7 @@ flutter:
- assets/svg/fruit-sorbet-theme.svg
- assets/svg/forest-theme.svg
- assets/svg/chanstheme.svg
+ - assets/svg/darkChansTheme.svg
# light theme specific
- assets/svg/themed/light/
@@ -363,6 +364,9 @@ flutter:
# basic
- assets/lottie/test2.json
+ # gifs
+ - assets/gif/
+
# coin gifs
- assets/gif/coins/bitcoin/
- assets/gif/coins/bitcoincash/
diff --git a/test/cached_electrumx_test.mocks.dart b/test/cached_electrumx_test.mocks.dart
index ca8544cc4..6f96a5875 100644
--- a/test/cached_electrumx_test.mocks.dart
+++ b/test/cached_electrumx_test.mocks.dart
@@ -4,7 +4,7 @@
// ignore_for_file: no_leading_underscores_for_library_prefixes
import 'dart:async' as _i4;
-import 'dart:ui' as _i8;
+import 'dart:ui' as _i9;
import 'package:decimal/decimal.dart' as _i2;
import 'package:mockito/mockito.dart' as _i1;
@@ -12,6 +12,7 @@ import 'package:stackwallet/electrumx_rpc/electrumx.dart' as _i3;
import 'package:stackwallet/utilities/enums/backup_frequency_type.dart' as _i7;
import 'package:stackwallet/utilities/enums/sync_type_enum.dart' as _i6;
import 'package:stackwallet/utilities/prefs.dart' as _i5;
+import 'package:stackwallet/utilities/theme/color_theme.dart' as _i8;
// ignore_for_file: type=lint
// ignore_for_file: avoid_redundant_argument_values
@@ -665,6 +666,61 @@ class MockPrefs extends _i1.Mock implements _i5.Prefs {
returnValueForMissingStub: null,
);
@override
+ bool get enableSystemBrightness => (super.noSuchMethod(
+ Invocation.getter(#enableSystemBrightness),
+ returnValue: false,
+ ) as bool);
+ @override
+ set enableSystemBrightness(bool? enableSystemBrightness) =>
+ super.noSuchMethod(
+ Invocation.setter(
+ #enableSystemBrightness,
+ enableSystemBrightness,
+ ),
+ returnValueForMissingStub: null,
+ );
+ @override
+ _i8.ThemeType get theme => (super.noSuchMethod(
+ Invocation.getter(#theme),
+ returnValue: _i8.ThemeType.light,
+ ) as _i8.ThemeType);
+ @override
+ set theme(_i8.ThemeType? theme) => super.noSuchMethod(
+ Invocation.setter(
+ #theme,
+ theme,
+ ),
+ returnValueForMissingStub: null,
+ );
+ @override
+ _i8.ThemeType get systemBrightnessLightTheme => (super.noSuchMethod(
+ Invocation.getter(#systemBrightnessLightTheme),
+ returnValue: _i8.ThemeType.light,
+ ) as _i8.ThemeType);
+ @override
+ set systemBrightnessLightTheme(_i8.ThemeType? systemBrightnessLightTheme) =>
+ super.noSuchMethod(
+ Invocation.setter(
+ #systemBrightnessLightTheme,
+ systemBrightnessLightTheme,
+ ),
+ returnValueForMissingStub: null,
+ );
+ @override
+ _i8.ThemeType get systemBrightnessDarkTheme => (super.noSuchMethod(
+ Invocation.getter(#systemBrightnessDarkTheme),
+ returnValue: _i8.ThemeType.light,
+ ) as _i8.ThemeType);
+ @override
+ set systemBrightnessDarkTheme(_i8.ThemeType? systemBrightnessDarkTheme) =>
+ super.noSuchMethod(
+ Invocation.setter(
+ #systemBrightnessDarkTheme,
+ systemBrightnessDarkTheme,
+ ),
+ returnValueForMissingStub: null,
+ );
+ @override
bool get hasListeners => (super.noSuchMethod(
Invocation.getter(#hasListeners),
returnValue: false,
@@ -714,7 +770,7 @@ class MockPrefs extends _i1.Mock implements _i5.Prefs {
returnValueForMissingStub: _i4.Future.value(),
) as _i4.Future);
@override
- void addListener(_i8.VoidCallback? listener) => super.noSuchMethod(
+ void addListener(_i9.VoidCallback? listener) => super.noSuchMethod(
Invocation.method(
#addListener,
[listener],
@@ -722,7 +778,7 @@ class MockPrefs extends _i1.Mock implements _i5.Prefs {
returnValueForMissingStub: null,
);
@override
- void removeListener(_i8.VoidCallback? listener) => super.noSuchMethod(
+ void removeListener(_i9.VoidCallback? listener) => super.noSuchMethod(
Invocation.method(
#removeListener,
[listener],
diff --git a/test/electrumx_test.mocks.dart b/test/electrumx_test.mocks.dart
index b7147a3b8..e18e0aedf 100644
--- a/test/electrumx_test.mocks.dart
+++ b/test/electrumx_test.mocks.dart
@@ -4,13 +4,14 @@
// ignore_for_file: no_leading_underscores_for_library_prefixes
import 'dart:async' as _i3;
-import 'dart:ui' as _i7;
+import 'dart:ui' as _i8;
import 'package:mockito/mockito.dart' as _i1;
import 'package:stackwallet/electrumx_rpc/rpc.dart' as _i2;
import 'package:stackwallet/utilities/enums/backup_frequency_type.dart' as _i6;
import 'package:stackwallet/utilities/enums/sync_type_enum.dart' as _i5;
import 'package:stackwallet/utilities/prefs.dart' as _i4;
+import 'package:stackwallet/utilities/theme/color_theme.dart' as _i7;
// ignore_for_file: type=lint
// ignore_for_file: avoid_redundant_argument_values
@@ -386,6 +387,61 @@ class MockPrefs extends _i1.Mock implements _i4.Prefs {
returnValueForMissingStub: null,
);
@override
+ bool get enableSystemBrightness => (super.noSuchMethod(
+ Invocation.getter(#enableSystemBrightness),
+ returnValue: false,
+ ) as bool);
+ @override
+ set enableSystemBrightness(bool? enableSystemBrightness) =>
+ super.noSuchMethod(
+ Invocation.setter(
+ #enableSystemBrightness,
+ enableSystemBrightness,
+ ),
+ returnValueForMissingStub: null,
+ );
+ @override
+ _i7.ThemeType get theme => (super.noSuchMethod(
+ Invocation.getter(#theme),
+ returnValue: _i7.ThemeType.light,
+ ) as _i7.ThemeType);
+ @override
+ set theme(_i7.ThemeType? theme) => super.noSuchMethod(
+ Invocation.setter(
+ #theme,
+ theme,
+ ),
+ returnValueForMissingStub: null,
+ );
+ @override
+ _i7.ThemeType get systemBrightnessLightTheme => (super.noSuchMethod(
+ Invocation.getter(#systemBrightnessLightTheme),
+ returnValue: _i7.ThemeType.light,
+ ) as _i7.ThemeType);
+ @override
+ set systemBrightnessLightTheme(_i7.ThemeType? systemBrightnessLightTheme) =>
+ super.noSuchMethod(
+ Invocation.setter(
+ #systemBrightnessLightTheme,
+ systemBrightnessLightTheme,
+ ),
+ returnValueForMissingStub: null,
+ );
+ @override
+ _i7.ThemeType get systemBrightnessDarkTheme => (super.noSuchMethod(
+ Invocation.getter(#systemBrightnessDarkTheme),
+ returnValue: _i7.ThemeType.light,
+ ) as _i7.ThemeType);
+ @override
+ set systemBrightnessDarkTheme(_i7.ThemeType? systemBrightnessDarkTheme) =>
+ super.noSuchMethod(
+ Invocation.setter(
+ #systemBrightnessDarkTheme,
+ systemBrightnessDarkTheme,
+ ),
+ returnValueForMissingStub: null,
+ );
+ @override
bool get hasListeners => (super.noSuchMethod(
Invocation.getter(#hasListeners),
returnValue: false,
@@ -435,7 +491,7 @@ class MockPrefs extends _i1.Mock implements _i4.Prefs {
returnValueForMissingStub: _i3.Future.value(),
) as _i3.Future);
@override
- void addListener(_i7.VoidCallback? listener) => super.noSuchMethod(
+ void addListener(_i8.VoidCallback? listener) => super.noSuchMethod(
Invocation.method(
#addListener,
[listener],
@@ -443,7 +499,7 @@ class MockPrefs extends _i1.Mock implements _i4.Prefs {
returnValueForMissingStub: null,
);
@override
- void removeListener(_i7.VoidCallback? listener) => super.noSuchMethod(
+ void removeListener(_i8.VoidCallback? listener) => super.noSuchMethod(
Invocation.method(
#removeListener,
[listener],
diff --git a/test/pages/send_view/send_view_test.mocks.dart b/test/pages/send_view/send_view_test.mocks.dart
index 47b651143..149d690b1 100644
--- a/test/pages/send_view/send_view_test.mocks.dart
+++ b/test/pages/send_view/send_view_test.mocks.dart
@@ -37,6 +37,7 @@ import 'package:stackwallet/utilities/enums/sync_type_enum.dart' as _i31;
import 'package:stackwallet/utilities/flutter_secure_storage_interface.dart'
as _i7;
import 'package:stackwallet/utilities/prefs.dart' as _i23;
+import 'package:stackwallet/utilities/theme/color_theme.dart' as _i33;
import 'package:tuple/tuple.dart' as _i15;
// ignore_for_file: type=lint
@@ -2547,6 +2548,61 @@ class MockPrefs extends _i1.Mock implements _i23.Prefs {
returnValueForMissingStub: null,
);
@override
+ bool get enableSystemBrightness => (super.noSuchMethod(
+ Invocation.getter(#enableSystemBrightness),
+ returnValue: false,
+ ) as bool);
+ @override
+ set enableSystemBrightness(bool? enableSystemBrightness) =>
+ super.noSuchMethod(
+ Invocation.setter(
+ #enableSystemBrightness,
+ enableSystemBrightness,
+ ),
+ returnValueForMissingStub: null,
+ );
+ @override
+ _i33.ThemeType get theme => (super.noSuchMethod(
+ Invocation.getter(#theme),
+ returnValue: _i33.ThemeType.light,
+ ) as _i33.ThemeType);
+ @override
+ set theme(_i33.ThemeType? theme) => super.noSuchMethod(
+ Invocation.setter(
+ #theme,
+ theme,
+ ),
+ returnValueForMissingStub: null,
+ );
+ @override
+ _i33.ThemeType get systemBrightnessLightTheme => (super.noSuchMethod(
+ Invocation.getter(#systemBrightnessLightTheme),
+ returnValue: _i33.ThemeType.light,
+ ) as _i33.ThemeType);
+ @override
+ set systemBrightnessLightTheme(_i33.ThemeType? systemBrightnessLightTheme) =>
+ super.noSuchMethod(
+ Invocation.setter(
+ #systemBrightnessLightTheme,
+ systemBrightnessLightTheme,
+ ),
+ returnValueForMissingStub: null,
+ );
+ @override
+ _i33.ThemeType get systemBrightnessDarkTheme => (super.noSuchMethod(
+ Invocation.getter(#systemBrightnessDarkTheme),
+ returnValue: _i33.ThemeType.light,
+ ) as _i33.ThemeType);
+ @override
+ set systemBrightnessDarkTheme(_i33.ThemeType? systemBrightnessDarkTheme) =>
+ super.noSuchMethod(
+ Invocation.setter(
+ #systemBrightnessDarkTheme,
+ systemBrightnessDarkTheme,
+ ),
+ returnValueForMissingStub: null,
+ );
+ @override
bool get hasListeners => (super.noSuchMethod(
Invocation.getter(#hasListeners),
returnValue: false,
@@ -2781,6 +2837,11 @@ class MockManager extends _i1.Mock implements _i6.Manager {
returnValue: false,
) as bool);
@override
+ bool get hasWhirlpoolSupport => (super.noSuchMethod(
+ Invocation.getter(#hasWhirlpoolSupport),
+ returnValue: false,
+ ) as bool);
+ @override
int get rescanOnOpenVersion => (super.noSuchMethod(
Invocation.getter(#rescanOnOpenVersion),
returnValue: 0,
diff --git a/test/screen_tests/address_book_view/subviews/add_address_book_view_screen_test.mocks.dart b/test/screen_tests/address_book_view/subviews/add_address_book_view_screen_test.mocks.dart
index 010eb83a3..a36548d2d 100644
--- a/test/screen_tests/address_book_view/subviews/add_address_book_view_screen_test.mocks.dart
+++ b/test/screen_tests/address_book_view/subviews/add_address_book_view_screen_test.mocks.dart
@@ -378,6 +378,11 @@ class MockManager extends _i1.Mock implements _i11.Manager {
returnValue: false,
) as bool);
@override
+ bool get hasWhirlpoolSupport => (super.noSuchMethod(
+ Invocation.getter(#hasWhirlpoolSupport),
+ returnValue: false,
+ ) as bool);
+ @override
int get rescanOnOpenVersion => (super.noSuchMethod(
Invocation.getter(#rescanOnOpenVersion),
returnValue: 0,
diff --git a/test/screen_tests/address_book_view/subviews/address_book_entry_details_view_screen_test.mocks.dart b/test/screen_tests/address_book_view/subviews/address_book_entry_details_view_screen_test.mocks.dart
index addfaf6ee..b78f3f23e 100644
--- a/test/screen_tests/address_book_view/subviews/address_book_entry_details_view_screen_test.mocks.dart
+++ b/test/screen_tests/address_book_view/subviews/address_book_entry_details_view_screen_test.mocks.dart
@@ -339,6 +339,11 @@ class MockManager extends _i1.Mock implements _i9.Manager {
returnValue: false,
) as bool);
@override
+ bool get hasWhirlpoolSupport => (super.noSuchMethod(
+ Invocation.getter(#hasWhirlpoolSupport),
+ returnValue: false,
+ ) as bool);
+ @override
int get rescanOnOpenVersion => (super.noSuchMethod(
Invocation.getter(#rescanOnOpenVersion),
returnValue: 0,
diff --git a/test/screen_tests/address_book_view/subviews/edit_address_book_entry_view_screen_test.mocks.dart b/test/screen_tests/address_book_view/subviews/edit_address_book_entry_view_screen_test.mocks.dart
index ed28d7edc..68697c039 100644
--- a/test/screen_tests/address_book_view/subviews/edit_address_book_entry_view_screen_test.mocks.dart
+++ b/test/screen_tests/address_book_view/subviews/edit_address_book_entry_view_screen_test.mocks.dart
@@ -337,6 +337,11 @@ class MockManager extends _i1.Mock implements _i9.Manager {
returnValue: false,
) as bool);
@override
+ bool get hasWhirlpoolSupport => (super.noSuchMethod(
+ Invocation.getter(#hasWhirlpoolSupport),
+ returnValue: false,
+ ) as bool);
+ @override
int get rescanOnOpenVersion => (super.noSuchMethod(
Invocation.getter(#rescanOnOpenVersion),
returnValue: 0,
diff --git a/test/screen_tests/exchange/exchange_view_test.mocks.dart b/test/screen_tests/exchange/exchange_view_test.mocks.dart
index 079c2ead2..d926e9e5b 100644
--- a/test/screen_tests/exchange/exchange_view_test.mocks.dart
+++ b/test/screen_tests/exchange/exchange_view_test.mocks.dart
@@ -3,35 +3,37 @@
// Do not manually edit this file.
// ignore_for_file: no_leading_underscores_for_library_prefixes
-import 'dart:async' as _i6;
-import 'dart:ui' as _i7;
+import 'dart:async' as _i7;
+import 'dart:ui' as _i8;
-import 'package:decimal/decimal.dart' as _i14;
-import 'package:http/http.dart' as _i12;
+import 'package:decimal/decimal.dart' as _i15;
+import 'package:http/http.dart' as _i13;
import 'package:mockito/mockito.dart' as _i1;
import 'package:stackwallet/models/exchange/change_now/cn_exchange_estimate.dart'
- as _i17;
-import 'package:stackwallet/models/exchange/change_now/exchange_transaction.dart'
- as _i19;
-import 'package:stackwallet/models/exchange/change_now/exchange_transaction_status.dart'
- as _i20;
-import 'package:stackwallet/models/exchange/response_objects/estimate.dart'
- as _i16;
-import 'package:stackwallet/models/exchange/response_objects/fixed_rate_market.dart'
as _i18;
+import 'package:stackwallet/models/exchange/change_now/exchange_transaction.dart'
+ as _i20;
+import 'package:stackwallet/models/exchange/change_now/exchange_transaction_status.dart'
+ as _i21;
+import 'package:stackwallet/models/exchange/response_objects/estimate.dart'
+ as _i17;
+import 'package:stackwallet/models/exchange/response_objects/fixed_rate_market.dart'
+ as _i19;
import 'package:stackwallet/models/exchange/response_objects/range.dart'
- as _i15;
-import 'package:stackwallet/models/exchange/response_objects/trade.dart' as _i9;
-import 'package:stackwallet/models/isar/exchange_cache/currency.dart' as _i13;
-import 'package:stackwallet/models/isar/exchange_cache/pair.dart' as _i21;
+ as _i16;
+import 'package:stackwallet/models/exchange/response_objects/trade.dart'
+ as _i10;
+import 'package:stackwallet/models/isar/exchange_cache/currency.dart' as _i14;
+import 'package:stackwallet/models/isar/exchange_cache/pair.dart' as _i22;
import 'package:stackwallet/services/exchange/change_now/change_now_api.dart'
- as _i11;
+ as _i12;
import 'package:stackwallet/services/exchange/exchange_response.dart' as _i2;
-import 'package:stackwallet/services/trade_notes_service.dart' as _i10;
-import 'package:stackwallet/services/trade_service.dart' as _i8;
+import 'package:stackwallet/services/trade_notes_service.dart' as _i11;
+import 'package:stackwallet/services/trade_service.dart' as _i9;
import 'package:stackwallet/utilities/enums/backup_frequency_type.dart' as _i5;
import 'package:stackwallet/utilities/enums/sync_type_enum.dart' as _i4;
import 'package:stackwallet/utilities/prefs.dart' as _i3;
+import 'package:stackwallet/utilities/theme/color_theme.dart' as _i6;
// ignore_for_file: type=lint
// ignore_for_file: avoid_redundant_argument_values
@@ -335,56 +337,111 @@ class MockPrefs extends _i1.Mock implements _i3.Prefs {
returnValueForMissingStub: null,
);
@override
+ bool get enableSystemBrightness => (super.noSuchMethod(
+ Invocation.getter(#enableSystemBrightness),
+ returnValue: false,
+ ) as bool);
+ @override
+ set enableSystemBrightness(bool? enableSystemBrightness) =>
+ super.noSuchMethod(
+ Invocation.setter(
+ #enableSystemBrightness,
+ enableSystemBrightness,
+ ),
+ returnValueForMissingStub: null,
+ );
+ @override
+ _i6.ThemeType get theme => (super.noSuchMethod(
+ Invocation.getter(#theme),
+ returnValue: _i6.ThemeType.light,
+ ) as _i6.ThemeType);
+ @override
+ set theme(_i6.ThemeType? theme) => super.noSuchMethod(
+ Invocation.setter(
+ #theme,
+ theme,
+ ),
+ returnValueForMissingStub: null,
+ );
+ @override
+ _i6.ThemeType get systemBrightnessLightTheme => (super.noSuchMethod(
+ Invocation.getter(#systemBrightnessLightTheme),
+ returnValue: _i6.ThemeType.light,
+ ) as _i6.ThemeType);
+ @override
+ set systemBrightnessLightTheme(_i6.ThemeType? systemBrightnessLightTheme) =>
+ super.noSuchMethod(
+ Invocation.setter(
+ #systemBrightnessLightTheme,
+ systemBrightnessLightTheme,
+ ),
+ returnValueForMissingStub: null,
+ );
+ @override
+ _i6.ThemeType get systemBrightnessDarkTheme => (super.noSuchMethod(
+ Invocation.getter(#systemBrightnessDarkTheme),
+ returnValue: _i6.ThemeType.light,
+ ) as _i6.ThemeType);
+ @override
+ set systemBrightnessDarkTheme(_i6.ThemeType? systemBrightnessDarkTheme) =>
+ super.noSuchMethod(
+ Invocation.setter(
+ #systemBrightnessDarkTheme,
+ systemBrightnessDarkTheme,
+ ),
+ returnValueForMissingStub: null,
+ );
+ @override
bool get hasListeners => (super.noSuchMethod(
Invocation.getter(#hasListeners),
returnValue: false,
) as bool);
@override
- _i6.Future init() => (super.noSuchMethod(
+ _i7.Future init() => (super.noSuchMethod(
Invocation.method(
#init,
[],
),
- returnValue: _i6.Future.value(),
- returnValueForMissingStub: _i6.Future.value(),
- ) as _i6.Future);
+ returnValue: _i7.Future.value(),
+ returnValueForMissingStub: _i7.Future.value(),
+ ) as _i7.Future);
@override
- _i6.Future incrementCurrentNotificationIndex() => (super.noSuchMethod(
+ _i7.Future incrementCurrentNotificationIndex() => (super.noSuchMethod(
Invocation.method(
#incrementCurrentNotificationIndex,
[],
),
- returnValue: _i6.Future.value(),
- returnValueForMissingStub: _i6.Future.value(),
- ) as _i6.Future);
+ returnValue: _i7.Future.value(),
+ returnValueForMissingStub: _i7.Future.value(),
+ ) as _i7.Future);
@override
- _i6.Future isExternalCallsSet() => (super.noSuchMethod(
+ _i7.Future isExternalCallsSet() => (super.noSuchMethod(
Invocation.method(
#isExternalCallsSet,
[],
),
- returnValue: _i6.Future.value(false),
- ) as _i6.Future);
+ returnValue: _i7.Future.value(false),
+ ) as _i7.Future);
@override
- _i6.Future saveUserID(String? userId) => (super.noSuchMethod(
+ _i7.Future saveUserID(String? userId) => (super.noSuchMethod(
Invocation.method(
#saveUserID,
[userId],
),
- returnValue: _i6.Future.value(),
- returnValueForMissingStub: _i6.Future.value(),
- ) as _i6.Future);
+ returnValue: _i7.Future.value(),
+ returnValueForMissingStub: _i7.Future.value(),
+ ) as _i7.Future);
@override
- _i6.Future saveSignupEpoch(int? signupEpoch) => (super.noSuchMethod(
+ _i7.Future saveSignupEpoch(int? signupEpoch) => (super.noSuchMethod(
Invocation.method(
#saveSignupEpoch,
[signupEpoch],
),
- returnValue: _i6.Future.value(),
- returnValueForMissingStub: _i6.Future.value(),
- ) as _i6.Future);
+ returnValue: _i7.Future.value(),
+ returnValueForMissingStub: _i7.Future.value(),
+ ) as _i7.Future);
@override
- void addListener(_i7.VoidCallback? listener) => super.noSuchMethod(
+ void addListener(_i8.VoidCallback? listener) => super.noSuchMethod(
Invocation.method(
#addListener,
[listener],
@@ -392,7 +449,7 @@ class MockPrefs extends _i1.Mock implements _i3.Prefs {
returnValueForMissingStub: null,
);
@override
- void removeListener(_i7.VoidCallback? listener) => super.noSuchMethod(
+ void removeListener(_i8.VoidCallback? listener) => super.noSuchMethod(
Invocation.method(
#removeListener,
[listener],
@@ -420,29 +477,29 @@ class MockPrefs extends _i1.Mock implements _i3.Prefs {
/// A class which mocks [TradesService].
///
/// See the documentation for Mockito's code generation for more information.
-class MockTradesService extends _i1.Mock implements _i8.TradesService {
+class MockTradesService extends _i1.Mock implements _i9.TradesService {
MockTradesService() {
_i1.throwOnMissingStub(this);
}
@override
- List<_i9.Trade> get trades => (super.noSuchMethod(
+ List<_i10.Trade> get trades => (super.noSuchMethod(
Invocation.getter(#trades),
- returnValue: <_i9.Trade>[],
- ) as List<_i9.Trade>);
+ returnValue: <_i10.Trade>[],
+ ) as List<_i10.Trade>);
@override
bool get hasListeners => (super.noSuchMethod(
Invocation.getter(#hasListeners),
returnValue: false,
) as bool);
@override
- _i9.Trade? get(String? tradeId) => (super.noSuchMethod(Invocation.method(
+ _i10.Trade? get(String? tradeId) => (super.noSuchMethod(Invocation.method(
#get,
[tradeId],
- )) as _i9.Trade?);
+ )) as _i10.Trade?);
@override
- _i6.Future add({
- required _i9.Trade? trade,
+ _i7.Future add({
+ required _i10.Trade? trade,
required bool? shouldNotifyListeners,
}) =>
(super.noSuchMethod(
@@ -454,12 +511,12 @@ class MockTradesService extends _i1.Mock implements _i8.TradesService {
#shouldNotifyListeners: shouldNotifyListeners,
},
),
- returnValue: _i6.Future.value(),
- returnValueForMissingStub: _i6.Future.value(),
- ) as _i6.Future);
+ returnValue: _i7.Future.value(),
+ returnValueForMissingStub: _i7.Future.value(),
+ ) as _i7.Future);
@override
- _i6.Future edit({
- required _i9.Trade? trade,
+ _i7.Future edit({
+ required _i10.Trade? trade,
required bool? shouldNotifyListeners,
}) =>
(super.noSuchMethod(
@@ -471,12 +528,12 @@ class MockTradesService extends _i1.Mock implements _i8.TradesService {
#shouldNotifyListeners: shouldNotifyListeners,
},
),
- returnValue: _i6.Future.value(),
- returnValueForMissingStub: _i6.Future.value(),
- ) as _i6.Future);
+ returnValue: _i7.Future.value(),
+ returnValueForMissingStub: _i7.Future.value(),
+ ) as _i7.Future);
@override
- _i6.Future delete({
- required _i9.Trade? trade,
+ _i7.Future delete({
+ required _i10.Trade? trade,
required bool? shouldNotifyListeners,
}) =>
(super.noSuchMethod(
@@ -488,11 +545,11 @@ class MockTradesService extends _i1.Mock implements _i8.TradesService {
#shouldNotifyListeners: shouldNotifyListeners,
},
),
- returnValue: _i6.Future.value(),
- returnValueForMissingStub: _i6.Future.value(),
- ) as _i6.Future);
+ returnValue: _i7.Future.value(),
+ returnValueForMissingStub: _i7.Future.value(),
+ ) as _i7.Future);
@override
- _i6.Future deleteByUuid({
+ _i7.Future deleteByUuid({
required String? uuid,
required bool? shouldNotifyListeners,
}) =>
@@ -505,11 +562,11 @@ class MockTradesService extends _i1.Mock implements _i8.TradesService {
#shouldNotifyListeners: shouldNotifyListeners,
},
),
- returnValue: _i6.Future.value(),
- returnValueForMissingStub: _i6.Future.value(),
- ) as _i6.Future);
+ returnValue: _i7.Future.value(),
+ returnValueForMissingStub: _i7.Future.value(),
+ ) as _i7.Future);
@override
- void addListener(_i7.VoidCallback? listener) => super.noSuchMethod(
+ void addListener(_i8.VoidCallback? listener) => super.noSuchMethod(
Invocation.method(
#addListener,
[listener],
@@ -517,7 +574,7 @@ class MockTradesService extends _i1.Mock implements _i8.TradesService {
returnValueForMissingStub: null,
);
@override
- void removeListener(_i7.VoidCallback? listener) => super.noSuchMethod(
+ void removeListener(_i8.VoidCallback? listener) => super.noSuchMethod(
Invocation.method(
#removeListener,
[listener],
@@ -545,7 +602,7 @@ class MockTradesService extends _i1.Mock implements _i8.TradesService {
/// A class which mocks [TradeNotesService].
///
/// See the documentation for Mockito's code generation for more information.
-class MockTradeNotesService extends _i1.Mock implements _i10.TradeNotesService {
+class MockTradeNotesService extends _i1.Mock implements _i11.TradeNotesService {
MockTradeNotesService() {
_i1.throwOnMissingStub(this);
}
@@ -570,7 +627,7 @@ class MockTradeNotesService extends _i1.Mock implements _i10.TradeNotesService {
returnValue: '',
) as String);
@override
- _i6.Future set({
+ _i7.Future set({
required String? tradeId,
required String? note,
}) =>
@@ -583,21 +640,21 @@ class MockTradeNotesService extends _i1.Mock implements _i10.TradeNotesService {
#note: note,
},
),
- returnValue: _i6.Future.value(),
- returnValueForMissingStub: _i6.Future.value(),
- ) as _i6.Future);
+ returnValue: _i7.Future.value(),
+ returnValueForMissingStub: _i7.Future.value(),
+ ) as _i7.Future);
@override
- _i6.Future delete({required String? tradeId}) => (super.noSuchMethod(
+ _i7.Future delete({required String? tradeId}) => (super.noSuchMethod(
Invocation.method(
#delete,
[],
{#tradeId: tradeId},
),
- returnValue: _i6.Future.value(),
- returnValueForMissingStub: _i6.Future.value(),
- ) as _i6.Future);
+ returnValue: _i7.Future.value(),
+ returnValueForMissingStub: _i7.Future.value(),
+ ) as _i7.Future);
@override
- void addListener(_i7.VoidCallback? listener) => super.noSuchMethod(
+ void addListener(_i8.VoidCallback? listener) => super.noSuchMethod(
Invocation.method(
#addListener,
[listener],
@@ -605,7 +662,7 @@ class MockTradeNotesService extends _i1.Mock implements _i10.TradeNotesService {
returnValueForMissingStub: null,
);
@override
- void removeListener(_i7.VoidCallback? listener) => super.noSuchMethod(
+ void removeListener(_i8.VoidCallback? listener) => super.noSuchMethod(
Invocation.method(
#removeListener,
[listener],
@@ -633,13 +690,13 @@ class MockTradeNotesService extends _i1.Mock implements _i10.TradeNotesService {
/// A class which mocks [ChangeNowAPI].
///
/// See the documentation for Mockito's code generation for more information.
-class MockChangeNowAPI extends _i1.Mock implements _i11.ChangeNowAPI {
+class MockChangeNowAPI extends _i1.Mock implements _i12.ChangeNowAPI {
MockChangeNowAPI() {
_i1.throwOnMissingStub(this);
}
@override
- set client(_i12.Client? _client) => super.noSuchMethod(
+ set client(_i13.Client? _client) => super.noSuchMethod(
Invocation.setter(
#client,
_client,
@@ -647,7 +704,7 @@ class MockChangeNowAPI extends _i1.Mock implements _i11.ChangeNowAPI {
returnValueForMissingStub: null,
);
@override
- _i6.Future<_i2.ExchangeResponse>> getAvailableCurrencies({
+ _i7.Future<_i2.ExchangeResponse>> getAvailableCurrencies({
bool? fixedRate,
bool? active,
}) =>
@@ -661,8 +718,8 @@ class MockChangeNowAPI extends _i1.Mock implements _i11.ChangeNowAPI {
},
),
returnValue:
- _i6.Future<_i2.ExchangeResponse>>.value(
- _FakeExchangeResponse_0>(
+ _i7.Future<_i2.ExchangeResponse>>.value(
+ _FakeExchangeResponse_0>(
this,
Invocation.method(
#getAvailableCurrencies,
@@ -673,9 +730,9 @@ class MockChangeNowAPI extends _i1.Mock implements _i11.ChangeNowAPI {
},
),
)),
- ) as _i6.Future<_i2.ExchangeResponse>>);
+ ) as _i7.Future<_i2.ExchangeResponse>>);
@override
- _i6.Future<_i2.ExchangeResponse>> getPairedCurrencies({
+ _i7.Future<_i2.ExchangeResponse>> getPairedCurrencies({
required String? ticker,
bool? fixedRate,
}) =>
@@ -689,8 +746,8 @@ class MockChangeNowAPI extends _i1.Mock implements _i11.ChangeNowAPI {
},
),
returnValue:
- _i6.Future<_i2.ExchangeResponse>>.value(
- _FakeExchangeResponse_0>(
+ _i7.Future<_i2.ExchangeResponse>>.value(
+ _FakeExchangeResponse_0>(
this,
Invocation.method(
#getPairedCurrencies,
@@ -701,9 +758,9 @@ class MockChangeNowAPI extends _i1.Mock implements _i11.ChangeNowAPI {
},
),
)),
- ) as _i6.Future<_i2.ExchangeResponse>>);
+ ) as _i7.Future<_i2.ExchangeResponse>>);
@override
- _i6.Future<_i2.ExchangeResponse<_i14.Decimal>> getMinimalExchangeAmount({
+ _i7.Future<_i2.ExchangeResponse<_i15.Decimal>> getMinimalExchangeAmount({
required String? fromTicker,
required String? toTicker,
String? apiKey,
@@ -718,8 +775,8 @@ class MockChangeNowAPI extends _i1.Mock implements _i11.ChangeNowAPI {
#apiKey: apiKey,
},
),
- returnValue: _i6.Future<_i2.ExchangeResponse<_i14.Decimal>>.value(
- _FakeExchangeResponse_0<_i14.Decimal>(
+ returnValue: _i7.Future<_i2.ExchangeResponse<_i15.Decimal>>.value(
+ _FakeExchangeResponse_0<_i15.Decimal>(
this,
Invocation.method(
#getMinimalExchangeAmount,
@@ -731,9 +788,9 @@ class MockChangeNowAPI extends _i1.Mock implements _i11.ChangeNowAPI {
},
),
)),
- ) as _i6.Future<_i2.ExchangeResponse<_i14.Decimal>>);
+ ) as _i7.Future<_i2.ExchangeResponse<_i15.Decimal>>);
@override
- _i6.Future<_i2.ExchangeResponse<_i15.Range>> getRange({
+ _i7.Future<_i2.ExchangeResponse<_i16.Range>> getRange({
required String? fromTicker,
required String? toTicker,
required bool? isFixedRate,
@@ -750,8 +807,8 @@ class MockChangeNowAPI extends _i1.Mock implements _i11.ChangeNowAPI {
#apiKey: apiKey,
},
),
- returnValue: _i6.Future<_i2.ExchangeResponse<_i15.Range>>.value(
- _FakeExchangeResponse_0<_i15.Range>(
+ returnValue: _i7.Future<_i2.ExchangeResponse<_i16.Range>>.value(
+ _FakeExchangeResponse_0<_i16.Range>(
this,
Invocation.method(
#getRange,
@@ -764,12 +821,12 @@ class MockChangeNowAPI extends _i1.Mock implements _i11.ChangeNowAPI {
},
),
)),
- ) as _i6.Future<_i2.ExchangeResponse<_i15.Range>>);
+ ) as _i7.Future<_i2.ExchangeResponse<_i16.Range>>);
@override
- _i6.Future<_i2.ExchangeResponse<_i16.Estimate>> getEstimatedExchangeAmount({
+ _i7.Future<_i2.ExchangeResponse<_i17.Estimate>> getEstimatedExchangeAmount({
required String? fromTicker,
required String? toTicker,
- required _i14.Decimal? fromAmount,
+ required _i15.Decimal? fromAmount,
String? apiKey,
}) =>
(super.noSuchMethod(
@@ -783,8 +840,8 @@ class MockChangeNowAPI extends _i1.Mock implements _i11.ChangeNowAPI {
#apiKey: apiKey,
},
),
- returnValue: _i6.Future<_i2.ExchangeResponse<_i16.Estimate>>.value(
- _FakeExchangeResponse_0<_i16.Estimate>(
+ returnValue: _i7.Future<_i2.ExchangeResponse<_i17.Estimate>>.value(
+ _FakeExchangeResponse_0<_i17.Estimate>(
this,
Invocation.method(
#getEstimatedExchangeAmount,
@@ -797,13 +854,13 @@ class MockChangeNowAPI extends _i1.Mock implements _i11.ChangeNowAPI {
},
),
)),
- ) as _i6.Future<_i2.ExchangeResponse<_i16.Estimate>>);
+ ) as _i7.Future<_i2.ExchangeResponse<_i17.Estimate>>);
@override
- _i6.Future<_i2.ExchangeResponse<_i16.Estimate>>
+ _i7.Future<_i2.ExchangeResponse<_i17.Estimate>>
getEstimatedExchangeAmountFixedRate({
required String? fromTicker,
required String? toTicker,
- required _i14.Decimal? fromAmount,
+ required _i15.Decimal? fromAmount,
required bool? reversed,
bool? useRateId = true,
String? apiKey,
@@ -821,8 +878,8 @@ class MockChangeNowAPI extends _i1.Mock implements _i11.ChangeNowAPI {
#apiKey: apiKey,
},
),
- returnValue: _i6.Future<_i2.ExchangeResponse<_i16.Estimate>>.value(
- _FakeExchangeResponse_0<_i16.Estimate>(
+ returnValue: _i7.Future<_i2.ExchangeResponse<_i17.Estimate>>.value(
+ _FakeExchangeResponse_0<_i17.Estimate>(
this,
Invocation.method(
#getEstimatedExchangeAmountFixedRate,
@@ -837,17 +894,17 @@ class MockChangeNowAPI extends _i1.Mock implements _i11.ChangeNowAPI {
},
),
)),
- ) as _i6.Future<_i2.ExchangeResponse<_i16.Estimate>>);
+ ) as _i7.Future<_i2.ExchangeResponse<_i17.Estimate>>);
@override
- _i6.Future<_i2.ExchangeResponse<_i17.CNExchangeEstimate>>
+ _i7.Future<_i2.ExchangeResponse<_i18.CNExchangeEstimate>>
getEstimatedExchangeAmountV2({
required String? fromTicker,
required String? toTicker,
- required _i17.CNEstimateType? fromOrTo,
- required _i14.Decimal? amount,
+ required _i18.CNEstimateType? fromOrTo,
+ required _i15.Decimal? amount,
String? fromNetwork,
String? toNetwork,
- _i17.CNFlowType? flow = _i17.CNFlowType.standard,
+ _i18.CNFlowType? flow = _i18.CNFlowType.standard,
String? apiKey,
}) =>
(super.noSuchMethod(
@@ -866,8 +923,8 @@ class MockChangeNowAPI extends _i1.Mock implements _i11.ChangeNowAPI {
},
),
returnValue:
- _i6.Future<_i2.ExchangeResponse<_i17.CNExchangeEstimate>>.value(
- _FakeExchangeResponse_0<_i17.CNExchangeEstimate>(
+ _i7.Future<_i2.ExchangeResponse<_i18.CNExchangeEstimate>>.value(
+ _FakeExchangeResponse_0<_i18.CNExchangeEstimate>(
this,
Invocation.method(
#getEstimatedExchangeAmountV2,
@@ -884,18 +941,18 @@ class MockChangeNowAPI extends _i1.Mock implements _i11.ChangeNowAPI {
},
),
)),
- ) as _i6.Future<_i2.ExchangeResponse<_i17.CNExchangeEstimate>>);
+ ) as _i7.Future<_i2.ExchangeResponse<_i18.CNExchangeEstimate>>);
@override
- _i6.Future<_i2.ExchangeResponse>>
+ _i7.Future<_i2.ExchangeResponse>>
getAvailableFixedRateMarkets({String? apiKey}) => (super.noSuchMethod(
Invocation.method(
#getAvailableFixedRateMarkets,
[],
{#apiKey: apiKey},
),
- returnValue: _i6.Future<
- _i2.ExchangeResponse