mirror of
https://github.com/cake-tech/cake_wallet.git
synced 2024-12-26 13:39:39 +00:00
Merge branch 'main' of https://github.com/cake-tech/cake_wallet into CW-328-Restore-wallet-from-QRCode-and-sweep-all-funds-in-a-new-wallet
This commit is contained in:
commit
d3915366a7
64 changed files with 776 additions and 685 deletions
22
README.md
22
README.md
|
@ -5,9 +5,10 @@
|
|||
## Links
|
||||
|
||||
* Website: https://cakewallet.com
|
||||
* App Store: https://cakewallet.com/ios
|
||||
* App Store (iOS / MacOS): https://cakewallet.com/ios
|
||||
* Google Play: https://cakewallet.com/gp
|
||||
* APK: https://github.com/cake-tech/cake_wallet/releases
|
||||
* Linux: https://github.com/cake-tech/cake_wallet/releases
|
||||
|
||||
## Features
|
||||
|
||||
|
@ -15,18 +16,22 @@
|
|||
|
||||
* Completely noncustodial. *Your keys, your coins.*
|
||||
* Built-in exchange for dozens of pairs
|
||||
* Buy cryptocurrency with credit/debit/bank
|
||||
* Easily pay cryptocurrency invoices with fixed rate exchanges
|
||||
* Buy cryptocurrency (BTC/LTC/XMR) with credit/debit/bank
|
||||
* Sell cryptocurrency by bank transfer
|
||||
* Purchase gift cards at a discount using only an email with [Cake Pay](https://cakepay.com), available in-app
|
||||
* Scan QR codes for easy cryptocurrency transfers
|
||||
* Create several wallets
|
||||
* Select your own custom nodes/servers
|
||||
* Address book
|
||||
* Backup to external location or iCloud
|
||||
* Send to OpenAlias, Unstoppable Domains, Yats, and FIO Crypto Handles
|
||||
* Set custom fee levels
|
||||
* Set desired network fee level
|
||||
* Store local transaction notes
|
||||
* Extremely simple user experience
|
||||
* Convenient exchange and sending templates for recurring payments
|
||||
* Create donation links and invoices in the receive screen
|
||||
* Robust privacy settings (eg: Tor-only connections)
|
||||
|
||||
### Monero Specific Features
|
||||
|
||||
|
@ -34,13 +39,13 @@
|
|||
* Full support for Monero subaddresses and accounts
|
||||
* Specify restore height for faster syncing
|
||||
* Specify multiple recipients for batch sending
|
||||
* Optionally set Monero nodes as trusted for faster syncing
|
||||
|
||||
### Bitcoin Specific Features
|
||||
|
||||
* Bitcoin coin control (specify specific outputs to spend)
|
||||
* Automatically generate new addresses
|
||||
* Specify multiple recipients for batch sending
|
||||
* Buy BTC with over a dozen fiat currencies
|
||||
* Sell BTC for USD
|
||||
|
||||
### Litecoin Specific Features
|
||||
|
@ -48,7 +53,6 @@
|
|||
* Litecoin coin control (specify specific outputs to spend)
|
||||
* Automatically generate new addresses
|
||||
* Specify multiple recipients for batch sending
|
||||
* Buy LTC with over a dozen fiat currencies
|
||||
|
||||
### Haven Specific Features
|
||||
|
||||
|
@ -63,7 +67,7 @@
|
|||
## Links
|
||||
|
||||
* Website: https://monero.com
|
||||
* App Store: https://apps.apple.com/app/id1601990386
|
||||
* App Store (iOS): https://apps.apple.com/app/id1601990386
|
||||
* Google Play: https://play.google.com/store/apps/details?id=com.monero.app
|
||||
* APK: https://github.com/cake-tech/cake_wallet/releases
|
||||
|
||||
|
@ -71,6 +75,8 @@
|
|||
|
||||
We have 24/7 free support. Please contact support@cakewallet.com
|
||||
|
||||
We have excellent user guides, which are also open-source and open for contributions: https://guides.cakewallet.com
|
||||
|
||||
# Build Instructions
|
||||
|
||||
More instructions to follow
|
||||
|
@ -136,3 +142,7 @@ The only parts to be translated, if needed, are the values m and s after the var
|
|||
3. Add the raw mapping underneath in `lib/entities/fiat_currency.dart` following the same format as the others.
|
||||
|
||||
4. Add a flag of the issuing country or organization to `assets/images/flags/XXXX.png`, replacing XXXX with the ISO 3166-1 alpha-3 code used above (eg: `usa.png`, `eur.png`). Do not add this if the flag with the same name already exists. The image must be 42x26 pixels with a 3 pixels of transparent margin on all 4 sides.
|
||||
|
||||
---
|
||||
|
||||
Copyright (C) 2018-2023 Cake Labs LLC
|
||||
|
|
|
@ -1 +1,3 @@
|
|||
Fix Restore from QR code
|
||||
Reliability fixes for PIN login, transaction appearance, keyboard inputs, and QR codes
|
||||
Show amount received by each Monero account in account overview
|
||||
Other bugfixes
|
|
@ -1,4 +1,3 @@
|
|||
Fix for QR codes
|
||||
Fix for creating sub-addresses
|
||||
Fix Add/Edit nodes
|
||||
Fix issues with text/amount fields
|
||||
Reliability fixes for PIN login, transaction appearance, keyboard inputs, and QR codes
|
||||
Show amount received by each Monero account in account overview
|
||||
Other bugfixes
|
|
@ -88,7 +88,7 @@ class ElectrumClient {
|
|||
unterminatedString = '';
|
||||
}
|
||||
} on TypeError catch (e) {
|
||||
if (!e.toString().contains('Map<String, Object>') || !e.toString().contains('Map<String, dynamic>')) {
|
||||
if (!e.toString().contains('Map<String, Object>') && !e.toString().contains('Map<String, dynamic>')) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -113,7 +113,7 @@ PODS:
|
|||
- OrderedSet (~> 5.0)
|
||||
- flutter_mailer (0.0.1):
|
||||
- Flutter
|
||||
- flutter_secure_storage (3.3.1):
|
||||
- flutter_secure_storage (6.0.0):
|
||||
- Flutter
|
||||
- in_app_review (0.2.0):
|
||||
- Flutter
|
||||
|
@ -264,19 +264,19 @@ SPEC CHECKSUMS:
|
|||
Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854
|
||||
flutter_inappwebview: bfd58618f49dc62f2676de690fc6dcda1d6c3721
|
||||
flutter_mailer: 2ef5a67087bc8c6c4cefd04a178bf1ae2c94cd83
|
||||
flutter_secure_storage: 7953c38a04c3fdbb00571bcd87d8e3b5ceb9daec
|
||||
flutter_secure_storage: 23fc622d89d073675f2eaa109381aefbcf5a49be
|
||||
in_app_review: 318597b3a06c22bb46dc454d56828c85f444f99d
|
||||
local_auth_ios: c6cf091ded637a88f24f86a8875d8b0f526e2605
|
||||
MTBBarcodeScanner: f453b33c4b7dfe545d8c6484ed744d55671788cb
|
||||
OrderedSet: aaeb196f7fef5a9edf55d89760da9176ad40b93c
|
||||
package_info: 873975fc26034f0b863a300ad47e7f1ac6c7ec62
|
||||
path_provider_foundation: c68054786f1b4f3343858c1e1d0caaded73f0be9
|
||||
path_provider_foundation: eaf5b3e458fc0e5fbb9940fb09980e853fe058b8
|
||||
permission_handler_apple: 44366e37eaf29454a1e7b1b7d736c2cceaeb17ce
|
||||
platform_device_id: 81b3e2993881f87d0c82ef151dc274df4869aef5
|
||||
Reachability: 33e18b67625424e47b6cde6d202dce689ad7af96
|
||||
SDWebImage: fd7e1a22f00303e058058278639bf6196ee431fe
|
||||
share_plus: 056a1e8ac890df3e33cb503afffaf1e9b4fbae68
|
||||
shared_preferences_foundation: 986fc17f3d3251412d18b0265f9c64113a8c2472
|
||||
shared_preferences_foundation: e2dae3258e06f44cc55f49d42024fd8dd03c590c
|
||||
SwiftProtobuf: afced68785854575756db965e9da52bbf3dc45e7
|
||||
SwiftyGif: 93a1cc87bf3a51916001cf8f3d63835fb64c819f
|
||||
uni_links: d97da20c7701486ba192624d99bffaaffcfc298a
|
||||
|
|
|
@ -52,16 +52,6 @@
|
|||
<string>bitcoin-wallet</string>
|
||||
</array>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>CFBundleTypeRole</key>
|
||||
<string>Editor</string>
|
||||
<key>CFBundleURLName</key>
|
||||
<string>bitcoin_wallet</string>
|
||||
<key>CFBundleURLSchemes</key>
|
||||
<array>
|
||||
<string>bitcoin_wallet</string>
|
||||
</array>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>CFBundleTypeRole</key>
|
||||
<string>Editor</string>
|
||||
|
@ -82,16 +72,6 @@
|
|||
<string>monero-wallet</string>
|
||||
</array>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>CFBundleTypeRole</key>
|
||||
<string>Editor</string>
|
||||
<key>CFBundleURLName</key>
|
||||
<string>monero_wallet</string>
|
||||
<key>CFBundleURLSchemes</key>
|
||||
<array>
|
||||
<string>monero_wallet</string>
|
||||
</array>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>CFBundleTypeRole</key>
|
||||
<string>Editor</string>
|
||||
|
@ -112,16 +92,6 @@
|
|||
<string>litecoin-wallet</string>
|
||||
</array>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>CFBundleTypeRole</key>
|
||||
<string>Viewer</string>
|
||||
<key>CFBundleURLName</key>
|
||||
<string>litecoin_wallet</string>
|
||||
<key>CFBundleURLSchemes</key>
|
||||
<array>
|
||||
<string>litecoin_wallet</string>
|
||||
</array>
|
||||
</dict>
|
||||
</array>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>$(CURRENT_PROJECT_VERSION)</string>
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import 'package:cake_wallet/.secrets.g.dart' as secrets;
|
||||
import 'package:cake_wallet/store/settings_store.dart';
|
||||
import 'package:cake_wallet/themes/theme_base.dart';
|
||||
import 'package:cw_core/crypto_currency.dart';
|
||||
import 'package:cw_core/wallet_base.dart';
|
||||
|
||||
class OnRamperBuyProvider {
|
||||
|
@ -13,7 +14,16 @@ class OnRamperBuyProvider {
|
|||
|
||||
static const _baseUrl = 'buy.onramper.com';
|
||||
|
||||
static String get _apiKey => secrets.onramperApiKey;
|
||||
String get _apiKey => secrets.onramperApiKey;
|
||||
|
||||
String get _normalizeCryptoCurrency {
|
||||
switch (_wallet.currency) {
|
||||
case CryptoCurrency.ltc:
|
||||
return "LTC_LITECOIN";
|
||||
default:
|
||||
return _wallet.currency.title;
|
||||
}
|
||||
}
|
||||
|
||||
Uri requestUrl() {
|
||||
String primaryColor,
|
||||
|
@ -53,7 +63,7 @@ class OnRamperBuyProvider {
|
|||
|
||||
return Uri.https(_baseUrl, '', <String, dynamic>{
|
||||
'apiKey': _apiKey,
|
||||
'defaultCrypto': _wallet.currency.title,
|
||||
'defaultCrypto': _normalizeCryptoCurrency,
|
||||
'defaultFiat': _settingsStore.fiatCurrency.title,
|
||||
'wallets': '${_wallet.currency.title}:${_wallet.walletAddresses.address}',
|
||||
'supportSell': "false",
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import 'package:flutter/foundation.dart';
|
||||
import 'package:bitcoin_flutter/bitcoin_flutter.dart' as bitcoin;
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/core/validator.dart';
|
||||
import 'package:cw_core/crypto_currency.dart';
|
||||
|
@ -7,6 +7,9 @@ class AddressValidator extends TextValidator {
|
|||
AddressValidator({required CryptoCurrency type})
|
||||
: super(
|
||||
errorMessage: S.current.error_text_address,
|
||||
useAdditionalValidation: type == CryptoCurrency.btc
|
||||
? bitcoin.Address.validateAddress
|
||||
: null,
|
||||
pattern: getPattern(type),
|
||||
length: getLength(type));
|
||||
|
||||
|
@ -18,8 +21,7 @@ class AddressValidator extends TextValidator {
|
|||
return '^[0-9a-zA-Z]{59}\$|^[0-9a-zA-Z]{92}\$|^[0-9a-zA-Z]{104}\$'
|
||||
'|^[0-9a-zA-Z]{105}\$|^addr1[0-9a-zA-Z]{98}\$';
|
||||
case CryptoCurrency.btc:
|
||||
return '^1[0-9a-zA-Z]{32}\$|^1[0-9a-zA-Z]{33}\$|^3[0-9a-zA-Z]{32}\$'
|
||||
'|^3[0-9a-zA-Z]{33}\$|^bc1[0-9a-zA-Z]{39}\$|^bc1[0-9a-zA-Z]{59}\$';
|
||||
return '^3[0-9a-zA-Z]{32}\$|^3[0-9a-zA-Z]{33}\$|^bc1[0-9a-zA-Z]{59}\$';
|
||||
case CryptoCurrency.nano:
|
||||
return '[0-9a-zA-Z_]';
|
||||
case CryptoCurrency.usdc:
|
||||
|
|
|
@ -210,6 +210,8 @@ class BackupService {
|
|||
final currentFiatCurrency = data[PreferencesKey.currentFiatCurrencyKey] as String?;
|
||||
final shouldSaveRecipientAddress = data[PreferencesKey.shouldSaveRecipientAddressKey] as bool?;
|
||||
final isAppSecure = data[PreferencesKey.isAppSecureKey] as bool?;
|
||||
final disableBuy = data[PreferencesKey.disableBuyKey] as bool?;
|
||||
final disableSell = data[PreferencesKey.disableSellKey] as bool?;
|
||||
final currentTransactionPriorityKeyLegacy = data[PreferencesKey.currentTransactionPriorityKeyLegacy] as int?;
|
||||
final allowBiometricalAuthentication = data[PreferencesKey.allowBiometricalAuthenticationKey] as bool?;
|
||||
final currentBitcoinElectrumSererId = data[PreferencesKey.currentBitcoinElectrumSererIdKey] as int?;
|
||||
|
@ -251,6 +253,16 @@ class BackupService {
|
|||
PreferencesKey.isAppSecureKey,
|
||||
isAppSecure);
|
||||
|
||||
if (disableBuy != null)
|
||||
await _sharedPreferences.setBool(
|
||||
PreferencesKey.disableBuyKey,
|
||||
disableBuy);
|
||||
|
||||
if (disableSell != null)
|
||||
await _sharedPreferences.setBool(
|
||||
PreferencesKey.disableSellKey,
|
||||
disableSell);
|
||||
|
||||
if (currentTransactionPriorityKeyLegacy != null)
|
||||
await _sharedPreferences.setInt(
|
||||
PreferencesKey.currentTransactionPriorityKeyLegacy,
|
||||
|
@ -421,6 +433,10 @@ class BackupService {
|
|||
_sharedPreferences.getString(PreferencesKey.currentFiatCurrencyKey),
|
||||
PreferencesKey.shouldSaveRecipientAddressKey: _sharedPreferences
|
||||
.getBool(PreferencesKey.shouldSaveRecipientAddressKey),
|
||||
PreferencesKey.disableBuyKey: _sharedPreferences
|
||||
.getBool(PreferencesKey.disableBuyKey),
|
||||
PreferencesKey.disableSellKey: _sharedPreferences
|
||||
.getBool(PreferencesKey.disableSellKey),
|
||||
PreferencesKey.isDarkThemeLegacy:
|
||||
_sharedPreferences.getBool(PreferencesKey.isDarkThemeLegacy),
|
||||
PreferencesKey.currentPinLength:
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
import 'package:flutter/foundation.dart';
|
||||
|
||||
abstract class Validator<T> {
|
||||
Validator({required this.errorMessage});
|
||||
Validator({required this.errorMessage, this.useAdditionalValidation});
|
||||
|
||||
final String errorMessage;
|
||||
final bool Function(T)? useAdditionalValidation;
|
||||
|
||||
bool isValid(T? value);
|
||||
|
||||
|
@ -11,14 +10,17 @@ abstract class Validator<T> {
|
|||
}
|
||||
|
||||
class TextValidator extends Validator<String> {
|
||||
TextValidator(
|
||||
{this.minLength,
|
||||
TextValidator({
|
||||
bool Function(String)? useAdditionalValidation,
|
||||
this.minLength,
|
||||
this.maxLength,
|
||||
this.pattern,
|
||||
String errorMessage = '',
|
||||
this.length,
|
||||
this.isAutovalidate = false})
|
||||
: super(errorMessage: errorMessage);
|
||||
this.isAutovalidate = false,
|
||||
}) : super(
|
||||
errorMessage: errorMessage,
|
||||
useAdditionalValidation: useAdditionalValidation);
|
||||
|
||||
final int? minLength;
|
||||
final int? maxLength;
|
||||
|
@ -32,11 +34,26 @@ class TextValidator extends Validator<String> {
|
|||
return isAutovalidate ? true : false;
|
||||
}
|
||||
|
||||
return value.length > (minLength ?? 0) &&
|
||||
(length?.contains(value.length) ?? true) &&
|
||||
((maxLength ?? 0) > 0 ? (value.length <= maxLength!) : true) &&
|
||||
(pattern != null ? match(value) : true);
|
||||
final greaterThanMinLength = value.length > (minLength ?? 0);
|
||||
if (!greaterThanMinLength) return false;
|
||||
|
||||
final lengthMatched = length?.contains(value.length) ?? true;
|
||||
if (!lengthMatched) return false;
|
||||
|
||||
final lowerThanMaxLength =
|
||||
(maxLength ?? 0) > 0 ? (value.length <= maxLength!) : true;
|
||||
if (!lowerThanMaxLength) return false;
|
||||
|
||||
if (pattern == null) return true;
|
||||
|
||||
final valueMatched = match(value);
|
||||
final valueValidated = useAdditionalValidation != null
|
||||
? useAdditionalValidation!(value) || valueMatched
|
||||
: valueMatched;
|
||||
|
||||
return valueValidated;
|
||||
}
|
||||
|
||||
bool match(String value) => pattern != null ? RegExp(pattern!).hasMatch(value) : false;
|
||||
bool match(String value) =>
|
||||
pattern != null ? RegExp(pattern!).hasMatch(value) : false;
|
||||
}
|
||||
|
|
|
@ -47,24 +47,24 @@ class MainActions {
|
|||
switch (walletType) {
|
||||
case WalletType.bitcoin:
|
||||
case WalletType.litecoin:
|
||||
if (viewModel.isEnabledBuyAction) {
|
||||
if (DeviceInfo.instance.isMobile) {
|
||||
Navigator.of(context).pushNamed(Routes.onramperPage);
|
||||
} else {
|
||||
final uri = getIt
|
||||
.get<OnRamperBuyProvider>()
|
||||
.requestUrl();
|
||||
final uri = getIt.get<OnRamperBuyProvider>().requestUrl();
|
||||
await launchUrl(uri);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case WalletType.monero:
|
||||
if (viewModel.isEnabledBuyAction) {
|
||||
if (DeviceInfo.instance.isMobile) {
|
||||
Navigator.of(context).pushNamed(Routes.payfuraPage);
|
||||
} else {
|
||||
final uri = getIt
|
||||
.get<PayfuraBuyProvider>()
|
||||
.requestUrl();
|
||||
final uri = getIt.get<PayfuraBuyProvider>().requestUrl();
|
||||
await launchUrl(uri);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
await showPopUp<void>(
|
||||
|
@ -118,12 +118,14 @@ class MainActions {
|
|||
|
||||
switch (walletType) {
|
||||
case WalletType.bitcoin:
|
||||
if (viewModel.isEnabledSellAction) {
|
||||
final moonPaySellProvider = MoonPaySellProvider();
|
||||
final uri = await moonPaySellProvider.requestUrl(
|
||||
currency: viewModel.wallet.currency,
|
||||
refundWalletAddress: viewModel.wallet.walletAddresses.address,
|
||||
);
|
||||
await launchUrl(uri);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
await showPopUp<void>(
|
||||
|
|
|
@ -10,6 +10,8 @@ class PreferencesKey {
|
|||
static const currentBalanceDisplayModeKey = 'current_balance_display_mode';
|
||||
static const shouldSaveRecipientAddressKey = 'save_recipient_address';
|
||||
static const isAppSecureKey = 'is_app_secure';
|
||||
static const disableBuyKey = 'disable_buy';
|
||||
static const disableSellKey = 'disable_sell';
|
||||
static const currentFiatApiModeKey = 'current_fiat_api_mode';
|
||||
static const allowBiometricalAuthenticationKey =
|
||||
'allow_biometrical_authentication';
|
||||
|
|
|
@ -169,6 +169,7 @@ Route<dynamic> createRoute(RouteSettings settings) {
|
|||
fullscreenDialog: true);
|
||||
} else if (isSingleCoin) {
|
||||
return MaterialPageRoute<void>(
|
||||
fullscreenDialog: true,
|
||||
builder: (_) => getIt.get<WalletRestorePage>(
|
||||
param1: availableWalletTypes.first
|
||||
));
|
||||
|
@ -188,6 +189,7 @@ Route<dynamic> createRoute(RouteSettings settings) {
|
|||
|
||||
case Routes.restoreWallet:
|
||||
return MaterialPageRoute<void>(
|
||||
fullscreenDialog: true,
|
||||
builder: (_) => getIt.get<WalletRestorePage>(
|
||||
param1: settings.arguments as WalletType));
|
||||
|
||||
|
@ -509,7 +511,9 @@ Route<dynamic> createRoute(RouteSettings settings) {
|
|||
|
||||
case Routes.anonPayInvoicePage:
|
||||
final args = settings.arguments as List;
|
||||
return CupertinoPageRoute<void>(builder: (_) => getIt.get<AnonPayInvoicePage>(param1: args));
|
||||
return CupertinoPageRoute<void>(
|
||||
fullscreenDialog: true,
|
||||
builder: (_) => getIt.get<AnonPayInvoicePage>(param1: args));
|
||||
|
||||
case Routes.anonPayReceivePage:
|
||||
final anonInvoiceViewData = settings.arguments as AnonpayInfoBase;
|
||||
|
|
|
@ -1,13 +1,11 @@
|
|||
import 'package:cake_wallet/core/validator.dart';
|
||||
import 'package:cake_wallet/core/address_validator.dart';
|
||||
import 'package:cake_wallet/palette.dart';
|
||||
import 'package:cake_wallet/utils/show_pop_up.dart';
|
||||
import 'package:cw_core/currency.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter_mobx/flutter_mobx.dart';
|
||||
import 'package:mobx/mobx.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/core/address_validator.dart';
|
||||
import 'package:cake_wallet/core/contact_name_validator.dart';
|
||||
import 'package:cake_wallet/core/execution_state.dart';
|
||||
import 'package:cake_wallet/view_model/contact_list/contact_view_model.dart';
|
||||
|
@ -33,8 +31,8 @@ class ContactPage extends BasePage {
|
|||
_addressController
|
||||
.addListener(() => contactViewModel.address = _addressController.text);
|
||||
|
||||
autorun((_) =>
|
||||
_currencyTypeController.text = contactViewModel.currency?.toString()??'');
|
||||
autorun((_) => _currencyTypeController.text =
|
||||
contactViewModel.currency?.toString() ?? '');
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -61,7 +59,8 @@ class ContactPage extends BasePage {
|
|||
}
|
||||
});
|
||||
|
||||
return ScrollableWithBottomSection(
|
||||
return Observer(
|
||||
builder: (_) => ScrollableWithBottomSection(
|
||||
contentPadding: EdgeInsets.all(24),
|
||||
content: Form(
|
||||
key: _formKey,
|
||||
|
@ -90,22 +89,25 @@ class ContactPage extends BasePage {
|
|||
),
|
||||
),
|
||||
),
|
||||
if (contactViewModel.currency != null)
|
||||
Padding(
|
||||
padding: EdgeInsets.only(top: 20),
|
||||
child: Observer(
|
||||
builder: (_) => AddressTextField(
|
||||
child: AddressTextField(
|
||||
controller: _addressController,
|
||||
options: [
|
||||
AddressTextFieldOption.paste,
|
||||
AddressTextFieldOption.qrCode,
|
||||
],
|
||||
buttonColor: Theme.of(context).accentTextTheme!.headline3!.color!,
|
||||
buttonColor:
|
||||
Theme.of(context).accentTextTheme!.headline3!.color!,
|
||||
iconColor: PaletteDark.gray,
|
||||
borderColor: Theme.of(context).primaryTextTheme!.headline6!.backgroundColor!,
|
||||
validator: TextValidator()
|
||||
// AddressValidator(
|
||||
// type: contactViewModel.currency),
|
||||
)),
|
||||
borderColor: Theme.of(context)
|
||||
.primaryTextTheme!
|
||||
.headline6!
|
||||
.backgroundColor!,
|
||||
validator:
|
||||
AddressValidator(type: contactViewModel.currency!),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
|
@ -130,27 +132,32 @@ class ContactPage extends BasePage {
|
|||
child: Observer(
|
||||
builder: (_) => PrimaryButton(
|
||||
onPressed: () async {
|
||||
if (_formKey.currentState != null && !_formKey.currentState!.validate()) {
|
||||
if (_formKey.currentState != null &&
|
||||
!_formKey.currentState!.validate()) {
|
||||
return;
|
||||
}
|
||||
|
||||
await contactViewModel.save();
|
||||
},
|
||||
text: S.of(context).save,
|
||||
color: Theme.of(context).accentTextTheme!.bodyText1!.color!,
|
||||
color: Theme.of(context)
|
||||
.accentTextTheme!
|
||||
.bodyText1!
|
||||
.color!,
|
||||
textColor: Colors.white,
|
||||
isDisabled: !contactViewModel.isReady)))
|
||||
],
|
||||
));
|
||||
)),
|
||||
);
|
||||
}
|
||||
|
||||
void _presentCurrencyPicker(BuildContext context) {
|
||||
showPopUp<void>(
|
||||
builder: (_) => CurrencyPicker(
|
||||
selectedAtIndex:
|
||||
contactViewModel.currency != null
|
||||
? contactViewModel.currencies.indexOf(contactViewModel.currency!)
|
||||
: 0,
|
||||
selectedAtIndex: contactViewModel.currency != null
|
||||
? contactViewModel.currencies
|
||||
.indexOf(contactViewModel.currency!)
|
||||
: -1,
|
||||
items: contactViewModel.currencies,
|
||||
title: S.of(context).please_select,
|
||||
hintText: S.of(context).search_currency,
|
||||
|
|
|
@ -96,7 +96,10 @@ class AddressPage extends BasePage {
|
|||
|
||||
@override
|
||||
Widget middle(BuildContext context) =>
|
||||
PresentReceiveOptionPicker(receiveOptionViewModel: receiveOptionViewModel);
|
||||
PresentReceiveOptionPicker(
|
||||
receiveOptionViewModel: receiveOptionViewModel,
|
||||
hasWhiteBackground: currentTheme.type == ThemeType.light,
|
||||
);
|
||||
|
||||
@override
|
||||
Widget Function(BuildContext, Widget) get rootWrapper =>
|
||||
|
|
|
@ -1,13 +1,9 @@
|
|||
import 'dart:ui';
|
||||
import 'package:cake_wallet/palette.dart';
|
||||
import 'package:cake_wallet/src/screens/dashboard/widgets/filter_tile.dart';
|
||||
import 'package:cake_wallet/src/widgets/section_divider.dart';
|
||||
import 'package:cake_wallet/src/widgets/standard_checkbox.dart';
|
||||
import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:cake_wallet/src/widgets/alert_background.dart';
|
||||
import 'package:cake_wallet/src/widgets/alert_close_button.dart';
|
||||
import 'package:cake_wallet/src/widgets/picker_wrapper_widget.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:flutter_mobx/flutter_mobx.dart';
|
||||
//import 'package:date_range_picker/date_range_picker.dart' as date_rage_picker;
|
||||
|
@ -20,26 +16,26 @@ class FilterWidget extends StatelessWidget {
|
|||
@override
|
||||
Widget build(BuildContext context) {
|
||||
const sectionDivider = const SectionDivider();
|
||||
return AlertBackground(
|
||||
child: Stack(
|
||||
alignment: Alignment.center,
|
||||
children: <Widget>[
|
||||
Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: <Widget>[
|
||||
return PickerWrapperWidget(
|
||||
children: [
|
||||
Padding(
|
||||
padding: EdgeInsets.only(left: 24, right: 24, top: 24),
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.all(Radius.circular(24)),
|
||||
child: Container(
|
||||
color: Theme.of(context).textTheme!.bodyText1!.decorationColor!,
|
||||
child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Padding(
|
||||
padding: EdgeInsets.all(24.0),
|
||||
child: Text(
|
||||
S.of(context).filter_by,
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).primaryTextTheme.overline!.color!,
|
||||
color: Theme.of(context)
|
||||
.primaryTextTheme
|
||||
.overline!
|
||||
.color!,
|
||||
fontSize: 16,
|
||||
fontFamily: 'Lato',
|
||||
decoration: TextDecoration.none,
|
||||
|
@ -54,17 +50,23 @@ class FilterWidget extends StatelessWidget {
|
|||
itemCount: dashboardViewModel.filterItems.length,
|
||||
separatorBuilder: (context, _) => sectionDivider,
|
||||
itemBuilder: (_, index1) {
|
||||
final title = dashboardViewModel.filterItems.keys.elementAt(index1);
|
||||
final section = dashboardViewModel.filterItems.values.elementAt(index1);
|
||||
final title = dashboardViewModel.filterItems.keys
|
||||
.elementAt(index1);
|
||||
final section = dashboardViewModel.filterItems.values
|
||||
.elementAt(index1);
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
Padding(
|
||||
padding: EdgeInsets.only(top: 20, left: 24, right: 24),
|
||||
padding:
|
||||
EdgeInsets.only(top: 20, left: 24, right: 24),
|
||||
child: Text(
|
||||
title,
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).primaryTextTheme!.headline6!.color!,
|
||||
color: Theme.of(context)
|
||||
.primaryTextTheme!
|
||||
.headline6!
|
||||
.color!,
|
||||
fontSize: 16,
|
||||
fontFamily: 'Lato',
|
||||
fontWeight: FontWeight.bold,
|
||||
|
@ -83,9 +85,11 @@ class FilterWidget extends StatelessWidget {
|
|||
value: item.value(),
|
||||
caption: item.caption,
|
||||
gradientBackground: true,
|
||||
borderColor: Theme.of(context).dividerColor,
|
||||
borderColor:
|
||||
Theme.of(context).dividerColor,
|
||||
iconColor: Colors.white,
|
||||
onChanged: (value) => item.onChanged(),
|
||||
onChanged: (value) =>
|
||||
item.onChanged(),
|
||||
));
|
||||
return FilterTile(child: content);
|
||||
},
|
||||
|
@ -97,12 +101,8 @@ class FilterWidget extends StatelessWidget {
|
|||
]),
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
AlertCloseButton()
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,14 +9,22 @@ import 'package:flutter_mobx/flutter_mobx.dart';
|
|||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
|
||||
class PresentReceiveOptionPicker extends StatelessWidget {
|
||||
PresentReceiveOptionPicker({required this.receiveOptionViewModel});
|
||||
PresentReceiveOptionPicker(
|
||||
{required this.receiveOptionViewModel, this.hasWhiteBackground = false});
|
||||
|
||||
final ReceiveOptionViewModel receiveOptionViewModel;
|
||||
final bool hasWhiteBackground;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final arrowBottom =
|
||||
Image.asset('assets/images/arrow_bottom_purple_icon.png', color: Colors.white, height: 6);
|
||||
final textIconTheme = hasWhiteBackground
|
||||
? Theme.of(context).accentTextTheme.headline2!.backgroundColor!
|
||||
: Colors.white;
|
||||
final arrowBottom = Image.asset(
|
||||
'assets/images/arrow_bottom_purple_icon.png',
|
||||
color: textIconTheme,
|
||||
height: 6,
|
||||
);
|
||||
|
||||
return TextButton(
|
||||
onPressed: () => _showPicker(context),
|
||||
|
@ -40,14 +48,14 @@ class PresentReceiveOptionPicker extends StatelessWidget {
|
|||
fontSize: 18.0,
|
||||
fontWeight: FontWeight.bold,
|
||||
fontFamily: 'Lato',
|
||||
color: Theme.of(context).accentTextTheme.headline2!.backgroundColor!),
|
||||
color: textIconTheme),
|
||||
),
|
||||
Observer(
|
||||
builder: (_) => Text(receiveOptionViewModel.selectedReceiveOption.toString(),
|
||||
style: TextStyle(
|
||||
fontSize: 10.0,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Theme.of(context).textTheme.headline5!.color!)))
|
||||
color: textIconTheme)))
|
||||
],
|
||||
),
|
||||
SizedBox(width: 5),
|
||||
|
|
|
@ -32,7 +32,7 @@ class AnonpayCurrencyInputField extends StatelessWidget {
|
|||
decoration: BoxDecoration(
|
||||
border: Border(
|
||||
bottom: BorderSide(
|
||||
color: Theme.of(context).accentTextTheme.headline6!.backgroundColor!,
|
||||
color: Theme.of(context).primaryTextTheme.bodyText1!.color!,
|
||||
width: 1)),
|
||||
),
|
||||
child: Padding(
|
||||
|
|
|
@ -69,7 +69,7 @@ class AnonInvoiceForm extends StatelessWidget {
|
|||
BaseTextFormField(
|
||||
controller: nameController,
|
||||
focusNode: _nameFocusNode,
|
||||
borderColor: Theme.of(context).accentTextTheme.headline6!.backgroundColor,
|
||||
borderColor: Theme.of(context).primaryTextTheme.bodyText1!.color!,
|
||||
suffixIcon: SizedBox(width: 36),
|
||||
hintText: S.of(context).optional_name,
|
||||
textInputAction: TextInputAction.next,
|
||||
|
@ -88,7 +88,7 @@ class AnonInvoiceForm extends StatelessWidget {
|
|||
controller: descriptionController,
|
||||
focusNode: _descriptionFocusNode,
|
||||
textInputAction: TextInputAction.next,
|
||||
borderColor: Theme.of(context).accentTextTheme.headline6!.backgroundColor,
|
||||
borderColor: Theme.of(context).primaryTextTheme.bodyText1!.color!,
|
||||
suffixIcon: SizedBox(width: 36),
|
||||
hintText: S.of(context).optional_description,
|
||||
placeholderTextStyle: TextStyle(
|
||||
|
@ -104,7 +104,7 @@ class AnonInvoiceForm extends StatelessWidget {
|
|||
controller: emailController,
|
||||
textInputAction: TextInputAction.next,
|
||||
focusNode: _emailFocusNode,
|
||||
borderColor: Theme.of(context).accentTextTheme.headline6!.backgroundColor,
|
||||
borderColor: Theme.of(context).primaryTextTheme.bodyText1!.color!,
|
||||
suffixIcon: SizedBox(width: 36),
|
||||
keyboardType: TextInputType.emailAddress,
|
||||
hintText: S.of(context).optional_email_hint,
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import 'package:cake_wallet/core/amount_validator.dart';
|
||||
import 'package:cake_wallet/src/widgets/base_text_form_field.dart';
|
||||
import 'package:cw_core/currency.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
@ -10,18 +9,20 @@ class CurrencyInputField extends StatelessWidget {
|
|||
required this.onTapPicker,
|
||||
required this.selectedCurrency,
|
||||
this.focusNode,
|
||||
required this.controller,
|
||||
required this.controller, required this.isLight,
|
||||
});
|
||||
|
||||
final Function() onTapPicker;
|
||||
final Currency selectedCurrency;
|
||||
final FocusNode? focusNode;
|
||||
final TextEditingController controller;
|
||||
final bool isLight;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final arrowBottomPurple = Image.asset(
|
||||
'assets/images/arrow_bottom_purple_icon.png',
|
||||
color: Colors.white,
|
||||
color: Theme.of(context).accentTextTheme.headline2!.backgroundColor!,
|
||||
height: 8,
|
||||
);
|
||||
final _width = MediaQuery.of(context).size.width;
|
||||
|
@ -38,14 +39,14 @@ class CurrencyInputField extends StatelessWidget {
|
|||
keyboardType: TextInputType.numberWithOptions(signed: false, decimal: true),
|
||||
inputFormatters: [FilteringTextInputFormatter.allow(RegExp(r'^\d+(\.|\,)?\d{0,8}'))],
|
||||
hintText: '0.000',
|
||||
placeholderTextStyle: TextStyle(
|
||||
placeholderTextStyle: isLight ? null : TextStyle(
|
||||
color: Theme.of(context).primaryTextTheme.headline5!.color!,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
borderColor: Theme.of(context).accentTextTheme.headline6!.backgroundColor!,
|
||||
textColor: Colors.white,
|
||||
textColor: Theme.of(context).accentTextTheme.headline2!.backgroundColor!,
|
||||
textStyle: TextStyle(
|
||||
color: Colors.white,
|
||||
color: Theme.of(context).accentTextTheme.headline2!.backgroundColor!,
|
||||
),
|
||||
prefixIcon: Padding(
|
||||
padding: EdgeInsets.only(
|
||||
|
@ -68,7 +69,7 @@ class CurrencyInputField extends StatelessWidget {
|
|||
style: TextStyle(
|
||||
fontWeight: FontWeight.w600,
|
||||
fontSize: 16,
|
||||
color: Colors.white,
|
||||
color: Theme.of(context).accentTextTheme.headline2!.backgroundColor!,
|
||||
),
|
||||
),
|
||||
if (selectedCurrency.tag != null)
|
||||
|
@ -103,7 +104,8 @@ class CurrencyInputField extends StatelessWidget {
|
|||
style: TextStyle(
|
||||
fontWeight: FontWeight.w600,
|
||||
fontSize: 20,
|
||||
color: Colors.white,
|
||||
color:
|
||||
Theme.of(context).accentTextTheme.headline2!.backgroundColor!,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
|
@ -23,7 +23,7 @@ class QrImage extends StatelessWidget {
|
|||
size: size,
|
||||
foregroundColor: Colors.black,
|
||||
backgroundColor: Colors.white,
|
||||
padding: EdgeInsets.zero,
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -119,6 +119,7 @@ class QRWidget extends StatelessWidget {
|
|||
controller: amountController,
|
||||
onTapPicker: () => _presentPicker(context),
|
||||
selectedCurrency: addressListViewModel.selectedCurrency,
|
||||
isLight: isLight,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
|
@ -1,83 +0,0 @@
|
|||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/src/widgets/blockchain_height_widget.dart';
|
||||
import 'package:cake_wallet/src/widgets/base_text_form_field.dart';
|
||||
|
||||
class RestoreFromKeysFrom extends StatefulWidget {
|
||||
@override
|
||||
_RestoreFromKeysFromState createState() => _RestoreFromKeysFromState();
|
||||
}
|
||||
|
||||
class _RestoreFromKeysFromState extends State<RestoreFromKeysFrom> {
|
||||
final _formKey = GlobalKey<FormState>();
|
||||
final _blockchainHeightKey = GlobalKey<BlockchainHeightState>();
|
||||
final _nameController = TextEditingController();
|
||||
final _addressController = TextEditingController();
|
||||
final _viewKeyController = TextEditingController();
|
||||
final _spendKeyController = TextEditingController();
|
||||
final _wifController = TextEditingController();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
// _nameController.addListener(() =>
|
||||
// widget.walletRestorationFromKeysVM.name = _nameController.text);
|
||||
// _addressController.addListener(() =>
|
||||
// widget.walletRestorationFromKeysVM.address = _addressController.text);
|
||||
// _viewKeyController.addListener(() =>
|
||||
// widget.walletRestorationFromKeysVM.viewKey = _viewKeyController.text);
|
||||
// _spendKeyController.addListener(() =>
|
||||
// widget.walletRestorationFromKeysVM.spendKey = _spendKeyController.text);
|
||||
// _wifController.addListener(() =>
|
||||
// widget.walletRestorationFromKeysVM.wif = _wifController.text);
|
||||
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_nameController.dispose();
|
||||
_addressController.dispose();
|
||||
_viewKeyController.dispose();
|
||||
_spendKeyController.dispose();
|
||||
_wifController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
padding: EdgeInsets.only(left: 24, right: 24),
|
||||
child: Form(
|
||||
key: _formKey,
|
||||
child: Column(children: <Widget>[
|
||||
BaseTextFormField(
|
||||
controller: _addressController,
|
||||
keyboardType: TextInputType.multiline,
|
||||
maxLines: null,
|
||||
hintText: S.of(context).restore_address,
|
||||
),
|
||||
Container(
|
||||
padding: EdgeInsets.only(top: 20.0),
|
||||
child: BaseTextFormField(
|
||||
controller: _viewKeyController,
|
||||
hintText: S.of(context).restore_view_key_private,
|
||||
)),
|
||||
Container(
|
||||
padding: EdgeInsets.only(top: 20.0),
|
||||
child: BaseTextFormField(
|
||||
controller: _spendKeyController,
|
||||
hintText: S.of(context).restore_spend_key_private,
|
||||
)),
|
||||
BlockchainHeightWidget(
|
||||
key: _blockchainHeightKey,
|
||||
onHeightChange: (height) {
|
||||
// widget.walletRestorationFromKeysVM.height = height;
|
||||
print(height);
|
||||
}),
|
||||
]),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -548,6 +548,10 @@ class SendCardState extends State<SendCard>
|
|||
}
|
||||
|
||||
void _setEffects(BuildContext context) {
|
||||
if (_effectsInstalled) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (output.address.isNotEmpty) {
|
||||
addressController.text = output.address;
|
||||
}
|
||||
|
@ -558,10 +562,6 @@ class SendCardState extends State<SendCard>
|
|||
noteController.text = output.note;
|
||||
extractedAddressController.text = output.extractedAddress;
|
||||
|
||||
if (_effectsInstalled) {
|
||||
return;
|
||||
}
|
||||
|
||||
cryptoAmountController.addListener(() {
|
||||
final amount = cryptoAmountController.text;
|
||||
|
||||
|
|
|
@ -56,6 +56,18 @@ class PrivacyPage extends BasePage {
|
|||
onValueChange: (BuildContext _, bool value) {
|
||||
_privacySettingsViewModel.setIsAppSecure(value);
|
||||
}),
|
||||
SettingsSwitcherCell(
|
||||
title: S.current.disable_buy,
|
||||
value: _privacySettingsViewModel.disableBuy,
|
||||
onValueChange: (BuildContext _, bool value) {
|
||||
_privacySettingsViewModel.setDisableBuy(value);
|
||||
}),
|
||||
SettingsSwitcherCell(
|
||||
title: S.current.disable_sell,
|
||||
value: _privacySettingsViewModel.disableSell,
|
||||
onValueChange: (BuildContext _, bool value) {
|
||||
_privacySettingsViewModel.setDisableSell(value);
|
||||
}),
|
||||
],
|
||||
);
|
||||
}),
|
||||
|
|
|
@ -8,6 +8,7 @@ import 'package:cake_wallet/src/screens/settings/widgets/settings_cell_with_arro
|
|||
import 'package:cake_wallet/src/screens/settings/widgets/settings_picker_cell.dart';
|
||||
import 'package:cake_wallet/src/screens/settings/widgets/settings_switcher_cell.dart';
|
||||
import 'package:cake_wallet/src/widgets/standard_list.dart';
|
||||
import 'package:cake_wallet/utils/device_info.dart';
|
||||
import 'package:cake_wallet/view_model/settings/security_settings_view_model.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_mobx/flutter_mobx.dart';
|
||||
|
@ -48,6 +49,7 @@ class SecurityBackupPage extends BasePage {
|
|||
),
|
||||
),
|
||||
StandardListSeparator(padding: EdgeInsets.symmetric(horizontal: 24)),
|
||||
if (DeviceInfo.instance.isMobile)
|
||||
Observer(builder: (_) {
|
||||
return SettingsSwitcherCell(
|
||||
title: S.current.settings_allow_biometrical_authentication,
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
import 'package:cake_wallet/palette.dart';
|
||||
import 'package:cake_wallet/utils/responsive_layout_util.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:cake_wallet/src/widgets/alert_background.dart';
|
||||
import 'package:cake_wallet/src/widgets/alert_close_button.dart';
|
||||
import 'package:cake_wallet/src/widgets/picker_wrapper_widget.dart';
|
||||
|
||||
class CheckBoxPicker extends StatefulWidget {
|
||||
CheckBoxPicker({
|
||||
|
@ -32,16 +31,8 @@ class CheckBoxPickerState extends State<CheckBoxPicker> {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AlertBackground(
|
||||
child: Column(
|
||||
return PickerWrapperWidget(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Stack(
|
||||
alignment: Alignment.center,
|
||||
children: [
|
||||
Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: <Widget>[
|
||||
if (widget.title.isNotEmpty)
|
||||
Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 24),
|
||||
|
@ -91,14 +82,6 @@ class CheckBoxPickerState extends State<CheckBoxPicker> {
|
|||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: ResponsiveLayoutUtil.kPopupSpaceHeight),
|
||||
AlertCloseButton(),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -111,7 +94,10 @@ class CheckBoxPickerState extends State<CheckBoxPicker> {
|
|||
shrinkWrap: true,
|
||||
separatorBuilder: (context, index) => widget.isSeparated
|
||||
? Divider(
|
||||
color: Theme.of(context).accentTextTheme.headline6!.backgroundColor!,
|
||||
color: Theme.of(context)
|
||||
.accentTextTheme
|
||||
.headline6!
|
||||
.backgroundColor!,
|
||||
height: 1,
|
||||
)
|
||||
: const SizedBox(),
|
||||
|
|
|
@ -2,9 +2,8 @@
|
|||
|
||||
import 'package:cake_wallet/utils/responsive_layout_util.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:cake_wallet/src/widgets/alert_background.dart';
|
||||
import 'package:cake_wallet/src/widgets/alert_close_button.dart';
|
||||
import 'package:cw_core/currency.dart';
|
||||
import 'package:cake_wallet/src/widgets/picker_wrapper_widget.dart';
|
||||
|
||||
class Picker<Item> extends StatefulWidget {
|
||||
Picker({
|
||||
|
@ -114,37 +113,16 @@ class _PickerState<Item> extends State<Picker<Item>> {
|
|||
final mq = MediaQuery.of(context);
|
||||
final bottom = mq.viewInsets.bottom;
|
||||
final height = mq.size.height - bottom;
|
||||
final screenCenter = height / 2;
|
||||
|
||||
double closeButtonBottom = 60;
|
||||
double containerHeight = height * 0.65;
|
||||
if (bottom > 0) {
|
||||
// increase a bit or it gets too squished in the top
|
||||
containerHeight = height * 0.75;
|
||||
|
||||
final containerCenter = containerHeight / 2;
|
||||
final containerBottom = screenCenter - containerCenter;
|
||||
|
||||
final hasTitle = widget.title == null || widget.title!.isEmpty;
|
||||
|
||||
// position the close button right below the search container
|
||||
closeButtonBottom = closeButtonBottom -
|
||||
containerBottom +
|
||||
(hasTitle ? padding : padding / 1.5);
|
||||
}
|
||||
|
||||
return AlertBackground(
|
||||
child: Column(
|
||||
return PickerWrapperWidget(
|
||||
hasTitle: widget.title?.isNotEmpty ?? false,
|
||||
children: [
|
||||
Expanded(
|
||||
flex: 1,
|
||||
child: Stack(
|
||||
alignment: Alignment.center,
|
||||
children: <Widget>[
|
||||
Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
if (widget.title?.isNotEmpty ?? false)
|
||||
Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: padding),
|
||||
|
@ -165,10 +143,7 @@ class _PickerState<Item> extends State<Picker<Item>> {
|
|||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.all(Radius.circular(30)),
|
||||
child: Container(
|
||||
color: Theme.of(context)
|
||||
.accentTextTheme
|
||||
.headline6!
|
||||
.color!,
|
||||
color: Theme.of(context).accentTextTheme.headline6!.color!,
|
||||
child: ConstrainedBox(
|
||||
constraints: BoxConstraints(
|
||||
maxHeight: containerHeight,
|
||||
|
@ -189,26 +164,23 @@ class _PickerState<Item> extends State<Picker<Item>> {
|
|||
.color!),
|
||||
decoration: InputDecoration(
|
||||
hintText: widget.hintText,
|
||||
prefixIcon: Image.asset(
|
||||
"assets/images/search_icon.png"),
|
||||
prefixIcon:
|
||||
Image.asset("assets/images/search_icon.png"),
|
||||
filled: true,
|
||||
fillColor: Theme.of(context)
|
||||
.accentTextTheme
|
||||
.headline3!
|
||||
.color!,
|
||||
alignLabelWithHint: false,
|
||||
contentPadding:
|
||||
const EdgeInsets.symmetric(
|
||||
contentPadding: const EdgeInsets.symmetric(
|
||||
vertical: 4, horizontal: 16),
|
||||
enabledBorder: OutlineInputBorder(
|
||||
borderRadius:
|
||||
BorderRadius.circular(14),
|
||||
borderRadius: BorderRadius.circular(14),
|
||||
borderSide: const BorderSide(
|
||||
color: Colors.transparent,
|
||||
)),
|
||||
focusedBorder: OutlineInputBorder(
|
||||
borderRadius:
|
||||
BorderRadius.circular(14),
|
||||
borderRadius: BorderRadius.circular(14),
|
||||
borderSide: const BorderSide(
|
||||
color: Colors.transparent,
|
||||
)),
|
||||
|
@ -246,8 +218,7 @@ class _PickerState<Item> extends State<Picker<Item>> {
|
|||
fontSize: 12,
|
||||
fontWeight: FontWeight.w500,
|
||||
fontFamily: 'Lato',
|
||||
decoration:
|
||||
TextDecoration.none,
|
||||
decoration: TextDecoration.none,
|
||||
color: Theme.of(context)
|
||||
.primaryTextTheme
|
||||
.headline6!
|
||||
|
@ -266,19 +237,6 @@ class _PickerState<Item> extends State<Picker<Item>> {
|
|||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
SizedBox(height: ResponsiveLayoutUtil.kPopupSpaceHeight),
|
||||
AlertCloseButton(bottom: closeButtonBottom),
|
||||
],
|
||||
),
|
||||
),
|
||||
// gives the extra spacing using MediaQuery.viewInsets.bottom
|
||||
// to simulate a keyboard area
|
||||
SizedBox(
|
||||
height: bottom,
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
61
lib/src/widgets/picker_wrapper_widget.dart
Normal file
61
lib/src/widgets/picker_wrapper_widget.dart
Normal file
|
@ -0,0 +1,61 @@
|
|||
import 'package:cake_wallet/utils/responsive_layout_util.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:cake_wallet/src/widgets/alert_background.dart';
|
||||
import 'package:cake_wallet/src/widgets/alert_close_button.dart';
|
||||
|
||||
class PickerWrapperWidget extends StatelessWidget {
|
||||
PickerWrapperWidget({required this.children, this.hasTitle = false});
|
||||
|
||||
final List<Widget> children;
|
||||
final bool hasTitle;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final double padding = 24;
|
||||
|
||||
final mq = MediaQuery.of(context);
|
||||
final bottom = mq.viewInsets.bottom;
|
||||
final height = mq.size.height - bottom;
|
||||
final screenCenter = height / 2;
|
||||
|
||||
double closeButtonBottom = 60;
|
||||
double containerHeight = height * 0.65;
|
||||
if (bottom > 0) {
|
||||
// increase a bit or it gets too squished in the top
|
||||
containerHeight = height * 0.75;
|
||||
|
||||
final containerCenter = containerHeight / 2;
|
||||
final containerBottom = screenCenter - containerCenter;
|
||||
|
||||
// position the close button right below the search container
|
||||
closeButtonBottom = closeButtonBottom -
|
||||
containerBottom + (!hasTitle ? padding : padding / 1.5);
|
||||
}
|
||||
|
||||
return AlertBackground(
|
||||
child: Column(
|
||||
children: [
|
||||
Expanded(
|
||||
flex: 1,
|
||||
child: Stack(
|
||||
alignment: Alignment.center,
|
||||
children: <Widget>[
|
||||
Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: children,
|
||||
),
|
||||
SizedBox(height: ResponsiveLayoutUtil.kPopupSpaceHeight),
|
||||
AlertCloseButton(bottom: closeButtonBottom),
|
||||
],
|
||||
),
|
||||
),
|
||||
// gives the extra spacing using MediaQuery.viewInsets.bottom
|
||||
// to simulate a keyboard area
|
||||
SizedBox(
|
||||
height: bottom,
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -34,6 +34,8 @@ abstract class SettingsStoreBase with Store {
|
|||
required BalanceDisplayMode initialBalanceDisplayMode,
|
||||
required bool initialSaveRecipientAddress,
|
||||
required bool initialAppSecure,
|
||||
required bool initialDisableBuy,
|
||||
required bool initialDisableSell,
|
||||
required FiatApiMode initialFiatMode,
|
||||
required bool initialAllowBiometricalAuthentication,
|
||||
required ExchangeApiMode initialExchangeStatus,
|
||||
|
@ -57,6 +59,8 @@ abstract class SettingsStoreBase with Store {
|
|||
balanceDisplayMode = initialBalanceDisplayMode,
|
||||
shouldSaveRecipientAddress = initialSaveRecipientAddress,
|
||||
isAppSecure = initialAppSecure,
|
||||
disableBuy = initialDisableBuy,
|
||||
disableSell = initialDisableSell,
|
||||
fiatApiMode = initialFiatMode,
|
||||
allowBiometricalAuthentication = initialAllowBiometricalAuthentication,
|
||||
shouldShowMarketPlaceInDashboard = initialShouldShowMarketPlaceInDashboard,
|
||||
|
@ -130,6 +134,16 @@ abstract class SettingsStoreBase with Store {
|
|||
}
|
||||
});
|
||||
|
||||
reaction(
|
||||
(_) => disableBuy,
|
||||
(bool disableBuy) => sharedPreferences.setBool(
|
||||
PreferencesKey.disableBuyKey, disableBuy));
|
||||
|
||||
reaction(
|
||||
(_) => disableSell,
|
||||
(bool disableSell) => sharedPreferences.setBool(
|
||||
PreferencesKey.disableSellKey, disableSell));
|
||||
|
||||
if (Platform.isAndroid) {
|
||||
setIsAppSecureNative(isAppSecure);
|
||||
}
|
||||
|
@ -217,6 +231,12 @@ abstract class SettingsStoreBase with Store {
|
|||
@observable
|
||||
bool isAppSecure;
|
||||
|
||||
@observable
|
||||
bool disableBuy;
|
||||
|
||||
@observable
|
||||
bool disableSell;
|
||||
|
||||
@observable
|
||||
bool allowBiometricalAuthentication;
|
||||
|
||||
|
@ -309,6 +329,10 @@ abstract class SettingsStoreBase with Store {
|
|||
sharedPreferences.getBool(PreferencesKey.shouldSaveRecipientAddressKey) ?? false;
|
||||
final isAppSecure =
|
||||
sharedPreferences.getBool(PreferencesKey.isAppSecureKey) ?? false;
|
||||
final disableBuy =
|
||||
sharedPreferences.getBool(PreferencesKey.disableBuyKey) ?? false;
|
||||
final disableSell =
|
||||
sharedPreferences.getBool(PreferencesKey.disableSellKey) ?? false;
|
||||
final currentFiatApiMode = FiatApiMode.deserialize(
|
||||
raw: sharedPreferences
|
||||
.getInt(PreferencesKey.currentFiatApiModeKey) ?? FiatApiMode.enabled.raw);
|
||||
|
@ -388,6 +412,8 @@ abstract class SettingsStoreBase with Store {
|
|||
initialBalanceDisplayMode: currentBalanceDisplayMode,
|
||||
initialSaveRecipientAddress: shouldSaveRecipientAddress,
|
||||
initialAppSecure: isAppSecure,
|
||||
initialDisableBuy: disableBuy,
|
||||
initialDisableSell: disableSell,
|
||||
initialFiatMode: currentFiatApiMode,
|
||||
initialAllowBiometricalAuthentication: allowBiometricalAuthentication,
|
||||
initialExchangeStatus: exchangeStatus,
|
||||
|
@ -435,6 +461,10 @@ abstract class SettingsStoreBase with Store {
|
|||
sharedPreferences.getBool(PreferencesKey.shouldSaveRecipientAddressKey) ?? shouldSaveRecipientAddress;
|
||||
isAppSecure =
|
||||
sharedPreferences.getBool(PreferencesKey.isAppSecureKey) ?? isAppSecure;
|
||||
disableBuy =
|
||||
sharedPreferences.getBool(PreferencesKey.disableBuyKey) ?? disableBuy;
|
||||
disableSell =
|
||||
sharedPreferences.getBool(PreferencesKey.disableSellKey) ?? disableSell;
|
||||
allowBiometricalAuthentication = sharedPreferences
|
||||
.getBool(PreferencesKey.allowBiometricalAuthenticationKey) ??
|
||||
allowBiometricalAuthentication;
|
||||
|
|
|
@ -141,9 +141,9 @@ class ExceptionHandler {
|
|||
"errno = 103", // SocketException: Software caused connection abort
|
||||
"errno = 104", // SocketException: Connection reset by peer
|
||||
"errno = 110", // SocketException: Connection timed out
|
||||
"HttpException: Connection reset by peer",
|
||||
"HttpException: Connection closed before full header was received",
|
||||
"HandshakeException: Connection terminated during handshake",
|
||||
"Connection reset by peer",
|
||||
"Connection closed before full header was received",
|
||||
"Connection terminated during handshake",
|
||||
"PERMISSION_NOT_GRANTED",
|
||||
];
|
||||
|
||||
|
@ -172,7 +172,7 @@ class ExceptionHandler {
|
|||
}
|
||||
|
||||
await file.writeAsString(
|
||||
"App Version: $currentVersion\n\nDevice Info $deviceInfo",
|
||||
"App Version: $currentVersion\n\nDevice Info $deviceInfo\n\n",
|
||||
mode: FileMode.append,
|
||||
);
|
||||
}
|
||||
|
@ -193,6 +193,7 @@ class ExceptionHandler {
|
|||
'systemVersion': data.systemVersion,
|
||||
'model': data.model,
|
||||
'localizedModel': data.localizedModel,
|
||||
'isPhysicalDevice': data.isPhysicalDevice,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -46,9 +46,7 @@ abstract class DashboardViewModelBase with Store {
|
|||
required this.anonpayTransactionsStore})
|
||||
: isOutdatedElectrumWallet = false,
|
||||
hasSellAction = false,
|
||||
isEnabledSellAction = false,
|
||||
hasBuyAction = false,
|
||||
isEnabledBuyAction = false,
|
||||
hasExchangeAction = false,
|
||||
isShowFirstYatIntroduction = false,
|
||||
isShowSecondYatIntroduction = false,
|
||||
|
@ -287,14 +285,19 @@ abstract class DashboardViewModelBase with Store {
|
|||
@observable
|
||||
bool hasExchangeAction;
|
||||
|
||||
@observable
|
||||
bool isEnabledBuyAction;
|
||||
@computed
|
||||
bool get isEnabledBuyAction =>
|
||||
!settingsStore.disableBuy && wallet.type != WalletType.haven;
|
||||
|
||||
@observable
|
||||
bool hasBuyAction;
|
||||
|
||||
@observable
|
||||
bool isEnabledSellAction;
|
||||
@computed
|
||||
bool get isEnabledSellAction =>
|
||||
!settingsStore.disableSell &&
|
||||
wallet.type != WalletType.haven &&
|
||||
wallet.type != WalletType.monero &&
|
||||
wallet.type != WalletType.litecoin;
|
||||
|
||||
@observable
|
||||
bool hasSellAction;
|
||||
|
@ -398,11 +401,7 @@ abstract class DashboardViewModelBase with Store {
|
|||
|
||||
void updateActions() {
|
||||
hasExchangeAction = !isHaven;
|
||||
isEnabledBuyAction = wallet.type != WalletType.haven;
|
||||
hasBuyAction = !isHaven;
|
||||
isEnabledSellAction = wallet.type != WalletType.haven
|
||||
&& wallet.type != WalletType.monero
|
||||
&& wallet.type != WalletType.litecoin;
|
||||
hasSellAction = !isHaven;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -123,8 +123,8 @@ abstract class ExchangeTradeViewModelBase with Store {
|
|||
}
|
||||
|
||||
void _updateItems() {
|
||||
final tagFrom = trade.from.tag != null ? '${trade.from.tag}' + ' ' : '';
|
||||
final tagTo = trade.to.tag != null ? '${trade.to.tag}' + ' ' : '';
|
||||
final tagFrom = tradesStore.trade!.from.tag != null ? '${tradesStore.trade!.from.tag}' + ' ' : '';
|
||||
final tagTo = tradesStore.trade!.to.tag != null ? '${tradesStore.trade!.to.tag}' + ' ' : '';
|
||||
items.clear();
|
||||
items.add(ExchangeTradeItem(
|
||||
title: "${trade.provider.title} ${S.current.id}", data: '${trade.id}', isCopied: true));
|
||||
|
@ -142,11 +142,11 @@ abstract class ExchangeTradeViewModelBase with Store {
|
|||
items.addAll([
|
||||
ExchangeTradeItem(title: S.current.amount, data: '${trade.amount}', isCopied: true),
|
||||
ExchangeTradeItem(
|
||||
title: S.current.send_to_this_address('${trade.from}', tagFrom) + ':',
|
||||
title: S.current.send_to_this_address('${tradesStore.trade!.from}', tagFrom) + ':',
|
||||
data: trade.inputAddress ?? '',
|
||||
isCopied: true),
|
||||
ExchangeTradeItem(
|
||||
title: S.current.arrive_in_this_address('${trade.to}', tagTo) + ':',
|
||||
title: S.current.arrive_in_this_address('${tradesStore.trade!.to}', tagTo) + ':',
|
||||
data: trade.payoutAddress ?? '',
|
||||
isCopied: true),
|
||||
]);
|
||||
|
|
|
@ -3,7 +3,6 @@ import 'dart:collection';
|
|||
import 'dart:convert';
|
||||
|
||||
import 'package:cake_wallet/entities/exchange_api_mode.dart';
|
||||
import 'package:cake_wallet/entities/fiat_api_mode.dart';
|
||||
import 'package:cake_wallet/entities/preferences_key.dart';
|
||||
import 'package:cake_wallet/exchange/sideshift/sideshift_exchange_provider.dart';
|
||||
import 'package:cake_wallet/exchange/sideshift/sideshift_request.dart';
|
||||
|
@ -244,7 +243,7 @@ abstract class ExchangeViewModelBase with Store {
|
|||
|
||||
List<CryptoCurrency> depositCurrencies;
|
||||
|
||||
NumberFormat _cryptoNumberFormat;
|
||||
final NumberFormat _cryptoNumberFormat;
|
||||
|
||||
final SettingsStore _settingsStore;
|
||||
|
||||
|
@ -388,6 +387,7 @@ abstract class ExchangeViewModelBase with Store {
|
|||
double? lowestMin = double.maxFinite;
|
||||
double? highestMax = 0.0;
|
||||
|
||||
try {
|
||||
for (var provider in selectedProviders) {
|
||||
/// if this provider is not valid for the current pair, skip it
|
||||
if (!providersForCurrentPair().contains(provider)) {
|
||||
|
@ -410,6 +410,14 @@ abstract class ExchangeViewModelBase with Store {
|
|||
continue;
|
||||
}
|
||||
}
|
||||
} on ConcurrentModificationError {
|
||||
/// if user changed the selected providers while fetching limits
|
||||
/// then delay the fetching limits a bit and try again
|
||||
///
|
||||
/// this is because the limitation of collections that
|
||||
/// you can't modify it while iterating through it
|
||||
Future.delayed(Duration(milliseconds: 200), loadLimits);
|
||||
}
|
||||
|
||||
if (lowestMin != double.maxFinite) {
|
||||
limits = Limits(min: lowestMin, max: highestMax);
|
||||
|
@ -534,7 +542,7 @@ abstract class ExchangeViewModelBase with Store {
|
|||
///
|
||||
/// this is because the limitation of the SplayTreeMap that
|
||||
/// you can't modify it while iterating through it
|
||||
Future.delayed(Duration(milliseconds: 500), createTrade);
|
||||
Future.delayed(Duration(milliseconds: 200), createTrade);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -24,6 +24,12 @@ abstract class PrivacySettingsViewModelBase with Store {
|
|||
@computed
|
||||
bool get isAppSecure => _settingsStore.isAppSecure;
|
||||
|
||||
@computed
|
||||
bool get disableBuy => _settingsStore.disableBuy;
|
||||
|
||||
@computed
|
||||
bool get disableSell => _settingsStore.disableSell;
|
||||
|
||||
@action
|
||||
void setShouldSaveRecipientAddress(bool value) => _settingsStore.shouldSaveRecipientAddress = value;
|
||||
|
||||
|
@ -36,4 +42,10 @@ abstract class PrivacySettingsViewModelBase with Store {
|
|||
@action
|
||||
void setIsAppSecure(bool value) => _settingsStore.isAppSecure = value;
|
||||
|
||||
@action
|
||||
void setDisableBuy(bool value) => _settingsStore.disableBuy = value;
|
||||
|
||||
@action
|
||||
void setDisableSell(bool value) => _settingsStore.disableSell = value;
|
||||
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
|||
CwMoneroPlugin.register(with: registry.registrar(forPlugin: "CwMoneroPlugin"))
|
||||
DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin"))
|
||||
DevicelocalePlugin.register(with: registry.registrar(forPlugin: "DevicelocalePlugin"))
|
||||
FlutterSecureStorageMacosPlugin.register(with: registry.registrar(forPlugin: "FlutterSecureStorageMacosPlugin"))
|
||||
FlutterSecureStoragePlugin.register(with: registry.registrar(forPlugin: "FlutterSecureStoragePlugin"))
|
||||
InAppReviewPlugin.register(with: registry.registrar(forPlugin: "InAppReviewPlugin"))
|
||||
FLTPackageInfoPlugin.register(with: registry.registrar(forPlugin: "FLTPackageInfoPlugin"))
|
||||
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
|
||||
|
|
|
@ -23,7 +23,7 @@ PODS:
|
|||
- FlutterMacOS
|
||||
- devicelocale (0.0.1):
|
||||
- FlutterMacOS
|
||||
- flutter_secure_storage_macos (3.3.1):
|
||||
- flutter_secure_storage_macos (6.1.1):
|
||||
- FlutterMacOS
|
||||
- FlutterMacOS (1.0.0)
|
||||
- in_app_review (0.2.0):
|
||||
|
@ -106,16 +106,16 @@ SPEC CHECKSUMS:
|
|||
cw_monero: ec03de55a19c4a2b174ea687e0f4202edc716fa4
|
||||
device_info_plus: 5401765fde0b8d062a2f8eb65510fb17e77cf07f
|
||||
devicelocale: 9f0f36ac651cabae2c33f32dcff4f32b61c38225
|
||||
flutter_secure_storage_macos: 6ceee8fbc7f484553ad17f79361b556259df89aa
|
||||
flutter_secure_storage_macos: d56e2d218c1130b262bef8b4a7d64f88d7f9c9ea
|
||||
FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24
|
||||
in_app_review: a850789fad746e89bce03d4aeee8078b45a53fd0
|
||||
package_info: 6eba2fd8d3371dda2d85c8db6fe97488f24b74b2
|
||||
path_provider_foundation: c68054786f1b4f3343858c1e1d0caaded73f0be9
|
||||
path_provider_foundation: eaf5b3e458fc0e5fbb9940fb09980e853fe058b8
|
||||
platform_device_id: 3e414428f45df149bbbfb623e2c0ca27c545b763
|
||||
platform_device_id_macos: f763bb55f088be804d61b96eb4710b8ab6598e94
|
||||
Reachability: 33e18b67625424e47b6cde6d202dce689ad7af96
|
||||
share_plus_macos: 853ee48e7dce06b633998ca0735d482dd671ade4
|
||||
shared_preferences_foundation: 986fc17f3d3251412d18b0265f9c64113a8c2472
|
||||
shared_preferences_foundation: e2dae3258e06f44cc55f49d42024fd8dd03c590c
|
||||
url_launcher_macos: 5335912b679c073563f29d89d33d10d459f95451
|
||||
wakelock_macos: bc3f2a9bd8d2e6c89fee1e1822e7ddac3bd004a9
|
||||
|
||||
|
|
|
@ -17,8 +17,8 @@ dependencies:
|
|||
git:
|
||||
url: https://github.com/cake-tech/flutter_secure_storage.git
|
||||
path: flutter_secure_storage
|
||||
ref: cake-6.0.0
|
||||
version: 6.0.0
|
||||
ref: cake-8.0.0
|
||||
version: 8.0.0
|
||||
# provider: ^6.0.3
|
||||
rxdart: ^0.27.4
|
||||
yaml: ^3.1.1
|
||||
|
@ -81,6 +81,10 @@ dependencies:
|
|||
path_provider_android: 2.0.24
|
||||
shared_preferences_android: 2.0.17
|
||||
url_launcher_android: 6.0.24
|
||||
bitcoin_flutter:
|
||||
git:
|
||||
url: https://github.com/cake-tech/bitcoin_flutter.git
|
||||
ref: cake-update-v2
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
|
|
@ -706,5 +706,7 @@
|
|||
"error_text_input_below_minimum_limit":" المبلغ أقل من الحد الأدنى",
|
||||
"error_text_input_above_maximum_limit":"المبلغ أكبر من الحد الأقصى",
|
||||
"show_market_place": "إظهار السوق",
|
||||
"prevent_screenshots": "منع لقطات الشاشة وتسجيل الشاشة"
|
||||
"prevent_screenshots": "منع لقطات الشاشة وتسجيل الشاشة",
|
||||
"disable_buy": "تعطيل إجراء الشراء",
|
||||
"disable_sell": "قم بتعطيل إجراء البيع"
|
||||
}
|
||||
|
|
|
@ -702,5 +702,7 @@
|
|||
"error_text_input_below_minimum_limit" : "Сумата е по-малко от минималната",
|
||||
"error_text_input_above_maximum_limit" : "Сумата надвишава максималната",
|
||||
"show_market_place":"Покажи пазар",
|
||||
"prevent_screenshots": "Предотвратете екранни снимки и запис на екрана"
|
||||
"prevent_screenshots": "Предотвратете екранни снимки и запис на екрана",
|
||||
"disable_buy": "Деактивирайте действието за покупка",
|
||||
"disable_sell": "Деактивирайте действието за продажба"
|
||||
}
|
||||
|
|
|
@ -702,5 +702,7 @@
|
|||
"error_text_input_below_minimum_limit" : "Částka je menší než minimální hodnota",
|
||||
"error_text_input_above_maximum_limit" : "Částka je větší než maximální hodnota",
|
||||
"show_market_place": "Zobrazit trh",
|
||||
"prevent_screenshots": "Zabránit vytváření snímků obrazovky a nahrávání obrazovky"
|
||||
"prevent_screenshots": "Zabránit vytváření snímků obrazovky a nahrávání obrazovky",
|
||||
"disable_buy": "Zakázat akci nákupu",
|
||||
"disable_sell": "Zakázat akci prodeje"
|
||||
}
|
||||
|
|
|
@ -708,5 +708,7 @@
|
|||
"error_text_input_below_minimum_limit" : "Menge ist unter dem Minimum",
|
||||
"error_text_input_above_maximum_limit" : "Menge ist über dem Maximum",
|
||||
"show_market_place": "Marktplatz anzeigen",
|
||||
"prevent_screenshots": "Verhindern Sie Screenshots und Bildschirmaufzeichnungen"
|
||||
"prevent_screenshots": "Verhindern Sie Screenshots und Bildschirmaufzeichnungen",
|
||||
"disable_buy": "Kaufaktion deaktivieren",
|
||||
"disable_sell": "Verkaufsaktion deaktivieren"
|
||||
}
|
||||
|
|
|
@ -708,5 +708,7 @@
|
|||
"error_text_input_below_minimum_limit" : "Amount is less than the minimum",
|
||||
"error_text_input_above_maximum_limit" : "Amount is more than the maximum",
|
||||
"show_market_place" :"Show Marketplace",
|
||||
"prevent_screenshots": "Prevent screenshots and screen recording"
|
||||
"prevent_screenshots": "Prevent screenshots and screen recording",
|
||||
"disable_buy": "Disable buy action",
|
||||
"disable_sell": "Disable sell action"
|
||||
}
|
||||
|
|
|
@ -708,5 +708,7 @@
|
|||
"error_text_input_below_minimum_limit" : "La cantidad es menos que mínima",
|
||||
"error_text_input_above_maximum_limit" : "La cantidad es más que el máximo",
|
||||
"show_market_place": "Mostrar mercado",
|
||||
"prevent_screenshots": "Evitar capturas de pantalla y grabación de pantalla"
|
||||
"prevent_screenshots": "Evitar capturas de pantalla y grabación de pantalla",
|
||||
"disable_buy": "Desactivar acción de compra",
|
||||
"disable_sell": "Desactivar acción de venta"
|
||||
}
|
||||
|
|
|
@ -708,5 +708,7 @@
|
|||
"error_text_input_below_minimum_limit" : "Le montant est inférieur au minimum",
|
||||
"error_text_input_above_maximum_limit" : "Le montant est supérieur au maximum",
|
||||
"show_market_place" :"Afficher la place de marché",
|
||||
"prevent_screenshots": "Empêcher les captures d'écran et l'enregistrement d'écran"
|
||||
"prevent_screenshots": "Empêcher les captures d'écran et l'enregistrement d'écran",
|
||||
"disable_buy": "Désactiver l'action d'achat",
|
||||
"disable_sell": "Désactiver l'action de vente"
|
||||
}
|
||||
|
|
|
@ -708,5 +708,7 @@
|
|||
"error_text_input_below_minimum_limit" : "राशि न्यूनतम से कम है",
|
||||
"error_text_input_above_maximum_limit" : "राशि अधिकतम से अधिक है",
|
||||
"show_market_place":"बाज़ार दिखाएँ",
|
||||
"prevent_screenshots": "स्क्रीनशॉट और स्क्रीन रिकॉर्डिंग रोकें"
|
||||
"prevent_screenshots": "स्क्रीनशॉट और स्क्रीन रिकॉर्डिंग रोकें",
|
||||
"disable_buy": "खरीद कार्रवाई अक्षम करें",
|
||||
"disable_sell": "बेचने की कार्रवाई अक्षम करें"
|
||||
}
|
||||
|
|
|
@ -708,5 +708,7 @@
|
|||
"error_text_input_below_minimum_limit" : "Iznos je manji od minimalnog",
|
||||
"error_text_input_above_maximum_limit" : "Iznos je veći od maskimalnog",
|
||||
"show_market_place" : "Prikaži tržište",
|
||||
"prevent_screenshots": "Spriječite snimke zaslona i snimanje zaslona"
|
||||
"prevent_screenshots": "Spriječite snimke zaslona i snimanje zaslona",
|
||||
"disable_buy": "Onemogući kupnju",
|
||||
"disable_sell": "Onemogući akciju prodaje"
|
||||
}
|
||||
|
|
|
@ -684,5 +684,7 @@
|
|||
"error_text_input_below_minimum_limit" : "Jumlah kurang dari minimal",
|
||||
"error_text_input_above_maximum_limit" : "Jumlah lebih dari maksimal",
|
||||
"show_market_place": "Tampilkan Pasar",
|
||||
"prevent_screenshots": "Cegah tangkapan layar dan perekaman layar"
|
||||
"prevent_screenshots": "Cegah tangkapan layar dan perekaman layar",
|
||||
"disable_buy": "Nonaktifkan tindakan beli",
|
||||
"disable_sell": "Nonaktifkan aksi jual"
|
||||
}
|
||||
|
|
|
@ -708,5 +708,7 @@
|
|||
"error_text_input_below_minimum_limit" : "L'ammontare è inferiore al minimo",
|
||||
"error_text_input_above_maximum_limit" : "L'ammontare è superiore al massimo",
|
||||
"show_market_place":"Mostra mercato",
|
||||
"prevent_screenshots": "Impedisci screenshot e registrazione dello schermo"
|
||||
"prevent_screenshots": "Impedisci screenshot e registrazione dello schermo",
|
||||
"disable_buy": "Disabilita l'azione di acquisto",
|
||||
"disable_sell": "Disabilita l'azione di vendita"
|
||||
}
|
||||
|
|
|
@ -708,5 +708,7 @@
|
|||
"error_text_input_below_minimum_limit" : "金額は最小額より少ない",
|
||||
"error_text_input_above_maximum_limit" : "金額は最大値を超えています",
|
||||
"show_market_place":"マーケットプレイスを表示",
|
||||
"prevent_screenshots": "スクリーンショットと画面録画を防止する"
|
||||
"prevent_screenshots": "スクリーンショットと画面録画を防止する",
|
||||
"disable_buy": "購入アクションを無効にする",
|
||||
"disable_sell": "販売アクションを無効にする"
|
||||
}
|
||||
|
|
|
@ -708,5 +708,7 @@
|
|||
"error_text_input_below_minimum_limit" : "금액이 최소보다 적습니다.",
|
||||
"error_text_input_above_maximum_limit" : "금액이 최대 값보다 많습니다.",
|
||||
"show_market_place":"마켓플레이스 표시",
|
||||
"prevent_screenshots": "스크린샷 및 화면 녹화 방지"
|
||||
"prevent_screenshots": "스크린샷 및 화면 녹화 방지",
|
||||
"disable_buy": "구매 행동 비활성화",
|
||||
"disable_sell": "판매 조치 비활성화"
|
||||
}
|
||||
|
|
|
@ -708,5 +708,7 @@
|
|||
"error_text_input_below_minimum_limit" : "ပမာဏသည် အနိမ့်ဆုံးထက်နည်းသည်။",
|
||||
"error_text_input_above_maximum_limit" : "ပမာဏသည် အများဆုံးထက် ပိုများသည်။",
|
||||
"show_market_place":"စျေးကွက်ကိုပြသပါ။",
|
||||
"prevent_screenshots": "ဖန်သားပြင်ဓာတ်ပုံများနှင့် မျက်နှာပြင်ရိုက်ကူးခြင်းကို တားဆီးပါ။"
|
||||
"prevent_screenshots": "ဖန်သားပြင်ဓာတ်ပုံများနှင့် မျက်နှာပြင်ရိုက်ကူးခြင်းကို တားဆီးပါ။",
|
||||
"disable_buy": "ဝယ်ယူမှု လုပ်ဆောင်ချက်ကို ပိတ်ပါ။",
|
||||
"disable_sell": "ရောင်းချခြင်းလုပ်ဆောင်ချက်ကို ပိတ်ပါ။"
|
||||
}
|
||||
|
|
|
@ -708,5 +708,7 @@
|
|||
"error_text_input_below_minimum_limit" : "Bedrag is minder dan minimaal",
|
||||
"error_text_input_above_maximum_limit" : "Bedrag is meer dan maximaal",
|
||||
"show_market_place":"Toon Marktplaats",
|
||||
"prevent_screenshots": "Voorkom screenshots en schermopname"
|
||||
"prevent_screenshots": "Voorkom screenshots en schermopname",
|
||||
"disable_buy": "Koopactie uitschakelen",
|
||||
"disable_sell": "Verkoopactie uitschakelen"
|
||||
}
|
||||
|
|
|
@ -708,5 +708,7 @@
|
|||
"error_text_input_below_minimum_limit" : "Kwota jest mniejsza niż minimalna",
|
||||
"error_text_input_above_maximum_limit" : "Kwota jest większa niż maksymalna",
|
||||
"show_market_place" : "Pokaż rynek",
|
||||
"prevent_screenshots": "Zapobiegaj zrzutom ekranu i nagrywaniu ekranu"
|
||||
"prevent_screenshots": "Zapobiegaj zrzutom ekranu i nagrywaniu ekranu",
|
||||
"disable_buy": "Wyłącz akcję kupna",
|
||||
"disable_sell": "Wyłącz akcję sprzedaży"
|
||||
}
|
||||
|
|
|
@ -707,5 +707,7 @@
|
|||
"error_text_input_below_minimum_limit" : "O valor é menor que o mínimo",
|
||||
"error_text_input_above_maximum_limit" : "O valor é superior ao máximo",
|
||||
"show_market_place":"Mostrar mercado",
|
||||
"prevent_screenshots": "Evite capturas de tela e gravação de tela"
|
||||
"prevent_screenshots": "Evite capturas de tela e gravação de tela",
|
||||
"disable_buy": "Desativar ação de compra",
|
||||
"disable_sell": "Desativar ação de venda"
|
||||
}
|
||||
|
|
|
@ -708,5 +708,7 @@
|
|||
"error_text_input_below_minimum_limit" : "Сумма меньше минимальной",
|
||||
"error_text_input_above_maximum_limit" : "Сумма больше максимальной",
|
||||
"show_market_place":"Показать торговую площадку",
|
||||
"prevent_screenshots": "Предотвратить скриншоты и запись экрана"
|
||||
"prevent_screenshots": "Предотвратить скриншоты и запись экрана",
|
||||
"disable_buy": "Отключить действие покупки",
|
||||
"disable_sell": "Отключить действие продажи"
|
||||
}
|
||||
|
|
|
@ -706,5 +706,7 @@
|
|||
"error_text_input_below_minimum_limit" : "จำนวนเงินน้อยกว่าขั้นต่ำ",
|
||||
"error_text_input_above_maximum_limit" : "จำนวนเงินสูงกว่าค่าสูงสุด",
|
||||
"show_market_place":"แสดงตลาดกลาง",
|
||||
"prevent_screenshots": "ป้องกันภาพหน้าจอและการบันทึกหน้าจอ"
|
||||
"prevent_screenshots": "ป้องกันภาพหน้าจอและการบันทึกหน้าจอ",
|
||||
"disable_buy": "ปิดการใช้งานการซื้อ",
|
||||
"disable_sell": "ปิดการใช้งานการขาย"
|
||||
}
|
||||
|
|
|
@ -708,5 +708,7 @@
|
|||
"error_text_input_below_minimum_limit" : "Miktar minimumdan daha azdır",
|
||||
"error_text_input_above_maximum_limit" : "Miktar maksimumdan daha fazla",
|
||||
"show_market_place":"Pazar Yerini Göster",
|
||||
"prevent_screenshots": "Ekran görüntülerini ve ekran kaydını önleyin"
|
||||
"prevent_screenshots": "Ekran görüntülerini ve ekran kaydını önleyin",
|
||||
"disable_buy": "Satın alma işlemini devre dışı bırak",
|
||||
"disable_sell": "Satış işlemini devre dışı bırak"
|
||||
}
|
||||
|
|
|
@ -707,5 +707,7 @@
|
|||
"error_text_input_below_minimum_limit" : "Сума менша мінімальної",
|
||||
"error_text_input_above_maximum_limit" : "Сума більше максимальної",
|
||||
"show_market_place":"Відображати маркетплейс",
|
||||
"prevent_screenshots": "Запобігати знімкам екрана та запису екрана"
|
||||
"prevent_screenshots": "Запобігати знімкам екрана та запису екрана",
|
||||
"disable_buy": "Вимкнути дію покупки",
|
||||
"disable_sell": "Вимкнути дію продажу"
|
||||
}
|
||||
|
|
|
@ -703,5 +703,7 @@
|
|||
"error_text_input_below_minimum_limit" : "رقم کم از کم سے کم ہے۔",
|
||||
"error_text_input_above_maximum_limit" : "رقم زیادہ سے زیادہ سے زیادہ ہے۔",
|
||||
"show_market_place":"بازار دکھائیں۔",
|
||||
"prevent_screenshots": "اسکرین شاٹس اور اسکرین ریکارڈنگ کو روکیں۔"
|
||||
"prevent_screenshots": "اسکرین شاٹس اور اسکرین ریکارڈنگ کو روکیں۔",
|
||||
"disable_buy": "خرید ایکشن کو غیر فعال کریں۔",
|
||||
"disable_sell": "فروخت کی کارروائی کو غیر فعال کریں۔"
|
||||
}
|
||||
|
|
|
@ -707,5 +707,7 @@
|
|||
"error_text_input_below_minimum_limit" : "金额小于最小值",
|
||||
"error_text_input_above_maximum_limit" : "金额大于最大值",
|
||||
"show_market_place" :"显示市场",
|
||||
"prevent_screenshots": "防止截屏和录屏"
|
||||
"prevent_screenshots": "防止截屏和录屏",
|
||||
"disable_buy": "禁用购买操作",
|
||||
"disable_sell": "禁用卖出操作"
|
||||
}
|
||||
|
|
|
@ -14,14 +14,14 @@ TYPES=($MONERO_COM $CAKEWALLET $HAVEN)
|
|||
APP_ANDROID_TYPE=$1
|
||||
|
||||
MONERO_COM_NAME="Monero.com"
|
||||
MONERO_COM_VERSION="1.3.5"
|
||||
MONERO_COM_BUILD_NUMBER=48
|
||||
MONERO_COM_VERSION="1.3.6"
|
||||
MONERO_COM_BUILD_NUMBER=49
|
||||
MONERO_COM_BUNDLE_ID="com.monero.app"
|
||||
MONERO_COM_PACKAGE="com.monero.app"
|
||||
|
||||
CAKEWALLET_NAME="Cake Wallet"
|
||||
CAKEWALLET_VERSION="4.6.4"
|
||||
CAKEWALLET_BUILD_NUMBER=158
|
||||
CAKEWALLET_VERSION="4.6.5"
|
||||
CAKEWALLET_BUILD_NUMBER=159
|
||||
CAKEWALLET_BUNDLE_ID="com.cakewallet.cake_wallet"
|
||||
CAKEWALLET_PACKAGE="com.cakewallet.cake_wallet"
|
||||
|
||||
|
|
|
@ -13,13 +13,13 @@ TYPES=($MONERO_COM $CAKEWALLET $HAVEN)
|
|||
APP_IOS_TYPE=$1
|
||||
|
||||
MONERO_COM_NAME="Monero.com"
|
||||
MONERO_COM_VERSION="1.3.5"
|
||||
MONERO_COM_BUILD_NUMBER=46
|
||||
MONERO_COM_VERSION="1.3.6"
|
||||
MONERO_COM_BUILD_NUMBER=47
|
||||
MONERO_COM_BUNDLE_ID="com.cakewallet.monero"
|
||||
|
||||
CAKEWALLET_NAME="Cake Wallet"
|
||||
CAKEWALLET_VERSION="4.6.4"
|
||||
CAKEWALLET_BUILD_NUMBER=153
|
||||
CAKEWALLET_VERSION="4.6.5"
|
||||
CAKEWALLET_BUILD_NUMBER=154
|
||||
CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet"
|
||||
|
||||
HAVEN_NAME="Haven"
|
||||
|
|
|
@ -15,8 +15,8 @@ if [ -n "$1" ]; then
|
|||
fi
|
||||
|
||||
CAKEWALLET_NAME="Cake Wallet"
|
||||
CAKEWALLET_VERSION="1.0.3"
|
||||
CAKEWALLET_BUILD_NUMBER=20
|
||||
CAKEWALLET_VERSION="1.0.4"
|
||||
CAKEWALLET_BUILD_NUMBER=22
|
||||
CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet"
|
||||
|
||||
if ! [[ " ${TYPES[*]} " =~ " ${APP_MACOS_TYPE} " ]]; then
|
||||
|
|
Loading…
Reference in a new issue