mirror of
https://github.com/cake-tech/cake_wallet.git
synced 2024-12-23 12:09:43 +00:00
Merge branch 'main' of https://github.com/cake-tech/cake_wallet into CW-438-add-nano
This commit is contained in:
commit
82c7648897
58 changed files with 672 additions and 252 deletions
|
@ -1,6 +1,8 @@
|
|||
Improved edit/delete for nodes and wallets
|
||||
Wallets can now be renamed
|
||||
Accessibility improvements
|
||||
Improve Monero wallet rescan
|
||||
Additional exchange assets: SHIB, AAVE, ARB, BAT, COMP, CRO, ENS, FTM, FRAX, GUSD, GTC, GRT, LDO, NEXO, CAKE, PEPE, STORJ, TUSD, WBTC, WETH, ZRX, DYDX, STETH
|
||||
Cake Pay is temporarily removed, see https://cakelabs.com/news/cake-pay-mobile-to-shut-down/
|
||||
Monero background syncing! See https://guides.cakewallet.com/docs/monero/#background-syncing
|
||||
Cake 2FA access control settings! See https://guides.cakewallet.com/docs/advanced-features/authentication/#cake-2fa-presets-and-access-control-settings
|
||||
Support Monero node proxy
|
||||
UI improvements when sending to Address Book entry
|
||||
Allow renaming Monero account names
|
||||
Send templates now support multiple recipients (try using to make Monero change)
|
||||
Onramper improvements
|
||||
Scan node QR codes (for Umbrel)
|
|
@ -1,7 +1,9 @@
|
|||
Improved edit/delete for nodes and wallets
|
||||
Wallets can now be renamed
|
||||
Accessibility improvements
|
||||
Bitcoin transaction bug fixes
|
||||
Improve Monero wallet rescan
|
||||
Additional exchange assets: SHIB, AAVE, ARB, BAT, COMP, CRO, ENS, FTM, FRAX, GUSD, GTC, GRT, LDO, NEXO, CAKE, PEPE, STORJ, TUSD, WBTC, WETH, ZRX, DYDX, STETH
|
||||
Cake Pay is temporarily removed, see https://cakelabs.com/news/cake-pay-mobile-to-shut-down/
|
||||
Ethereum! Store ETH and ERC-20 tokens
|
||||
Monero background syncing! See https://guides.cakewallet.com/docs/monero/#background-syncing
|
||||
Cake 2FA access control settings! See https://guides.cakewallet.com/docs/advanced-features/authentication/#cake-2fa-presets-and-access-control-settings
|
||||
Support Monero node proxy
|
||||
UI improvements when sending to Address Book entry
|
||||
Allow renaming Monero/Haven account names
|
||||
Send templates now support multiple recipients (try using to make Monero change)
|
||||
Onramper improvements
|
||||
Scan node QR codes (for Umbrel)
|
|
@ -1,7 +1,9 @@
|
|||
import 'package:flutter/services.dart';
|
||||
|
||||
const utils = const MethodChannel('com.cake_wallet/native_utils');
|
||||
|
||||
void setIsAppSecureNative(bool isAppSecure) {
|
||||
utils.invokeMethod<Uint8List>('setIsAppSecure', {'isAppSecure': isAppSecure});
|
||||
}
|
||||
try {
|
||||
final utils = const MethodChannel('com.cake_wallet/native_utils');
|
||||
|
||||
utils.invokeMethod<Uint8List>('setIsAppSecure', {'isAppSecure': isAppSecure});
|
||||
} catch (_) {}
|
||||
}
|
||||
|
|
|
@ -134,6 +134,8 @@ PODS:
|
|||
- SDWebImage (5.16.0):
|
||||
- SDWebImage/Core (= 5.16.0)
|
||||
- SDWebImage/Core (5.16.0)
|
||||
- sensitive_clipboard (0.0.1):
|
||||
- Flutter
|
||||
- share_plus (0.0.1):
|
||||
- Flutter
|
||||
- shared_preferences_foundation (0.0.1):
|
||||
|
@ -150,6 +152,8 @@ PODS:
|
|||
- Flutter
|
||||
- wakelock (0.0.1):
|
||||
- Flutter
|
||||
- workmanager (0.0.1):
|
||||
- Flutter
|
||||
|
||||
DEPENDENCIES:
|
||||
- barcode_scan2 (from `.symlinks/plugins/barcode_scan2/ios`)
|
||||
|
@ -173,12 +177,14 @@ DEPENDENCIES:
|
|||
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/ios`)
|
||||
- permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`)
|
||||
- platform_device_id (from `.symlinks/plugins/platform_device_id/ios`)
|
||||
- sensitive_clipboard (from `.symlinks/plugins/sensitive_clipboard/ios`)
|
||||
- share_plus (from `.symlinks/plugins/share_plus/ios`)
|
||||
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/ios`)
|
||||
- uni_links (from `.symlinks/plugins/uni_links/ios`)
|
||||
- UnstoppableDomainsResolution (~> 4.0.0)
|
||||
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
|
||||
- wakelock (from `.symlinks/plugins/wakelock/ios`)
|
||||
- workmanager (from `.symlinks/plugins/workmanager/ios`)
|
||||
|
||||
SPEC REPOS:
|
||||
https://github.com/CocoaPods/Specs.git:
|
||||
|
@ -235,6 +241,8 @@ EXTERNAL SOURCES:
|
|||
:path: ".symlinks/plugins/permission_handler_apple/ios"
|
||||
platform_device_id:
|
||||
:path: ".symlinks/plugins/platform_device_id/ios"
|
||||
sensitive_clipboard:
|
||||
:path: ".symlinks/plugins/sensitive_clipboard/ios"
|
||||
share_plus:
|
||||
:path: ".symlinks/plugins/share_plus/ios"
|
||||
shared_preferences_foundation:
|
||||
|
@ -245,6 +253,8 @@ EXTERNAL SOURCES:
|
|||
:path: ".symlinks/plugins/url_launcher_ios/ios"
|
||||
wakelock:
|
||||
:path: ".symlinks/plugins/wakelock/ios"
|
||||
workmanager:
|
||||
:path: ".symlinks/plugins/workmanager/ios"
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
barcode_scan2: 0af2bb63c81b4565aab6cd78278e4c0fa136dbb0
|
||||
|
@ -270,11 +280,12 @@ SPEC CHECKSUMS:
|
|||
MTBBarcodeScanner: f453b33c4b7dfe545d8c6484ed744d55671788cb
|
||||
OrderedSet: aaeb196f7fef5a9edf55d89760da9176ad40b93c
|
||||
package_info: 873975fc26034f0b863a300ad47e7f1ac6c7ec62
|
||||
path_provider_foundation: eaf5b3e458fc0e5fbb9940fb09980e853fe058b8
|
||||
path_provider_foundation: 29f094ae23ebbca9d3d0cec13889cd9060c0e943
|
||||
permission_handler_apple: e76247795d700c14ea09e3a2d8855d41ee80a2e6
|
||||
platform_device_id: 81b3e2993881f87d0c82ef151dc274df4869aef5
|
||||
ReachabilitySwift: 985039c6f7b23a1da463388634119492ff86c825
|
||||
SDWebImage: 2aea163b50bfcb569a2726b6a754c54a4506fcf6
|
||||
sensitive_clipboard: d4866e5d176581536c27bb1618642ee83adca986
|
||||
share_plus: 056a1e8ac890df3e33cb503afffaf1e9b4fbae68
|
||||
shared_preferences_foundation: 5b919d13b803cadd15ed2dc053125c68730e5126
|
||||
SwiftProtobuf: 40bd808372cb8706108f22d28f8ab4a6b9bc6989
|
||||
|
@ -283,6 +294,7 @@ SPEC CHECKSUMS:
|
|||
UnstoppableDomainsResolution: c3c67f4d0a5e2437cb00d4bd50c2e00d6e743841
|
||||
url_launcher_ios: 08a3dfac5fb39e8759aeb0abbd5d9480f30fc8b4
|
||||
wakelock: d0fc7c864128eac40eba1617cb5264d9c940b46f
|
||||
workmanager: 0afdcf5628bbde6924c21af7836fed07b42e30e6
|
||||
|
||||
PODFILE CHECKSUM: 09df1114e7c360f55770d35a79356bf5446e0100
|
||||
|
||||
|
|
|
@ -606,4 +606,9 @@
|
|||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = 97C146E61CF9000F007C117D /* Project object */;
|
||||
SystemCapabilities = {
|
||||
com.apple.BackgroundModes = {
|
||||
enabled = 1;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import UIKit
|
||||
import Flutter
|
||||
import UnstoppableDomainsResolution
|
||||
import workmanager
|
||||
|
||||
@UIApplicationMain
|
||||
@objc class AppDelegate: FlutterAppDelegate {
|
||||
|
@ -16,6 +17,15 @@ import UnstoppableDomainsResolution
|
|||
UNUserNotificationCenter.current().delegate = self as? UNUserNotificationCenterDelegate
|
||||
}
|
||||
|
||||
WorkmanagerPlugin.setPluginRegistrantCallback { registry in
|
||||
// Registry in this case is the FlutterEngine that is created in Workmanager's
|
||||
// performFetchWithCompletionHandler or BGAppRefreshTask.
|
||||
// This will make other plugins available during a background operation.
|
||||
GeneratedPluginRegistrant.register(with: registry)
|
||||
}
|
||||
|
||||
WorkmanagerPlugin.registerTask(withIdentifier: "com.fotolockr.cakewallet.monero_sync_task")
|
||||
|
||||
makeSecure()
|
||||
|
||||
let controller : FlutterViewController = window?.rootViewController as! FlutterViewController
|
||||
|
|
|
@ -2,6 +2,10 @@
|
|||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>BGTaskSchedulerPermittedIdentifiers</key>
|
||||
<array>
|
||||
<string>com.fotolockr.cakewallet.monero_sync_task</string>
|
||||
</array>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||
<key>CFBundleDisplayName</key>
|
||||
|
@ -113,6 +117,7 @@
|
|||
<key>UIBackgroundModes</key>
|
||||
<array>
|
||||
<string>fetch</string>
|
||||
<string>processing</string>
|
||||
<string>remote-notification</string>
|
||||
</array>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
|
|
|
@ -243,6 +243,8 @@ class BackupService {
|
|||
final sortBalanceTokensBy = data[PreferencesKey.sortBalanceBy] as int?;
|
||||
final pinNativeTokenAtTop = data[PreferencesKey.pinNativeTokenAtTop] as bool?;
|
||||
final useEtherscan = data[PreferencesKey.useEtherscan] as bool?;
|
||||
final syncAll = data[PreferencesKey.syncAllKey] as bool?;
|
||||
final syncMode = data[PreferencesKey.syncModeKey] as int?;
|
||||
|
||||
await _sharedPreferences.setString(PreferencesKey.currentWalletName, currentWalletName);
|
||||
|
||||
|
@ -361,11 +363,11 @@ class BackupService {
|
|||
if (useEtherscan != null)
|
||||
await _sharedPreferences.setBool(PreferencesKey.useEtherscan, useEtherscan);
|
||||
|
||||
if (sortBalanceTokensBy != null)
|
||||
await _sharedPreferences.setInt(PreferencesKey.sortBalanceBy, sortBalanceTokensBy);
|
||||
if (syncAll != null)
|
||||
await _sharedPreferences.setBool(PreferencesKey.syncAllKey, syncAll);
|
||||
|
||||
if (pinNativeTokenAtTop != null)
|
||||
await _sharedPreferences.setBool(PreferencesKey.pinNativeTokenAtTop, pinNativeTokenAtTop);
|
||||
if (syncMode != null)
|
||||
await _sharedPreferences.setInt(PreferencesKey.syncModeKey, syncMode);
|
||||
|
||||
await preferencesFile.delete();
|
||||
}
|
||||
|
@ -516,6 +518,10 @@ class BackupService {
|
|||
_sharedPreferences.getBool(PreferencesKey.pinNativeTokenAtTop),
|
||||
PreferencesKey.useEtherscan:
|
||||
_sharedPreferences.getBool(PreferencesKey.useEtherscan),
|
||||
PreferencesKey.syncModeKey:
|
||||
_sharedPreferences.getInt(PreferencesKey.syncModeKey),
|
||||
PreferencesKey.syncAllKey:
|
||||
_sharedPreferences.getBool(PreferencesKey.syncAllKey),
|
||||
};
|
||||
|
||||
return json.encode(preferences);
|
||||
|
|
11
lib/di.dart
11
lib/di.dart
|
@ -4,6 +4,7 @@ import 'package:cake_wallet/anonpay/anonpay_invoice_info.dart';
|
|||
import 'package:cake_wallet/buy/onramper/onramper_buy_provider.dart';
|
||||
import 'package:cake_wallet/buy/payfura/payfura_buy_provider.dart';
|
||||
import 'package:cake_wallet/core/yat_service.dart';
|
||||
import 'package:cake_wallet/entities/background_tasks.dart';
|
||||
import 'package:cake_wallet/entities/exchange_api_mode.dart';
|
||||
import 'package:cake_wallet/entities/parse_address_from_domain.dart';
|
||||
import 'package:cake_wallet/entities/receive_page_option.dart';
|
||||
|
@ -24,6 +25,7 @@ import 'package:cake_wallet/src/screens/dashboard/widgets/transactions_page.dart
|
|||
import 'package:cake_wallet/src/screens/receive/anonpay_invoice_page.dart';
|
||||
import 'package:cake_wallet/src/screens/receive/anonpay_receive_page.dart';
|
||||
import 'package:cake_wallet/src/screens/settings/display_settings_page.dart';
|
||||
import 'package:cake_wallet/src/screens/settings/manage_nodes_page.dart';
|
||||
import 'package:cake_wallet/src/screens/settings/other_settings_page.dart';
|
||||
import 'package:cake_wallet/src/screens/settings/privacy_page.dart';
|
||||
import 'package:cake_wallet/src/screens/settings/security_backup_page.dart';
|
||||
|
@ -245,6 +247,10 @@ Future setup({
|
|||
getIt.registerSingletonAsync<SharedPreferences>(() => SharedPreferences.getInstance());
|
||||
}
|
||||
|
||||
if (!_isSetupFinished) {
|
||||
getIt.registerFactory(() => BackgroundTasks());
|
||||
}
|
||||
|
||||
final isBitcoinBuyEnabled = (secrets.wyreSecretKey.isNotEmpty) &&
|
||||
(secrets.wyreApiKey.isNotEmpty) &&
|
||||
(secrets.wyreAccountId.isNotEmpty);
|
||||
|
@ -682,8 +688,7 @@ Future setup({
|
|||
return NodeListViewModel(_nodeSource, appStore);
|
||||
});
|
||||
|
||||
getIt.registerFactory(
|
||||
() => ConnectionSyncPage(getIt.get<NodeListViewModel>(), getIt.get<DashboardViewModel>()));
|
||||
getIt.registerFactory(() => ConnectionSyncPage(getIt.get<DashboardViewModel>()));
|
||||
|
||||
getIt.registerFactory(
|
||||
() => SecurityBackupPage(getIt.get<SecuritySettingsViewModel>(), getIt.get<AuthService>()));
|
||||
|
@ -1058,5 +1063,7 @@ Future setup({
|
|||
),
|
||||
);
|
||||
|
||||
getIt.registerFactory<ManageNodesPage>(() => ManageNodesPage(getIt.get<NodeListViewModel>()));
|
||||
|
||||
_isSetupFinished = true;
|
||||
}
|
||||
|
|
164
lib/entities/background_tasks.dart
Normal file
164
lib/entities/background_tasks.dart
Normal file
|
@ -0,0 +1,164 @@
|
|||
import 'dart:io';
|
||||
|
||||
import 'package:cake_wallet/core/wallet_loading_service.dart';
|
||||
import 'package:cake_wallet/entities/preferences_key.dart';
|
||||
import 'package:cake_wallet/store/settings_store.dart';
|
||||
import 'package:cake_wallet/utils/device_info.dart';
|
||||
import 'package:cake_wallet/view_model/settings/sync_mode.dart';
|
||||
import 'package:cake_wallet/view_model/wallet_list/wallet_list_item.dart';
|
||||
import 'package:cake_wallet/view_model/wallet_list/wallet_list_view_model.dart';
|
||||
import 'package:cw_core/wallet_base.dart';
|
||||
import 'package:cw_core/wallet_type.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:workmanager/workmanager.dart';
|
||||
import 'package:cake_wallet/main.dart';
|
||||
import 'package:cake_wallet/di.dart';
|
||||
|
||||
const moneroSyncTaskKey = "com.fotolockr.cakewallet.monero_sync_task";
|
||||
|
||||
@pragma('vm:entry-point')
|
||||
void callbackDispatcher() {
|
||||
Workmanager().executeTask((task, inputData) async {
|
||||
try {
|
||||
switch (task) {
|
||||
case moneroSyncTaskKey:
|
||||
|
||||
/// The work manager runs on a separate isolate from the main flutter isolate.
|
||||
/// thus we initialize app configs first; hive, getIt, etc...
|
||||
await initializeAppConfigs();
|
||||
|
||||
final walletLoadingService = getIt.get<WalletLoadingService>();
|
||||
|
||||
final node = getIt.get<SettingsStore>().getCurrentNode(WalletType.monero);
|
||||
|
||||
final typeRaw = getIt.get<SharedPreferences>().getInt(PreferencesKey.currentWalletType);
|
||||
|
||||
WalletBase? wallet;
|
||||
|
||||
if (inputData!['sync_all'] as bool) {
|
||||
/// get all Monero wallets of the user and sync them
|
||||
final List<WalletListItem> moneroWallets = getIt
|
||||
.get<WalletListViewModel>()
|
||||
.wallets
|
||||
.where((element) => element.type == WalletType.monero)
|
||||
.toList();
|
||||
|
||||
for (int i = 0; i < moneroWallets.length; i++) {
|
||||
wallet = await walletLoadingService.load(WalletType.monero, moneroWallets[i].name);
|
||||
|
||||
await wallet.connectToNode(node: node);
|
||||
await wallet.startSync();
|
||||
}
|
||||
} else {
|
||||
/// if the user chose to sync only active wallet
|
||||
/// if the current wallet is monero; sync it only
|
||||
if (typeRaw == WalletType.monero.index) {
|
||||
final name =
|
||||
getIt.get<SharedPreferences>().getString(PreferencesKey.currentWalletName);
|
||||
|
||||
wallet = await walletLoadingService.load(WalletType.monero, name!);
|
||||
|
||||
await wallet.connectToNode(node: node);
|
||||
await wallet.startSync();
|
||||
}
|
||||
}
|
||||
|
||||
if (wallet?.syncStatus.progress() == null) {
|
||||
return Future.error("No Monero wallet found");
|
||||
}
|
||||
|
||||
for (int i = 0;; i++) {
|
||||
await Future<void>.delayed(const Duration(seconds: 1));
|
||||
if (wallet?.syncStatus.progress() == 1.0) {
|
||||
break;
|
||||
}
|
||||
if (i > 600) {
|
||||
return Future.error("Synchronization Timed out");
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return Future.value(true);
|
||||
} catch (error, stackTrace) {
|
||||
print(error);
|
||||
print(stackTrace);
|
||||
return Future.error(error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
class BackgroundTasks {
|
||||
void registerSyncTask({bool changeExisting = false}) async {
|
||||
try {
|
||||
bool hasMonero = getIt
|
||||
.get<WalletListViewModel>()
|
||||
.wallets
|
||||
.any((element) => element.type == WalletType.monero);
|
||||
|
||||
/// if its not android nor ios, or the user has no monero wallets; exit
|
||||
if (!DeviceInfo.instance.isMobile || !hasMonero) {
|
||||
return;
|
||||
}
|
||||
|
||||
final settingsStore = getIt.get<SettingsStore>();
|
||||
|
||||
final SyncMode syncMode = settingsStore.currentSyncMode;
|
||||
final bool syncAll = settingsStore.currentSyncAll;
|
||||
|
||||
if (syncMode.type == SyncType.disabled) {
|
||||
cancelSyncTask();
|
||||
return;
|
||||
}
|
||||
|
||||
await Workmanager().initialize(
|
||||
callbackDispatcher,
|
||||
isInDebugMode: kDebugMode,
|
||||
);
|
||||
|
||||
final inputData = <String, dynamic>{"sync_all": syncAll};
|
||||
final constraints = Constraints(
|
||||
networkType:
|
||||
syncMode.type == SyncType.unobtrusive ? NetworkType.unmetered : NetworkType.connected,
|
||||
requiresBatteryNotLow: syncMode.type == SyncType.unobtrusive,
|
||||
requiresCharging: syncMode.type == SyncType.unobtrusive,
|
||||
requiresDeviceIdle: syncMode.type == SyncType.unobtrusive,
|
||||
);
|
||||
|
||||
if (Platform.isIOS) {
|
||||
await Workmanager().registerOneOffTask(
|
||||
moneroSyncTaskKey,
|
||||
moneroSyncTaskKey,
|
||||
initialDelay: syncMode.frequency,
|
||||
existingWorkPolicy: ExistingWorkPolicy.replace,
|
||||
inputData: inputData,
|
||||
constraints: constraints,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
await Workmanager().registerPeriodicTask(
|
||||
moneroSyncTaskKey,
|
||||
moneroSyncTaskKey,
|
||||
initialDelay: syncMode.frequency,
|
||||
frequency: syncMode.frequency,
|
||||
existingWorkPolicy: changeExisting ? ExistingWorkPolicy.replace : ExistingWorkPolicy.keep,
|
||||
inputData: inputData,
|
||||
constraints: constraints,
|
||||
);
|
||||
} catch (error, stackTrace) {
|
||||
print(error);
|
||||
print(stackTrace);
|
||||
}
|
||||
}
|
||||
|
||||
void cancelSyncTask() {
|
||||
try {
|
||||
Workmanager().cancelByUniqueName(moneroSyncTaskKey);
|
||||
} catch (error, stackTrace) {
|
||||
print(error);
|
||||
print(stackTrace);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,8 +1,7 @@
|
|||
import 'package:cake_wallet/di.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:cake_wallet/store/app_store.dart';
|
||||
import 'package:cake_wallet/core/key_service.dart';
|
||||
import 'package:cw_core/wallet_service.dart';
|
||||
import 'package:cake_wallet/entities/background_tasks.dart';
|
||||
import 'package:cake_wallet/entities/preferences_key.dart';
|
||||
import 'package:cw_core/wallet_type.dart';
|
||||
import 'package:cake_wallet/core/wallet_loading_service.dart';
|
||||
|
@ -24,4 +23,6 @@ Future<void> loadCurrentWallet() async {
|
|||
final walletLoadingService = getIt.get<WalletLoadingService>();
|
||||
final wallet = await walletLoadingService.load(type, name);
|
||||
appStore.changeCurrentWallet(wallet);
|
||||
|
||||
getIt.get<BackgroundTasks>().registerSyncTask();
|
||||
}
|
||||
|
|
|
@ -37,6 +37,8 @@ class PreferencesKey {
|
|||
static const shouldShowReceiveWarning = 'should_show_receive_warning';
|
||||
static const shouldShowYatPopup = 'should_show_yat_popup';
|
||||
static const moneroWalletPasswordUpdateV1Base = 'monero_wallet_update_v1';
|
||||
static const syncModeKey = 'sync_mode';
|
||||
static const syncAllKey = 'sync_all';
|
||||
static const pinTimeOutDuration = 'pin_timeout_duration';
|
||||
static const lastAuthTimeMilliseconds = 'last_auth_time_milliseconds';
|
||||
static const lastPopupDate = 'last_popup_date';
|
||||
|
|
172
lib/main.dart
172
lib/main.dart
|
@ -57,97 +57,103 @@ Future<void> main() async {
|
|||
return true;
|
||||
};
|
||||
|
||||
final appDir = await getApplicationDocumentsDirectory();
|
||||
await Hive.close();
|
||||
Hive.init(appDir.path);
|
||||
|
||||
if (!Hive.isAdapterRegistered(Contact.typeId)) {
|
||||
Hive.registerAdapter(ContactAdapter());
|
||||
}
|
||||
await initializeAppConfigs();
|
||||
|
||||
if (!Hive.isAdapterRegistered(Node.typeId)) {
|
||||
Hive.registerAdapter(NodeAdapter());
|
||||
}
|
||||
|
||||
if (!Hive.isAdapterRegistered(TransactionDescription.typeId)) {
|
||||
Hive.registerAdapter(TransactionDescriptionAdapter());
|
||||
}
|
||||
|
||||
if (!Hive.isAdapterRegistered(Trade.typeId)) {
|
||||
Hive.registerAdapter(TradeAdapter());
|
||||
}
|
||||
|
||||
if (!Hive.isAdapterRegistered(WalletInfo.typeId)) {
|
||||
Hive.registerAdapter(WalletInfoAdapter());
|
||||
}
|
||||
|
||||
if (!Hive.isAdapterRegistered(walletTypeTypeId)) {
|
||||
Hive.registerAdapter(WalletTypeAdapter());
|
||||
}
|
||||
|
||||
if (!Hive.isAdapterRegistered(Template.typeId)) {
|
||||
Hive.registerAdapter(TemplateAdapter());
|
||||
}
|
||||
|
||||
if (!Hive.isAdapterRegistered(ExchangeTemplate.typeId)) {
|
||||
Hive.registerAdapter(ExchangeTemplateAdapter());
|
||||
}
|
||||
|
||||
if (!Hive.isAdapterRegistered(Order.typeId)) {
|
||||
Hive.registerAdapter(OrderAdapter());
|
||||
}
|
||||
|
||||
if (!isMoneroOnly && !Hive.isAdapterRegistered(UnspentCoinsInfo.typeId)) {
|
||||
Hive.registerAdapter(UnspentCoinsInfoAdapter());
|
||||
}
|
||||
|
||||
if (!Hive.isAdapterRegistered(AnonpayInvoiceInfo.typeId)) {
|
||||
Hive.registerAdapter(AnonpayInvoiceInfoAdapter());
|
||||
}
|
||||
|
||||
final secureStorage = FlutterSecureStorage();
|
||||
final transactionDescriptionsBoxKey =
|
||||
await getEncryptionKey(secureStorage: secureStorage, forKey: TransactionDescription.boxKey);
|
||||
final tradesBoxKey = await getEncryptionKey(secureStorage: secureStorage, forKey: Trade.boxKey);
|
||||
final ordersBoxKey = await getEncryptionKey(secureStorage: secureStorage, forKey: Order.boxKey);
|
||||
final contacts = await Hive.openBox<Contact>(Contact.boxName);
|
||||
final nodes = await Hive.openBox<Node>(Node.boxName);
|
||||
final transactionDescriptions = await Hive.openBox<TransactionDescription>(
|
||||
TransactionDescription.boxName,
|
||||
encryptionKey: transactionDescriptionsBoxKey);
|
||||
final trades = await Hive.openBox<Trade>(Trade.boxName, encryptionKey: tradesBoxKey);
|
||||
final orders = await Hive.openBox<Order>(Order.boxName, encryptionKey: ordersBoxKey);
|
||||
final walletInfoSource = await Hive.openBox<WalletInfo>(WalletInfo.boxName);
|
||||
final templates = await Hive.openBox<Template>(Template.boxName);
|
||||
final exchangeTemplates = await Hive.openBox<ExchangeTemplate>(ExchangeTemplate.boxName);
|
||||
final anonpayInvoiceInfo = await Hive.openBox<AnonpayInvoiceInfo>(AnonpayInvoiceInfo.boxName);
|
||||
Box<UnspentCoinsInfo>? unspentCoinsInfoSource;
|
||||
|
||||
if (!isMoneroOnly) {
|
||||
unspentCoinsInfoSource = await Hive.openBox<UnspentCoinsInfo>(UnspentCoinsInfo.boxName);
|
||||
}
|
||||
|
||||
await initialSetup(
|
||||
sharedPreferences: await SharedPreferences.getInstance(),
|
||||
nodes: nodes,
|
||||
walletInfoSource: walletInfoSource,
|
||||
contactSource: contacts,
|
||||
tradesSource: trades,
|
||||
ordersSource: orders,
|
||||
unspentCoinsInfoSource: unspentCoinsInfoSource,
|
||||
// fiatConvertationService: fiatConvertationService,
|
||||
templates: templates,
|
||||
exchangeTemplates: exchangeTemplates,
|
||||
transactionDescriptions: transactionDescriptions,
|
||||
secureStorage: secureStorage,
|
||||
anonpayInvoiceInfo: anonpayInvoiceInfo,
|
||||
initialMigrationVersion: 22);
|
||||
runApp(App());
|
||||
}, (error, stackTrace) async {
|
||||
ExceptionHandler.onError(FlutterErrorDetails(exception: error, stack: stackTrace));
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> initializeAppConfigs() async {
|
||||
final appDir = await getApplicationDocumentsDirectory();
|
||||
Hive.init(appDir.path);
|
||||
|
||||
if (!Hive.isAdapterRegistered(Contact.typeId)) {
|
||||
Hive.registerAdapter(ContactAdapter());
|
||||
}
|
||||
|
||||
if (!Hive.isAdapterRegistered(Node.typeId)) {
|
||||
Hive.registerAdapter(NodeAdapter());
|
||||
}
|
||||
|
||||
if (!Hive.isAdapterRegistered(TransactionDescription.typeId)) {
|
||||
Hive.registerAdapter(TransactionDescriptionAdapter());
|
||||
}
|
||||
|
||||
if (!Hive.isAdapterRegistered(Trade.typeId)) {
|
||||
Hive.registerAdapter(TradeAdapter());
|
||||
}
|
||||
|
||||
if (!Hive.isAdapterRegistered(WalletInfo.typeId)) {
|
||||
Hive.registerAdapter(WalletInfoAdapter());
|
||||
}
|
||||
|
||||
if (!Hive.isAdapterRegistered(walletTypeTypeId)) {
|
||||
Hive.registerAdapter(WalletTypeAdapter());
|
||||
}
|
||||
|
||||
if (!Hive.isAdapterRegistered(Template.typeId)) {
|
||||
Hive.registerAdapter(TemplateAdapter());
|
||||
}
|
||||
|
||||
if (!Hive.isAdapterRegistered(ExchangeTemplate.typeId)) {
|
||||
Hive.registerAdapter(ExchangeTemplateAdapter());
|
||||
}
|
||||
|
||||
if (!Hive.isAdapterRegistered(Order.typeId)) {
|
||||
Hive.registerAdapter(OrderAdapter());
|
||||
}
|
||||
|
||||
if (!isMoneroOnly && !Hive.isAdapterRegistered(UnspentCoinsInfo.typeId)) {
|
||||
Hive.registerAdapter(UnspentCoinsInfoAdapter());
|
||||
}
|
||||
|
||||
if (!Hive.isAdapterRegistered(AnonpayInvoiceInfo.typeId)) {
|
||||
Hive.registerAdapter(AnonpayInvoiceInfoAdapter());
|
||||
}
|
||||
|
||||
final secureStorage = FlutterSecureStorage();
|
||||
final transactionDescriptionsBoxKey =
|
||||
await getEncryptionKey(secureStorage: secureStorage, forKey: TransactionDescription.boxKey);
|
||||
final tradesBoxKey = await getEncryptionKey(secureStorage: secureStorage, forKey: Trade.boxKey);
|
||||
final ordersBoxKey = await getEncryptionKey(secureStorage: secureStorage, forKey: Order.boxKey);
|
||||
final contacts = await Hive.openBox<Contact>(Contact.boxName);
|
||||
final nodes = await Hive.openBox<Node>(Node.boxName);
|
||||
final transactionDescriptions = await Hive.openBox<TransactionDescription>(
|
||||
TransactionDescription.boxName,
|
||||
encryptionKey: transactionDescriptionsBoxKey);
|
||||
final trades = await Hive.openBox<Trade>(Trade.boxName, encryptionKey: tradesBoxKey);
|
||||
final orders = await Hive.openBox<Order>(Order.boxName, encryptionKey: ordersBoxKey);
|
||||
final walletInfoSource = await Hive.openBox<WalletInfo>(WalletInfo.boxName);
|
||||
final templates = await Hive.openBox<Template>(Template.boxName);
|
||||
final exchangeTemplates = await Hive.openBox<ExchangeTemplate>(ExchangeTemplate.boxName);
|
||||
final anonpayInvoiceInfo = await Hive.openBox<AnonpayInvoiceInfo>(AnonpayInvoiceInfo.boxName);
|
||||
Box<UnspentCoinsInfo>? unspentCoinsInfoSource;
|
||||
|
||||
if (!isMoneroOnly) {
|
||||
unspentCoinsInfoSource = await Hive.openBox<UnspentCoinsInfo>(UnspentCoinsInfo.boxName);
|
||||
}
|
||||
|
||||
await initialSetup(
|
||||
sharedPreferences: await SharedPreferences.getInstance(),
|
||||
nodes: nodes,
|
||||
walletInfoSource: walletInfoSource,
|
||||
contactSource: contacts,
|
||||
tradesSource: trades,
|
||||
ordersSource: orders,
|
||||
unspentCoinsInfoSource: unspentCoinsInfoSource,
|
||||
// fiatConvertationService: fiatConvertationService,
|
||||
templates: templates,
|
||||
exchangeTemplates: exchangeTemplates,
|
||||
transactionDescriptions: transactionDescriptions,
|
||||
secureStorage: secureStorage,
|
||||
anonpayInvoiceInfo: anonpayInvoiceInfo,
|
||||
initialMigrationVersion: 21);
|
||||
}
|
||||
|
||||
Future<void> initialSetup(
|
||||
{required SharedPreferences sharedPreferences,
|
||||
required Box<Node> nodes,
|
||||
|
@ -319,7 +325,7 @@ class _HomeState extends State<_Home> {
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return const SizedBox.shrink();
|
||||
|
|
|
@ -20,6 +20,7 @@ import 'package:cake_wallet/src/screens/dashboard/desktop_widgets/desktop_dashbo
|
|||
import 'package:cake_wallet/src/screens/dashboard/widgets/transactions_page.dart';
|
||||
import 'package:cake_wallet/src/screens/settings/desktop_settings/desktop_settings_page.dart';
|
||||
import 'package:cake_wallet/src/screens/settings/display_settings_page.dart';
|
||||
import 'package:cake_wallet/src/screens/settings/manage_nodes_page.dart';
|
||||
import 'package:cake_wallet/src/screens/settings/other_settings_page.dart';
|
||||
import 'package:cake_wallet/src/screens/settings/privacy_page.dart';
|
||||
import 'package:cake_wallet/src/screens/settings/security_backup_page.dart';
|
||||
|
@ -569,6 +570,9 @@ Route<dynamic> createRoute(RouteSettings settings) {
|
|||
),
|
||||
);
|
||||
|
||||
case Routes.manageNodes:
|
||||
return MaterialPageRoute<void>(builder: (_) => getIt.get<ManageNodesPage>());
|
||||
|
||||
default:
|
||||
return MaterialPageRoute<void>(
|
||||
builder: (_) => Scaffold(
|
||||
|
|
|
@ -91,4 +91,5 @@ class Routes {
|
|||
static const modify2FAPage = '/modify_2fa_page';
|
||||
static const homeSettings = '/home_settings';
|
||||
static const editToken = '/edit_token';
|
||||
static const manageNodes = '/manage_nodes';
|
||||
}
|
||||
|
|
|
@ -298,24 +298,7 @@ class _DashboardPageView extends BasePage {
|
|||
}
|
||||
});
|
||||
|
||||
final sharedPrefs = await SharedPreferences.getInstance();
|
||||
final currentAppVersion =
|
||||
VersionComparator.getExtendedVersionNumber(dashboardViewModel.settingsStore.appVersion);
|
||||
final lastSeenAppVersion = sharedPrefs.getInt(PreferencesKey.lastSeenAppVersion);
|
||||
final isNewInstall = sharedPrefs.getBool(PreferencesKey.isNewInstall);
|
||||
|
||||
if (currentAppVersion != lastSeenAppVersion && !isNewInstall!) {
|
||||
await Future<void>.delayed(Duration(seconds: 1));
|
||||
await showPopUp<void>(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return ReleaseNotesScreen(
|
||||
title: 'Version ${dashboardViewModel.settingsStore.appVersion}');
|
||||
});
|
||||
sharedPrefs.setInt(PreferencesKey.lastSeenAppVersion, currentAppVersion);
|
||||
} else if (isNewInstall!) {
|
||||
sharedPrefs.setInt(PreferencesKey.lastSeenAppVersion, currentAppVersion);
|
||||
}
|
||||
_showReleaseNotesPopup(context);
|
||||
|
||||
var needToPresentYat = false;
|
||||
var isInactive = false;
|
||||
|
@ -341,4 +324,27 @@ class _DashboardPageView extends BasePage {
|
|||
needToPresentYat = true;
|
||||
});
|
||||
}
|
||||
|
||||
void _showReleaseNotesPopup(BuildContext context) async {
|
||||
final sharedPrefs = await SharedPreferences.getInstance();
|
||||
final currentAppVersion =
|
||||
VersionComparator.getExtendedVersionNumber(dashboardViewModel.settingsStore.appVersion);
|
||||
final lastSeenAppVersion = sharedPrefs.getInt(PreferencesKey.lastSeenAppVersion);
|
||||
final isNewInstall = sharedPrefs.getBool(PreferencesKey.isNewInstall);
|
||||
|
||||
if (currentAppVersion != lastSeenAppVersion && !isNewInstall!) {
|
||||
Future<void>.delayed(Duration(seconds: 1), () {
|
||||
showPopUp<void>(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return ReleaseNotesScreen(
|
||||
title: 'Version ${dashboardViewModel.settingsStore.appVersion}');
|
||||
});
|
||||
});
|
||||
|
||||
sharedPrefs.setInt(PreferencesKey.lastSeenAppVersion, currentAppVersion);
|
||||
} else if (isNewInstall!) {
|
||||
sharedPrefs.setInt(PreferencesKey.lastSeenAppVersion, currentAppVersion);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,25 +1,25 @@
|
|||
import 'package:cake_wallet/src/screens/settings/widgets/settings_cell_with_arrow.dart';
|
||||
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/utils/device_info.dart';
|
||||
import 'package:cake_wallet/utils/show_pop_up.dart';
|
||||
import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart';
|
||||
import 'package:cw_core/node.dart';
|
||||
import 'package:cake_wallet/view_model/settings/sync_mode.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter_mobx/flutter_mobx.dart';
|
||||
import 'package:cake_wallet/routes.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/src/screens/base_page.dart';
|
||||
import 'package:cake_wallet/src/screens/nodes/widgets/node_list_row.dart';
|
||||
import 'package:cake_wallet/src/widgets/standard_list.dart';
|
||||
import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart';
|
||||
import 'package:cake_wallet/view_model/node_list/node_list_view_model.dart';
|
||||
import 'package:flutter_mobx/flutter_mobx.dart';
|
||||
|
||||
class ConnectionSyncPage extends BasePage {
|
||||
ConnectionSyncPage(this.nodeListViewModel, this.dashboardViewModel);
|
||||
ConnectionSyncPage(this.dashboardViewModel);
|
||||
|
||||
@override
|
||||
String get title => S.current.connection_sync;
|
||||
|
||||
final NodeListViewModel nodeListViewModel;
|
||||
final DashboardViewModel dashboardViewModel;
|
||||
|
||||
@override
|
||||
|
@ -33,72 +33,39 @@ class ConnectionSyncPage extends BasePage {
|
|||
title: S.current.reconnect,
|
||||
handler: (context) => _presentReconnectAlert(context),
|
||||
),
|
||||
StandardListSeparator(padding: EdgeInsets.symmetric(horizontal: 24)),
|
||||
if (dashboardViewModel.hasRescan)
|
||||
const StandardListSeparator(padding: EdgeInsets.symmetric(horizontal: 24)),
|
||||
if (dashboardViewModel.hasRescan) ...[
|
||||
SettingsCellWithArrow(
|
||||
title: S.current.rescan,
|
||||
handler: (context) => Navigator.of(context).pushNamed(Routes.rescan),
|
||||
),
|
||||
StandardListSeparator(padding: EdgeInsets.symmetric(horizontal: 24)),
|
||||
Semantics(
|
||||
button: true,
|
||||
child: NodeHeaderListRow(
|
||||
title: S.of(context).add_new_node,
|
||||
onTap: (_) async =>
|
||||
await Navigator.of(context).pushNamed(Routes.newNode),
|
||||
),
|
||||
),
|
||||
StandardListSeparator(padding: EdgeInsets.symmetric(horizontal: 24)),
|
||||
SizedBox(height: 100),
|
||||
Observer(
|
||||
builder: (BuildContext context) {
|
||||
return Flexible(
|
||||
child: SectionStandardList(
|
||||
sectionCount: 1,
|
||||
context: context,
|
||||
dividerPadding: EdgeInsets.symmetric(horizontal: 24),
|
||||
itemCounter: (int sectionIndex) {
|
||||
return nodeListViewModel.nodes.length;
|
||||
},
|
||||
itemBuilder: (_, sectionIndex, index) {
|
||||
final node = nodeListViewModel.nodes[index];
|
||||
final isSelected = node.keyIndex == nodeListViewModel.currentNode.keyIndex;
|
||||
final nodeListRow = NodeListRow(
|
||||
title: node.uriRaw,
|
||||
node: node,
|
||||
isSelected: isSelected,
|
||||
onTap: (_) async {
|
||||
if (isSelected) {
|
||||
return;
|
||||
}
|
||||
|
||||
await showPopUp<void>(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return AlertWithTwoActions(
|
||||
alertTitle:
|
||||
S.of(context).change_current_node_title,
|
||||
alertContent: nodeListViewModel
|
||||
.getAlertContent(node.uriRaw),
|
||||
leftButtonText: S.of(context).cancel,
|
||||
rightButtonText: S.of(context).change,
|
||||
actionLeftButton: () =>
|
||||
Navigator.of(context).pop(),
|
||||
actionRightButton: () async {
|
||||
await nodeListViewModel.setAsCurrent(node);
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
);
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
return nodeListRow;
|
||||
},
|
||||
),
|
||||
);
|
||||
},
|
||||
const StandardListSeparator(padding: EdgeInsets.symmetric(horizontal: 24)),
|
||||
if (DeviceInfo.instance.isMobile) ...[
|
||||
Observer(builder: (context) {
|
||||
return SettingsPickerCell<SyncMode>(
|
||||
title: S.current.background_sync_mode,
|
||||
items: SyncMode.all,
|
||||
displayItem: (SyncMode syncMode) => syncMode.name,
|
||||
selectedItem: dashboardViewModel.syncMode,
|
||||
onItemSelected: dashboardViewModel.setSyncMode,
|
||||
);
|
||||
}),
|
||||
const StandardListSeparator(padding: EdgeInsets.symmetric(horizontal: 24)),
|
||||
Observer(builder: (context) {
|
||||
return SettingsSwitcherCell(
|
||||
title: S.current.sync_all_wallets,
|
||||
value: dashboardViewModel.syncAll,
|
||||
onValueChange: (_, bool value) => dashboardViewModel.setSyncAll(value),
|
||||
);
|
||||
}),
|
||||
const StandardListSeparator(padding: EdgeInsets.symmetric(horizontal: 24)),
|
||||
],
|
||||
],
|
||||
SettingsCellWithArrow(
|
||||
title: S.current.manage_nodes,
|
||||
handler: (context) => Navigator.of(context).pushNamed(Routes.manageNodes),
|
||||
),
|
||||
const StandardListSeparator(padding: EdgeInsets.symmetric(horizontal: 24)),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
|
85
lib/src/screens/settings/manage_nodes_page.dart
Normal file
85
lib/src/screens/settings/manage_nodes_page.dart
Normal file
|
@ -0,0 +1,85 @@
|
|||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/routes.dart';
|
||||
import 'package:cake_wallet/src/screens/base_page.dart';
|
||||
import 'package:cake_wallet/src/screens/nodes/widgets/node_list_row.dart';
|
||||
import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart';
|
||||
import 'package:cake_wallet/src/widgets/standard_list.dart';
|
||||
import 'package:cake_wallet/utils/show_pop_up.dart';
|
||||
import 'package:cake_wallet/view_model/node_list/node_list_view_model.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_mobx/flutter_mobx.dart';
|
||||
|
||||
class ManageNodesPage extends BasePage {
|
||||
ManageNodesPage(this.nodeListViewModel);
|
||||
|
||||
final NodeListViewModel nodeListViewModel;
|
||||
|
||||
@override
|
||||
String get title => S.current.manage_nodes;
|
||||
|
||||
@override
|
||||
Widget body(BuildContext context) {
|
||||
return Padding(
|
||||
padding: EdgeInsets.only(top: 10),
|
||||
child: Column(
|
||||
children: [
|
||||
Semantics(
|
||||
button: true,
|
||||
child: NodeHeaderListRow(
|
||||
title: S.of(context).add_new_node,
|
||||
onTap: (_) async => await Navigator.of(context).pushNamed(Routes.newNode),
|
||||
),
|
||||
),
|
||||
const StandardListSeparator(padding: EdgeInsets.symmetric(horizontal: 24)),
|
||||
SizedBox(height: 20),
|
||||
Observer(
|
||||
builder: (BuildContext context) {
|
||||
return Flexible(
|
||||
child: SectionStandardList(
|
||||
sectionCount: 1,
|
||||
context: context,
|
||||
dividerPadding: EdgeInsets.symmetric(horizontal: 24),
|
||||
itemCounter: (int sectionIndex) {
|
||||
return nodeListViewModel.nodes.length;
|
||||
},
|
||||
itemBuilder: (_, sectionIndex, index) {
|
||||
final node = nodeListViewModel.nodes[index];
|
||||
final isSelected = node.keyIndex == nodeListViewModel.currentNode.keyIndex;
|
||||
final nodeListRow = NodeListRow(
|
||||
title: node.uriRaw,
|
||||
node: node,
|
||||
isSelected: isSelected,
|
||||
onTap: (_) async {
|
||||
if (isSelected) {
|
||||
return;
|
||||
}
|
||||
|
||||
await showPopUp<void>(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return AlertWithTwoActions(
|
||||
alertTitle: S.of(context).change_current_node_title,
|
||||
alertContent: nodeListViewModel.getAlertContent(node.uriRaw),
|
||||
leftButtonText: S.of(context).cancel,
|
||||
rightButtonText: S.of(context).change,
|
||||
actionLeftButton: () => Navigator.of(context).pop(),
|
||||
actionRightButton: () async {
|
||||
await nodeListViewModel.setAsCurrent(node);
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
);
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
return nodeListRow;
|
||||
},
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -20,33 +20,38 @@ class OtherSettingsPage extends BasePage {
|
|||
|
||||
@override
|
||||
Widget body(BuildContext context) {
|
||||
return Observer(builder: (_) {
|
||||
return Container(
|
||||
padding: EdgeInsets.only(top: 10),
|
||||
child: Column(children: [
|
||||
SettingsPickerCell(
|
||||
title: S.current.settings_fee_priority,
|
||||
items: priorityForWalletType(_otherSettingsViewModel.walletType),
|
||||
displayItem: _otherSettingsViewModel.getDisplayPriority,
|
||||
selectedItem: _otherSettingsViewModel.transactionPriority,
|
||||
onItemSelected: _otherSettingsViewModel.onDisplayPrioritySelected,
|
||||
return Observer(
|
||||
builder: (_) {
|
||||
return Container(
|
||||
padding: EdgeInsets.only(top: 10),
|
||||
child: Column(
|
||||
children: [
|
||||
SettingsPickerCell(
|
||||
title: S.current.settings_fee_priority,
|
||||
items: priorityForWalletType(_otherSettingsViewModel.walletType),
|
||||
displayItem: _otherSettingsViewModel.getDisplayPriority,
|
||||
selectedItem: _otherSettingsViewModel.transactionPriority,
|
||||
onItemSelected: _otherSettingsViewModel.onDisplayPrioritySelected,
|
||||
),
|
||||
if (_otherSettingsViewModel.changeRepresentativeEnabled)
|
||||
SettingsCellWithArrow(
|
||||
title: S.current.change_rep,
|
||||
handler: (BuildContext context) =>
|
||||
Navigator.of(context).pushNamed(Routes.changeRep),
|
||||
),
|
||||
SettingsCellWithArrow(
|
||||
title: S.current.settings_terms_and_conditions,
|
||||
handler: (BuildContext context) =>
|
||||
Navigator.of(context).pushNamed(Routes.readDisclaimer),
|
||||
),
|
||||
StandardListSeparator(padding: EdgeInsets.symmetric(horizontal: 24)),
|
||||
Spacer(),
|
||||
SettingsVersionCell(
|
||||
title: S.of(context).version(_otherSettingsViewModel.currentVersion)),
|
||||
],
|
||||
),
|
||||
if (_otherSettingsViewModel.changeRepresentativeEnabled)
|
||||
SettingsCellWithArrow(
|
||||
title: S.current.change_rep,
|
||||
handler: (BuildContext context) =>
|
||||
Navigator.of(context).pushNamed(Routes.changeRep),
|
||||
),
|
||||
SettingsCellWithArrow(
|
||||
title: S.current.settings_terms_and_conditions,
|
||||
handler: (BuildContext context) =>
|
||||
Navigator.of(context).pushNamed(Routes.readDisclaimer),
|
||||
),
|
||||
StandardListSeparator(padding: EdgeInsets.symmetric(horizontal: 24)),
|
||||
Spacer(),
|
||||
SettingsVersionCell(title: S.of(context).version(_otherSettingsViewModel.currentVersion))
|
||||
]),
|
||||
);
|
||||
});
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -78,7 +78,7 @@ class SectionHeaderListRow extends StatelessWidget {
|
|||
|
||||
class StandardListSeparator extends StatelessWidget {
|
||||
|
||||
StandardListSeparator({this.padding, this.height = 1});
|
||||
const StandardListSeparator({this.padding, this.height = 1});
|
||||
|
||||
final EdgeInsets? padding;
|
||||
final double height;
|
||||
|
|
|
@ -2,10 +2,12 @@ import 'dart:io';
|
|||
|
||||
import 'package:cake_wallet/bitcoin/bitcoin.dart';
|
||||
import 'package:cake_wallet/entities/cake_2fa_preset_options.dart';
|
||||
import 'package:cake_wallet/entities/background_tasks.dart';
|
||||
import 'package:cake_wallet/entities/exchange_api_mode.dart';
|
||||
import 'package:cake_wallet/entities/pin_code_required_duration.dart';
|
||||
import 'package:cake_wallet/entities/preferences_key.dart';
|
||||
import 'package:cake_wallet/entities/sort_balance_types.dart';
|
||||
import 'package:cake_wallet/view_model/settings/sync_mode.dart';
|
||||
import 'package:cake_wallet/utils/device_info.dart';
|
||||
import 'package:cake_wallet/ethereum/ethereum.dart';
|
||||
import 'package:cw_core/transaction_priority.dart';
|
||||
|
@ -34,7 +36,8 @@ class SettingsStore = SettingsStoreBase with _$SettingsStore;
|
|||
|
||||
abstract class SettingsStoreBase with Store {
|
||||
SettingsStoreBase(
|
||||
{required SharedPreferences sharedPreferences,
|
||||
{required BackgroundTasks backgroundTasks,
|
||||
required SharedPreferences sharedPreferences,
|
||||
required bool initialShouldShowMarketPlaceInDashboard,
|
||||
required FiatCurrency initialFiatCurrency,
|
||||
required BalanceDisplayMode initialBalanceDisplayMode,
|
||||
|
@ -51,6 +54,8 @@ abstract class SettingsStoreBase with Store {
|
|||
required ThemeBase initialTheme,
|
||||
required int initialPinLength,
|
||||
required String initialLanguageCode,
|
||||
required SyncMode initialSyncMode,
|
||||
required bool initialSyncAll,
|
||||
// required String initialCurrentLocale,
|
||||
required this.appVersion,
|
||||
required this.deviceName,
|
||||
|
@ -78,6 +83,7 @@ abstract class SettingsStoreBase with Store {
|
|||
TransactionPriority? initialEthereumTransactionPriority})
|
||||
: nodes = ObservableMap<WalletType, Node>.of(nodes),
|
||||
_sharedPreferences = sharedPreferences,
|
||||
_backgroundTasks = backgroundTasks,
|
||||
fiatCurrency = initialFiatCurrency,
|
||||
balanceDisplayMode = initialBalanceDisplayMode,
|
||||
shouldSaveRecipientAddress = initialSaveRecipientAddress,
|
||||
|
@ -107,6 +113,8 @@ abstract class SettingsStoreBase with Store {
|
|||
initialShouldRequireTOTP2FAForCreatingNewWallets,
|
||||
shouldRequireTOTP2FAForAllSecurityAndBackupSettings =
|
||||
initialShouldRequireTOTP2FAForAllSecurityAndBackupSettings,
|
||||
currentSyncMode = initialSyncMode,
|
||||
currentSyncAll = initialSyncAll,
|
||||
priority = ObservableMap<WalletType, TransactionPriority>() {
|
||||
//this.nodes = ObservableMap<WalletType, Node>.of(nodes);
|
||||
|
||||
|
@ -287,6 +295,18 @@ abstract class SettingsStoreBase with Store {
|
|||
(BalanceDisplayMode mode) => sharedPreferences.setInt(
|
||||
PreferencesKey.currentBalanceDisplayModeKey, mode.serialize()));
|
||||
|
||||
reaction((_) => currentSyncMode, (SyncMode syncMode) {
|
||||
sharedPreferences.setInt(PreferencesKey.syncModeKey, syncMode.type.index);
|
||||
|
||||
_backgroundTasks.registerSyncTask(changeExisting: true);
|
||||
});
|
||||
|
||||
reaction((_) => currentSyncAll, (bool syncAll) {
|
||||
sharedPreferences.setBool(PreferencesKey.syncAllKey, syncAll);
|
||||
|
||||
_backgroundTasks.registerSyncTask(changeExisting: true);
|
||||
});
|
||||
|
||||
reaction(
|
||||
(_) => exchangeStatus,
|
||||
(ExchangeApiMode mode) =>
|
||||
|
@ -422,11 +442,18 @@ abstract class SettingsStoreBase with Store {
|
|||
@observable
|
||||
bool useEtherscan;
|
||||
|
||||
@observable
|
||||
SyncMode currentSyncMode;
|
||||
|
||||
@observable
|
||||
bool currentSyncAll;
|
||||
|
||||
String appVersion;
|
||||
|
||||
String deviceName;
|
||||
|
||||
SharedPreferences _sharedPreferences;
|
||||
final SharedPreferences _sharedPreferences;
|
||||
final BackgroundTasks _backgroundTasks;
|
||||
|
||||
ObservableMap<WalletType, Node> nodes;
|
||||
|
||||
|
@ -455,6 +482,7 @@ abstract class SettingsStoreBase with Store {
|
|||
BalanceDisplayMode initialBalanceDisplayMode = BalanceDisplayMode.availableBalance,
|
||||
ThemeBase? initialTheme}) async {
|
||||
final sharedPreferences = await getIt.getAsync<SharedPreferences>();
|
||||
final backgroundTasks = getIt.get<BackgroundTasks>();
|
||||
final currentFiatCurrency = FiatCurrency.deserialize(
|
||||
raw: sharedPreferences.getString(PreferencesKey.currentFiatCurrencyKey)!);
|
||||
|
||||
|
@ -602,6 +630,11 @@ abstract class SettingsStoreBase with Store {
|
|||
if (nanoNode != null) {
|
||||
nodes[WalletType.nano] = nanoNode;
|
||||
}
|
||||
|
||||
final savedSyncMode = SyncMode.all.firstWhere((element) {
|
||||
return element.type.index == (sharedPreferences.getInt(PreferencesKey.syncModeKey) ?? 1);
|
||||
});
|
||||
final savedSyncAll = sharedPreferences.getBool(PreferencesKey.syncAllKey) ?? true;
|
||||
|
||||
return SettingsStore(
|
||||
sharedPreferences: sharedPreferences,
|
||||
|
@ -647,6 +680,9 @@ abstract class SettingsStoreBase with Store {
|
|||
initialShouldRequireTOTP2FAForAllSecurityAndBackupSettings:
|
||||
shouldRequireTOTP2FAForAllSecurityAndBackupSettings,
|
||||
initialEthereumTransactionPriority: ethereumTransactionPriority,
|
||||
backgroundTasks: backgroundTasks,
|
||||
initialSyncMode: savedSyncMode,
|
||||
initialSyncAll: savedSyncAll,
|
||||
shouldShowYatPopup: shouldShowYatPopup);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import 'package:cake_wallet/entities/exchange_api_mode.dart';
|
||||
import 'package:cake_wallet/store/anonpay/anonpay_transactions_store.dart';
|
||||
import 'package:cake_wallet/view_model/dashboard/anonpay_transaction_list_item.dart';
|
||||
import 'package:cake_wallet/view_model/settings/sync_mode.dart';
|
||||
import 'package:cake_wallet/wallet_type_utils.dart';
|
||||
import 'package:cw_core/transaction_history.dart';
|
||||
import 'package:cw_core/balance.dart';
|
||||
|
@ -403,4 +404,16 @@ abstract class DashboardViewModelBase with Store {
|
|||
hasBuyAction = !isHaven;
|
||||
hasSellAction = !isHaven;
|
||||
}
|
||||
|
||||
@computed
|
||||
SyncMode get syncMode => settingsStore.currentSyncMode;
|
||||
|
||||
@action
|
||||
void setSyncMode(SyncMode syncMode) => settingsStore.currentSyncMode = syncMode;
|
||||
|
||||
@computed
|
||||
bool get syncAll => settingsStore.currentSyncAll;
|
||||
|
||||
@action
|
||||
void setSyncAll(bool value) => settingsStore.currentSyncAll = value;
|
||||
}
|
||||
|
|
|
@ -1,20 +1,19 @@
|
|||
import 'package:flutter/foundation.dart';
|
||||
import 'package:cake_wallet/view_model/settings/settings_list_item.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class ChoicesListItem<ItemType> extends SettingsListItem {
|
||||
ChoicesListItem(
|
||||
{required String title,
|
||||
required this.selectedItem,
|
||||
required this.items,
|
||||
this.displayItem,
|
||||
String Function(ItemType item)? displayItem,
|
||||
void Function(ItemType item)? onItemSelected})
|
||||
: _onItemSelected = onItemSelected,
|
||||
_displayItem = displayItem,
|
||||
super(title);
|
||||
|
||||
final ItemType selectedItem;
|
||||
final List<ItemType> items;
|
||||
final String Function(ItemType item)? displayItem;
|
||||
final String Function(ItemType item)? _displayItem;
|
||||
final void Function(ItemType item)? _onItemSelected;
|
||||
|
||||
void onItemSelected(dynamic item) {
|
||||
|
@ -22,4 +21,11 @@ class ChoicesListItem<ItemType> extends SettingsListItem {
|
|||
_onItemSelected?.call(item);
|
||||
}
|
||||
}
|
||||
|
||||
String displayItem(dynamic item) {
|
||||
if (item is ItemType && _displayItem != null) {
|
||||
return _displayItem!.call(item);
|
||||
}
|
||||
return item.toString();
|
||||
}
|
||||
}
|
||||
|
|
15
lib/view_model/settings/sync_mode.dart
Normal file
15
lib/view_model/settings/sync_mode.dart
Normal file
|
@ -0,0 +1,15 @@
|
|||
enum SyncType { disabled, unobtrusive, aggressive }
|
||||
|
||||
class SyncMode {
|
||||
SyncMode(this.name, this.type, this.frequency);
|
||||
|
||||
final String name;
|
||||
final SyncType type;
|
||||
final Duration frequency;
|
||||
|
||||
static final all = [
|
||||
SyncMode("Disabled", SyncType.disabled, Duration.zero),
|
||||
SyncMode("Unobtrusive", SyncType.unobtrusive, Duration(days: 1)),
|
||||
SyncMode("Aggressive", SyncType.aggressive, Duration(hours: 6)),
|
||||
];
|
||||
}
|
|
@ -1,4 +1,6 @@
|
|||
import 'package:cake_wallet/core/wallet_creation_service.dart';
|
||||
import 'package:cake_wallet/di.dart';
|
||||
import 'package:cake_wallet/entities/background_tasks.dart';
|
||||
import 'package:cake_wallet/view_model/restore/restore_wallet.dart';
|
||||
import 'package:hive/hive.dart';
|
||||
import 'package:mobx/mobx.dart';
|
||||
|
@ -71,6 +73,7 @@ abstract class WalletCreationVMBase with Store {
|
|||
walletInfo.address = wallet.walletAddresses.address;
|
||||
await _walletInfoSource.add(walletInfo);
|
||||
_appStore.changeCurrentWallet(wallet);
|
||||
getIt.get<BackgroundTasks>().registerSyncTask();
|
||||
_appStore.authenticationStore.allowed();
|
||||
state = ExecutedSuccessfullyState();
|
||||
} catch (e) {
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import 'package:cake_wallet/core/auth_service.dart';
|
||||
import 'package:cake_wallet/core/wallet_loading_service.dart';
|
||||
import 'package:cw_core/wallet_base.dart';
|
||||
import 'package:hive/hive.dart';
|
||||
import 'package:mobx/mobx.dart';
|
||||
import 'package:cake_wallet/store/app_store.dart';
|
||||
|
@ -58,8 +57,8 @@ abstract class WalletListViewModelBase with Store {
|
|||
name: info.name,
|
||||
type: info.type,
|
||||
key: info.key,
|
||||
isCurrent: info.name == _appStore.wallet!.name &&
|
||||
info.type == _appStore.wallet!.type,
|
||||
isCurrent: info.name == _appStore.wallet?.name &&
|
||||
info.type == _appStore.wallet?.type,
|
||||
isEnabled: availableWalletTypes.contains(info.type),
|
||||
),
|
||||
),
|
||||
|
|
|
@ -110,13 +110,13 @@ SPEC CHECKSUMS:
|
|||
FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24
|
||||
in_app_review: a850789fad746e89bce03d4aeee8078b45a53fd0
|
||||
package_info: 6eba2fd8d3371dda2d85c8db6fe97488f24b74b2
|
||||
path_provider_foundation: eaf5b3e458fc0e5fbb9940fb09980e853fe058b8
|
||||
path_provider_foundation: 29f094ae23ebbca9d3d0cec13889cd9060c0e943
|
||||
platform_device_id: 3e414428f45df149bbbfb623e2c0ca27c545b763
|
||||
platform_device_id_macos: f763bb55f088be804d61b96eb4710b8ab6598e94
|
||||
ReachabilitySwift: 985039c6f7b23a1da463388634119492ff86c825
|
||||
share_plus_macos: 853ee48e7dce06b633998ca0735d482dd671ade4
|
||||
shared_preferences_foundation: 5b919d13b803cadd15ed2dc053125c68730e5126
|
||||
url_launcher_macos: 5335912b679c073563f29d89d33d10d459f95451
|
||||
url_launcher_macos: d2691c7dd33ed713bf3544850a623080ec693d95
|
||||
wakelock_macos: bc3f2a9bd8d2e6c89fee1e1822e7ddac3bd004a9
|
||||
|
||||
PODFILE CHECKSUM: 5107934592df7813b33d744aebc8ddc6b5a5445f
|
||||
|
|
|
@ -66,6 +66,7 @@ dependencies:
|
|||
# check unorm_dart for usage and for replace
|
||||
permission_handler: ^10.0.0
|
||||
device_display_brightness: ^0.0.6
|
||||
workmanager: ^0.5.1
|
||||
platform_device_id: ^1.0.1
|
||||
wakelock: ^0.6.2
|
||||
flutter_mailer: ^2.0.2
|
||||
|
|
|
@ -669,5 +669,6 @@
|
|||
"etherscan_history": "Etherscan تاريخ",
|
||||
"template_name": "اسم القالب",
|
||||
"change_rep": "ﺏﻭﺪﻨﻣ ﺮﻴﻴﻐﺗ",
|
||||
"change_rep_message": "؟ﻦﻴﻠﺜﻤﻤﻟﺍ ﺮﻴﻴﻐﺗ ﺪﻳﺮﺗ ﻚﻧﺃ ﺪﻛﺄﺘﻣ ﺖﻧﺃ ﻞﻫ"
|
||||
"change_rep_message": "؟ﻦﻴﻠﺜﻤﻤﻟﺍ ﺮﻴﻴﻐﺗ ﺪﻳﺮﺗ ﻚﻧﺃ ﺪﻛﺄﺘﻣ ﺖﻧﺃ ﻞﻫ",
|
||||
"manage_nodes": "ﺪﻘﻌﻟﺍ ﺓﺭﺍﺩﺇ"
|
||||
}
|
||||
|
|
|
@ -665,5 +665,6 @@
|
|||
"etherscan_history": "История на Etherscan",
|
||||
"template_name": "Име на шаблон",
|
||||
"change_rep": "Смяна на представител",
|
||||
"change_rep_message": "Сигурни ли сте, че искате да смените представителите?"
|
||||
"change_rep_message": "Сигурни ли сте, че искате да смените представителите?",
|
||||
"manage_nodes": "Управление на възли"
|
||||
}
|
||||
|
|
|
@ -662,6 +662,7 @@
|
|||
"balance_page": "Stránka zůstatku",
|
||||
"share": "Podíl",
|
||||
"slidable": "Posuvné",
|
||||
"manage_nodes": "Spravovat uzly",
|
||||
"etherscan_history": "Historie Etherscanu",
|
||||
"template_name": "Název šablony",
|
||||
"change_rep": "Změna zástupce",
|
||||
|
|
|
@ -538,6 +538,8 @@
|
|||
"open_gift_card": "Geschenkkarte öffnen",
|
||||
"contact_support": "Support kontaktieren",
|
||||
"gift_cards_unavailable": "Geschenkkarten können derzeit nur über Monero, Bitcoin und Litecoin erworben werden",
|
||||
"background_sync_mode": "Hintergrundsynchronisierungsmodus",
|
||||
"sync_all_wallets": "Alle Wallets synchronisieren",
|
||||
"introducing_cake_pay": "Einführung von Cake Pay!",
|
||||
"cake_pay_learn_more": "Kaufen und lösen Sie Geschenkkarten sofort in der App ein!\nWischen Sie von links nach rechts, um mehr zu erfahren.",
|
||||
"automatic": "Automatisch",
|
||||
|
@ -668,6 +670,7 @@
|
|||
"balance_page": "Balance-Seite",
|
||||
"share": "Aktie",
|
||||
"slidable": "Verschiebbar",
|
||||
"manage_nodes": "Knoten verwalten",
|
||||
"etherscan_history": "Etherscan-Geschichte",
|
||||
"template_name": "Vorlagenname",
|
||||
"change_rep": "Change-Beauftragter",
|
||||
|
|
|
@ -538,6 +538,8 @@
|
|||
"open_gift_card": "Open Gift Card",
|
||||
"contact_support": "Contact Support",
|
||||
"gift_cards_unavailable": "Gift cards are available for purchase only with Monero, Bitcoin, and Litecoin at this time",
|
||||
"background_sync_mode": "Background sync mode",
|
||||
"sync_all_wallets": "Sync all wallets",
|
||||
"introducing_cake_pay": "Introducing Cake Pay!",
|
||||
"cake_pay_learn_more": "Instantly purchase and redeem gift cards in the app!\nSwipe left to right to learn more.",
|
||||
"automatic": "Automatic",
|
||||
|
@ -668,6 +670,7 @@
|
|||
"balance_page": "Balance Page",
|
||||
"share": "Share",
|
||||
"slidable": "Slidable",
|
||||
"manage_nodes": "Manage nodes",
|
||||
"etherscan_history": "Etherscan history",
|
||||
"template_name": "Template Name",
|
||||
"change_rep": "Change Representative",
|
||||
|
|
|
@ -538,6 +538,8 @@
|
|||
"open_gift_card": "Abrir tarjeta de regalo",
|
||||
"contact_support": "Contactar con Soporte",
|
||||
"gift_cards_unavailable": "Las tarjetas de regalo están disponibles para comprar solo a través de Monero, Bitcoin y Litecoin en este momento",
|
||||
"background_sync_mode": "Modo de sincronización en segundo plano",
|
||||
"sync_all_wallets": "Sincronizar todas las billeteras",
|
||||
"introducing_cake_pay": "¡Presentamos Cake Pay!",
|
||||
"cake_pay_learn_more": "¡Compre y canjee tarjetas de regalo al instante en la aplicación!\nDeslice el dedo de izquierda a derecha para obtener más información.",
|
||||
"automatic": "Automático",
|
||||
|
@ -668,6 +670,7 @@
|
|||
"balance_page": "Página de saldo",
|
||||
"share": "Compartir",
|
||||
"slidable": "deslizable",
|
||||
"manage_nodes": "Administrar nodos",
|
||||
"etherscan_history": "historia de etherscan",
|
||||
"template_name": "Nombre de la plantilla",
|
||||
"change_rep": "Representante de cambio",
|
||||
|
|
|
@ -536,8 +536,10 @@
|
|||
"gift_card_is_generated": "La carte-cadeau est générée",
|
||||
"open_gift_card": "Ouvrir la carte-cadeau",
|
||||
"contact_support": "Contacter l'assistance",
|
||||
"gift_cards": "Cartes-Cadeaux",
|
||||
"gift_cards_unavailable": "Les cartes-cadeaux ne sont disponibles à l'achat que via Monero, Bitcoin et Litecoin pour le moment",
|
||||
"background_sync_mode": "Mode de synchronisation en arrière-plan",
|
||||
"sync_all_wallets": "Synchroniser tous les portefeuilles",
|
||||
"gift_cards": "Cartes-Cadeaux",
|
||||
"introducing_cake_pay": "Présentation de Cake Pay !",
|
||||
"cake_pay_learn_more": "Achetez et utilisez instantanément des cartes-cadeaux dans l'application !\nBalayer de gauche à droite pour en savoir plus.",
|
||||
"automatic": "Automatique",
|
||||
|
@ -668,6 +670,7 @@
|
|||
"balance_page": "Page Solde",
|
||||
"share": "Partager",
|
||||
"slidable": "Glissable",
|
||||
"manage_nodes": "Gérer les nœuds",
|
||||
"etherscan_history": "Historique d'Etherscan",
|
||||
"template_name": "Nom du modèle",
|
||||
"change_rep": "Changer de représentant",
|
||||
|
|
|
@ -651,5 +651,6 @@
|
|||
"etherscan_history": "Etherscan tarihin kowane zamani",
|
||||
"template_name": "Sunan Samfura",
|
||||
"change_rep": "Canza Wakili",
|
||||
"change_rep_message": "Shin kun tabbata kuna son canza wakilai?"
|
||||
"change_rep_message": "Shin kun tabbata kuna son canza wakilai?",
|
||||
"manage_nodes": "Sarrafa nodes"
|
||||
}
|
||||
|
|
|
@ -538,6 +538,8 @@
|
|||
"open_gift_card": "गिफ्ट कार्ड खोलें",
|
||||
"contact_support": "सहायता से संपर्क करें",
|
||||
"gift_cards_unavailable": "उपहार कार्ड इस समय केवल मोनेरो, बिटकॉइन और लिटकोइन के माध्यम से खरीदने के लिए उपलब्ध हैं",
|
||||
"background_sync_mode": "बैकग्राउंड सिंक मोड",
|
||||
"sync_all_wallets": "सभी वॉलेट सिंक करें",
|
||||
"introducing_cake_pay": "परिचय Cake Pay!",
|
||||
"cake_pay_learn_more": "ऐप में उपहार कार्ड तुरंत खरीदें और रिडीम करें!\nअधिक जानने के लिए बाएं से दाएं स्वाइप करें।",
|
||||
"automatic": "स्वचालित",
|
||||
|
@ -668,6 +670,7 @@
|
|||
"balance_page": "बैलेंस पेज",
|
||||
"share": "शेयर करना",
|
||||
"slidable": "फिसलने लायक",
|
||||
"manage_nodes": "नोड्स प्रबंधित करें",
|
||||
"etherscan_history": "इथरस्कैन इतिहास",
|
||||
"template_name": "टेम्पलेट नाम",
|
||||
"change_rep": "प्रतिनिधि बदलें",
|
||||
|
|
|
@ -538,6 +538,8 @@
|
|||
"open_gift_card": "Otvori darovnu karticu",
|
||||
"contact_support": "Kontaktirajte podršku",
|
||||
"gift_cards_unavailable": "Poklon kartice trenutno su dostupne za kupnju samo putem Monera, Bitcoina i Litecoina",
|
||||
"background_sync_mode": "Sinkronizacija u pozadini",
|
||||
"sync_all_wallets": "Sinkronizirajte sve novčanike",
|
||||
"introducing_cake_pay": "Predstavljamo Cake Pay!",
|
||||
"cake_pay_learn_more": "Azonnal vásárolhat és válthat be ajándékutalványokat az alkalmazásban!\nTovábbi információért csúsztassa balról jobbra az ujját.",
|
||||
"automatic": "Automatski",
|
||||
|
@ -668,6 +670,7 @@
|
|||
"balance_page": "Stranica sa stanjem",
|
||||
"share": "Udio",
|
||||
"slidable": "Klizna",
|
||||
"manage_nodes": "Upravljanje čvorovima",
|
||||
"etherscan_history": "Etherscan povijest",
|
||||
"template_name": "Naziv predloška",
|
||||
"change_rep": "Promjena predstavnika",
|
||||
|
|
|
@ -658,6 +658,7 @@
|
|||
"balance_page": "Halaman Saldo",
|
||||
"share": "Membagikan",
|
||||
"slidable": "Dapat digeser",
|
||||
"manage_nodes": "Kelola node",
|
||||
"etherscan_history": "Sejarah Etherscan",
|
||||
"template_name": "Nama Templat",
|
||||
"change_rep": "Ubah Perwakilan",
|
||||
|
|
|
@ -538,6 +538,8 @@
|
|||
"open_gift_card": "Apri carta regalo",
|
||||
"contact_support": "Contatta l'assistenza",
|
||||
"gift_cards_unavailable": "Le carte regalo sono disponibili per l'acquisto solo tramite Monero, Bitcoin e Litecoin in questo momento",
|
||||
"background_sync_mode": "Modalità di sincronizzazione in background",
|
||||
"sync_all_wallets": "Sincronizza tutti i portafogli",
|
||||
"introducing_cake_pay": "Presentazione di Cake Pay!",
|
||||
"cake_pay_learn_more": "Acquista e riscatta istantaneamente carte regalo nell'app!\nScorri da sinistra a destra per saperne di più.",
|
||||
"automatic": "Automatico",
|
||||
|
@ -668,6 +670,7 @@
|
|||
"balance_page": "Pagina di equilibrio",
|
||||
"share": "Condividere",
|
||||
"slidable": "Scorrevole",
|
||||
"manage_nodes": "Gestisci i nodi",
|
||||
"etherscan_history": "Storia Etherscan",
|
||||
"template_name": "Nome modello",
|
||||
"change_rep": "Cambia rappresentante",
|
||||
|
|
|
@ -538,6 +538,8 @@
|
|||
"open_gift_card": "オープンギフトカード",
|
||||
"contact_support": "サポートに連絡する",
|
||||
"gift_cards_unavailable": "現時点では、ギフトカードはMonero、Bitcoin、Litecoinからのみ購入できます。",
|
||||
"background_sync_mode": "バックグラウンド同期モード",
|
||||
"sync_all_wallets": "すべてのウォレットを同期",
|
||||
"introducing_cake_pay": "序章Cake Pay!",
|
||||
"cake_pay_learn_more": "アプリですぐにギフトカードを購入して引き換えましょう!\n左から右にスワイプして詳細をご覧ください。",
|
||||
"automatic": "自動",
|
||||
|
@ -668,6 +670,7 @@
|
|||
"balance_page": "残高ページ",
|
||||
"share": "共有",
|
||||
"slidable": "スライド可能",
|
||||
"manage_nodes": "ノードの管理",
|
||||
"etherscan_history": "イーサスキャンの歴史",
|
||||
"template_name": "テンプレート名",
|
||||
"change_rep": "代表者の変更",
|
||||
|
|
|
@ -539,6 +539,8 @@
|
|||
"open_gift_card": "기프트 카드 열기",
|
||||
"contact_support": "지원팀에 문의",
|
||||
"gift_cards_unavailable": "기프트 카드는 현재 Monero, Bitcoin 및 Litecoin을 통해서만 구매할 수 있습니다.",
|
||||
"background_sync_mode": "백그라운드 동기화 모드",
|
||||
"sync_all_wallets": "모든 지갑 동기화",
|
||||
"introducing_cake_pay": "소개 Cake Pay!",
|
||||
"cake_pay_learn_more": "앱에서 즉시 기프트 카드를 구매하고 사용하세요!\n자세히 알아보려면 왼쪽에서 오른쪽으로 스와이프하세요.",
|
||||
"automatic": "자동적 인",
|
||||
|
@ -669,6 +671,7 @@
|
|||
"balance_page": "잔액 페이지",
|
||||
"share": "공유하다",
|
||||
"slidable": "슬라이딩 가능",
|
||||
"manage_nodes": "노드 관리",
|
||||
"etherscan_history": "이더스캔 역사",
|
||||
"template_name": "템플릿 이름",
|
||||
"change_rep": "대표자 변경",
|
||||
|
|
|
@ -668,6 +668,7 @@
|
|||
"balance_page": "လက်ကျန်စာမျက်နှာ",
|
||||
"share": "မျှဝေပါ။",
|
||||
"slidable": "လျှောချနိုင်သည်။",
|
||||
"manage_nodes": "ဆုံမှတ်များကို စီမံပါ။",
|
||||
"etherscan_history": "Etherscan သမိုင်း",
|
||||
"template_name": "နမူနာပုံစံ",
|
||||
"change_rep": "ကိုယ်စားလှယ်ပြောင်းပါ။",
|
||||
|
|
|
@ -538,6 +538,8 @@
|
|||
"open_gift_card": "Geschenkkaart openen",
|
||||
"contact_support": "Contact opnemen met ondersteuning",
|
||||
"gift_cards_unavailable": "Cadeaubonnen kunnen momenteel alleen worden gekocht via Monero, Bitcoin en Litecoin",
|
||||
"background_sync_mode": "Achtergrondsynchronisatiemodus",
|
||||
"sync_all_wallets": "Alle portemonnees synchroniseren",
|
||||
"introducing_cake_pay": "Introductie van Cake Pay!",
|
||||
"cake_pay_learn_more": "Koop en wissel cadeaubonnen direct in de app in!\nSwipe van links naar rechts voor meer informatie.",
|
||||
"automatic": "automatisch",
|
||||
|
@ -668,6 +670,7 @@
|
|||
"balance_page": "Saldo pagina",
|
||||
"share": "Deel",
|
||||
"slidable": "Verschuifbaar",
|
||||
"manage_nodes": "Beheer knooppunten",
|
||||
"etherscan_history": "Etherscan-geschiedenis",
|
||||
"template_name": "Sjabloonnaam",
|
||||
"change_rep": "Vertegenwoordiger wijzigen",
|
||||
|
|
|
@ -538,6 +538,8 @@
|
|||
"open_gift_card": "Otwórz kartę podarunkową",
|
||||
"contact_support": "Skontaktuj się z pomocą techniczną",
|
||||
"gift_cards_unavailable": "Karty podarunkowe można obecnie kupić tylko za pośrednictwem Monero, Bitcoin i Litecoin",
|
||||
"background_sync_mode": "Tryb synchronizacji w tle",
|
||||
"sync_all_wallets": "Synchronizuj wszystkie portfele",
|
||||
"introducing_cake_pay": "Przedstawiamy Cake Pay!",
|
||||
"cake_pay_learn_more": "Kupuj i wykorzystuj karty podarunkowe od razu w aplikacji!\nPrzesuń od lewej do prawej, aby dowiedzieć się więcej.",
|
||||
"automatic": "Automatyczny",
|
||||
|
@ -668,6 +670,7 @@
|
|||
"balance_page": "Strona salda",
|
||||
"share": "Udział",
|
||||
"slidable": "Przesuwne",
|
||||
"manage_nodes": "Zarządzaj węzłami",
|
||||
"etherscan_history": "Historia Etherscanu",
|
||||
"template_name": "Nazwa szablonu",
|
||||
"change_rep": "Zmień przedstawiciela",
|
||||
|
|
|
@ -537,6 +537,8 @@
|
|||
"open_gift_card": "Abrir vale-presente",
|
||||
"contact_support": "Contatar Suporte",
|
||||
"gift_cards_unavailable": "Os cartões-presente estão disponíveis para compra apenas através do Monero, Bitcoin e Litecoin no momento",
|
||||
"background_sync_mode": "Modo de sincronização em segundo plano",
|
||||
"sync_all_wallets": "Sincronize todas as carteiras",
|
||||
"introducing_cake_pay": "Apresentando o Cake Pay!",
|
||||
"cake_pay_learn_more": "Compre e resgate vales-presente instantaneamente no app!\nDeslize da esquerda para a direita para saber mais.",
|
||||
"automatic": "Automático",
|
||||
|
@ -667,6 +669,7 @@
|
|||
"balance_page": "Página de saldo",
|
||||
"share": "Compartilhar",
|
||||
"slidable": "Deslizável",
|
||||
"manage_nodes": "Gerenciar nós",
|
||||
"etherscan_history": "história Etherscan",
|
||||
"template_name": "Nome do modelo",
|
||||
"change_rep": "Alterar representante",
|
||||
|
|
|
@ -538,6 +538,8 @@
|
|||
"open_gift_card": "Открыть подарочную карту",
|
||||
"contact_support": "Связаться со службой поддержки",
|
||||
"gift_cards_unavailable": "В настоящее время подарочные карты можно приобрести только через Monero, Bitcoin и Litecoin.",
|
||||
"background_sync_mode": "Режим фоновой синхронизации",
|
||||
"sync_all_wallets": "Синхронизировать все кошельки",
|
||||
"introducing_cake_pay": "Представляем Cake Pay!",
|
||||
"cake_pay_learn_more": "Мгновенно покупайте и используйте подарочные карты в приложении!\nПроведите по экрану слева направо, чтобы узнать больше.",
|
||||
"automatic": "автоматический",
|
||||
|
@ -668,6 +670,7 @@
|
|||
"balance_page": "Страница баланса",
|
||||
"share": "Делиться",
|
||||
"slidable": "Скользящий",
|
||||
"manage_nodes": "Управление узлами",
|
||||
"etherscan_history": "История Эфириума",
|
||||
"template_name": "Имя Шаблона",
|
||||
"change_rep": "Изменить представителя",
|
||||
|
|
|
@ -668,6 +668,7 @@
|
|||
"balance_page": "หน้ายอดคงเหลือ",
|
||||
"share": "แบ่งปัน",
|
||||
"slidable": "เลื่อนได้",
|
||||
"manage_nodes": "จัดการโหนด",
|
||||
"etherscan_history": "ประวัติอีเธอร์สแกน",
|
||||
"template_name": "ชื่อแม่แบบ",
|
||||
"change_rep": "เปลี่ยนผู้แทน",
|
||||
|
|
|
@ -631,7 +631,7 @@
|
|||
"setup_2fa_text": "Cake 2FA, soğuk hava deposu kadar güvenli DEĞİLDİR. 2FA, siz uyurken arkadaşınızın parmak izinizi sağlaması gibi temel saldırı türlerine karşı koruma sağlar.\n\n Cake 2FA, gelişmiş bir saldırgan tarafından güvenliği ihlal edilmiş bir cihaza karşı koruma SAĞLAMAZ.\n\n 2FA kodlarınıza erişimi kaybederseniz , BU CÜZDANA ERİŞİMİNİZİ KAYBEDECEKSİNİZ. Mnemonic seed'den cüzdanınızı geri yüklemeniz gerekecek. BU NEDENLE HATIRLAYICI TOHUMLARINIZI YEDEKLEMELİSİNİZ! Ayrıca anımsatıcı tohumlarınıza erişimi olan biri, Cake 2FA'yı atlayarak paranızı çalabilir.\n\n Cake, anımsatıcı tohumlarınıza erişimi kaybederseniz size yardımcı olamaz, çünkü Cake bir saklama dışı cüzdan.",
|
||||
"setup_totp_recommended": "TOTP'yi kurun (Önerilir)",
|
||||
"disable_buy": "Satın alma işlemini devre dışı bırak",
|
||||
"disable_sell": "Satış işlemini devre dışı bırak",
|
||||
"disable_sell": "Satış işlemini devre dışı bırak",
|
||||
"cake_2fa_preset" : "Kek 2FA Ön Ayarı",
|
||||
"narrow": "Dar",
|
||||
"normal": "Normal",
|
||||
|
@ -669,6 +669,7 @@
|
|||
"balance_page": "Bakiye Sayfası",
|
||||
"share": "Paylaşmak",
|
||||
"slidable": "kaydırılabilir",
|
||||
"manage_nodes": "Düğümleri yönet",
|
||||
"etherscan_history": "Etherscan geçmişi",
|
||||
"template_name": "şablon adı",
|
||||
"change_rep": "Temsilciyi Değiştir",
|
||||
|
|
|
@ -538,6 +538,8 @@
|
|||
"open_gift_card": "Відкрити подарункову картку",
|
||||
"contact_support": "Звернутися до служби підтримки",
|
||||
"gift_cards_unavailable": "Наразі подарункові картки можна придбати лише через Monero, Bitcoin і Litecoin",
|
||||
"background_sync_mode": "Фоновий режим синхронізації",
|
||||
"sync_all_wallets": "Синхронізувати всі гаманці",
|
||||
"introducing_cake_pay": "Представляємо Cake Pay!",
|
||||
"cake_pay_learn_more": "Миттєво купуйте та активуйте подарункові картки в додатку!\nПроведіть пальцем зліва направо, щоб дізнатися більше.",
|
||||
"automatic": "Автоматичний",
|
||||
|
@ -668,6 +670,7 @@
|
|||
"balance_page": "Сторінка балансу",
|
||||
"share": "Поділіться",
|
||||
"slidable": "Розсувний",
|
||||
"manage_nodes": "Керуйте вузлами",
|
||||
"etherscan_history": "Історія Etherscan",
|
||||
"template_name": "Назва шаблону",
|
||||
"change_rep": "Зміна представника",
|
||||
|
|
|
@ -662,6 +662,7 @@
|
|||
"balance_page": "بیلنس صفحہ",
|
||||
"share": "بانٹیں",
|
||||
"slidable": "سلائیڈ ایبل",
|
||||
"manage_nodes": "۔ﮟﯾﺮﮐ ﻢﻈﻧ ﺎﮐ ﺱﮈﻮﻧ",
|
||||
"etherscan_history": "ﺦﯾﺭﺎﺗ ﯽﮐ ﻦﯿﮑﺳﺍ ﺮﮭﺘﯾﺍ",
|
||||
"template_name": "ٹیمپلیٹ کا نام",
|
||||
"change_rep": "۔ﮟﯾﺮﮐ ﻞﯾﺪﺒﺗ ﮦﺪﻨﺋﺎﻤﻧ",
|
||||
|
|
|
@ -664,6 +664,7 @@
|
|||
"balance_page": "Oju-iwe iwọntunwọnsi",
|
||||
"share": "Pinpin",
|
||||
"slidable": "Slidable",
|
||||
"manage_nodes": "Ṣakoso awọn apa",
|
||||
"etherscan_history": "Etherscan itan",
|
||||
"template_name": "Orukọ Awoṣe",
|
||||
"change_rep": "Yi Aṣoju",
|
||||
|
|
|
@ -537,6 +537,8 @@
|
|||
"open_gift_card": "打开礼品卡",
|
||||
"contact_support": "联系支持",
|
||||
"gift_cards_unavailable": "目前只能通过门罗币、比特币和莱特币购买礼品卡",
|
||||
"background_sync_mode": "后台同步模式",
|
||||
"sync_all_wallets": "同步所有钱包",
|
||||
"introducing_cake_pay": "介绍 Cake Pay!",
|
||||
"cake_pay_learn_more": "立即在应用中购买和兑换礼品卡!\n从左向右滑动以了解详情。",
|
||||
"automatic": "自动的",
|
||||
|
@ -667,6 +669,7 @@
|
|||
"balance_page": "余额页",
|
||||
"share": "分享",
|
||||
"slidable": "可滑动",
|
||||
"manage_nodes": "管理节点",
|
||||
"etherscan_history": "以太扫描历史",
|
||||
"template_name": "模板名称",
|
||||
"change_rep": "变革代表",
|
||||
|
|
|
@ -14,14 +14,14 @@ TYPES=($MONERO_COM $CAKEWALLET $HAVEN)
|
|||
APP_ANDROID_TYPE=$1
|
||||
|
||||
MONERO_COM_NAME="Monero.com"
|
||||
MONERO_COM_VERSION="1.4.0"
|
||||
MONERO_COM_BUILD_NUMBER=52
|
||||
MONERO_COM_VERSION="1.5.0"
|
||||
MONERO_COM_BUILD_NUMBER=54
|
||||
MONERO_COM_BUNDLE_ID="com.monero.app"
|
||||
MONERO_COM_PACKAGE="com.monero.app"
|
||||
|
||||
CAKEWALLET_NAME="Cake Wallet"
|
||||
CAKEWALLET_VERSION="4.7.0"
|
||||
CAKEWALLET_BUILD_NUMBER=162
|
||||
CAKEWALLET_VERSION="4.8.0"
|
||||
CAKEWALLET_BUILD_NUMBER=167
|
||||
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.4.0"
|
||||
MONERO_COM_BUILD_NUMBER=50
|
||||
MONERO_COM_VERSION="1.5.0"
|
||||
MONERO_COM_BUILD_NUMBER=52
|
||||
MONERO_COM_BUNDLE_ID="com.cakewallet.monero"
|
||||
|
||||
CAKEWALLET_NAME="Cake Wallet"
|
||||
CAKEWALLET_VERSION="4.7.0"
|
||||
CAKEWALLET_BUILD_NUMBER=165
|
||||
CAKEWALLET_VERSION="4.8.0"
|
||||
CAKEWALLET_BUILD_NUMBER=175
|
||||
CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet"
|
||||
|
||||
HAVEN_NAME="Haven"
|
||||
|
|
|
@ -23,7 +23,7 @@ CONFIG_ARGS=""
|
|||
|
||||
case $APP_MACOS_TYPE in
|
||||
$CAKEWALLET)
|
||||
CONFIG_ARGS="--monero --bitcoin";; #--haven
|
||||
CONFIG_ARGS="--monero --bitcoin --ethereum";; #--haven
|
||||
esac
|
||||
|
||||
cp -rf pubspec_description.yaml pubspec.yaml
|
||||
|
|
|
@ -15,8 +15,8 @@ if [ -n "$1" ]; then
|
|||
fi
|
||||
|
||||
CAKEWALLET_NAME="Cake Wallet"
|
||||
CAKEWALLET_VERSION="1.0.7"
|
||||
CAKEWALLET_BUILD_NUMBER=26
|
||||
CAKEWALLET_VERSION="1.1.0"
|
||||
CAKEWALLET_BUILD_NUMBER=28
|
||||
CAKEWALLET_BUNDLE_ID="com.fotolockr.cakewallet"
|
||||
|
||||
if ! [[ " ${TYPES[*]} " =~ " ${APP_MACOS_TYPE} " ]]; then
|
||||
|
|
|
@ -497,8 +497,6 @@ Future<void> generateEthereum(bool hasImplementation) async {
|
|||
|
||||
final outputFile = File(ethereumOutputPath);
|
||||
const ethereumCommonHeaders = """
|
||||
""";
|
||||
const ethereumCWHeaders = """
|
||||
import 'package:cake_wallet/view_model/send/output.dart';
|
||||
import 'package:cw_core/crypto_amount_format.dart';
|
||||
import 'package:cw_core/crypto_currency.dart';
|
||||
|
@ -510,6 +508,9 @@ import 'package:cw_core/wallet_base.dart';
|
|||
import 'package:cw_core/wallet_credentials.dart';
|
||||
import 'package:cw_core/wallet_info.dart';
|
||||
import 'package:cw_core/wallet_service.dart';
|
||||
import 'package:hive/hive.dart';
|
||||
""";
|
||||
const ethereumCWHeaders = """
|
||||
import 'package:cw_ethereum/ethereum_formatter.dart';
|
||||
import 'package:cw_ethereum/ethereum_mnemonics.dart';
|
||||
import 'package:cw_ethereum/ethereum_transaction_credentials.dart';
|
||||
|
@ -518,7 +519,6 @@ import 'package:cw_ethereum/ethereum_wallet.dart';
|
|||
import 'package:cw_ethereum/ethereum_wallet_creation_credentials.dart';
|
||||
import 'package:cw_ethereum/ethereum_wallet_service.dart';
|
||||
import 'package:cw_ethereum/ethereum_transaction_priority.dart';
|
||||
import 'package:hive/hive.dart';
|
||||
""";
|
||||
const ethereumCwPart = "part 'cw_ethereum.dart';";
|
||||
const ethereumContent = """
|
||||
|
|
Loading…
Reference in a new issue