mirror of
https://github.com/cake-tech/cake_wallet.git
synced 2024-12-22 19:49:22 +00:00
Cw 397 chatwoot live support (#1011)
* initial button refactor and gradient background * CW-397 Use a separate Hive instance to avoid Issues with plugins using Hive * CW-397 Add Support Page Strings * CW-397 Add new Support Page * CW-397 Add Support Live Chat Page * CW-397 Add Hive Type Ids Doc * CW-397 Use Newer Chatwoot SDK Version and add new Images * CW-397 Update pubspec_base.yaml * CW-397 Add own Chatwoot Widget * Lowercase `s` skip-ci * CW-397 Fix WebMessageListener * CW-397 Fix Merge conflicts * CW-397 Add Erc20 Hive Type ID * CW-397 Fix Ethereum Hive Error * CW-397 Revert to Restore Button * CW-397 Only use In App chat on mobile * CW-397 Move Chatwoot Website Token to secrets * CW-397 Add Chatwoot Website Token to workflow * CW-397 Move Chatwoot fetchUrl to Support View Model --------- Co-authored-by: Rafael Saes <git@saes.io> Co-authored-by: Justin Ehrenhofer <justin.ehrenhofer@gmail.com>
This commit is contained in:
parent
e348f12491
commit
af9b5ff10c
63 changed files with 762 additions and 260 deletions
1
.github/workflows/pr_test_build.yml
vendored
1
.github/workflows/pr_test_build.yml
vendored
|
@ -127,6 +127,7 @@ jobs:
|
||||||
echo "const fiatApiKey = '${{ secrets.FIAT_API_KEY }}';" >> lib/.secrets.g.dart
|
echo "const fiatApiKey = '${{ secrets.FIAT_API_KEY }}';" >> lib/.secrets.g.dart
|
||||||
echo "const payfuraApiKey = '${{ secrets.PAYFURA_API_KEY }}';" >> lib/.secrets.g.dart
|
echo "const payfuraApiKey = '${{ secrets.PAYFURA_API_KEY }}';" >> lib/.secrets.g.dart
|
||||||
echo "const etherScanApiKey = '${{ secrets.ETHER_SCAN_API_KEY }}';" >> cw_ethereum/lib/.secrets.g.dart
|
echo "const etherScanApiKey = '${{ secrets.ETHER_SCAN_API_KEY }}';" >> cw_ethereum/lib/.secrets.g.dart
|
||||||
|
echo "const chatwootWebsiteToken = '${{ secrets.CHATWOOT_WEBSITE_TOKEN }}';" >> lib/.secrets.g.dart
|
||||||
|
|
||||||
- name: Rename app
|
- name: Rename app
|
||||||
run: echo -e "id=com.cakewallet.test\nname=$GITHUB_HEAD_REF" > /opt/android/cake_wallet/android/app.properties
|
run: echo -e "id=com.cakewallet.test\nname=$GITHUB_HEAD_REF" > /opt/android/cake_wallet/android/app.properties
|
||||||
|
|
BIN
assets/images/live_support.png
Normal file
BIN
assets/images/live_support.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.7 KiB |
BIN
assets/images/more_links.png
Normal file
BIN
assets/images/more_links.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.8 KiB |
BIN
assets/images/wallet_guides.png
Normal file
BIN
assets/images/wallet_guides.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.7 KiB |
4
cw_core/lib/cake_hive.dart
Normal file
4
cw_core/lib/cake_hive.dart
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
import 'package:hive/hive.dart';
|
||||||
|
import 'package:hive/src/hive_impl.dart';
|
||||||
|
|
||||||
|
final HiveInterface CakeHive = HiveImpl();
|
|
@ -1,4 +1,5 @@
|
||||||
import 'package:cw_core/crypto_currency.dart';
|
import 'package:cw_core/crypto_currency.dart';
|
||||||
|
import 'package:cw_core/hive_type_ids.dart';
|
||||||
import 'package:hive/hive.dart';
|
import 'package:hive/hive.dart';
|
||||||
|
|
||||||
part 'erc20_token.g.dart';
|
part 'erc20_token.g.dart';
|
||||||
|
@ -53,7 +54,7 @@ class Erc20Token extends CryptoCurrency with HiveObjectMixin {
|
||||||
iconPath: icon,
|
iconPath: icon,
|
||||||
);
|
);
|
||||||
|
|
||||||
static const typeId = 12;
|
static const typeId = ERC20_TOKEN_TYPE_ID;
|
||||||
static const boxName = 'Erc20Tokens';
|
static const boxName = 'Erc20Tokens';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
13
cw_core/lib/hive_type_ids.dart
Normal file
13
cw_core/lib/hive_type_ids.dart
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
const CONTACT_TYPE_ID = 0;
|
||||||
|
const NODE_TYPE_ID = 1;
|
||||||
|
const TRANSACTION_TYPE_ID = 2;
|
||||||
|
const TRADE_TYPE_ID = 3;
|
||||||
|
const WALLET_INFO_TYPE_ID = 4;
|
||||||
|
const WALLET_TYPE_TYPE_ID = 5;
|
||||||
|
const TEMPLATE_TYPE_ID = 6;
|
||||||
|
const EXCHANGE_TEMPLATE_TYPE_ID = 7;
|
||||||
|
const ORDER_TYPE_ID = 8;
|
||||||
|
const UNSPENT_COINS_INFO_TYPE_ID = 9;
|
||||||
|
const ANONPAY_INVOICE_INFO_TYPE_ID = 10;
|
||||||
|
|
||||||
|
const ERC20_TOKEN_TYPE_ID = 12;
|
|
@ -3,6 +3,7 @@ import 'package:cw_core/keyable.dart';
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'package:http/http.dart' as http;
|
import 'package:http/http.dart' as http;
|
||||||
import 'package:hive/hive.dart';
|
import 'package:hive/hive.dart';
|
||||||
|
import 'package:cw_core/hive_type_ids.dart';
|
||||||
import 'package:cw_core/wallet_type.dart';
|
import 'package:cw_core/wallet_type.dart';
|
||||||
import 'package:http/io_client.dart' as ioc;
|
import 'package:http/io_client.dart' as ioc;
|
||||||
|
|
||||||
|
@ -37,7 +38,7 @@ class Node extends HiveObject with Keyable {
|
||||||
trusted = map['trusted'] as bool? ?? false,
|
trusted = map['trusted'] as bool? ?? false,
|
||||||
socksProxyAddress = map['socksProxyPort'] as String?;
|
socksProxyAddress = map['socksProxyPort'] as String?;
|
||||||
|
|
||||||
static const typeId = 1;
|
static const typeId = NODE_TYPE_ID;
|
||||||
static const boxName = 'Nodes';
|
static const boxName = 'Nodes';
|
||||||
|
|
||||||
@HiveField(0, defaultValue: '')
|
@HiveField(0, defaultValue: '')
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import 'package:cw_core/hive_type_ids.dart';
|
||||||
import 'package:hive/hive.dart';
|
import 'package:hive/hive.dart';
|
||||||
|
|
||||||
part 'unspent_coins_info.g.dart';
|
part 'unspent_coins_info.g.dart';
|
||||||
|
@ -14,7 +15,7 @@ class UnspentCoinsInfo extends HiveObject {
|
||||||
required this.vout,
|
required this.vout,
|
||||||
required this.value});
|
required this.value});
|
||||||
|
|
||||||
static const typeId = 9;
|
static const typeId = UNSPENT_COINS_INFO_TYPE_ID;
|
||||||
static const boxName = 'Unspent';
|
static const boxName = 'Unspent';
|
||||||
static const boxKey = 'unspentBoxKey';
|
static const boxKey = 'unspentBoxKey';
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import 'package:flutter/foundation.dart';
|
|
||||||
import 'package:hive/hive.dart';
|
|
||||||
import 'package:cw_core/wallet_type.dart';
|
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
import 'package:cw_core/hive_type_ids.dart';
|
||||||
|
import 'package:cw_core/wallet_type.dart';
|
||||||
|
import 'package:hive/hive.dart';
|
||||||
|
|
||||||
part 'wallet_info.g.dart';
|
part 'wallet_info.g.dart';
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@ class WalletInfo extends HiveObject {
|
||||||
yatEid, yatLastUsedAddressRaw, showIntroCakePayCard);
|
yatEid, yatLastUsedAddressRaw, showIntroCakePayCard);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const typeId = 4;
|
static const typeId = WALLET_INFO_TYPE_ID;
|
||||||
static const boxName = 'WalletInfo';
|
static const boxName = 'WalletInfo';
|
||||||
|
|
||||||
@HiveField(0, defaultValue: '')
|
@HiveField(0, defaultValue: '')
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import 'package:cw_core/crypto_currency.dart';
|
import 'package:cw_core/crypto_currency.dart';
|
||||||
|
import 'package:cw_core/hive_type_ids.dart';
|
||||||
import 'package:hive/hive.dart';
|
import 'package:hive/hive.dart';
|
||||||
|
|
||||||
part 'wallet_type.g.dart';
|
part 'wallet_type.g.dart';
|
||||||
|
@ -10,9 +11,8 @@ const walletTypes = [
|
||||||
WalletType.haven,
|
WalletType.haven,
|
||||||
WalletType.ethereum,
|
WalletType.ethereum,
|
||||||
];
|
];
|
||||||
const walletTypeTypeId = 5;
|
|
||||||
|
|
||||||
@HiveType(typeId: walletTypeTypeId)
|
@HiveType(typeId: WALLET_TYPE_TYPE_ID)
|
||||||
enum WalletType {
|
enum WalletType {
|
||||||
@HiveField(0)
|
@HiveField(0)
|
||||||
monero,
|
monero,
|
||||||
|
|
|
@ -4,6 +4,7 @@ import 'dart:io';
|
||||||
import 'dart:math';
|
import 'dart:math';
|
||||||
|
|
||||||
import 'package:cw_core/crypto_currency.dart';
|
import 'package:cw_core/crypto_currency.dart';
|
||||||
|
import 'package:cw_core/cake_hive.dart';
|
||||||
import 'package:cw_core/node.dart';
|
import 'package:cw_core/node.dart';
|
||||||
import 'package:cw_core/pathForWallet.dart';
|
import 'package:cw_core/pathForWallet.dart';
|
||||||
import 'package:cw_core/pending_transaction.dart';
|
import 'package:cw_core/pending_transaction.dart';
|
||||||
|
@ -58,8 +59,8 @@ abstract class EthereumWalletBase
|
||||||
this.walletInfo = walletInfo;
|
this.walletInfo = walletInfo;
|
||||||
transactionHistory = EthereumTransactionHistory(walletInfo: walletInfo, password: password);
|
transactionHistory = EthereumTransactionHistory(walletInfo: walletInfo, password: password);
|
||||||
|
|
||||||
if (!Hive.isAdapterRegistered(Erc20Token.typeId)) {
|
if (!CakeHive.isAdapterRegistered(Erc20Token.typeId)) {
|
||||||
Hive.registerAdapter(Erc20TokenAdapter());
|
CakeHive.registerAdapter(Erc20TokenAdapter());
|
||||||
}
|
}
|
||||||
|
|
||||||
_sharedPrefs.complete(SharedPreferences.getInstance());
|
_sharedPrefs.complete(SharedPreferences.getInstance());
|
||||||
|
@ -95,7 +96,7 @@ abstract class EthereumWalletBase
|
||||||
Completer<SharedPreferences> _sharedPrefs = Completer();
|
Completer<SharedPreferences> _sharedPrefs = Completer();
|
||||||
|
|
||||||
Future<void> init() async {
|
Future<void> init() async {
|
||||||
erc20TokensBox = await Hive.openBox<Erc20Token>(Erc20Token.boxName);
|
erc20TokensBox = await CakeHive.openBox<Erc20Token>(Erc20Token.boxName);
|
||||||
await walletAddresses.init();
|
await walletAddresses.init();
|
||||||
await transactionHistory.init();
|
await transactionHistory.init();
|
||||||
_privateKey = await getPrivateKey(_mnemonic, _password);
|
_privateKey = await getPrivateKey(_mnemonic, _password);
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import 'package:cake_wallet/anonpay/anonpay_info_base.dart';
|
import 'package:cake_wallet/anonpay/anonpay_info_base.dart';
|
||||||
|
import 'package:cw_core/hive_type_ids.dart';
|
||||||
import 'package:cw_core/keyable.dart';
|
import 'package:cw_core/keyable.dart';
|
||||||
import 'package:hive/hive.dart';
|
import 'package:hive/hive.dart';
|
||||||
|
|
||||||
|
@ -35,7 +36,7 @@ class AnonpayInvoiceInfo extends HiveObject with Keyable implements AnonpayInfoB
|
||||||
@HiveField(13)
|
@HiveField(13)
|
||||||
final String provider;
|
final String provider;
|
||||||
|
|
||||||
static const typeId = 10;
|
static const typeId = ANONPAY_INVOICE_INFO_TYPE_ID;
|
||||||
static const boxName = 'AnonpayInvoiceInfo';
|
static const boxName = 'AnonpayInvoiceInfo';
|
||||||
|
|
||||||
AnonpayInvoiceInfo({
|
AnonpayInvoiceInfo({
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
import 'package:cake_wallet/buy/buy_provider_description.dart';
|
import 'package:cake_wallet/buy/buy_provider_description.dart';
|
||||||
import 'package:hive/hive.dart';
|
|
||||||
import 'package:cake_wallet/exchange/trade_state.dart';
|
import 'package:cake_wallet/exchange/trade_state.dart';
|
||||||
import 'package:cw_core/format_amount.dart';
|
import 'package:cw_core/format_amount.dart';
|
||||||
|
import 'package:cw_core/hive_type_ids.dart';
|
||||||
|
import 'package:hive/hive.dart';
|
||||||
|
|
||||||
part 'order.g.dart';
|
part 'order.g.dart';
|
||||||
|
|
||||||
|
@ -26,7 +27,7 @@ class Order extends HiveObject {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static const typeId = 8;
|
static const typeId = ORDER_TYPE_ID;
|
||||||
static const boxName = 'Orders';
|
static const boxName = 'Orders';
|
||||||
static const boxKey = 'ordersBoxKey';
|
static const boxKey = 'ordersBoxKey';
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
import 'dart:typed_data';
|
import 'dart:typed_data';
|
||||||
import 'package:cake_wallet/entities/cake_2fa_preset_options.dart';
|
|
||||||
import 'package:cw_core/wallet_type.dart';
|
import 'package:cw_core/wallet_type.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:hive/hive.dart';
|
import 'package:hive/hive.dart';
|
||||||
|
@ -10,6 +9,7 @@ import 'package:path_provider/path_provider.dart';
|
||||||
import 'package:cryptography/cryptography.dart';
|
import 'package:cryptography/cryptography.dart';
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
import 'package:archive/archive_io.dart';
|
import 'package:archive/archive_io.dart';
|
||||||
|
import 'package:cw_core/cake_hive.dart';
|
||||||
import 'package:cake_wallet/core/key_service.dart';
|
import 'package:cake_wallet/core/key_service.dart';
|
||||||
import 'package:cake_wallet/entities/encrypt.dart';
|
import 'package:cake_wallet/entities/encrypt.dart';
|
||||||
import 'package:cake_wallet/entities/preferences_key.dart';
|
import 'package:cake_wallet/entities/preferences_key.dart';
|
||||||
|
@ -17,6 +17,7 @@ import 'package:cake_wallet/entities/secret_store_key.dart';
|
||||||
import 'package:cw_core/wallet_info.dart';
|
import 'package:cw_core/wallet_info.dart';
|
||||||
import 'package:cake_wallet/.secrets.g.dart' as secrets;
|
import 'package:cake_wallet/.secrets.g.dart' as secrets;
|
||||||
import 'package:cake_wallet/wallet_types.g.dart';
|
import 'package:cake_wallet/wallet_types.g.dart';
|
||||||
|
|
||||||
import 'package:cake_backup/backup.dart' as cake_backup;
|
import 'package:cake_backup/backup.dart' as cake_backup;
|
||||||
|
|
||||||
class BackupService {
|
class BackupService {
|
||||||
|
@ -170,14 +171,14 @@ class BackupService {
|
||||||
|
|
||||||
Future<Box<WalletInfo>> _reloadHiveWalletInfoBox() async {
|
Future<Box<WalletInfo>> _reloadHiveWalletInfoBox() async {
|
||||||
final appDir = await getApplicationDocumentsDirectory();
|
final appDir = await getApplicationDocumentsDirectory();
|
||||||
await Hive.close();
|
await CakeHive.close();
|
||||||
Hive.init(appDir.path);
|
CakeHive.init(appDir.path);
|
||||||
|
|
||||||
if (!Hive.isAdapterRegistered(WalletInfo.typeId)) {
|
if (!CakeHive.isAdapterRegistered(WalletInfo.typeId)) {
|
||||||
Hive.registerAdapter(WalletInfoAdapter());
|
CakeHive.registerAdapter(WalletInfoAdapter());
|
||||||
}
|
}
|
||||||
|
|
||||||
return await Hive.openBox<WalletInfo>(WalletInfo.boxName);
|
return await CakeHive.openBox<WalletInfo>(WalletInfo.boxName);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _importPreferencesDump() async {
|
Future<void> _importPreferencesDump() async {
|
||||||
|
|
|
@ -36,6 +36,8 @@ import 'package:cake_wallet/src/screens/setup_2fa/modify_2fa_page.dart';
|
||||||
import 'package:cake_wallet/src/screens/setup_2fa/setup_2fa_qr_page.dart';
|
import 'package:cake_wallet/src/screens/setup_2fa/setup_2fa_qr_page.dart';
|
||||||
import 'package:cake_wallet/src/screens/setup_2fa/setup_2fa.dart';
|
import 'package:cake_wallet/src/screens/setup_2fa/setup_2fa.dart';
|
||||||
import 'package:cake_wallet/src/screens/setup_2fa/setup_2fa_enter_code_page.dart';
|
import 'package:cake_wallet/src/screens/setup_2fa/setup_2fa_enter_code_page.dart';
|
||||||
|
import 'package:cake_wallet/src/screens/support_chat/support_chat_page.dart';
|
||||||
|
import 'package:cake_wallet/src/screens/support_other_links/support_other_links_page.dart';
|
||||||
import 'package:cake_wallet/src/screens/wallet/wallet_edit_page.dart';
|
import 'package:cake_wallet/src/screens/wallet/wallet_edit_page.dart';
|
||||||
import 'package:cake_wallet/themes/theme_list.dart';
|
import 'package:cake_wallet/themes/theme_list.dart';
|
||||||
import 'package:cake_wallet/utils/device_info.dart';
|
import 'package:cake_wallet/utils/device_info.dart';
|
||||||
|
@ -869,6 +871,12 @@ Future setup({
|
||||||
|
|
||||||
getIt.registerFactory(() => SupportPage(getIt.get<SupportViewModel>()));
|
getIt.registerFactory(() => SupportPage(getIt.get<SupportViewModel>()));
|
||||||
|
|
||||||
|
getIt.registerFactory(() =>
|
||||||
|
SupportChatPage(
|
||||||
|
getIt.get<SupportViewModel>(), secureStorage: getIt.get<FlutterSecureStorage>()));
|
||||||
|
|
||||||
|
getIt.registerFactory(() => SupportOtherLinksPage(getIt.get<SupportViewModel>()));
|
||||||
|
|
||||||
getIt.registerFactory(() {
|
getIt.registerFactory(() {
|
||||||
final wallet = getIt.get<AppStore>().wallet;
|
final wallet = getIt.get<AppStore>().wallet;
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
import 'package:flutter/foundation.dart';
|
|
||||||
import 'package:hive/hive.dart';
|
|
||||||
import 'package:cw_core/crypto_currency.dart';
|
import 'package:cw_core/crypto_currency.dart';
|
||||||
import 'package:cake_wallet/utils/mobx.dart';
|
import 'package:cw_core/hive_type_ids.dart';
|
||||||
import 'package:cw_core/keyable.dart';
|
import 'package:cw_core/keyable.dart';
|
||||||
|
import 'package:hive/hive.dart';
|
||||||
|
|
||||||
part 'contact.g.dart';
|
part 'contact.g.dart';
|
||||||
|
|
||||||
|
@ -14,7 +13,7 @@ class Contact extends HiveObject with Keyable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static const typeId = 0;
|
static const typeId = CONTACT_TYPE_ID;
|
||||||
static const boxName = 'Contacts';
|
static const boxName = 'Contacts';
|
||||||
|
|
||||||
@HiveField(0, defaultValue: '')
|
@HiveField(0, defaultValue: '')
|
||||||
|
|
|
@ -1,22 +1,17 @@
|
||||||
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
||||||
import 'package:hive/hive.dart';
|
import 'package:cw_core/cake_hive.dart';
|
||||||
|
|
||||||
Future<List<int>> getEncryptionKey(
|
Future<List<int>> getEncryptionKey(
|
||||||
{required String forKey, required FlutterSecureStorage secureStorage}) async {
|
{required String forKey, required FlutterSecureStorage secureStorage}) async {
|
||||||
final stringifiedKey =
|
final stringifiedKey = await secureStorage.read(key: 'transactionDescriptionsBoxKey');
|
||||||
await secureStorage.read(key: 'transactionDescriptionsBoxKey');
|
|
||||||
List<int> key;
|
List<int> key;
|
||||||
|
|
||||||
if (stringifiedKey == null) {
|
if (stringifiedKey == null) {
|
||||||
key = Hive.generateSecureKey();
|
key = CakeHive.generateSecureKey();
|
||||||
final keyStringified = key.join(',');
|
final keyStringified = key.join(',');
|
||||||
await secureStorage.write(
|
await secureStorage.write(key: 'transactionDescriptionsBoxKey', value: keyStringified);
|
||||||
key: 'transactionDescriptionsBoxKey', value: keyStringified);
|
|
||||||
} else {
|
} else {
|
||||||
key = stringifiedKey
|
key = stringifiedKey.split(',').map((i) => int.parse(i)).toList();
|
||||||
.split(',')
|
|
||||||
.map((i) => int.parse(i))
|
|
||||||
.toList();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return key;
|
return key;
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import 'package:cw_core/hive_type_ids.dart';
|
||||||
import 'package:hive/hive.dart';
|
import 'package:hive/hive.dart';
|
||||||
|
|
||||||
part 'template.g.dart';
|
part 'template.g.dart';
|
||||||
|
@ -14,7 +15,7 @@ class Template extends HiveObject {
|
||||||
required this.amountFiatRaw,
|
required this.amountFiatRaw,
|
||||||
this.additionalRecipientsRaw});
|
this.additionalRecipientsRaw});
|
||||||
|
|
||||||
static const typeId = 6;
|
static const typeId = TEMPLATE_TYPE_ID;
|
||||||
static const boxName = 'Template';
|
static const boxName = 'Template';
|
||||||
|
|
||||||
@HiveField(0)
|
@HiveField(0)
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import 'package:cw_core/hive_type_ids.dart';
|
||||||
import 'package:hive/hive.dart';
|
import 'package:hive/hive.dart';
|
||||||
|
|
||||||
part 'transaction_description.g.dart';
|
part 'transaction_description.g.dart';
|
||||||
|
@ -6,7 +7,7 @@ part 'transaction_description.g.dart';
|
||||||
class TransactionDescription extends HiveObject {
|
class TransactionDescription extends HiveObject {
|
||||||
TransactionDescription({required this.id, this.recipientAddress, this.transactionNote});
|
TransactionDescription({required this.id, this.recipientAddress, this.transactionNote});
|
||||||
|
|
||||||
static const typeId = 2;
|
static const typeId = TRANSACTION_TYPE_ID;
|
||||||
static const boxName = 'TransactionDescriptions';
|
static const boxName = 'TransactionDescriptions';
|
||||||
static const boxKey = 'transactionDescriptionsBoxKey';
|
static const boxKey = 'transactionDescriptionsBoxKey';
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import 'package:cw_core/hive_type_ids.dart';
|
||||||
import 'package:hive/hive.dart';
|
import 'package:hive/hive.dart';
|
||||||
|
|
||||||
part 'exchange_template.g.dart';
|
part 'exchange_template.g.dart';
|
||||||
|
@ -14,7 +15,7 @@ class ExchangeTemplate extends HiveObject {
|
||||||
required this.depositCurrencyTitleRaw,
|
required this.depositCurrencyTitleRaw,
|
||||||
required this.receiveCurrencyTitleRaw});
|
required this.receiveCurrencyTitleRaw});
|
||||||
|
|
||||||
static const typeId = 7;
|
static const typeId = EXCHANGE_TEMPLATE_TYPE_ID;
|
||||||
static const boxName = 'ExchangeTemplate';
|
static const boxName = 'ExchangeTemplate';
|
||||||
|
|
||||||
@HiveField(0)
|
@HiveField(0)
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
import 'package:hive/hive.dart';
|
|
||||||
import 'package:cw_core/crypto_currency.dart';
|
import 'package:cw_core/crypto_currency.dart';
|
||||||
import 'package:cake_wallet/exchange/exchange_provider_description.dart';
|
import 'package:cake_wallet/exchange/exchange_provider_description.dart';
|
||||||
import 'package:cake_wallet/exchange/trade_state.dart';
|
import 'package:cake_wallet/exchange/trade_state.dart';
|
||||||
import 'package:cw_core/format_amount.dart';
|
import 'package:cw_core/format_amount.dart';
|
||||||
|
import 'package:cw_core/hive_type_ids.dart';
|
||||||
|
import 'package:hive/hive.dart';
|
||||||
|
|
||||||
part 'trade.g.dart';
|
part 'trade.g.dart';
|
||||||
|
|
||||||
|
@ -41,7 +42,7 @@ class Trade extends HiveObject {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static const typeId = 3;
|
static const typeId = TRADE_TYPE_ID;
|
||||||
static const boxName = 'Trades';
|
static const boxName = 'Trades';
|
||||||
static const boxKey = 'tradesBoxKey';
|
static const boxKey = 'tradesBoxKey';
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@ import 'package:cake_wallet/locales/locale.dart';
|
||||||
import 'package:cake_wallet/store/yat/yat_store.dart';
|
import 'package:cake_wallet/store/yat/yat_store.dart';
|
||||||
import 'package:cake_wallet/utils/exception_handler.dart';
|
import 'package:cake_wallet/utils/exception_handler.dart';
|
||||||
import 'package:cake_wallet/utils/responsive_layout_util.dart';
|
import 'package:cake_wallet/utils/responsive_layout_util.dart';
|
||||||
|
import 'package:cw_core/hive_type_ids.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
|
@ -38,6 +39,7 @@ import 'package:uni_links/uni_links.dart';
|
||||||
import 'package:cw_core/unspent_coins_info.dart';
|
import 'package:cw_core/unspent_coins_info.dart';
|
||||||
import 'package:cake_wallet/monero/monero.dart';
|
import 'package:cake_wallet/monero/monero.dart';
|
||||||
import 'package:cake_wallet/wallet_type_utils.dart';
|
import 'package:cake_wallet/wallet_type_utils.dart';
|
||||||
|
import 'package:cw_core/cake_hive.dart';
|
||||||
|
|
||||||
final navigatorKey = GlobalKey<NavigatorState>();
|
final navigatorKey = GlobalKey<NavigatorState>();
|
||||||
final rootKey = GlobalKey<RootState>();
|
final rootKey = GlobalKey<RootState>();
|
||||||
|
@ -57,7 +59,7 @@ Future<void> main() async {
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
await Hive.close();
|
await CakeHive.close();
|
||||||
|
|
||||||
await initializeAppConfigs();
|
await initializeAppConfigs();
|
||||||
|
|
||||||
|
@ -69,50 +71,50 @@ Future<void> main() async {
|
||||||
|
|
||||||
Future<void> initializeAppConfigs() async {
|
Future<void> initializeAppConfigs() async {
|
||||||
final appDir = await getApplicationDocumentsDirectory();
|
final appDir = await getApplicationDocumentsDirectory();
|
||||||
Hive.init(appDir.path);
|
CakeHive.init(appDir.path);
|
||||||
|
|
||||||
if (!Hive.isAdapterRegistered(Contact.typeId)) {
|
if (!CakeHive.isAdapterRegistered(Contact.typeId)) {
|
||||||
Hive.registerAdapter(ContactAdapter());
|
CakeHive.registerAdapter(ContactAdapter());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Hive.isAdapterRegistered(Node.typeId)) {
|
if (!CakeHive.isAdapterRegistered(Node.typeId)) {
|
||||||
Hive.registerAdapter(NodeAdapter());
|
CakeHive.registerAdapter(NodeAdapter());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Hive.isAdapterRegistered(TransactionDescription.typeId)) {
|
if (!CakeHive.isAdapterRegistered(TransactionDescription.typeId)) {
|
||||||
Hive.registerAdapter(TransactionDescriptionAdapter());
|
CakeHive.registerAdapter(TransactionDescriptionAdapter());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Hive.isAdapterRegistered(Trade.typeId)) {
|
if (!CakeHive.isAdapterRegistered(Trade.typeId)) {
|
||||||
Hive.registerAdapter(TradeAdapter());
|
CakeHive.registerAdapter(TradeAdapter());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Hive.isAdapterRegistered(WalletInfo.typeId)) {
|
if (!CakeHive.isAdapterRegistered(WalletInfo.typeId)) {
|
||||||
Hive.registerAdapter(WalletInfoAdapter());
|
CakeHive.registerAdapter(WalletInfoAdapter());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Hive.isAdapterRegistered(walletTypeTypeId)) {
|
if (!CakeHive.isAdapterRegistered(WALLET_TYPE_TYPE_ID)) {
|
||||||
Hive.registerAdapter(WalletTypeAdapter());
|
CakeHive.registerAdapter(WalletTypeAdapter());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Hive.isAdapterRegistered(Template.typeId)) {
|
if (!CakeHive.isAdapterRegistered(Template.typeId)) {
|
||||||
Hive.registerAdapter(TemplateAdapter());
|
CakeHive.registerAdapter(TemplateAdapter());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Hive.isAdapterRegistered(ExchangeTemplate.typeId)) {
|
if (!CakeHive.isAdapterRegistered(ExchangeTemplate.typeId)) {
|
||||||
Hive.registerAdapter(ExchangeTemplateAdapter());
|
CakeHive.registerAdapter(ExchangeTemplateAdapter());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Hive.isAdapterRegistered(Order.typeId)) {
|
if (!CakeHive.isAdapterRegistered(Order.typeId)) {
|
||||||
Hive.registerAdapter(OrderAdapter());
|
CakeHive.registerAdapter(OrderAdapter());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isMoneroOnly && !Hive.isAdapterRegistered(UnspentCoinsInfo.typeId)) {
|
if (!isMoneroOnly && !CakeHive.isAdapterRegistered(UnspentCoinsInfo.typeId)) {
|
||||||
Hive.registerAdapter(UnspentCoinsInfoAdapter());
|
CakeHive.registerAdapter(UnspentCoinsInfoAdapter());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Hive.isAdapterRegistered(AnonpayInvoiceInfo.typeId)) {
|
if (!CakeHive.isAdapterRegistered(AnonpayInvoiceInfo.typeId)) {
|
||||||
Hive.registerAdapter(AnonpayInvoiceInfoAdapter());
|
CakeHive.registerAdapter(AnonpayInvoiceInfoAdapter());
|
||||||
}
|
}
|
||||||
|
|
||||||
final secureStorage = FlutterSecureStorage();
|
final secureStorage = FlutterSecureStorage();
|
||||||
|
@ -120,21 +122,21 @@ Future<void> initializeAppConfigs() async {
|
||||||
await getEncryptionKey(secureStorage: secureStorage, forKey: TransactionDescription.boxKey);
|
await getEncryptionKey(secureStorage: secureStorage, forKey: TransactionDescription.boxKey);
|
||||||
final tradesBoxKey = await getEncryptionKey(secureStorage: secureStorage, forKey: Trade.boxKey);
|
final tradesBoxKey = await getEncryptionKey(secureStorage: secureStorage, forKey: Trade.boxKey);
|
||||||
final ordersBoxKey = await getEncryptionKey(secureStorage: secureStorage, forKey: Order.boxKey);
|
final ordersBoxKey = await getEncryptionKey(secureStorage: secureStorage, forKey: Order.boxKey);
|
||||||
final contacts = await Hive.openBox<Contact>(Contact.boxName);
|
final contacts = await CakeHive.openBox<Contact>(Contact.boxName);
|
||||||
final nodes = await Hive.openBox<Node>(Node.boxName);
|
final nodes = await CakeHive.openBox<Node>(Node.boxName);
|
||||||
final transactionDescriptions = await Hive.openBox<TransactionDescription>(
|
final transactionDescriptions = await CakeHive.openBox<TransactionDescription>(
|
||||||
TransactionDescription.boxName,
|
TransactionDescription.boxName,
|
||||||
encryptionKey: transactionDescriptionsBoxKey);
|
encryptionKey: transactionDescriptionsBoxKey);
|
||||||
final trades = await Hive.openBox<Trade>(Trade.boxName, encryptionKey: tradesBoxKey);
|
final trades = await CakeHive.openBox<Trade>(Trade.boxName, encryptionKey: tradesBoxKey);
|
||||||
final orders = await Hive.openBox<Order>(Order.boxName, encryptionKey: ordersBoxKey);
|
final orders = await CakeHive.openBox<Order>(Order.boxName, encryptionKey: ordersBoxKey);
|
||||||
final walletInfoSource = await Hive.openBox<WalletInfo>(WalletInfo.boxName);
|
final walletInfoSource = await CakeHive.openBox<WalletInfo>(WalletInfo.boxName);
|
||||||
final templates = await Hive.openBox<Template>(Template.boxName);
|
final templates = await CakeHive.openBox<Template>(Template.boxName);
|
||||||
final exchangeTemplates = await Hive.openBox<ExchangeTemplate>(ExchangeTemplate.boxName);
|
final exchangeTemplates = await CakeHive.openBox<ExchangeTemplate>(ExchangeTemplate.boxName);
|
||||||
final anonpayInvoiceInfo = await Hive.openBox<AnonpayInvoiceInfo>(AnonpayInvoiceInfo.boxName);
|
final anonpayInvoiceInfo = await CakeHive.openBox<AnonpayInvoiceInfo>(AnonpayInvoiceInfo.boxName);
|
||||||
Box<UnspentCoinsInfo>? unspentCoinsInfoSource;
|
Box<UnspentCoinsInfo>? unspentCoinsInfoSource;
|
||||||
|
|
||||||
if (!isMoneroOnly) {
|
if (!isMoneroOnly) {
|
||||||
unspentCoinsInfoSource = await Hive.openBox<UnspentCoinsInfo>(UnspentCoinsInfo.boxName);
|
unspentCoinsInfoSource = await CakeHive.openBox<UnspentCoinsInfo>(UnspentCoinsInfo.boxName);
|
||||||
}
|
}
|
||||||
|
|
||||||
await initialSetup(
|
await initialSetup(
|
||||||
|
|
|
@ -41,6 +41,8 @@ import 'package:cake_wallet/src/screens/setup_2fa/setup_2fa_qr_page.dart';
|
||||||
import 'package:cake_wallet/src/screens/setup_2fa/setup_2fa.dart';
|
import 'package:cake_wallet/src/screens/setup_2fa/setup_2fa.dart';
|
||||||
import 'package:cake_wallet/src/screens/setup_2fa/setup_2fa_enter_code_page.dart';
|
import 'package:cake_wallet/src/screens/setup_2fa/setup_2fa_enter_code_page.dart';
|
||||||
import 'package:cake_wallet/src/screens/support/support_page.dart';
|
import 'package:cake_wallet/src/screens/support/support_page.dart';
|
||||||
|
import 'package:cake_wallet/src/screens/support_chat/support_chat_page.dart';
|
||||||
|
import 'package:cake_wallet/src/screens/support_other_links/support_other_links_page.dart';
|
||||||
import 'package:cake_wallet/src/screens/unspent_coins/unspent_coins_details_page.dart';
|
import 'package:cake_wallet/src/screens/unspent_coins/unspent_coins_details_page.dart';
|
||||||
import 'package:cake_wallet/src/screens/unspent_coins/unspent_coins_list_page.dart';
|
import 'package:cake_wallet/src/screens/unspent_coins/unspent_coins_list_page.dart';
|
||||||
import 'package:cake_wallet/utils/payment_request.dart';
|
import 'package:cake_wallet/utils/payment_request.dart';
|
||||||
|
@ -48,7 +50,6 @@ import 'package:cake_wallet/view_model/dashboard/dashboard_view_model.dart';
|
||||||
import 'package:cake_wallet/view_model/monero_account_list/account_list_item.dart';
|
import 'package:cake_wallet/view_model/monero_account_list/account_list_item.dart';
|
||||||
import 'package:cake_wallet/view_model/node_list/node_create_or_edit_view_model.dart';
|
import 'package:cake_wallet/view_model/node_list/node_create_or_edit_view_model.dart';
|
||||||
import 'package:cake_wallet/view_model/advanced_privacy_settings_view_model.dart';
|
import 'package:cake_wallet/view_model/advanced_privacy_settings_view_model.dart';
|
||||||
import 'package:cake_wallet/view_model/wallet_list/wallet_list_item.dart';
|
|
||||||
import 'package:cake_wallet/wallet_type_utils.dart';
|
import 'package:cake_wallet/wallet_type_utils.dart';
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
@ -442,9 +443,17 @@ Route<dynamic> createRoute(RouteSettings settings) {
|
||||||
|
|
||||||
case Routes.support:
|
case Routes.support:
|
||||||
return CupertinoPageRoute<void>(
|
return CupertinoPageRoute<void>(
|
||||||
fullscreenDialog: true,
|
|
||||||
builder: (_) => getIt.get<SupportPage>());
|
builder: (_) => getIt.get<SupportPage>());
|
||||||
|
|
||||||
|
case Routes.supportLiveChat:
|
||||||
|
return CupertinoPageRoute<void>(
|
||||||
|
builder: (_) => getIt.get<SupportChatPage>());
|
||||||
|
|
||||||
|
case Routes.supportOtherLinks:
|
||||||
|
return CupertinoPageRoute<void>(
|
||||||
|
fullscreenDialog: true,
|
||||||
|
builder: (_) => getIt.get<SupportOtherLinksPage>());
|
||||||
|
|
||||||
case Routes.unspentCoinsList:
|
case Routes.unspentCoinsList:
|
||||||
return MaterialPageRoute<void>(
|
return MaterialPageRoute<void>(
|
||||||
builder: (_) => getIt.get<UnspentCoinsListPage>());
|
builder: (_) => getIt.get<UnspentCoinsListPage>());
|
||||||
|
|
|
@ -48,6 +48,8 @@ class Routes {
|
||||||
static const editBackupPassword = '/edit_backup_passowrd';
|
static const editBackupPassword = '/edit_backup_passowrd';
|
||||||
static const restoreFromBackup = '/restore_from_backup';
|
static const restoreFromBackup = '/restore_from_backup';
|
||||||
static const support = '/support';
|
static const support = '/support';
|
||||||
|
static const supportLiveChat = '/support/live_chat';
|
||||||
|
static const supportOtherLinks = '/support/other';
|
||||||
static const orderDetails = '/order_details';
|
static const orderDetails = '/order_details';
|
||||||
static const preOrder = '/pre_order';
|
static const preOrder = '/pre_order';
|
||||||
static const buyWebView = '/buy_web_view';
|
static const buyWebView = '/buy_web_view';
|
||||||
|
|
|
@ -2,12 +2,10 @@ import 'package:cake_wallet/core/execution_state.dart';
|
||||||
import 'package:cake_wallet/di.dart';
|
import 'package:cake_wallet/di.dart';
|
||||||
import 'package:cake_wallet/src/screens/pin_code/pin_code_widget.dart';
|
import 'package:cake_wallet/src/screens/pin_code/pin_code_widget.dart';
|
||||||
import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
|
import 'package:cake_wallet/src/widgets/alert_with_one_action.dart';
|
||||||
import 'package:cake_wallet/utils/language_list.dart';
|
|
||||||
import 'package:cake_wallet/utils/show_pop_up.dart';
|
import 'package:cake_wallet/utils/show_pop_up.dart';
|
||||||
import 'package:cake_wallet/view_model/restore/restore_from_qr_vm.dart';
|
import 'package:cake_wallet/view_model/restore/restore_from_qr_vm.dart';
|
||||||
import 'package:cake_wallet/view_model/restore/wallet_restore_from_qr_code.dart';
|
import 'package:cake_wallet/view_model/restore/wallet_restore_from_qr_code.dart';
|
||||||
import 'package:cake_wallet/utils/responsive_layout_util.dart';
|
import 'package:cake_wallet/utils/responsive_layout_util.dart';
|
||||||
import 'package:cake_wallet/wallet_type_utils.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:cake_wallet/routes.dart';
|
import 'package:cake_wallet/routes.dart';
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
import 'package:flutter/cupertino.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class RestoreButton extends StatelessWidget {
|
class RestoreButton extends StatelessWidget {
|
||||||
const RestoreButton({
|
const RestoreButton(
|
||||||
required this.onPressed,
|
{required this.onPressed,
|
||||||
required this.image,
|
required this.image,
|
||||||
required this.title,
|
required this.title,
|
||||||
required this.description});
|
required this.description});
|
||||||
|
@ -24,10 +23,7 @@ class RestoreButton extends StatelessWidget {
|
||||||
alignment: Alignment.topLeft,
|
alignment: Alignment.topLeft,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
borderRadius: BorderRadius.all(Radius.circular(12)),
|
borderRadius: BorderRadius.all(Radius.circular(12)),
|
||||||
color: Theme.of(context)
|
color: Theme.of(context).accentTextTheme.bodySmall!.color!,
|
||||||
.accentTextTheme!
|
|
||||||
.bodySmall!
|
|
||||||
.color!,
|
|
||||||
),
|
),
|
||||||
child: Row(
|
child: Row(
|
||||||
mainAxisSize: MainAxisSize.max,
|
mainAxisSize: MainAxisSize.max,
|
||||||
|
@ -49,7 +45,7 @@ class RestoreButton extends StatelessWidget {
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.w500,
|
||||||
color: Theme.of(context)
|
color: Theme.of(context)
|
||||||
.primaryTextTheme!
|
.primaryTextTheme
|
||||||
.titleLarge!
|
.titleLarge!
|
||||||
.color!),
|
.color!),
|
||||||
),
|
),
|
||||||
|
@ -61,7 +57,7 @@ class RestoreButton extends StatelessWidget {
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
fontWeight: FontWeight.normal,
|
fontWeight: FontWeight.normal,
|
||||||
color: Theme.of(context)
|
color: Theme.of(context)
|
||||||
.primaryTextTheme!
|
.primaryTextTheme
|
||||||
.labelSmall!
|
.labelSmall!
|
||||||
.color!),
|
.color!),
|
||||||
),
|
),
|
||||||
|
|
|
@ -6,7 +6,6 @@ class SettingsCellWithArrow extends StandardListRow {
|
||||||
: super(title: title, isSelected: false, onTap: handler);
|
: super(title: title, isSelected: false, onTap: handler);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget buildTrailing(BuildContext context) =>
|
Widget buildTrailing(BuildContext context) => Image.asset('assets/images/select_arrow.png',
|
||||||
Image.asset('assets/images/select_arrow.png',
|
color: Theme.of(context).primaryTextTheme.labelSmall!.color!);
|
||||||
color: Theme.of(context).primaryTextTheme!.labelSmall!.color!);
|
|
||||||
}
|
}
|
|
@ -1,55 +1,78 @@
|
||||||
import 'package:cake_wallet/src/screens/settings/widgets/settings_cell_with_arrow.dart';
|
import 'package:cake_wallet/generated/i18n.dart';
|
||||||
import 'package:cake_wallet/src/screens/settings/widgets/settings_link_provider_cell.dart';
|
import 'package:cake_wallet/routes.dart';
|
||||||
import 'package:cake_wallet/src/widgets/standard_list.dart';
|
import 'package:cake_wallet/src/screens/support/widgets/support_tiles.dart';
|
||||||
import 'package:cake_wallet/utils/responsive_layout_util.dart';
|
import 'package:cake_wallet/src/screens/base_page.dart';
|
||||||
import 'package:cake_wallet/view_model/settings/link_list_item.dart';
|
import 'package:cake_wallet/utils/device_info.dart';
|
||||||
import 'package:cake_wallet/view_model/settings/regular_list_item.dart';
|
|
||||||
import 'package:cake_wallet/view_model/support_view_model.dart';
|
import 'package:cake_wallet/view_model/support_view_model.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:cake_wallet/src/screens/base_page.dart';
|
import 'package:url_launcher/url_launcher.dart';
|
||||||
import 'package:cake_wallet/generated/i18n.dart';
|
|
||||||
|
|
||||||
class SupportPage extends BasePage {
|
class SupportPage extends BasePage {
|
||||||
SupportPage(this.supportViewModel);
|
SupportPage(this.supportViewModel);
|
||||||
|
|
||||||
final SupportViewModel supportViewModel;
|
final SupportViewModel supportViewModel;
|
||||||
|
|
||||||
|
final imageLiveSupport = Image.asset('assets/images/live_support.png');
|
||||||
|
final imageWalletGuides = Image.asset('assets/images/wallet_guides.png');
|
||||||
|
final imageMoreLinks = Image.asset('assets/images/more_links.png');
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get title => S.current.settings_support;
|
String get title => S.current.settings_support;
|
||||||
|
|
||||||
|
@override
|
||||||
|
AppBarStyle get appBarStyle => AppBarStyle.regular;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget body(BuildContext context) {
|
Widget body(BuildContext context) {
|
||||||
final iconColor = Theme.of(context)
|
return Container(
|
||||||
.accentTextTheme!
|
child: Center(
|
||||||
.displayLarge!
|
|
||||||
.backgroundColor!;
|
|
||||||
// FIX-ME: Added `context` it was not used here before, maby bug ?
|
|
||||||
return Center(
|
|
||||||
child: ConstrainedBox(
|
child: ConstrainedBox(
|
||||||
constraints: BoxConstraints(maxWidth: 500),
|
constraints: BoxConstraints(maxWidth: 330),
|
||||||
child: SectionStandardList(
|
child: Column(
|
||||||
context: context,
|
children: [
|
||||||
sectionCount: 1,
|
Padding(
|
||||||
itemCounter: (int _) => supportViewModel.items.length,
|
padding: EdgeInsets.only(top: 24),
|
||||||
itemBuilder: (_, __, index) {
|
child: SupportTile(
|
||||||
final item = supportViewModel.items[index];
|
image: imageLiveSupport,
|
||||||
|
title: S.of(context).support_title_live_chat,
|
||||||
if (item is RegularListItem) {
|
description: S.of(context).support_description_live_chat,
|
||||||
return SettingsCellWithArrow(title: item.title, handler: item.handler);
|
onPressed: () {
|
||||||
|
if (DeviceInfo.instance.isDesktop) {
|
||||||
|
_launchUrl(supportViewModel.fetchUrl());
|
||||||
|
} else {
|
||||||
|
Navigator.pushNamed(context, Routes.supportLiveChat);
|
||||||
}
|
}
|
||||||
|
},
|
||||||
if (item is LinkListItem) {
|
),
|
||||||
return SettingsLinkProviderCell(
|
),
|
||||||
title: item.title,
|
Padding(
|
||||||
icon: item.icon,
|
padding: EdgeInsets.only(top: 24),
|
||||||
iconColor: item.hasIconColor ? iconColor : null,
|
child: SupportTile(
|
||||||
link: item.link,
|
image: imageWalletGuides,
|
||||||
linkTitle: item.linkTitle);
|
title: S.of(context).support_title_guides,
|
||||||
}
|
description: S.of(context).support_description_guides,
|
||||||
|
onPressed: () => _launchUrl(supportViewModel.guidesUrl),
|
||||||
return Container();
|
),
|
||||||
}),
|
),
|
||||||
|
Padding(
|
||||||
|
padding: EdgeInsets.only(top: 24),
|
||||||
|
child: SupportTile(
|
||||||
|
image: imageMoreLinks,
|
||||||
|
title: S.of(context).support_title_other_links,
|
||||||
|
description: S.of(context).support_description_other_links,
|
||||||
|
onPressed: () => Navigator.pushNamed(context, Routes.supportOtherLinks),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _launchUrl(String url) async {
|
||||||
|
try {
|
||||||
|
await launchUrl(Uri.parse(url), mode: LaunchMode.externalApplication);
|
||||||
|
} catch (e) {}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
69
lib/src/screens/support/widgets/support_tiles.dart
Normal file
69
lib/src/screens/support/widgets/support_tiles.dart
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class SupportTile extends StatelessWidget {
|
||||||
|
const SupportTile(
|
||||||
|
{required this.onPressed,
|
||||||
|
required this.image,
|
||||||
|
required this.title,
|
||||||
|
required this.description});
|
||||||
|
|
||||||
|
final VoidCallback onPressed;
|
||||||
|
final Image image;
|
||||||
|
final String title;
|
||||||
|
final String description;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return GestureDetector(
|
||||||
|
onTap: onPressed,
|
||||||
|
child: Container(
|
||||||
|
width: double.infinity,
|
||||||
|
padding: EdgeInsets.all(24),
|
||||||
|
alignment: Alignment.center,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.all(Radius.circular(12)),
|
||||||
|
color: Theme.of(context).accentTextTheme.bodySmall!.color!,
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
mainAxisSize: MainAxisSize.max,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: <Widget>[
|
||||||
|
image,
|
||||||
|
Expanded(
|
||||||
|
child: Padding(
|
||||||
|
padding: EdgeInsets.only(left: 16),
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.max,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: <Widget>[
|
||||||
|
Text(
|
||||||
|
title,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 20,
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
color: Theme.of(context).primaryTextTheme.titleLarge!.color!,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: EdgeInsets.only(top: 5),
|
||||||
|
child: Text(
|
||||||
|
description,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: FontWeight.normal,
|
||||||
|
color: Theme.of(context).primaryTextTheme.labelSmall!.color!,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
38
lib/src/screens/support_chat/support_chat_page.dart
Normal file
38
lib/src/screens/support_chat/support_chat_page.dart
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
import 'package:cake_wallet/generated/i18n.dart';
|
||||||
|
import 'package:cake_wallet/src/screens/base_page.dart';
|
||||||
|
import 'package:cake_wallet/src/screens/support_chat/widgets/chatwoot_widget.dart';
|
||||||
|
import 'package:cake_wallet/view_model/support_view_model.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
||||||
|
|
||||||
|
|
||||||
|
class SupportChatPage extends BasePage {
|
||||||
|
SupportChatPage(this.supportViewModel, {required this.secureStorage});
|
||||||
|
|
||||||
|
final SupportViewModel supportViewModel;
|
||||||
|
final FlutterSecureStorage secureStorage;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get title => S.current.settings_support;
|
||||||
|
|
||||||
|
@override
|
||||||
|
AppBarStyle get appBarStyle => AppBarStyle.regular;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget body(BuildContext context) => FutureBuilder<String>(
|
||||||
|
future: getCookie(),
|
||||||
|
builder: (BuildContext context, AsyncSnapshot<String> snapshot) {
|
||||||
|
print(snapshot.data);
|
||||||
|
if (snapshot.hasData)
|
||||||
|
return ChatwootWidget(
|
||||||
|
secureStorage,
|
||||||
|
supportUrl: supportViewModel.fetchUrl(authToken: snapshot.data!)
|
||||||
|
);
|
||||||
|
return Container();
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
Future<String> getCookie() async {
|
||||||
|
return await secureStorage.read(key: COOKIE_KEY) ?? "";
|
||||||
|
}
|
||||||
|
}
|
62
lib/src/screens/support_chat/widgets/chatwoot_widget.dart
Normal file
62
lib/src/screens/support_chat/widgets/chatwoot_widget.dart
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
import 'dart:convert';
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
|
||||||
|
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
||||||
|
|
||||||
|
const COOKIE_KEY = 'chatwootCookie';
|
||||||
|
|
||||||
|
class ChatwootWidget extends StatefulWidget {
|
||||||
|
ChatwootWidget(this.secureStorage, {required this.supportUrl});
|
||||||
|
|
||||||
|
final FlutterSecureStorage secureStorage;
|
||||||
|
final String supportUrl;
|
||||||
|
|
||||||
|
@override
|
||||||
|
ChatwootWidgetState createState() => ChatwootWidgetState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class ChatwootWidgetState extends State<ChatwootWidget> {
|
||||||
|
final GlobalKey _webViewkey = GlobalKey();
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) => InAppWebView(
|
||||||
|
key: _webViewkey,
|
||||||
|
initialOptions: InAppWebViewGroupOptions(
|
||||||
|
crossPlatform: InAppWebViewOptions(transparentBackground: true),
|
||||||
|
),
|
||||||
|
initialUrlRequest: URLRequest(url: Uri.tryParse(widget.supportUrl)),
|
||||||
|
onWebViewCreated: (InAppWebViewController controller) {
|
||||||
|
controller.addWebMessageListener(
|
||||||
|
WebMessageListener(
|
||||||
|
jsObjectName: 'ReactNativeWebView',
|
||||||
|
onPostMessage: (String? message, Uri? sourceOrigin, bool isMainFrame,
|
||||||
|
JavaScriptReplyProxy replyProxy) {
|
||||||
|
final shortenedMessage = message?.substring(16);
|
||||||
|
if (shortenedMessage != null && isJsonString(shortenedMessage)) {
|
||||||
|
final parsedMessage = jsonDecode(shortenedMessage);
|
||||||
|
final eventType = parsedMessage["event"];
|
||||||
|
if (eventType == 'loaded') {
|
||||||
|
final authToken = parsedMessage["config"]["authToken"];
|
||||||
|
print(authToken);
|
||||||
|
storeCookie(authToken as String);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
bool isJsonString(String str) {
|
||||||
|
try {
|
||||||
|
jsonDecode(str);
|
||||||
|
} catch (e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> storeCookie(String value) async =>
|
||||||
|
await widget.secureStorage.write(key: COOKIE_KEY, value: value);
|
||||||
|
}
|
|
@ -0,0 +1,58 @@
|
||||||
|
import 'package:cake_wallet/src/screens/settings/widgets/settings_cell_with_arrow.dart';
|
||||||
|
import 'package:cake_wallet/src/screens/settings/widgets/settings_link_provider_cell.dart';
|
||||||
|
import 'package:cake_wallet/src/widgets/standard_list.dart';
|
||||||
|
import 'package:cake_wallet/view_model/settings/link_list_item.dart';
|
||||||
|
import 'package:cake_wallet/view_model/settings/regular_list_item.dart';
|
||||||
|
import 'package:cake_wallet/view_model/support_view_model.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:cake_wallet/src/screens/base_page.dart';
|
||||||
|
import 'package:cake_wallet/generated/i18n.dart';
|
||||||
|
|
||||||
|
class SupportOtherLinksPage extends BasePage {
|
||||||
|
SupportOtherLinksPage(this.supportViewModel);
|
||||||
|
|
||||||
|
final SupportViewModel supportViewModel;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get title => S.current.settings_support;
|
||||||
|
|
||||||
|
@override
|
||||||
|
AppBarStyle get appBarStyle => AppBarStyle.transparent;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget body(BuildContext context) {
|
||||||
|
final iconColor =
|
||||||
|
Theme.of(context).accentTextTheme.displayLarge!.backgroundColor!;
|
||||||
|
|
||||||
|
return Container(
|
||||||
|
child: Center(
|
||||||
|
child: ConstrainedBox(
|
||||||
|
constraints: BoxConstraints(maxWidth: 500),
|
||||||
|
child: SectionStandardList(
|
||||||
|
context: context,
|
||||||
|
sectionCount: 1,
|
||||||
|
itemCounter: (int _) => supportViewModel.items.length,
|
||||||
|
itemBuilder: (_, __, index) {
|
||||||
|
final item = supportViewModel.items[index];
|
||||||
|
|
||||||
|
if (item is RegularListItem) {
|
||||||
|
return SettingsCellWithArrow(
|
||||||
|
title: item.title, handler: item.handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item is LinkListItem) {
|
||||||
|
return SettingsLinkProviderCell(
|
||||||
|
title: item.title,
|
||||||
|
icon: item.icon,
|
||||||
|
iconColor: item.hasIconColor ? iconColor : null,
|
||||||
|
link: item.link,
|
||||||
|
linkTitle: item.linkTitle);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Container();
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,12 +1,9 @@
|
||||||
import 'package:cake_wallet/generated/i18n.dart';
|
import 'package:cake_wallet/generated/i18n.dart';
|
||||||
import 'package:cake_wallet/view_model/settings/link_list_item.dart';
|
import 'package:cake_wallet/view_model/settings/link_list_item.dart';
|
||||||
import 'package:cake_wallet/view_model/settings/regular_list_item.dart';
|
|
||||||
import 'package:cake_wallet/view_model/settings/settings_list_item.dart';
|
import 'package:cake_wallet/view_model/settings/settings_list_item.dart';
|
||||||
import 'package:flutter/cupertino.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:mobx/mobx.dart';
|
|
||||||
import 'package:url_launcher/url_launcher.dart';
|
|
||||||
import 'package:cake_wallet/wallet_type_utils.dart';
|
import 'package:cake_wallet/wallet_type_utils.dart';
|
||||||
|
import 'package:mobx/mobx.dart';
|
||||||
|
import 'package:cake_wallet/.secrets.g.dart' as secrets;
|
||||||
|
|
||||||
part 'support_view_model.g.dart';
|
part 'support_view_model.g.dart';
|
||||||
|
|
||||||
|
@ -15,14 +12,6 @@ class SupportViewModel = SupportViewModelBase with _$SupportViewModel;
|
||||||
abstract class SupportViewModelBase with Store {
|
abstract class SupportViewModelBase with Store {
|
||||||
SupportViewModelBase()
|
SupportViewModelBase()
|
||||||
: items = [
|
: items = [
|
||||||
RegularListItem(
|
|
||||||
title: S.current.faq,
|
|
||||||
handler: (BuildContext context) async {
|
|
||||||
try {
|
|
||||||
await launch(url);
|
|
||||||
} catch (e) {}
|
|
||||||
},
|
|
||||||
),
|
|
||||||
LinkListItem(
|
LinkListItem(
|
||||||
title: 'Email',
|
title: 'Email',
|
||||||
linkTitle: 'support@cakewallet.com',
|
linkTitle: 'support@cakewallet.com',
|
||||||
|
@ -85,7 +74,17 @@ abstract class SupportViewModelBase with Store {
|
||||||
// link: 'mailto:support@y.at')
|
// link: 'mailto:support@y.at')
|
||||||
];
|
];
|
||||||
|
|
||||||
static const url = 'https://guides.cakewallet.com';
|
final guidesUrl = 'https://guides.cakewallet.com';
|
||||||
|
|
||||||
|
String fetchUrl({String locale = "en", String authToken = ""}) {
|
||||||
|
var supportUrl =
|
||||||
|
"https://support.cakewallet.com/widget?website_token=${secrets.chatwootWebsiteToken}&locale=${locale}";
|
||||||
|
|
||||||
|
if (authToken.isNotEmpty)
|
||||||
|
supportUrl += "&cw_conversation=$authToken";
|
||||||
|
|
||||||
|
return supportUrl;
|
||||||
|
}
|
||||||
|
|
||||||
List<SettingsListItem> items;
|
List<SettingsListItem> items;
|
||||||
}
|
}
|
|
@ -100,6 +100,7 @@ dev_dependencies:
|
||||||
# check flutter_launcher_icons for usage
|
# check flutter_launcher_icons for usage
|
||||||
pedantic: ^1.8.0
|
pedantic: ^1.8.0
|
||||||
# replace https://github.com/dart-lang/lints#migrating-from-packagepedantic
|
# replace https://github.com/dart-lang/lints#migrating-from-packagepedantic
|
||||||
|
translator: ^0.1.7
|
||||||
|
|
||||||
flutter_icons:
|
flutter_icons:
|
||||||
image_path: "assets/images/app_logo.png"
|
image_path: "assets/images/app_logo.png"
|
||||||
|
|
|
@ -668,5 +668,11 @@
|
||||||
"slidable": "قابل للانزلاق",
|
"slidable": "قابل للانزلاق",
|
||||||
"etherscan_history": "Etherscan تاريخ",
|
"etherscan_history": "Etherscan تاريخ",
|
||||||
"manage_nodes": "ﺪﻘﻌﻟﺍ ﺓﺭﺍﺩﺇ",
|
"manage_nodes": "ﺪﻘﻌﻟﺍ ﺓﺭﺍﺩﺇ",
|
||||||
"template_name": "اسم القالب"
|
"template_name": "اسم القالب",
|
||||||
|
"support_title_live_chat": "الدعم المباشر",
|
||||||
|
"support_description_live_chat": "حرة وسريعة! ممثلو الدعم المدربين متاحون للمساعدة",
|
||||||
|
"support_title_guides": "أدلة محفظة كعكة",
|
||||||
|
"support_description_guides": "توثيق ودعم القضايا المشتركة",
|
||||||
|
"support_title_other_links": "روابط دعم أخرى",
|
||||||
|
"support_description_other_links": "انضم إلى مجتمعاتنا أو تصل إلينا شركائنا من خلال أساليب أخرى"
|
||||||
}
|
}
|
|
@ -664,5 +664,11 @@
|
||||||
"slidable": "Плъзгащ се",
|
"slidable": "Плъзгащ се",
|
||||||
"etherscan_history": "История на Etherscan",
|
"etherscan_history": "История на Etherscan",
|
||||||
"manage_nodes": "Управление на възли",
|
"manage_nodes": "Управление на възли",
|
||||||
"template_name": "Име на шаблон"
|
"template_name": "Име на шаблон",
|
||||||
|
"support_title_live_chat": "Подкрепа на живо",
|
||||||
|
"support_description_live_chat": "Безплатно и бързо! Обучени представители на подкрепата са на разположение за подпомагане",
|
||||||
|
"support_title_guides": "Ръководства за портфейл за торта",
|
||||||
|
"support_description_guides": "Документация и подкрепа за общи проблеми",
|
||||||
|
"support_title_other_links": "Други връзки за поддръжка",
|
||||||
|
"support_description_other_links": "Присъединете се към нашите общности или се свържете с нас нашите партньори чрез други методи"
|
||||||
}
|
}
|
||||||
|
|
|
@ -664,5 +664,11 @@
|
||||||
"slidable": "Posuvné",
|
"slidable": "Posuvné",
|
||||||
"manage_nodes": "Spravovat uzly",
|
"manage_nodes": "Spravovat uzly",
|
||||||
"etherscan_history": "Historie Etherscanu",
|
"etherscan_history": "Historie Etherscanu",
|
||||||
"template_name": "Název šablony"
|
"template_name": "Název šablony",
|
||||||
|
"support_title_live_chat": "Živá podpora",
|
||||||
|
"support_description_live_chat": "Zdarma a rychle! K dispozici jsou zástupci vyškolených podpůrných podpory",
|
||||||
|
"support_title_guides": "Průvodce peněženkami dortu",
|
||||||
|
"support_description_guides": "Dokumentace a podpora běžných otázek",
|
||||||
|
"support_title_other_links": "Další odkazy na podporu",
|
||||||
|
"support_description_other_links": "Připojte se k našim komunitám nebo se k nám oslovte další metody"
|
||||||
}
|
}
|
||||||
|
|
|
@ -211,7 +211,7 @@
|
||||||
"settings_only_trades": "Nur Handel",
|
"settings_only_trades": "Nur Handel",
|
||||||
"settings_only_transactions": "Nur Transaktionen",
|
"settings_only_transactions": "Nur Transaktionen",
|
||||||
"settings_none": "Keiner",
|
"settings_none": "Keiner",
|
||||||
"settings_support": "Unterstützen",
|
"settings_support": "Hilfe",
|
||||||
"settings_terms_and_conditions": "Geschäftsbedingungen",
|
"settings_terms_and_conditions": "Geschäftsbedingungen",
|
||||||
"pin_is_incorrect": "PIN ist falsch",
|
"pin_is_incorrect": "PIN ist falsch",
|
||||||
"setup_pin": "PIN einrichten",
|
"setup_pin": "PIN einrichten",
|
||||||
|
@ -672,5 +672,11 @@
|
||||||
"slidable": "Verschiebbar",
|
"slidable": "Verschiebbar",
|
||||||
"manage_nodes": "Knoten verwalten",
|
"manage_nodes": "Knoten verwalten",
|
||||||
"etherscan_history": "Etherscan-Geschichte",
|
"etherscan_history": "Etherscan-Geschichte",
|
||||||
"template_name": "Vorlagenname"
|
"template_name": "Vorlagenname",
|
||||||
|
"support_title_live_chat": "Live Support",
|
||||||
|
"support_description_live_chat": "Kostenlos und schnell! Ausgebildete Mitarbeiter stehen zur Unterstützung bereit, um zu helfen",
|
||||||
|
"support_title_guides": "Cake Wallet Guides",
|
||||||
|
"support_description_guides": "Dokumentation und Hilfe für bekannte Probleme",
|
||||||
|
"support_title_other_links": "Andere Support-Links",
|
||||||
|
"support_description_other_links": "Treten Sie unseren Communities bei oder erreichen Sie uns oder unsere Partner über andere Methoden"
|
||||||
}
|
}
|
||||||
|
|
|
@ -672,5 +672,11 @@
|
||||||
"slidable": "Slidable",
|
"slidable": "Slidable",
|
||||||
"manage_nodes": "Manage nodes",
|
"manage_nodes": "Manage nodes",
|
||||||
"etherscan_history": "Etherscan history",
|
"etherscan_history": "Etherscan history",
|
||||||
"template_name": "Template Name"
|
"template_name": "Template Name",
|
||||||
|
"support_title_live_chat": "Live support",
|
||||||
|
"support_description_live_chat": "Free and fast! Trained support representatives are available to assist",
|
||||||
|
"support_title_guides": "Cake Wallet guides",
|
||||||
|
"support_description_guides": "Documentation and support for common issues",
|
||||||
|
"support_title_other_links": "Other support links",
|
||||||
|
"support_description_other_links": "Join our communities or reach us our our partners through other methods"
|
||||||
}
|
}
|
||||||
|
|
|
@ -672,5 +672,11 @@
|
||||||
"slidable": "deslizable",
|
"slidable": "deslizable",
|
||||||
"manage_nodes": "Administrar nodos",
|
"manage_nodes": "Administrar nodos",
|
||||||
"etherscan_history": "historia de etherscan",
|
"etherscan_history": "historia de etherscan",
|
||||||
"template_name": "Nombre de la plantilla"
|
"template_name": "Nombre de la plantilla",
|
||||||
|
"support_title_live_chat": "Soporte vital",
|
||||||
|
"support_description_live_chat": "¡GRATIS y RÁPIDO! Los representantes de apoyo capacitado están disponibles para ayudar",
|
||||||
|
"support_title_guides": "Guías de billetera para pastel",
|
||||||
|
"support_description_guides": "Documentación y apoyo para problemas comunes",
|
||||||
|
"support_title_other_links": "Otros enlaces de soporte",
|
||||||
|
"support_description_other_links": "Únase a nuestras comunidades o comuníquese con nosotros nuestros socios a través de otros métodos"
|
||||||
}
|
}
|
||||||
|
|
|
@ -672,5 +672,11 @@
|
||||||
"slidable": "Glissable",
|
"slidable": "Glissable",
|
||||||
"manage_nodes": "Gérer les nœuds",
|
"manage_nodes": "Gérer les nœuds",
|
||||||
"etherscan_history": "Historique d'Etherscan",
|
"etherscan_history": "Historique d'Etherscan",
|
||||||
"template_name": "Nom du modèle"
|
"template_name": "Nom du modèle",
|
||||||
|
"support_title_live_chat": "Support en direct",
|
||||||
|
"support_description_live_chat": "GRATUIT ET RAPIDE! Des représentants de soutien formé sont disponibles pour aider",
|
||||||
|
"support_title_guides": "Guides de portefeuille à gâteau",
|
||||||
|
"support_description_guides": "Documentation et soutien aux problèmes communs",
|
||||||
|
"support_title_other_links": "Autres liens d'assistance",
|
||||||
|
"support_description_other_links": "Rejoignez nos communautés ou contactez-nous nos partenaires à travers d'autres méthodes"
|
||||||
}
|
}
|
||||||
|
|
|
@ -650,5 +650,11 @@
|
||||||
"slidable": "Mai iya zamewa",
|
"slidable": "Mai iya zamewa",
|
||||||
"etherscan_history": "Etherscan tarihin kowane zamani",
|
"etherscan_history": "Etherscan tarihin kowane zamani",
|
||||||
"manage_nodes": "Sarrafa nodes",
|
"manage_nodes": "Sarrafa nodes",
|
||||||
"template_name": "Sunan Samfura"
|
"template_name": "Sunan Samfura",
|
||||||
|
"support_title_live_chat": "Tallafi na Live",
|
||||||
|
"support_description_live_chat": "Kyauta da sauri! An horar da wakilan tallafi na tallafi don taimakawa",
|
||||||
|
"support_title_guides": "Jagorar Cake",
|
||||||
|
"support_description_guides": "Tallafi da tallafi don batutuwa na yau da kullun",
|
||||||
|
"support_title_other_links": "Sauran hanyoyin tallafi",
|
||||||
|
"support_description_other_links": "Kasance tare da al'ummominmu ko kuma ka kai mu abokanmu ta hanyar wasu hanyoyi"
|
||||||
}
|
}
|
||||||
|
|
|
@ -672,5 +672,11 @@
|
||||||
"slidable": "फिसलने लायक",
|
"slidable": "फिसलने लायक",
|
||||||
"manage_nodes": "नोड्स प्रबंधित करें",
|
"manage_nodes": "नोड्स प्रबंधित करें",
|
||||||
"etherscan_history": "इथरस्कैन इतिहास",
|
"etherscan_history": "इथरस्कैन इतिहास",
|
||||||
"template_name": "टेम्पलेट नाम"
|
"template_name": "टेम्पलेट नाम",
|
||||||
|
"support_title_live_chat": "लाइव सहायता",
|
||||||
|
"support_description_live_chat": "मुक्त और तेजी से! प्रशिक्षित सहायता प्रतिनिधि सहायता के लिए उपलब्ध हैं",
|
||||||
|
"support_title_guides": "केक वॉलेट गाइड",
|
||||||
|
"support_description_guides": "सामान्य मुद्दों के लिए प्रलेखन और समर्थन",
|
||||||
|
"support_title_other_links": "अन्य समर्थन लिंक",
|
||||||
|
"support_description_other_links": "हमारे समुदायों में शामिल हों या अन्य तरीकों के माध्यम से हमारे साथी तक पहुंचें"
|
||||||
}
|
}
|
||||||
|
|
|
@ -672,5 +672,11 @@
|
||||||
"slidable": "Klizna",
|
"slidable": "Klizna",
|
||||||
"manage_nodes": "Upravljanje čvorovima",
|
"manage_nodes": "Upravljanje čvorovima",
|
||||||
"etherscan_history": "Etherscan povijest",
|
"etherscan_history": "Etherscan povijest",
|
||||||
"template_name": "Naziv predloška"
|
"template_name": "Naziv predloška",
|
||||||
|
"support_title_live_chat": "Podrška uživo",
|
||||||
|
"support_description_live_chat": "Besplatno i brzo! Obučeni predstavnici podrške dostupni su za pomoć",
|
||||||
|
"support_title_guides": "Vodiči za torte",
|
||||||
|
"support_description_guides": "Dokumentacija i podrška za uobičajena pitanja",
|
||||||
|
"support_title_other_links": "Ostale veze za podršku",
|
||||||
|
"support_description_other_links": "Pridružite se našim zajednicama ili nam dosegnu naše partnere drugim metodama"
|
||||||
}
|
}
|
||||||
|
|
|
@ -660,5 +660,11 @@
|
||||||
"slidable": "Dapat digeser",
|
"slidable": "Dapat digeser",
|
||||||
"manage_nodes": "Kelola node",
|
"manage_nodes": "Kelola node",
|
||||||
"etherscan_history": "Sejarah Etherscan",
|
"etherscan_history": "Sejarah Etherscan",
|
||||||
"template_name": "Nama Templat"
|
"template_name": "Nama Templat",
|
||||||
|
"support_title_live_chat": "Dukungan langsung",
|
||||||
|
"support_description_live_chat": "Gratis dan Cepat! Perwakilan dukungan terlatih tersedia untuk membantu",
|
||||||
|
"support_title_guides": "Panduan Dompet Kue",
|
||||||
|
"support_description_guides": "Dokumentasi dan dukungan untuk masalah umum",
|
||||||
|
"support_title_other_links": "Tautan dukungan lainnya",
|
||||||
|
"support_description_other_links": "Bergabunglah dengan komunitas kami atau hubungi kami mitra kami melalui metode lain"
|
||||||
}
|
}
|
||||||
|
|
|
@ -672,5 +672,11 @@
|
||||||
"slidable": "Scorrevole",
|
"slidable": "Scorrevole",
|
||||||
"manage_nodes": "Gestisci i nodi",
|
"manage_nodes": "Gestisci i nodi",
|
||||||
"etherscan_history": "Storia Etherscan",
|
"etherscan_history": "Storia Etherscan",
|
||||||
"template_name": "Nome modello"
|
"template_name": "Nome modello",
|
||||||
|
"support_title_live_chat": "Supporto dal vivo",
|
||||||
|
"support_description_live_chat": "Gratuito e veloce! I rappresentanti di supporto qualificati sono disponibili per assistere",
|
||||||
|
"support_title_guides": "Guide del portafoglio per torte",
|
||||||
|
"support_description_guides": "Documentazione e supporto per problemi comuni",
|
||||||
|
"support_title_other_links": "Altri collegamenti di supporto",
|
||||||
|
"support_description_other_links": "Unisciti alle nostre comunità o raggiungici i nostri partner attraverso altri metodi"
|
||||||
}
|
}
|
||||||
|
|
|
@ -672,5 +672,11 @@
|
||||||
"slidable": "スライド可能",
|
"slidable": "スライド可能",
|
||||||
"manage_nodes": "ノードの管理",
|
"manage_nodes": "ノードの管理",
|
||||||
"etherscan_history": "イーサスキャンの歴史",
|
"etherscan_history": "イーサスキャンの歴史",
|
||||||
"template_name": "テンプレート名"
|
"template_name": "テンプレート名",
|
||||||
|
"support_title_live_chat": "ライブサポート",
|
||||||
|
"support_description_live_chat": "無料で速い!訓練されたサポート担当者が支援することができます",
|
||||||
|
"support_title_guides": "ケーキウォレットガイド",
|
||||||
|
"support_description_guides": "一般的な問題のドキュメントとサポート",
|
||||||
|
"support_title_other_links": "その他のサポートリンク",
|
||||||
|
"support_description_other_links": "私たちのコミュニティに参加するか、他の方法を通して私たちのパートナーに連絡してください"
|
||||||
}
|
}
|
|
@ -672,5 +672,11 @@
|
||||||
"slidable": "슬라이딩 가능",
|
"slidable": "슬라이딩 가능",
|
||||||
"manage_nodes": "노드 관리",
|
"manage_nodes": "노드 관리",
|
||||||
"etherscan_history": "이더스캔 역사",
|
"etherscan_history": "이더스캔 역사",
|
||||||
"template_name": "템플릿 이름"
|
"template_name": "템플릿 이름",
|
||||||
|
"support_title_live_chat": "실시간 지원",
|
||||||
|
"support_description_live_chat": "자유롭고 빠릅니다! 훈련 된 지원 담당자가 지원할 수 있습니다",
|
||||||
|
"support_title_guides": "케이크 지갑 가이드",
|
||||||
|
"support_description_guides": "일반적인 문제에 대한 문서화 및 지원",
|
||||||
|
"support_title_other_links": "다른 지원 링크",
|
||||||
|
"support_description_other_links": "다른 방법을 통해 커뮤니티에 가입하거나 파트너에게 연락하십시오."
|
||||||
}
|
}
|
|
@ -670,5 +670,11 @@
|
||||||
"slidable": "လျှောချနိုင်သည်။",
|
"slidable": "လျှောချနိုင်သည်။",
|
||||||
"manage_nodes": "ဆုံမှတ်များကို စီမံပါ။",
|
"manage_nodes": "ဆုံမှတ်များကို စီမံပါ။",
|
||||||
"etherscan_history": "Etherscan သမိုင်း",
|
"etherscan_history": "Etherscan သမိုင်း",
|
||||||
"template_name": "နမူနာပုံစံ"
|
"template_name": "နမူနာပုံစံ",
|
||||||
|
"support_title_live_chat": "တိုက်ရိုက်ပံ့ပိုးမှု",
|
||||||
|
"support_description_live_chat": "အခမဲ့နှင့်အစာရှောင်ခြင်း! လေ့ကျင့်ထားသောထောက်ခံသူကိုယ်စားလှယ်များသည်ကူညီနိုင်သည်",
|
||||||
|
"support_title_guides": "ကိတ်မုန့်ပိုက်ဆံအိတ်လမ်းညွှန်များ",
|
||||||
|
"support_description_guides": "ဘုံပြ issues နာများအတွက်စာရွက်စာတမ်းများနှင့်ထောက်ခံမှု",
|
||||||
|
"support_title_other_links": "အခြားအထောက်အပံ့လင့်များ",
|
||||||
|
"support_description_other_links": "ကျွန်ုပ်တို့၏လူမှုအသိုင်းအဝိုင်းများသို့ 0 င်ရောက်ပါ"
|
||||||
}
|
}
|
|
@ -672,5 +672,11 @@
|
||||||
"slidable": "Verschuifbaar",
|
"slidable": "Verschuifbaar",
|
||||||
"manage_nodes": "Beheer knooppunten",
|
"manage_nodes": "Beheer knooppunten",
|
||||||
"etherscan_history": "Etherscan-geschiedenis",
|
"etherscan_history": "Etherscan-geschiedenis",
|
||||||
"template_name": "Sjabloonnaam"
|
"template_name": "Sjabloonnaam",
|
||||||
|
"support_title_live_chat": "Live ondersteuning",
|
||||||
|
"support_description_live_chat": "Gratis en snel! Getrainde ondersteuningsvertegenwoordigers zijn beschikbaar om te helpen",
|
||||||
|
"support_title_guides": "Cake -portemonnee gidsen",
|
||||||
|
"support_description_guides": "Documentatie en ondersteuning voor gemeenschappelijke problemen",
|
||||||
|
"support_title_other_links": "Andere ondersteuningslinks",
|
||||||
|
"support_description_other_links": "Word lid van onze gemeenschappen of bereik ons onze partners via andere methoden"
|
||||||
}
|
}
|
||||||
|
|
|
@ -672,5 +672,11 @@
|
||||||
"slidable": "Przesuwne",
|
"slidable": "Przesuwne",
|
||||||
"manage_nodes": "Zarządzaj węzłami",
|
"manage_nodes": "Zarządzaj węzłami",
|
||||||
"etherscan_history": "Historia Etherscanu",
|
"etherscan_history": "Historia Etherscanu",
|
||||||
"template_name": "Nazwa szablonu"
|
"template_name": "Nazwa szablonu",
|
||||||
|
"support_title_live_chat": "Wsparcie na żywo",
|
||||||
|
"support_description_live_chat": "Darmowe i szybkie! Do pomocy są dostępni przeszkoleni przedstawiciele wsparcia",
|
||||||
|
"support_title_guides": "Przewodniki portfela ciasta",
|
||||||
|
"support_description_guides": "Dokumentacja i wsparcie dla typowych problemów",
|
||||||
|
"support_title_other_links": "Inne linki wsparcia",
|
||||||
|
"support_description_other_links": "Dołącz do naszych społeczności lub skontaktuj się z nami naszymi partnerami za pomocą innych metod"
|
||||||
}
|
}
|
||||||
|
|
|
@ -671,5 +671,11 @@
|
||||||
"slidable": "Deslizável",
|
"slidable": "Deslizável",
|
||||||
"manage_nodes": "Gerenciar nós",
|
"manage_nodes": "Gerenciar nós",
|
||||||
"etherscan_history": "história Etherscan",
|
"etherscan_history": "história Etherscan",
|
||||||
"template_name": "Nome do modelo"
|
"template_name": "Nome do modelo",
|
||||||
|
"support_title_live_chat": "Apoio ao vivo",
|
||||||
|
"support_description_live_chat": "Livre e rápido! Representantes de suporte treinado estão disponíveis para ajudar",
|
||||||
|
"support_title_guides": "Guias da carteira de bolo",
|
||||||
|
"support_description_guides": "Documentação e suporte para problemas comuns",
|
||||||
|
"support_title_other_links": "Outros links de suporte",
|
||||||
|
"support_description_other_links": "Junte -se às nossas comunidades ou chegue a nós nossos parceiros por meio de outros métodos"
|
||||||
}
|
}
|
||||||
|
|
|
@ -270,7 +270,6 @@
|
||||||
"error_text_node_address": "Пожалуйста, введите iPv4 адрес",
|
"error_text_node_address": "Пожалуйста, введите iPv4 адрес",
|
||||||
"error_text_node_port": "Порт ноды может содержать только цифры от 0 до 65535",
|
"error_text_node_port": "Порт ноды может содержать только цифры от 0 до 65535",
|
||||||
"error_text_node_proxy_address": "Введите <IPv4-адрес>:<порт>, например 127.0.0.1:9050.",
|
"error_text_node_proxy_address": "Введите <IPv4-адрес>:<порт>, например 127.0.0.1:9050.",
|
||||||
|
|
||||||
"error_text_payment_id": "Идентификатор платежа может содержать от 16 до 64 символов в hex",
|
"error_text_payment_id": "Идентификатор платежа может содержать от 16 до 64 символов в hex",
|
||||||
"error_text_xmr": "Значение XMR не может превышать доступный баланс.\nКоличество цифр после запятой должно быть меньше или равно 12",
|
"error_text_xmr": "Значение XMR не может превышать доступный баланс.\nКоличество цифр после запятой должно быть меньше или равно 12",
|
||||||
"error_text_fiat": "Значение суммы не может превышать доступный баланс.\nКоличество цифр после запятой должно быть меньше или равно 2",
|
"error_text_fiat": "Значение суммы не может превышать доступный баланс.\nКоличество цифр после запятой должно быть меньше или равно 2",
|
||||||
|
@ -673,5 +672,11 @@
|
||||||
"slidable": "Скользящий",
|
"slidable": "Скользящий",
|
||||||
"manage_nodes": "Управление узлами",
|
"manage_nodes": "Управление узлами",
|
||||||
"etherscan_history": "История Эфириума",
|
"etherscan_history": "История Эфириума",
|
||||||
"template_name": "Имя Шаблона"
|
"template_name": "Имя Шаблона",
|
||||||
|
"support_title_live_chat": "Живая поддержка",
|
||||||
|
"support_description_live_chat": "Бесплатно и быстро! Обученные представители поддержки доступны для оказания помощи",
|
||||||
|
"support_title_guides": "Корт -гиды",
|
||||||
|
"support_description_guides": "Документация и поддержка общих вопросов",
|
||||||
|
"support_title_other_links": "Другие ссылки на поддержку",
|
||||||
|
"support_description_other_links": "Присоединяйтесь к нашим сообществам или охватите нас наших партнеров с помощью других методов"
|
||||||
}
|
}
|
|
@ -670,5 +670,11 @@
|
||||||
"slidable": "เลื่อนได้",
|
"slidable": "เลื่อนได้",
|
||||||
"manage_nodes": "จัดการโหนด",
|
"manage_nodes": "จัดการโหนด",
|
||||||
"etherscan_history": "ประวัติอีเธอร์สแกน",
|
"etherscan_history": "ประวัติอีเธอร์สแกน",
|
||||||
"template_name": "ชื่อแม่แบบ"
|
"template_name": "ชื่อแม่แบบ",
|
||||||
|
"support_title_live_chat": "การสนับสนุนสด",
|
||||||
|
"support_description_live_chat": "ฟรีและรวดเร็ว! ตัวแทนฝ่ายสนับสนุนที่ผ่านการฝึกอบรมพร้อมให้ความช่วยเหลือ",
|
||||||
|
"support_title_guides": "คู่มือกระเป๋าเงินเค้ก",
|
||||||
|
"support_description_guides": "เอกสารและการสนับสนุนสำหรับปัญหาทั่วไป",
|
||||||
|
"support_title_other_links": "ลิงค์สนับสนุนอื่น ๆ",
|
||||||
|
"support_description_other_links": "เข้าร่วมชุมชนของเราหรือเข้าถึงเราพันธมิตรของเราผ่านวิธีการอื่น ๆ"
|
||||||
}
|
}
|
|
@ -671,5 +671,11 @@
|
||||||
"slidable": "kaydırılabilir",
|
"slidable": "kaydırılabilir",
|
||||||
"manage_nodes": "Düğümleri yönet",
|
"manage_nodes": "Düğümleri yönet",
|
||||||
"etherscan_history": "Etherscan geçmişi",
|
"etherscan_history": "Etherscan geçmişi",
|
||||||
"template_name": "şablon adı"
|
"template_name": "şablon adı",
|
||||||
|
"support_title_live_chat": "Canlı destek",
|
||||||
|
"support_description_live_chat": "Ücretsiz ve hızlı! Eğitimli destek temsilcileri yardımcı olmak için mevcuttur",
|
||||||
|
"support_title_guides": "Kek Cüzdan Kılavuzları",
|
||||||
|
"support_description_guides": "Ortak sorunlara belge ve destek",
|
||||||
|
"support_title_other_links": "Diğer destek bağlantıları",
|
||||||
|
"support_description_other_links": "Topluluklarımıza katılın veya ortaklarımıza diğer yöntemlerle bize ulaşın"
|
||||||
}
|
}
|
||||||
|
|
|
@ -672,5 +672,11 @@
|
||||||
"slidable": "Розсувний",
|
"slidable": "Розсувний",
|
||||||
"manage_nodes": "Керуйте вузлами",
|
"manage_nodes": "Керуйте вузлами",
|
||||||
"etherscan_history": "Історія Etherscan",
|
"etherscan_history": "Історія Etherscan",
|
||||||
"template_name": "Назва шаблону"
|
"template_name": "Назва шаблону",
|
||||||
|
"support_title_live_chat": "Жива підтримка",
|
||||||
|
"support_description_live_chat": "Безкоштовно і швидко! Навчені представники підтримки доступні для надання допомоги",
|
||||||
|
"support_title_guides": "Поклики для гаманців тортів",
|
||||||
|
"support_description_guides": "Документація та підтримка загальних питань",
|
||||||
|
"support_title_other_links": "Інші посилання на підтримку",
|
||||||
|
"support_description_other_links": "Приєднуйтесь до наших спільнот або досягайте нас нашими партнерами іншими методами"
|
||||||
}
|
}
|
||||||
|
|
|
@ -664,5 +664,11 @@
|
||||||
"slidable": "سلائیڈ ایبل",
|
"slidable": "سلائیڈ ایبل",
|
||||||
"manage_nodes": "۔ﮟﯾﺮﮐ ﻢﻈﻧ ﺎﮐ ﺱﮈﻮﻧ",
|
"manage_nodes": "۔ﮟﯾﺮﮐ ﻢﻈﻧ ﺎﮐ ﺱﮈﻮﻧ",
|
||||||
"etherscan_history": "ﺦﯾﺭﺎﺗ ﯽﮐ ﻦﯿﮑﺳﺍ ﺮﮭﺘﯾﺍ",
|
"etherscan_history": "ﺦﯾﺭﺎﺗ ﯽﮐ ﻦﯿﮑﺳﺍ ﺮﮭﺘﯾﺍ",
|
||||||
"template_name": "ٹیمپلیٹ کا نام"
|
"template_name": "ٹیمپلیٹ کا نام",
|
||||||
|
"support_title_live_chat": "براہ راست مدد",
|
||||||
|
"support_description_live_chat": "مفت اور تیز! تربیت یافتہ معاون نمائندے مدد کے لئے دستیاب ہیں",
|
||||||
|
"support_title_guides": "کیک پرس گائڈز",
|
||||||
|
"support_description_guides": "عام مسائل کے لئے دستاویزات اور مدد",
|
||||||
|
"support_title_other_links": "دوسرے سپورٹ لنکس",
|
||||||
|
"support_description_other_links": "ہماری برادریوں میں شامل ہوں یا دوسرے طریقوں سے ہمارے شراکت داروں تک پہنچیں"
|
||||||
}
|
}
|
|
@ -666,5 +666,11 @@
|
||||||
"slidable": "Slidable",
|
"slidable": "Slidable",
|
||||||
"manage_nodes": "Ṣakoso awọn apa",
|
"manage_nodes": "Ṣakoso awọn apa",
|
||||||
"etherscan_history": "Etherscan itan",
|
"etherscan_history": "Etherscan itan",
|
||||||
"template_name": "Orukọ Awoṣe"
|
"template_name": "Orukọ Awoṣe",
|
||||||
|
"support_title_live_chat": "Atilẹyin ifiwe",
|
||||||
|
"support_description_live_chat": "Free ati sare! Ti oṣiṣẹ awọn aṣoju wa lati ṣe iranlọwọ",
|
||||||
|
"support_title_guides": "Akara oyinbo Awọn Itọsọna Awọki oyinbo",
|
||||||
|
"support_description_guides": "Iwe ati atilẹyin fun awọn ọran ti o wọpọ",
|
||||||
|
"support_title_other_links": "Awọn ọna asopọ atilẹyin miiran",
|
||||||
|
"support_description_other_links": "Darapọ mọ awọn agbegbe wa tabi de wa awọn alabaṣepọ wa nipasẹ awọn ọna miiran"
|
||||||
}
|
}
|
|
@ -671,5 +671,11 @@
|
||||||
"slidable": "可滑动",
|
"slidable": "可滑动",
|
||||||
"manage_nodes": "管理节点",
|
"manage_nodes": "管理节点",
|
||||||
"etherscan_history": "以太扫描历史",
|
"etherscan_history": "以太扫描历史",
|
||||||
"template_name": "模板名称"
|
"template_name": "模板名称",
|
||||||
|
"support_title_live_chat": "实时支持",
|
||||||
|
"support_description_live_chat": "免费快速!训练有素的支持代表可以协助",
|
||||||
|
"support_title_guides": "蛋糕钱包指南",
|
||||||
|
"support_description_guides": "对常见问题的文档和支持",
|
||||||
|
"support_title_other_links": "其他支持链接",
|
||||||
|
"support_description_other_links": "加入我们的社区或通过其他方法与我们联系我们的合作伙伴"
|
||||||
}
|
}
|
66
tool/append_translation.dart
Normal file
66
tool/append_translation.dart
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
import 'dart:convert';
|
||||||
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'package:translator/translator.dart';
|
||||||
|
|
||||||
|
const defaultLang = "en";
|
||||||
|
const langs = [
|
||||||
|
"ar", "bg", "cs", "de", "en", "es", "fr", "ha", "hi", "hr", "id", "it",
|
||||||
|
"ja", "ko", "my", "nl", "pl", "pt", "ru", "th", "tr", "uk", "ur", "yo",
|
||||||
|
"zh-cn" // zh, but Google Translate uses zh-cn for Chinese (Simplified)
|
||||||
|
];
|
||||||
|
final translator = GoogleTranslator();
|
||||||
|
|
||||||
|
void main(List<String> args) async {
|
||||||
|
if (args.length != 2) {
|
||||||
|
throw Exception(
|
||||||
|
'Insufficient arguments!\n\nTry to run `./append_translation.dart greetings "Hello World!"`');
|
||||||
|
}
|
||||||
|
|
||||||
|
final name = args.first;
|
||||||
|
final text = args.last;
|
||||||
|
|
||||||
|
print('Appending "$name": "$text"');
|
||||||
|
|
||||||
|
for (var lang in langs) {
|
||||||
|
final fileName = getFileName(lang);
|
||||||
|
final translation = await getTranslation(text, lang);
|
||||||
|
|
||||||
|
appendArbFile(fileName, name, translation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void appendArbFile(String fileName, String name, String text) {
|
||||||
|
final file = File(fileName);
|
||||||
|
final inputContent = file.readAsStringSync();
|
||||||
|
final arbObj = json.decode(inputContent) as Map<String, dynamic>;
|
||||||
|
|
||||||
|
if (arbObj.containsKey(name)) {
|
||||||
|
print("String $name already exists in $fileName!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
arbObj.addAll({name: text});
|
||||||
|
|
||||||
|
final outputContent = json
|
||||||
|
.encode(arbObj)
|
||||||
|
.replaceAll('","', '",\n "')
|
||||||
|
.replaceAll('{"', '{\n "')
|
||||||
|
.replaceAll('"}', '"\n}')
|
||||||
|
.replaceAll('":"', '": "');
|
||||||
|
|
||||||
|
file.writeAsStringSync(outputContent);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Future<String> getTranslation(String text, String lang) async {
|
||||||
|
if (lang == defaultLang) return text;
|
||||||
|
return (await translator.translate(text, from: defaultLang, to: lang)).text;
|
||||||
|
}
|
||||||
|
|
||||||
|
String getFileName(String lang) {
|
||||||
|
final shortLang = lang
|
||||||
|
.split("-")
|
||||||
|
.first;
|
||||||
|
return "./res/values/strings_$shortLang.arb";
|
||||||
|
}
|
|
@ -33,8 +33,7 @@ Future<void> updateSecretsConfig(List<String> args) async {
|
||||||
});
|
});
|
||||||
|
|
||||||
final fileConfig =
|
final fileConfig =
|
||||||
json.decode(configFile.readAsStringSync()) as Map<String, dynamic> ??
|
json.decode(configFile.readAsStringSync()) as Map<String, dynamic>;
|
||||||
<String, dynamic>{};
|
|
||||||
fileConfig.forEach((key, dynamic value) {
|
fileConfig.forEach((key, dynamic value) {
|
||||||
if (secrets[key] == null) {
|
if (secrets[key] == null) {
|
||||||
secrets[key] = value;
|
secrets[key] = value;
|
||||||
|
|
|
@ -31,6 +31,7 @@ class SecretKey {
|
||||||
SecretKey('anonPayReferralCode', () => ''),
|
SecretKey('anonPayReferralCode', () => ''),
|
||||||
SecretKey('fiatApiKey', () => ''),
|
SecretKey('fiatApiKey', () => ''),
|
||||||
SecretKey('payfuraApiKey', () => ''),
|
SecretKey('payfuraApiKey', () => ''),
|
||||||
|
SecretKey('chatwootWebsiteToken', () => ''),
|
||||||
];
|
];
|
||||||
|
|
||||||
static final ethereumSecrets = [
|
static final ethereumSecrets = [
|
||||||
|
|
Loading…
Reference in a new issue