mirror of
https://github.com/cypherstack/stack_wallet.git
synced 2025-03-09 10:15:22 +00:00
commit
1dc002166f
10 changed files with 132 additions and 22 deletions
lib
pages
address_book_views/subviews
send_view
wallet_view/sub_widgets
services
utilities/theme
|
@ -16,6 +16,7 @@ import 'package:stackwallet/utilities/constants.dart';
|
||||||
import 'package:stackwallet/utilities/text_styles.dart';
|
import 'package:stackwallet/utilities/text_styles.dart';
|
||||||
import 'package:stackwallet/utilities/theme/stack_colors.dart';
|
import 'package:stackwallet/utilities/theme/stack_colors.dart';
|
||||||
import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
|
import 'package:stackwallet/widgets/custom_buttons/app_bar_icon_button.dart';
|
||||||
|
import 'package:stackwallet/widgets/custom_buttons/blue_text_button.dart';
|
||||||
import 'package:stackwallet/widgets/emoji_select_sheet.dart';
|
import 'package:stackwallet/widgets/emoji_select_sheet.dart';
|
||||||
import 'package:stackwallet/widgets/icon_widgets/x_icon.dart';
|
import 'package:stackwallet/widgets/icon_widgets/x_icon.dart';
|
||||||
import 'package:stackwallet/widgets/stack_text_field.dart';
|
import 'package:stackwallet/widgets/stack_text_field.dart';
|
||||||
|
@ -73,10 +74,23 @@ class _AddAddressBookEntryViewState
|
||||||
}
|
}
|
||||||
|
|
||||||
List<NewContactAddressEntryForm> forms = [];
|
List<NewContactAddressEntryForm> forms = [];
|
||||||
int _formCount = 0;
|
final Set<int> _formIds = {};
|
||||||
|
|
||||||
|
void _removeForm(int id) {
|
||||||
|
forms.retainWhere((e) => e.id != id);
|
||||||
|
_formIds.remove(id);
|
||||||
|
ref.refresh(addressEntryDataProvider(id));
|
||||||
|
setState(() {});
|
||||||
|
}
|
||||||
|
|
||||||
void _addForm() {
|
void _addForm() {
|
||||||
int id = ++_formCount;
|
int id = 0;
|
||||||
|
// ensure unique form id while allowing reuse of removed form ids
|
||||||
|
while (_formIds.contains(id)) {
|
||||||
|
id++;
|
||||||
|
}
|
||||||
|
_formIds.add(id);
|
||||||
|
|
||||||
forms.add(
|
forms.add(
|
||||||
NewContactAddressEntryForm(
|
NewContactAddressEntryForm(
|
||||||
key: Key("contactAddressEntryForm_$id"),
|
key: Key("contactAddressEntryForm_$id"),
|
||||||
|
@ -303,22 +317,34 @@ class _AddAddressBookEntryViewState
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (_formCount <= 1)
|
if (forms.length <= 1)
|
||||||
const SizedBox(
|
const SizedBox(
|
||||||
height: 8,
|
height: 8,
|
||||||
),
|
),
|
||||||
if (_formCount <= 1) forms[0],
|
if (forms.length <= 1) forms[0],
|
||||||
if (_formCount > 1)
|
if (forms.length > 1)
|
||||||
for (int i = 0; i < _formCount; i++)
|
for (int i = 0; i < forms.length; i++)
|
||||||
Column(
|
Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
const SizedBox(
|
const SizedBox(
|
||||||
height: 12,
|
height: 12,
|
||||||
),
|
),
|
||||||
Text(
|
Row(
|
||||||
"Address ${i + 1}",
|
mainAxisAlignment:
|
||||||
style: STextStyles.smallMed12(context),
|
MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
"Address ${i + 1}",
|
||||||
|
style: STextStyles.smallMed12(context),
|
||||||
|
),
|
||||||
|
BlueTextButton(
|
||||||
|
onTap: () {
|
||||||
|
_removeForm(forms[i].id);
|
||||||
|
},
|
||||||
|
text: "Remove",
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(
|
const SizedBox(
|
||||||
height: 8,
|
height: 8,
|
||||||
|
@ -329,7 +355,7 @@ class _AddAddressBookEntryViewState
|
||||||
const SizedBox(
|
const SizedBox(
|
||||||
height: 16,
|
height: 16,
|
||||||
),
|
),
|
||||||
GestureDetector(
|
BlueTextButton(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
_addForm();
|
_addForm();
|
||||||
scrollController.animateTo(
|
scrollController.animateTo(
|
||||||
|
@ -338,11 +364,15 @@ class _AddAddressBookEntryViewState
|
||||||
curve: Curves.easeInOut,
|
curve: Curves.easeInOut,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
child: Text(
|
text: "+ Add another address",
|
||||||
"+ Add another address",
|
|
||||||
style: STextStyles.largeMedium14(context),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
|
// GestureDetector(
|
||||||
|
//
|
||||||
|
// child: Text(
|
||||||
|
// "+ Add another address",
|
||||||
|
// style: STextStyles.largeMedium14(context),
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
const SizedBox(
|
const SizedBox(
|
||||||
height: 16,
|
height: 16,
|
||||||
),
|
),
|
||||||
|
@ -411,10 +441,12 @@ class _AddAddressBookEntryViewState
|
||||||
}
|
}
|
||||||
List<ContactAddressEntry> entries =
|
List<ContactAddressEntry> entries =
|
||||||
[];
|
[];
|
||||||
for (int i = 0; i < _formCount; i++) {
|
for (int i = 0;
|
||||||
|
i < forms.length;
|
||||||
|
i++) {
|
||||||
entries.add(ref
|
entries.add(ref
|
||||||
.read(addressEntryDataProvider(
|
.read(addressEntryDataProvider(
|
||||||
i + 1))
|
forms[i].id))
|
||||||
.buildAddressEntry());
|
.buildAddressEntry());
|
||||||
}
|
}
|
||||||
Contact contact = Contact(
|
Contact contact = Contact(
|
||||||
|
@ -438,7 +470,15 @@ class _AddAddressBookEntryViewState
|
||||||
: null,
|
: null,
|
||||||
child: Text(
|
child: Text(
|
||||||
"Save",
|
"Save",
|
||||||
style: STextStyles.button(context),
|
style: STextStyles.button(context).copyWith(
|
||||||
|
color: shouldEnableSave
|
||||||
|
? Theme.of(context)
|
||||||
|
.extension<StackColors>()!
|
||||||
|
.buttonTextPrimary
|
||||||
|
: Theme.of(context)
|
||||||
|
.extension<StackColors>()!
|
||||||
|
.buttonTextPrimaryDisabled,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
|
@ -144,6 +144,7 @@ class _ConfirmTransactionViewState
|
||||||
final managerProvider = ref.watch(walletsChangeNotifierProvider
|
final managerProvider = ref.watch(walletsChangeNotifierProvider
|
||||||
.select((value) => value.getManagerProvider(walletId)));
|
.select((value) => value.getManagerProvider(walletId)));
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
|
backgroundColor: Theme.of(context).extension<StackColors>()!.background,
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
backgroundColor: Theme.of(context).extension<StackColors>()!.background,
|
backgroundColor: Theme.of(context).extension<StackColors>()!.background,
|
||||||
leading: AppBarBackButton(
|
leading: AppBarBackButton(
|
||||||
|
@ -294,7 +295,12 @@ class _ConfirmTransactionViewState
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
"Total amount",
|
"Total amount",
|
||||||
style: STextStyles.titleBold12(context),
|
style:
|
||||||
|
STextStyles.titleBold12(context).copyWith(
|
||||||
|
color: Theme.of(context)
|
||||||
|
.extension<StackColors>()!
|
||||||
|
.textConfirmTotalAmount,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
"${Format.satoshiAmountToPrettyString(
|
"${Format.satoshiAmountToPrettyString(
|
||||||
|
@ -308,7 +314,12 @@ class _ConfirmTransactionViewState
|
||||||
managerProvider
|
managerProvider
|
||||||
.select((value) => value.coin),
|
.select((value) => value.coin),
|
||||||
).ticker}",
|
).ticker}",
|
||||||
style: STextStyles.itemSubtitle12(context),
|
style: STextStyles.itemSubtitle12(context)
|
||||||
|
.copyWith(
|
||||||
|
color: Theme.of(context)
|
||||||
|
.extension<StackColors>()!
|
||||||
|
.textConfirmTotalAmount,
|
||||||
|
),
|
||||||
textAlign: TextAlign.right,
|
textAlign: TextAlign.right,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|
|
@ -1060,6 +1060,11 @@ class _SendViewState extends ConsumerState<SendView> {
|
||||||
height: 8,
|
height: 8,
|
||||||
),
|
),
|
||||||
TextField(
|
TextField(
|
||||||
|
style: STextStyles.smallMed14(context).copyWith(
|
||||||
|
color: Theme.of(context)
|
||||||
|
.extension<StackColors>()!
|
||||||
|
.textDark,
|
||||||
|
),
|
||||||
key: const Key("amountInputFieldCryptoTextFieldKey"),
|
key: const Key("amountInputFieldCryptoTextFieldKey"),
|
||||||
controller: cryptoAmountController,
|
controller: cryptoAmountController,
|
||||||
focusNode: _cryptoFocus,
|
focusNode: _cryptoFocus,
|
||||||
|
@ -1106,6 +1111,11 @@ class _SendViewState extends ConsumerState<SendView> {
|
||||||
height: 8,
|
height: 8,
|
||||||
),
|
),
|
||||||
TextField(
|
TextField(
|
||||||
|
style: STextStyles.smallMed14(context).copyWith(
|
||||||
|
color: Theme.of(context)
|
||||||
|
.extension<StackColors>()!
|
||||||
|
.textDark,
|
||||||
|
),
|
||||||
key: const Key("amountInputFieldFiatTextFieldKey"),
|
key: const Key("amountInputFieldFiatTextFieldKey"),
|
||||||
controller: baseAmountController,
|
controller: baseAmountController,
|
||||||
focusNode: _baseFocus,
|
focusNode: _baseFocus,
|
||||||
|
|
|
@ -27,7 +27,7 @@ class WalletNavigationBar extends StatelessWidget {
|
||||||
return Container(
|
return Container(
|
||||||
height: height,
|
height: height,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: Theme.of(context).extension<StackColors>()!.popupBG,
|
color: Theme.of(context).extension<StackColors>()!.bottomNavBack,
|
||||||
boxShadow: [
|
boxShadow: [
|
||||||
Theme.of(context).extension<StackColors>()!.standardBoxShadow
|
Theme.of(context).extension<StackColors>()!.standardBoxShadow
|
||||||
],
|
],
|
||||||
|
|
|
@ -623,6 +623,7 @@ Future<dynamic> isolateCreateJoinSplitTransaction(
|
||||||
"value": amount,
|
"value": amount,
|
||||||
"fees": Format.satoshisToAmount(fee).toDouble(),
|
"fees": Format.satoshisToAmount(fee).toDouble(),
|
||||||
"fee": fee,
|
"fee": fee,
|
||||||
|
"vSize": extTx.virtualSize(),
|
||||||
"jmintValue": changeToMint,
|
"jmintValue": changeToMint,
|
||||||
"publicCoin": "jmintData.publicCoin",
|
"publicCoin": "jmintData.publicCoin",
|
||||||
"spendCoinIndexes": spendCoinIndexes,
|
"spendCoinIndexes": spendCoinIndexes,
|
||||||
|
@ -1142,6 +1143,17 @@ class FiroWallet extends CoinServiceAPI {
|
||||||
throw Exception("Error Creating Transaction!");
|
throw Exception("Error Creating Transaction!");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
final fee = txHexOrError["fee"] as int;
|
||||||
|
final vSize = txHexOrError["vSize"] as int;
|
||||||
|
|
||||||
|
Logging.instance.log("prepared fee: $fee", level: LogLevel.Info);
|
||||||
|
Logging.instance.log("prepared vSize: $vSize", level: LogLevel.Info);
|
||||||
|
|
||||||
|
// fee should never be less than vSize sanity check
|
||||||
|
if (fee < vSize) {
|
||||||
|
throw Exception(
|
||||||
|
"Error in fee calculation: Transaction fee cannot be less than vSize");
|
||||||
|
}
|
||||||
return txHexOrError as Map<String, dynamic>;
|
return txHexOrError as Map<String, dynamic>;
|
||||||
}
|
}
|
||||||
} catch (e, s) {
|
} catch (e, s) {
|
||||||
|
|
|
@ -294,6 +294,10 @@ class WalletsService extends ChangeNotifier {
|
||||||
key: "${walletId}_mnemonicHasBeenVerified") as bool?;
|
key: "${walletId}_mnemonicHasBeenVerified") as bool?;
|
||||||
|
|
||||||
if (isVerified == null) {
|
if (isVerified == null) {
|
||||||
|
Logging.instance.log(
|
||||||
|
"isMnemonicVerified(walletId: $walletId) returned null which should never happen!",
|
||||||
|
level: LogLevel.Error,
|
||||||
|
);
|
||||||
throw Exception(
|
throw Exception(
|
||||||
"isMnemonicVerified(walletId: $walletId) returned null which should never happen!");
|
"isMnemonicVerified(walletId: $walletId) returned null which should never happen!");
|
||||||
} else {
|
} else {
|
||||||
|
@ -307,9 +311,17 @@ class WalletsService extends ChangeNotifier {
|
||||||
key: "${walletId}_mnemonicHasBeenVerified") as bool?;
|
key: "${walletId}_mnemonicHasBeenVerified") as bool?;
|
||||||
|
|
||||||
if (isVerified == null) {
|
if (isVerified == null) {
|
||||||
|
Logging.instance.log(
|
||||||
|
"setMnemonicVerified(walletId: $walletId) tried running on non existent wallet!",
|
||||||
|
level: LogLevel.Error,
|
||||||
|
);
|
||||||
throw Exception(
|
throw Exception(
|
||||||
"setMnemonicVerified(walletId: $walletId) tried running on non existent wallet!");
|
"setMnemonicVerified(walletId: $walletId) tried running on non existent wallet!");
|
||||||
} else if (isVerified) {
|
} else if (isVerified) {
|
||||||
|
Logging.instance.log(
|
||||||
|
"setMnemonicVerified(walletId: $walletId) tried running on already verified wallet!",
|
||||||
|
level: LogLevel.Error,
|
||||||
|
);
|
||||||
throw Exception(
|
throw Exception(
|
||||||
"setMnemonicVerified(walletId: $walletId) tried running on already verified wallet!");
|
"setMnemonicVerified(walletId: $walletId) tried running on already verified wallet!");
|
||||||
} else {
|
} else {
|
||||||
|
@ -317,6 +329,10 @@ class WalletsService extends ChangeNotifier {
|
||||||
boxName: DB.boxNameAllWalletsData,
|
boxName: DB.boxNameAllWalletsData,
|
||||||
key: "${walletId}_mnemonicHasBeenVerified",
|
key: "${walletId}_mnemonicHasBeenVerified",
|
||||||
value: true);
|
value: true);
|
||||||
|
Logging.instance.log(
|
||||||
|
"setMnemonicVerified(walletId: $walletId) successful",
|
||||||
|
level: LogLevel.Error,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -331,6 +347,11 @@ class WalletsService extends ChangeNotifier {
|
||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Logging.instance.log(
|
||||||
|
"deleteWallet called with name=$name and id=$walletId",
|
||||||
|
level: LogLevel.Warning,
|
||||||
|
);
|
||||||
|
|
||||||
final shell = names.remove(walletId);
|
final shell = names.remove(walletId);
|
||||||
|
|
||||||
if (shell == null) {
|
if (shell == null) {
|
||||||
|
|
|
@ -173,6 +173,7 @@ abstract class StackColorTheme {
|
||||||
|
|
||||||
Color get loadingOverlayTextColor;
|
Color get loadingOverlayTextColor;
|
||||||
Color get myStackContactIconBG;
|
Color get myStackContactIconBG;
|
||||||
|
Color get textConfirmTotalAmount;
|
||||||
}
|
}
|
||||||
|
|
||||||
class CoinThemeColor {
|
class CoinThemeColor {
|
||||||
|
|
|
@ -70,7 +70,7 @@ class DarkColors extends StackColorTheme {
|
||||||
@override
|
@override
|
||||||
Color get numpadBackDefault => const Color(0xFF4C86E9);
|
Color get numpadBackDefault => const Color(0xFF4C86E9);
|
||||||
@override
|
@override
|
||||||
Color get bottomNavBack => const Color(0xFFA2A2A2);
|
Color get bottomNavBack => const Color(0xFF3E4148);
|
||||||
|
|
||||||
// button text/element
|
// button text/element
|
||||||
@override
|
@override
|
||||||
|
@ -299,4 +299,6 @@ class DarkColors extends StackColorTheme {
|
||||||
Color get loadingOverlayTextColor => const Color(0xFFF7F7F7);
|
Color get loadingOverlayTextColor => const Color(0xFFF7F7F7);
|
||||||
@override
|
@override
|
||||||
Color get myStackContactIconBG => const Color(0x88747778);
|
Color get myStackContactIconBG => const Color(0x88747778);
|
||||||
|
@override
|
||||||
|
Color get textConfirmTotalAmount => const Color(0xFF003921);
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,7 +70,7 @@ class LightColors extends StackColorTheme {
|
||||||
@override
|
@override
|
||||||
Color get numpadBackDefault => const Color(0xFF232323);
|
Color get numpadBackDefault => const Color(0xFF232323);
|
||||||
@override
|
@override
|
||||||
Color get bottomNavBack => const Color(0xFFA2A2A2);
|
Color get bottomNavBack => const Color(0xFFFFFFFF);
|
||||||
|
|
||||||
// button text/element
|
// button text/element
|
||||||
@override
|
@override
|
||||||
|
@ -299,4 +299,6 @@ class LightColors extends StackColorTheme {
|
||||||
Color get loadingOverlayTextColor => const Color(0xFFF7F7F7);
|
Color get loadingOverlayTextColor => const Color(0xFFF7F7F7);
|
||||||
@override
|
@override
|
||||||
Color get myStackContactIconBG => textFieldDefaultBG;
|
Color get myStackContactIconBG => textFieldDefaultBG;
|
||||||
|
@override
|
||||||
|
Color get textConfirmTotalAmount => const Color(0xFF232323);
|
||||||
}
|
}
|
||||||
|
|
|
@ -168,6 +168,7 @@ class StackColors extends ThemeExtension<StackColors> {
|
||||||
final Color warningBackground;
|
final Color warningBackground;
|
||||||
final Color loadingOverlayTextColor;
|
final Color loadingOverlayTextColor;
|
||||||
final Color myStackContactIconBG;
|
final Color myStackContactIconBG;
|
||||||
|
final Color textConfirmTotalAmount;
|
||||||
|
|
||||||
StackColors({
|
StackColors({
|
||||||
required this.themeType,
|
required this.themeType,
|
||||||
|
@ -298,6 +299,7 @@ class StackColors extends ThemeExtension<StackColors> {
|
||||||
required this.warningBackground,
|
required this.warningBackground,
|
||||||
required this.loadingOverlayTextColor,
|
required this.loadingOverlayTextColor,
|
||||||
required this.myStackContactIconBG,
|
required this.myStackContactIconBG,
|
||||||
|
required this.textConfirmTotalAmount,
|
||||||
});
|
});
|
||||||
|
|
||||||
factory StackColors.fromStackColorTheme(StackColorTheme colorTheme) {
|
factory StackColors.fromStackColorTheme(StackColorTheme colorTheme) {
|
||||||
|
@ -432,6 +434,7 @@ class StackColors extends ThemeExtension<StackColors> {
|
||||||
warningBackground: colorTheme.warningBackground,
|
warningBackground: colorTheme.warningBackground,
|
||||||
loadingOverlayTextColor: colorTheme.loadingOverlayTextColor,
|
loadingOverlayTextColor: colorTheme.loadingOverlayTextColor,
|
||||||
myStackContactIconBG: colorTheme.myStackContactIconBG,
|
myStackContactIconBG: colorTheme.myStackContactIconBG,
|
||||||
|
textConfirmTotalAmount: colorTheme.textConfirmTotalAmount,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -565,6 +568,7 @@ class StackColors extends ThemeExtension<StackColors> {
|
||||||
Color? warningBackground,
|
Color? warningBackground,
|
||||||
Color? loadingOverlayTextColor,
|
Color? loadingOverlayTextColor,
|
||||||
Color? myStackContactIconBG,
|
Color? myStackContactIconBG,
|
||||||
|
Color? textConfirmTotalAmount,
|
||||||
}) {
|
}) {
|
||||||
return StackColors(
|
return StackColors(
|
||||||
themeType: themeType ?? this.themeType,
|
themeType: themeType ?? this.themeType,
|
||||||
|
@ -730,6 +734,8 @@ class StackColors extends ThemeExtension<StackColors> {
|
||||||
loadingOverlayTextColor:
|
loadingOverlayTextColor:
|
||||||
loadingOverlayTextColor ?? this.loadingOverlayTextColor,
|
loadingOverlayTextColor ?? this.loadingOverlayTextColor,
|
||||||
myStackContactIconBG: myStackContactIconBG ?? this.myStackContactIconBG,
|
myStackContactIconBG: myStackContactIconBG ?? this.myStackContactIconBG,
|
||||||
|
textConfirmTotalAmount:
|
||||||
|
textConfirmTotalAmount ?? this.textConfirmTotalAmount,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1377,6 +1383,11 @@ class StackColors extends ThemeExtension<StackColors> {
|
||||||
other.myStackContactIconBG,
|
other.myStackContactIconBG,
|
||||||
t,
|
t,
|
||||||
)!,
|
)!,
|
||||||
|
textConfirmTotalAmount: Color.lerp(
|
||||||
|
textConfirmTotalAmount,
|
||||||
|
other.textConfirmTotalAmount,
|
||||||
|
t,
|
||||||
|
)!,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue