mirror of
https://github.com/cake-tech/cake_wallet.git
synced 2024-12-22 03:29:36 +00:00
CW-782: Show error report popup without cooldown (#1739)
Some checks are pending
Cache Dependencies / test (push) Waiting to run
Some checks are pending
Cache Dependencies / test (push) Waiting to run
* improve exception throwing on broken wallets - put _lastOpenedWallet to avoid issues on windows (file is currently open by) - don't throw corruptedWalletsSeed - instead store it inside of secureStorage - await ExceptionHandler.onError calls where possible to makse sure that popup won't be canceled by some UI element - adjust BaseAlertDialog to be scrollable if the text is too long - add ExceptionHandler.resetLastPopupDate - that can be called when we want to show error report screen (bypassing cooldown) * fix: HiveError: Box has already been closed. * await the alerts to be sure that each one of them is being shown fix typo in secure storage * Update lib/core/backup_service.dart Co-authored-by: Omar Hatem <omarh.ismail1@gmail.com> * address comments on github * don't store seeds in secure storage * fix wallet password * update monero_c update corrupted seeds UI prevent app from crashing when wallet is corrupted * show alert with seeds * Update corrupted wallet UI Fix wallet opening cache * remove unused code --------- Co-authored-by: Omar Hatem <omarh.ismail1@gmail.com>
This commit is contained in:
parent
d8d4190608
commit
17d34beae9
51 changed files with 205 additions and 87 deletions
|
@ -81,6 +81,7 @@ void createWalletSync(
|
|||
wptr = newWptr;
|
||||
monero.Wallet_store(wptr!, path: path);
|
||||
openedWalletsByPath[path] = wptr!;
|
||||
_lastOpenedWallet = path;
|
||||
|
||||
// is the line below needed?
|
||||
// setupNodeSync(address: "node.moneroworld.com:18089");
|
||||
|
@ -116,6 +117,7 @@ void restoreWalletFromSeedSync(
|
|||
wptr = newWptr;
|
||||
|
||||
openedWalletsByPath[path] = wptr!;
|
||||
_lastOpenedWallet = path;
|
||||
}
|
||||
|
||||
void restoreWalletFromKeysSync(
|
||||
|
@ -183,6 +185,7 @@ void restoreWalletFromKeysSync(
|
|||
wptr = newWptr;
|
||||
|
||||
openedWalletsByPath[path] = wptr!;
|
||||
_lastOpenedWallet = path;
|
||||
}
|
||||
|
||||
void restoreWalletFromSpendKeySync(
|
||||
|
@ -231,6 +234,7 @@ void restoreWalletFromSpendKeySync(
|
|||
storeSync();
|
||||
|
||||
openedWalletsByPath[path] = wptr!;
|
||||
_lastOpenedWallet = path;
|
||||
}
|
||||
|
||||
String _lastOpenedWallet = "";
|
||||
|
@ -260,7 +264,7 @@ Future<void> restoreWalletFromHardwareWallet(
|
|||
throw WalletRestoreFromSeedException(message: error);
|
||||
}
|
||||
wptr = newWptr;
|
||||
|
||||
_lastOpenedWallet = path;
|
||||
openedWalletsByPath[path] = wptr!;
|
||||
}
|
||||
|
||||
|
@ -295,6 +299,11 @@ Future<void> loadWallet(
|
|||
password: password,
|
||||
kdfRounds: 1,
|
||||
);
|
||||
final status = monero.WalletManager_errorString(wmPtr);
|
||||
if (status != "") {
|
||||
print("loadWallet:"+status);
|
||||
throw WalletOpeningException(message: status);
|
||||
}
|
||||
} else {
|
||||
deviceType = 0;
|
||||
}
|
||||
|
@ -314,15 +323,15 @@ Future<void> loadWallet(
|
|||
|
||||
final newWptr = Pointer<Void>.fromAddress(newWptrAddr);
|
||||
|
||||
_lastOpenedWallet = path;
|
||||
final status = monero.Wallet_status(newWptr);
|
||||
if (status != 0) {
|
||||
final err = monero.Wallet_errorString(newWptr);
|
||||
print(err);
|
||||
print("loadWallet:"+err);
|
||||
throw WalletOpeningException(message: err);
|
||||
}
|
||||
|
||||
wptr = newWptr;
|
||||
_lastOpenedWallet = path;
|
||||
openedWalletsByPath[path] = wptr!;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -168,7 +168,7 @@ class MoneroWalletService extends WalletService<
|
|||
}
|
||||
|
||||
await restoreOrResetWalletFiles(name);
|
||||
return openWallet(name, password, retryOnFailure: false);
|
||||
return await openWallet(name, password, retryOnFailure: false);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -503,8 +503,8 @@ packages:
|
|||
dependency: "direct main"
|
||||
description:
|
||||
path: "impls/monero.dart"
|
||||
ref: d72c15f4339791a7bbdf17e9d827b7b56ca144e4
|
||||
resolved-ref: d72c15f4339791a7bbdf17e9d827b7b56ca144e4
|
||||
ref: c41c4dad9aa5003a914cfb2c528c76386f952665
|
||||
resolved-ref: c41c4dad9aa5003a914cfb2c528c76386f952665
|
||||
url: "https://github.com/mrcyjanek/monero_c"
|
||||
source: git
|
||||
version: "0.0.0"
|
||||
|
|
|
@ -25,7 +25,7 @@ dependencies:
|
|||
monero:
|
||||
git:
|
||||
url: https://github.com/mrcyjanek/monero_c
|
||||
ref: d72c15f4339791a7bbdf17e9d827b7b56ca144e4
|
||||
ref: c41c4dad9aa5003a914cfb2c528c76386f952665
|
||||
# ref: 6eb571ea498ed7b854934785f00fabfd0dadf75b # monero_c hash
|
||||
path: impls/monero.dart
|
||||
mutex: ^3.1.0
|
||||
|
|
|
@ -463,8 +463,8 @@ packages:
|
|||
dependency: "direct main"
|
||||
description:
|
||||
path: "impls/monero.dart"
|
||||
ref: d72c15f4339791a7bbdf17e9d827b7b56ca144e4
|
||||
resolved-ref: d72c15f4339791a7bbdf17e9d827b7b56ca144e4
|
||||
ref: c41c4dad9aa5003a914cfb2c528c76386f952665
|
||||
resolved-ref: c41c4dad9aa5003a914cfb2c528c76386f952665
|
||||
url: "https://github.com/mrcyjanek/monero_c"
|
||||
source: git
|
||||
version: "0.0.0"
|
||||
|
|
|
@ -25,7 +25,7 @@ dependencies:
|
|||
monero:
|
||||
git:
|
||||
url: https://github.com/mrcyjanek/monero_c
|
||||
ref: d72c15f4339791a7bbdf17e9d827b7b56ca144e4
|
||||
ref: c41c4dad9aa5003a914cfb2c528c76386f952665
|
||||
# ref: 6eb571ea498ed7b854934785f00fabfd0dadf75b # monero_c hash
|
||||
path: impls/monero.dart
|
||||
mutex: ^3.1.0
|
||||
|
|
|
@ -56,7 +56,7 @@ class AnyPayApi {
|
|||
final response = await post(url, headers: headers, body: utf8.encode(json.encode(body)));
|
||||
|
||||
if (response.statusCode != 200) {
|
||||
ExceptionHandler.onError(FlutterErrorDetails(exception: response));
|
||||
await ExceptionHandler.onError(FlutterErrorDetails(exception: response));
|
||||
throw Exception('Unexpected response http code: ${response.statusCode}');
|
||||
}
|
||||
|
||||
|
|
|
@ -230,17 +230,15 @@ class BackupService {
|
|||
json.decode(transactionDescriptionFile.readAsStringSync()) as Map<String, dynamic>;
|
||||
final descriptionsMap = jsonData.map((key, value) =>
|
||||
MapEntry(key, TransactionDescription.fromJson(value as Map<String, dynamic>)));
|
||||
|
||||
if (!_transactionDescriptionBox.isOpen) {
|
||||
final transactionDescriptionsBoxKey = await getEncryptionKey(secureStorage: secureStorageShared, forKey: TransactionDescription.boxKey);
|
||||
final transactionDescriptionBox = await CakeHive.openBox<TransactionDescription>(
|
||||
var box = _transactionDescriptionBox;
|
||||
if (!box.isOpen) {
|
||||
final transactionDescriptionsBoxKey =
|
||||
await getEncryptionKey(secureStorage: _secureStorage, forKey: TransactionDescription.boxKey);
|
||||
box = await CakeHive.openBox<TransactionDescription>(
|
||||
TransactionDescription.boxName,
|
||||
encryptionKey: transactionDescriptionsBoxKey,
|
||||
);
|
||||
await transactionDescriptionBox.putAll(descriptionsMap);
|
||||
return;
|
||||
}
|
||||
await _transactionDescriptionBox.putAll(descriptionsMap);
|
||||
encryptionKey: transactionDescriptionsBoxKey);
|
||||
}
|
||||
await box.putAll(descriptionsMap);
|
||||
}
|
||||
|
||||
Future<void> _importPreferencesDump() async {
|
||||
|
|
|
@ -2,15 +2,22 @@ import 'dart:async';
|
|||
|
||||
import 'package:cake_wallet/core/generate_wallet_password.dart';
|
||||
import 'package:cake_wallet/core/key_service.dart';
|
||||
import 'package:cake_wallet/core/secure_storage.dart';
|
||||
import 'package:cake_wallet/entities/preferences_key.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/main.dart';
|
||||
import 'package:cake_wallet/reactions/on_authentication_state_change.dart';
|
||||
import 'package:cake_wallet/src/screens/auth/auth_page.dart';
|
||||
import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart';
|
||||
import 'package:cake_wallet/utils/exception_handler.dart';
|
||||
import 'package:cake_wallet/utils/show_pop_up.dart';
|
||||
import 'package:cw_core/cake_hive.dart';
|
||||
import 'package:cw_core/wallet_base.dart';
|
||||
import 'package:cw_core/wallet_info.dart';
|
||||
import 'package:cw_core/wallet_service.dart';
|
||||
import 'package:cw_core/wallet_type.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
class WalletLoadingService {
|
||||
|
@ -58,24 +65,25 @@ class WalletLoadingService {
|
|||
|
||||
return wallet;
|
||||
} catch (error, stack) {
|
||||
ExceptionHandler.onError(FlutterErrorDetails(exception: error, stack: stack));
|
||||
await ExceptionHandler.resetLastPopupDate();
|
||||
await ExceptionHandler.onError(FlutterErrorDetails(exception: error, stack: stack));
|
||||
|
||||
// try fetching the seeds of the corrupted wallet to show it to the user
|
||||
String corruptedWalletsSeeds = "Corrupted wallets seeds (if retrievable, empty otherwise):";
|
||||
try {
|
||||
corruptedWalletsSeeds += await _getCorruptedWalletSeeds(name, type);
|
||||
} catch (e) {
|
||||
corruptedWalletsSeeds += "\nFailed to fetch $name seeds: $e";
|
||||
corruptedWalletsSeeds += "\nFailed to fetch $name seeds: $e";
|
||||
}
|
||||
|
||||
// try opening another wallet that is not corrupted to give user access to the app
|
||||
final walletInfoSource = await CakeHive.openBox<WalletInfo>(WalletInfo.boxName);
|
||||
|
||||
WalletBase? wallet;
|
||||
for (var walletInfo in walletInfoSource.values) {
|
||||
try {
|
||||
final walletService = walletServiceFactory.call(walletInfo.type);
|
||||
final walletPassword = password ?? (await keyService.getWalletPassword(walletName: name));
|
||||
final wallet = await walletService.openWallet(walletInfo.name, walletPassword);
|
||||
final walletPassword = await keyService.getWalletPassword(walletName: walletInfo.name);
|
||||
wallet = await walletService.openWallet(walletInfo.name, walletPassword);
|
||||
|
||||
if (walletInfo.type == WalletType.monero) {
|
||||
await updateMoneroWalletPassword(wallet);
|
||||
|
@ -88,8 +96,6 @@ class WalletLoadingService {
|
|||
|
||||
// if found a wallet that is not corrupted, then still display the seeds of the corrupted ones
|
||||
authenticatedErrorStreamController.add(corruptedWalletsSeeds);
|
||||
|
||||
return wallet;
|
||||
} catch (e) {
|
||||
print(e);
|
||||
// save seeds and show corrupted wallets' seeds to the user
|
||||
|
@ -99,16 +105,56 @@ class WalletLoadingService {
|
|||
corruptedWalletsSeeds += seeds;
|
||||
}
|
||||
} catch (e) {
|
||||
corruptedWalletsSeeds += "\nFailed to fetch $name seeds: $e";
|
||||
corruptedWalletsSeeds += "\nFailed to fetch $name seeds: $e";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if all user's wallets are corrupted throw exception
|
||||
throw error.toString() + "\n\n" + corruptedWalletsSeeds;
|
||||
final msg = error.toString() + "\n" + corruptedWalletsSeeds;
|
||||
if (navigatorKey.currentContext != null) {
|
||||
await showPopUp<void>(
|
||||
context: navigatorKey.currentContext!,
|
||||
builder: (BuildContext context) {
|
||||
return AlertWithTwoActions(
|
||||
alertTitle: "Corrupted seeds",
|
||||
alertContent: S.of(context).corrupted_seed_notice,
|
||||
leftButtonText: S.of(context).cancel,
|
||||
rightButtonText: S.of(context).show_seed,
|
||||
actionLeftButton: () => Navigator.of(context).pop(),
|
||||
actionRightButton: () => showSeedsPopup(context, msg),
|
||||
);
|
||||
});
|
||||
} else {
|
||||
throw msg;
|
||||
}
|
||||
if (wallet == null) {
|
||||
throw Exception("Wallet is null");
|
||||
}
|
||||
return wallet;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> showSeedsPopup(BuildContext context, String message) async {
|
||||
Navigator.of(context).pop();
|
||||
await showPopUp<void>(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return AlertWithTwoActions(
|
||||
alertTitle: "Corrupted seeds",
|
||||
alertContent: message,
|
||||
leftButtonText: S.of(context).copy,
|
||||
rightButtonText: S.of(context).ok,
|
||||
actionLeftButton: () async {
|
||||
await Clipboard.setData(ClipboardData(text: message));
|
||||
},
|
||||
actionRightButton: () async {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> updateMoneroWalletPassword(WalletBase wallet) async {
|
||||
final key = PreferencesKey.moneroWalletUpdateV1Key(wallet.name);
|
||||
var isPasswordUpdated = sharedPreferences.getBool(key) ?? false;
|
||||
|
|
|
@ -575,7 +575,7 @@ Future<void> setup({
|
|||
totpAuthPageState.changeProcessText('Loading the wallet');
|
||||
|
||||
if (loginError != null) {
|
||||
totpAuthPageState.changeProcessText('ERROR: ${loginError.toString()}');
|
||||
totpAuthPageState.changeProcessText('ERROR: ${loginError.toString()}'.trim());
|
||||
}
|
||||
|
||||
ReactionDisposer? _reaction;
|
||||
|
@ -604,7 +604,7 @@ Future<void> setup({
|
|||
authPageState.changeProcessText('Loading the wallet');
|
||||
|
||||
if (loginError != null) {
|
||||
authPageState.changeProcessText('ERROR: ${loginError.toString()}');
|
||||
authPageState.changeProcessText('ERROR: ${loginError.toString()}'.trim());
|
||||
loginError = null;
|
||||
}
|
||||
|
||||
|
@ -624,7 +624,7 @@ Future<void> setup({
|
|||
}
|
||||
|
||||
if (loginError != null) {
|
||||
authPageState.changeProcessText('ERROR: ${loginError.toString()}');
|
||||
authPageState.changeProcessText('ERROR: ${loginError.toString()}'.trim());
|
||||
timer.cancel();
|
||||
}
|
||||
});
|
||||
|
|
|
@ -89,7 +89,7 @@ Future<void> runAppWithZone({Key? topLevelKey}) async {
|
|||
);
|
||||
}
|
||||
|
||||
ExceptionHandler.onError(FlutterErrorDetails(exception: error, stack: stackTrace));
|
||||
await ExceptionHandler.onError(FlutterErrorDetails(exception: error, stack: stackTrace));
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -43,8 +43,8 @@ void startAuthenticationStateChange(
|
|||
if (!requireHardwareWalletConnection()) await loadCurrentWallet();
|
||||
} catch (error, stack) {
|
||||
loginError = error;
|
||||
ExceptionHandler.onError(
|
||||
FlutterErrorDetails(exception: error, stack: stack));
|
||||
await ExceptionHandler.resetLastPopupDate();
|
||||
await ExceptionHandler.onError(FlutterErrorDetails(exception: error, stack: stack));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -81,7 +81,7 @@ void startAuthenticationStateChange(
|
|||
.pushNamedAndRemoveUntil(Routes.dashboard, (route) => false);
|
||||
}
|
||||
if (!(await authenticatedErrorStreamController.stream.isEmpty)) {
|
||||
ExceptionHandler.showError(
|
||||
await ExceptionHandler.showError(
|
||||
(await authenticatedErrorStreamController.stream.first).toString());
|
||||
authenticatedErrorStreamController.stream.drain();
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import 'package:another_flushbar/flushbar.dart';
|
||||
import 'package:cake_wallet/utils/show_bar.dart';
|
||||
import 'package:cake_wallet/utils/show_pop_up.dart';
|
||||
import 'package:mobx/mobx.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
|
@ -9,6 +10,8 @@ import 'package:cake_wallet/view_model/auth_view_model.dart';
|
|||
import 'package:cake_wallet/src/screens/pin_code/pin_code.dart';
|
||||
import 'package:cake_wallet/src/screens/pin_code/pin_code_widget.dart';
|
||||
import 'package:cake_wallet/core/execution_state.dart';
|
||||
import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
typedef OnAuthenticationFinished = void Function(bool, AuthPageState);
|
||||
|
||||
|
@ -66,7 +69,6 @@ class AuthPagePinCodeStateImpl extends AuthPageState<AuthPage> {
|
|||
dismissFlushBar(_authBar);
|
||||
showBar<void>(
|
||||
context, S.of(context).failed_authentication(state.error));
|
||||
|
||||
widget.onAuthenticationFinished(false, this);
|
||||
});
|
||||
}
|
||||
|
@ -77,12 +79,12 @@ class AuthPagePinCodeStateImpl extends AuthPageState<AuthPage> {
|
|||
dismissFlushBar(_authBar);
|
||||
showBar<void>(
|
||||
context, S.of(context).failed_authentication(state.error));
|
||||
|
||||
widget.onAuthenticationFinished(false, this);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
if (widget.authViewModel.isBiometricalAuthenticationAllowed) {
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) async {
|
||||
await Future<void>.delayed(Duration(milliseconds: 100));
|
||||
|
@ -93,6 +95,23 @@ class AuthPagePinCodeStateImpl extends AuthPageState<AuthPage> {
|
|||
super.initState();
|
||||
}
|
||||
|
||||
Future<void> _showSeedsPopup(BuildContext context, String message) async {
|
||||
await showPopUp<void>(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return AlertWithTwoActions(
|
||||
alertTitle: "Corrupted seeds",
|
||||
alertContent: message,
|
||||
leftButtonText: S.of(context).copy,
|
||||
rightButtonText: S.of(context).ok,
|
||||
actionLeftButton: () async {
|
||||
await Clipboard.setData(ClipboardData(text: message));
|
||||
},
|
||||
actionRightButton: () => Navigator.of(context).pop(),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_reaction?.reaction.dispose();
|
||||
|
|
|
@ -154,7 +154,7 @@ class BackupPage extends BasePage {
|
|||
File returnedFile = File(outputFile!);
|
||||
await returnedFile.writeAsBytes(backup.content);
|
||||
} catch (exception, stackTrace) {
|
||||
ExceptionHandler.onError(FlutterErrorDetails(
|
||||
await ExceptionHandler.onError(FlutterErrorDetails(
|
||||
exception: exception,
|
||||
stack: stackTrace,
|
||||
library: "Export Backup",
|
||||
|
|
|
@ -11,6 +11,7 @@ import 'package:cake_wallet/src/screens/wallet_unlock/wallet_unlock_arguments.da
|
|||
import 'package:cake_wallet/src/widgets/alert_with_two_actions.dart';
|
||||
import 'package:cake_wallet/store/settings_store.dart';
|
||||
import 'package:cake_wallet/themes/extensions/menu_theme.dart';
|
||||
import 'package:cake_wallet/utils/exception_handler.dart';
|
||||
import 'package:cake_wallet/utils/show_bar.dart';
|
||||
import 'package:cake_wallet/utils/show_pop_up.dart';
|
||||
import 'package:cake_wallet/view_model/wallet_list/wallet_list_item.dart';
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import 'package:another_flushbar/flushbar.dart';
|
||||
import 'package:cake_wallet/core/auth_service.dart';
|
||||
import 'package:cake_wallet/core/new_wallet_arguments.dart';
|
||||
import 'package:cake_wallet/core/secure_storage.dart';
|
||||
import 'package:cake_wallet/entities/wallet_edit_page_arguments.dart';
|
||||
import 'package:cake_wallet/entities/wallet_list_order_types.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
|
@ -20,6 +21,7 @@ import 'package:cake_wallet/store/settings_store.dart';
|
|||
import 'package:cake_wallet/themes/extensions/cake_text_theme.dart';
|
||||
import 'package:cake_wallet/themes/extensions/filter_theme.dart';
|
||||
import 'package:cake_wallet/themes/extensions/wallet_list_theme.dart';
|
||||
import 'package:cake_wallet/utils/exception_handler.dart';
|
||||
import 'package:cake_wallet/utils/responsive_layout_util.dart';
|
||||
import 'package:cake_wallet/utils/show_bar.dart';
|
||||
import 'package:cake_wallet/utils/show_pop_up.dart';
|
||||
|
@ -459,6 +461,9 @@ class WalletListBodyState extends State<WalletListBody> {
|
|||
});
|
||||
}
|
||||
} catch (e) {
|
||||
await ExceptionHandler.resetLastPopupDate();
|
||||
final err = e.toString();
|
||||
await ExceptionHandler.onError(FlutterErrorDetails(exception: err));
|
||||
if (this.mounted) {
|
||||
changeProcessText(S
|
||||
.of(context)
|
||||
|
|
|
@ -73,15 +73,22 @@ class BaseAlertDialog extends StatelessWidget {
|
|||
}
|
||||
|
||||
Widget content(BuildContext context) {
|
||||
return Text(
|
||||
contentText,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.normal,
|
||||
fontFamily: 'Lato',
|
||||
color: Theme.of(context).extension<CakeTextTheme>()!.titleColor,
|
||||
decoration: TextDecoration.none,
|
||||
return SingleChildScrollView(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(
|
||||
contentText,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.normal,
|
||||
fontFamily: 'Lato',
|
||||
color: Theme.of(context).extension<CakeTextTheme>()!.titleColor,
|
||||
decoration: TextDecoration.none,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import 'dart:io';
|
||||
|
||||
import 'package:cake_wallet/core/secure_storage.dart';
|
||||
import 'package:cake_wallet/entities/preferences_key.dart';
|
||||
import 'package:cake_wallet/generated/i18n.dart';
|
||||
import 'package:cake_wallet/main.dart';
|
||||
|
@ -20,7 +21,7 @@ class ExceptionHandler {
|
|||
static const _coolDownDurationInDays = 7;
|
||||
static File? _file;
|
||||
|
||||
static void _saveException(String? error, StackTrace? stackTrace, {String? library}) async {
|
||||
static Future<void> _saveException(String? error, StackTrace? stackTrace, {String? library}) async {
|
||||
final appDocDir = await getAppDir();
|
||||
|
||||
if (_file == null) {
|
||||
|
@ -90,7 +91,12 @@ class ExceptionHandler {
|
|||
}
|
||||
}
|
||||
|
||||
static void onError(FlutterErrorDetails errorDetails) async {
|
||||
static Future<void> resetLastPopupDate() async {
|
||||
final sharedPrefs = await SharedPreferences.getInstance();
|
||||
await sharedPrefs.setString(PreferencesKey.lastPopupDate, DateTime(1971).toString());
|
||||
}
|
||||
|
||||
static Future<void> onError(FlutterErrorDetails errorDetails) async {
|
||||
if (kDebugMode || kProfileMode) {
|
||||
FlutterError.presentError(errorDetails);
|
||||
debugPrint(errorDetails.toString());
|
||||
|
@ -124,35 +130,40 @@ class ExceptionHandler {
|
|||
}
|
||||
_hasError = true;
|
||||
|
||||
sharedPrefs.setString(PreferencesKey.lastPopupDate, DateTime.now().toString());
|
||||
await sharedPrefs.setString(PreferencesKey.lastPopupDate, DateTime.now().toString());
|
||||
|
||||
WidgetsBinding.instance.addPostFrameCallback(
|
||||
(timeStamp) async {
|
||||
if (navigatorKey.currentContext != null) {
|
||||
await showPopUp<void>(
|
||||
context: navigatorKey.currentContext!,
|
||||
builder: (context) {
|
||||
return AlertWithTwoActions(
|
||||
isDividerExist: true,
|
||||
alertTitle: S.of(context).error,
|
||||
alertContent: S.of(context).error_dialog_content,
|
||||
rightButtonText: S.of(context).send,
|
||||
leftButtonText: S.of(context).do_not_send,
|
||||
actionRightButton: () {
|
||||
Navigator.of(context).pop();
|
||||
_sendExceptionFile();
|
||||
},
|
||||
actionLeftButton: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
);
|
||||
// Instead of using WidgetsBinding.instance.addPostFrameCallback we
|
||||
// await Future.delayed(Duration.zero), which does essentially the same (
|
||||
// but doesn't wait for actual frame to be rendered), but it allows us to
|
||||
// properly await the execution - which is what we want, without awaiting
|
||||
// other code may call functions like Navigator.pop(), and close the alert
|
||||
// instead of the intended UI.
|
||||
// WidgetsBinding.instance.addPostFrameCallback(
|
||||
// (timeStamp) async {
|
||||
await Future.delayed(Duration.zero);
|
||||
if (navigatorKey.currentContext != null) {
|
||||
await showPopUp<void>(
|
||||
context: navigatorKey.currentContext!,
|
||||
builder: (context) {
|
||||
return AlertWithTwoActions(
|
||||
isDividerExist: true,
|
||||
alertTitle: S.of(context).error,
|
||||
alertContent: S.of(context).error_dialog_content,
|
||||
rightButtonText: S.of(context).send,
|
||||
leftButtonText: S.of(context).do_not_send,
|
||||
actionRightButton: () {
|
||||
Navigator.of(context).pop();
|
||||
_sendExceptionFile();
|
||||
},
|
||||
actionLeftButton: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
_hasError = false;
|
||||
},
|
||||
);
|
||||
_hasError = false;
|
||||
}
|
||||
|
||||
/// Ignore User related errors or system errors
|
||||
|
@ -272,20 +283,18 @@ class ExceptionHandler {
|
|||
};
|
||||
}
|
||||
|
||||
static void showError(String error, {int? delayInSeconds}) async {
|
||||
static Future<void> showError(String error, {int? delayInSeconds}) async {
|
||||
if (_hasError) {
|
||||
return;
|
||||
}
|
||||
_hasError = true;
|
||||
|
||||
if (delayInSeconds != null) {
|
||||
Future.delayed(Duration(seconds: delayInSeconds), () => _showCopyPopup(error));
|
||||
return;
|
||||
}
|
||||
|
||||
WidgetsBinding.instance.addPostFrameCallback(
|
||||
(_) async => _showCopyPopup(error),
|
||||
);
|
||||
await Future.delayed(Duration.zero);
|
||||
await _showCopyPopup(error);
|
||||
}
|
||||
|
||||
static Future<void> _showCopyPopup(String content) async {
|
||||
|
|
|
@ -68,7 +68,7 @@ abstract class RestoreFromBackupViewModelBase with Store {
|
|||
if (msg.toLowerCase().contains("message authentication code (mac)")) {
|
||||
msg = 'Incorrect backup password';
|
||||
} else {
|
||||
ExceptionHandler.onError(FlutterErrorDetails(
|
||||
await ExceptionHandler.onError(FlutterErrorDetails(
|
||||
exception: e,
|
||||
stack: s,
|
||||
library: this.toString(),
|
||||
|
|
|
@ -10,7 +10,6 @@ list(APPEND FLUTTER_PLUGIN_LIST
|
|||
)
|
||||
|
||||
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
||||
sp_scanner
|
||||
)
|
||||
|
||||
set(PLUGIN_BUNDLED_LIBRARIES)
|
||||
|
|
|
@ -6,7 +6,6 @@ import FlutterMacOS
|
|||
import Foundation
|
||||
|
||||
import connectivity_plus
|
||||
import cw_mweb
|
||||
import device_info_plus
|
||||
import devicelocale
|
||||
import fast_scanner
|
||||
|
@ -24,7 +23,6 @@ import wakelock_plus
|
|||
|
||||
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
||||
ConnectivityPlugin.register(with: registry.registrar(forPlugin: "ConnectivityPlugin"))
|
||||
CwMwebPlugin.register(with: registry.registrar(forPlugin: "CwMwebPlugin"))
|
||||
DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin"))
|
||||
DevicelocalePlugin.register(with: registry.registrar(forPlugin: "DevicelocalePlugin"))
|
||||
MobileScannerPlugin.register(with: registry.registrar(forPlugin: "MobileScannerPlugin"))
|
||||
|
|
|
@ -177,6 +177,7 @@
|
|||
"copy_address": "نسخ العنوان",
|
||||
"copy_id": "نسخ معرف العملية",
|
||||
"copyWalletConnectLink": "ﺎﻨﻫ ﻪﻘﺼﻟﺍﻭ dApp ﻦﻣ WalletConnect ﻂﺑﺍﺭ ﺦﺴﻧﺍ",
|
||||
"corrupted_seed_notice": "تالف ملفات هذه المحفظة ولا يمكن فتحها. يرجى الاطلاع على عبارة البذور وحفظها واستعادة المحفظة.\n\nإذا كانت القيمة فارغة ، لم تتمكن البذور من استردادها بشكل صحيح.",
|
||||
"countries": "بلدان",
|
||||
"create_account": "إنشاء حساب",
|
||||
"create_backup": "انشئ نسخة احتياطية",
|
||||
|
|
|
@ -177,6 +177,7 @@
|
|||
"copy_address": "Copy Address",
|
||||
"copy_id": "Копиране на ID",
|
||||
"copyWalletConnectLink": "Копирайте връзката WalletConnect от dApp и я поставете тук",
|
||||
"corrupted_seed_notice": "Файловете за този портфейл са повредени и не могат да бъдат отворени. Моля, прегледайте фразата за семена, запазете я и възстановете портфейла.\n\nАко стойността е празна, тогава семето не успя да бъде правилно възстановено.",
|
||||
"countries": "Държави",
|
||||
"create_account": "Създаване на профил",
|
||||
"create_backup": "Създаване на резервно копие",
|
||||
|
|
|
@ -177,6 +177,7 @@
|
|||
"copy_address": "Zkopírovat adresu",
|
||||
"copy_id": "Kopírovat ID",
|
||||
"copyWalletConnectLink": "Zkopírujte odkaz WalletConnect z dApp a vložte jej sem",
|
||||
"corrupted_seed_notice": "Soubory pro tuto peněženku jsou poškozeny a nemohou být otevřeny. Podívejte se prosím na osivo, uložte ji a obnovte peněženku.\n\nPokud je hodnota prázdná, pak semeno nebylo možné správně obnovit.",
|
||||
"countries": "Země",
|
||||
"create_account": "Vytvořit účet",
|
||||
"create_backup": "Vytvořit zálohu",
|
||||
|
|
|
@ -177,6 +177,7 @@
|
|||
"copy_address": "Adresse kopieren",
|
||||
"copy_id": "ID kopieren",
|
||||
"copyWalletConnectLink": "Kopieren Sie den WalletConnect-Link von dApp und fügen Sie ihn hier ein",
|
||||
"corrupted_seed_notice": "Die Dateien für diese Brieftasche sind beschädigt und können nicht geöffnet werden. Bitte sehen Sie sich die Saatgutphrase an, speichern Sie sie und stellen Sie die Brieftasche wieder her.\n\nWenn der Wert leer ist, konnte der Samen nicht korrekt wiederhergestellt werden.",
|
||||
"countries": "Länder",
|
||||
"create_account": "Konto erstellen",
|
||||
"create_backup": "Backup erstellen",
|
||||
|
|
|
@ -177,6 +177,7 @@
|
|||
"copy_address": "Copy Address",
|
||||
"copy_id": "Copy ID",
|
||||
"copyWalletConnectLink": "Copy the WalletConnect link from dApp and paste here",
|
||||
"corrupted_seed_notice": "The files for this wallet are corrupted and are unable to be opened. Please view the seed phrase, save it, and restore the wallet.\n\nIf the value is empty, then the seed was unable to be correctly recovered.",
|
||||
"countries": "Countries",
|
||||
"create_account": "Create Account",
|
||||
"create_backup": "Create backup",
|
||||
|
|
|
@ -177,6 +177,7 @@
|
|||
"copy_address": "Copiar dirección ",
|
||||
"copy_id": "Copiar ID",
|
||||
"copyWalletConnectLink": "Copie el enlace de WalletConnect de dApp y péguelo aquí",
|
||||
"corrupted_seed_notice": "Los archivos para esta billetera están dañados y no pueden abrirse. Vea la frase de semillas, guárdela y restaura la billetera.\n\nSi el valor está vacío, entonces la semilla no pudo recuperarse correctamente.",
|
||||
"countries": "Países",
|
||||
"create_account": "Crear Cuenta",
|
||||
"create_backup": "Crear copia de seguridad",
|
||||
|
|
|
@ -177,6 +177,7 @@
|
|||
"copy_address": "Copier l'Adresse",
|
||||
"copy_id": "Copier l'ID",
|
||||
"copyWalletConnectLink": "Copiez le lien WalletConnect depuis l'application décentralisée (dApp) et collez-le ici",
|
||||
"corrupted_seed_notice": "Les fichiers de ce portefeuille sont corrompus et ne peuvent pas être ouverts. Veuillez consulter la phrase de graines, sauver et restaurer le portefeuille.\n\nSi la valeur est vide, la graine n'a pas pu être correctement récupérée.",
|
||||
"countries": "Des pays",
|
||||
"create_account": "Créer un compte",
|
||||
"create_backup": "Créer une sauvegarde",
|
||||
|
|
|
@ -177,6 +177,7 @@
|
|||
"copy_address": "Kwafi Adireshin",
|
||||
"copy_id": "Kwafi ID",
|
||||
"copyWalletConnectLink": "Kwafi hanyar haɗin WalletConnect daga dApp kuma liƙa a nan",
|
||||
"corrupted_seed_notice": "Fayilolin don wannan walat ɗin sun lalata kuma ba za a iya buɗe su ba. Da fatan za a duba kalmar iri, adana shi, da dawo da walat.\n\nIdan darajar ta kasance fanko, to sai zuriyar da ba ta iya murmurewa daidai ba.",
|
||||
"countries": "Kasashe",
|
||||
"create_account": "Kirkira ajiya",
|
||||
"create_backup": "Ƙirƙiri madadin",
|
||||
|
|
|
@ -177,6 +177,7 @@
|
|||
"copy_address": "पता कॉपी करें",
|
||||
"copy_id": "प्रतिलिपि ID",
|
||||
"copyWalletConnectLink": "dApp से वॉलेटकनेक्ट लिंक को कॉपी करें और यहां पेस्ट करें",
|
||||
"corrupted_seed_notice": "इस वॉलेट की फाइलें दूषित हैं और उन्हें खोलने में असमर्थ हैं। कृपया बीज वाक्यांश देखें, इसे बचाएं, और बटुए को पुनर्स्थापित करें।\n\nयदि मूल्य खाली है, तो बीज सही ढंग से पुनर्प्राप्त करने में असमर्थ था।",
|
||||
"countries": "देशों",
|
||||
"create_account": "खाता बनाएं",
|
||||
"create_backup": "बैकअप बनाएँ",
|
||||
|
|
|
@ -177,6 +177,7 @@
|
|||
"copy_address": "Kopiraj adresu",
|
||||
"copy_id": "Kopirati ID",
|
||||
"copyWalletConnectLink": "Kopirajte vezu WalletConnect iz dApp-a i zalijepite je ovdje",
|
||||
"corrupted_seed_notice": "Datoteke za ovaj novčanik su oštećene i nisu u mogućnosti otvoriti. Molimo pogledajte sjemensku frazu, spremite je i vratite novčanik.\n\nAko je vrijednost prazna, tada sjeme nije bilo u stanju ispravno oporaviti.",
|
||||
"countries": "Zemalja",
|
||||
"create_account": "Stvori račun",
|
||||
"create_backup": "Stvori sigurnosnu kopiju",
|
||||
|
|
|
@ -177,6 +177,7 @@
|
|||
"copy_address": "Պատճենել հասցեն",
|
||||
"copy_id": "Պատճենել ID",
|
||||
"copyWalletConnectLink": "Պատճենել WalletConnect հղումը dApp-ից և տեղադրել այստեղ",
|
||||
"corrupted_seed_notice": "Այս դրամապանակի համար ֆայլերը կոռումպացված են եւ չեն կարողանում բացվել: Խնդրում ենք դիտել սերմերի արտահայտությունը, պահպանել այն եւ վերականգնել դրամապանակը:\n\nԵթե արժեքը դատարկ է, ապա սերմը չկարողացավ ճիշտ վերականգնվել:",
|
||||
"countries": "Երկրներ",
|
||||
"create_account": "Ստեղծել հաշիվ",
|
||||
"create_backup": "Ստեղծել կրկնօրինակ",
|
||||
|
|
|
@ -177,6 +177,7 @@
|
|||
"copy_address": "Salin Alamat",
|
||||
"copy_id": "Salin ID",
|
||||
"copyWalletConnectLink": "Salin tautan WalletConnect dari dApp dan tempel di sini",
|
||||
"corrupted_seed_notice": "File untuk dompet ini rusak dan tidak dapat dibuka. Silakan lihat frasa benih, simpan, dan kembalikan dompet.\n\nJika nilainya kosong, maka benih tidak dapat dipulihkan dengan benar.",
|
||||
"countries": "Negara",
|
||||
"create_account": "Buat Akun",
|
||||
"create_backup": "Buat cadangan",
|
||||
|
|
|
@ -178,6 +178,7 @@
|
|||
"copy_address": "Copia Indirizzo",
|
||||
"copy_id": "Copia ID",
|
||||
"copyWalletConnectLink": "Copia il collegamento WalletConnect dalla dApp e incollalo qui",
|
||||
"corrupted_seed_notice": "I file per questo portafoglio sono corrotti e non sono in grado di essere aperti. Visualizza la frase del seme, salvala e ripristina il portafoglio.\n\nSe il valore è vuoto, il seme non è stato in grado di essere recuperato correttamente.",
|
||||
"countries": "Paesi",
|
||||
"create_account": "Crea account",
|
||||
"create_backup": "Crea backup",
|
||||
|
|
|
@ -177,6 +177,7 @@
|
|||
"copy_address": "住所をコピー",
|
||||
"copy_id": "IDをコピー",
|
||||
"copyWalletConnectLink": "dApp から WalletConnect リンクをコピーし、ここに貼り付けます",
|
||||
"corrupted_seed_notice": "このウォレットのファイルは破損しており、開くことができません。シードフレーズを表示し、保存し、財布を復元してください。\n\n値が空の場合、種子を正しく回復することができませんでした。",
|
||||
"countries": "国",
|
||||
"create_account": "アカウントの作成",
|
||||
"create_backup": "バックアップを作成",
|
||||
|
|
|
@ -177,6 +177,7 @@
|
|||
"copy_address": "주소 복사",
|
||||
"copy_id": "부 ID",
|
||||
"copyWalletConnectLink": "dApp에서 WalletConnect 링크를 복사하여 여기에 붙여넣으세요.",
|
||||
"corrupted_seed_notice": "이 지갑의 파일은 손상되어 열 수 없습니다. 씨앗 문구를보고 저장하고 지갑을 복원하십시오.\n\n값이 비어 있으면 씨앗을 올바르게 회수 할 수 없었습니다.",
|
||||
"countries": "국가",
|
||||
"create_account": "계정 만들기",
|
||||
"create_backup": "백업 생성",
|
||||
|
|
|
@ -177,6 +177,7 @@
|
|||
"copy_address": "လိပ်စာကို ကူးယူပါ။",
|
||||
"copy_id": "ID ကူးယူပါ။",
|
||||
"copyWalletConnectLink": "dApp မှ WalletConnect လင့်ခ်ကို ကူးယူပြီး ဤနေရာတွင် ကူးထည့်ပါ။",
|
||||
"corrupted_seed_notice": "ဤပိုက်ဆံအိတ်အတွက်ဖိုင်များသည်အကျင့်ပျက်ခြစားမှုများနှင့်မဖွင့်နိုင်ပါ။ ကျေးဇူးပြု. မျိုးစေ့များကိုကြည့်ပါ, ၎င်းကိုသိမ်းဆည်းပါ, ပိုက်ဆံအိတ်ကိုပြန်ယူပါ။\n\nအကယ်. တန်ဖိုးသည်အချည်းနှီးဖြစ်ပါကမျိုးစေ့ကိုမှန်ကန်စွာပြန်လည်ကောင်းမွန်မရရှိနိုင်ပါ။",
|
||||
"countries": "နိုင်ငံများ",
|
||||
"create_account": "အကောင့်ပြုလုပ်ပါ",
|
||||
"create_backup": "အရန်သိမ်းခြင်းကို ဖန်တီးပါ။",
|
||||
|
|
|
@ -177,6 +177,7 @@
|
|||
"copy_address": "Adres kopiëren",
|
||||
"copy_id": "ID kopiëren",
|
||||
"copyWalletConnectLink": "Kopieer de WalletConnect-link van dApp en plak deze hier",
|
||||
"corrupted_seed_notice": "De bestanden voor deze portemonnee zijn beschadigd en kunnen niet worden geopend. Bekijk de zaadzin, bewaar deze en herstel de portemonnee.\n\nAls de waarde leeg is, kon het zaad niet correct worden hersteld.",
|
||||
"countries": "Landen",
|
||||
"create_account": "Account aanmaken",
|
||||
"create_backup": "Maak een back-up",
|
||||
|
|
|
@ -177,6 +177,7 @@
|
|||
"copy_address": "Skopiuj adress",
|
||||
"copy_id": "skopiuj ID",
|
||||
"copyWalletConnectLink": "Skopiuj link do WalletConnect z dApp i wklej tutaj",
|
||||
"corrupted_seed_notice": "Pliki dla tego portfela są uszkodzone i nie można ich otworzyć. Zobacz wyrażenie nasion, zapisz je i przywróć portfel.\n\nJeśli wartość jest pusta, ziarno nie można było poprawnie odzyskać.",
|
||||
"countries": "Kraje",
|
||||
"create_account": "Utwórz konto",
|
||||
"create_backup": "Utwórz kopię zapasową",
|
||||
|
|
|
@ -177,6 +177,7 @@
|
|||
"copy_address": "Copiar endereço",
|
||||
"copy_id": "Copiar ID",
|
||||
"copyWalletConnectLink": "Copie o link WalletConnect do dApp e cole aqui",
|
||||
"corrupted_seed_notice": "Os arquivos para esta carteira estão corrompidos e não podem ser abertos. Veja a frase das sementes, salve -a e restaure a carteira.\n\nSe o valor estiver vazio, a semente não pôde ser recuperada corretamente.",
|
||||
"countries": "Países",
|
||||
"create_account": "Criar conta",
|
||||
"create_backup": "Criar backup",
|
||||
|
|
|
@ -177,6 +177,7 @@
|
|||
"copy_address": "Cкопировать адрес",
|
||||
"copy_id": "Скопировать ID",
|
||||
"copyWalletConnectLink": "Скопируйте ссылку WalletConnect из dApp и вставьте сюда.",
|
||||
"corrupted_seed_notice": "Файлы для этого кошелька повреждены и не могут быть открыты. Пожалуйста, просмотрите семенную фразу, сохраните ее и восстановите кошелек.\n\nЕсли значение пустое, то семя не смог правильно восстановить.",
|
||||
"countries": "Страны",
|
||||
"create_account": "Создать аккаунт",
|
||||
"create_backup": "Создать резервную копию",
|
||||
|
|
|
@ -177,6 +177,7 @@
|
|||
"copy_address": "คัดลอกที่อยู่",
|
||||
"copy_id": "คัดลอก ID",
|
||||
"copyWalletConnectLink": "คัดลอกลิงก์ WalletConnect จาก dApp แล้ววางที่นี่",
|
||||
"corrupted_seed_notice": "ไฟล์สำหรับกระเป๋าเงินนี้เสียหายและไม่สามารถเปิดได้ โปรดดูวลีเมล็ดบันทึกและกู้คืนกระเป๋าเงิน\n\nหากค่าว่างเปล่าเมล็ดก็ไม่สามารถกู้คืนได้อย่างถูกต้อง",
|
||||
"countries": "ประเทศ",
|
||||
"create_account": "สร้างบัญชี",
|
||||
"create_backup": "สร้างการสำรองข้อมูล",
|
||||
|
|
|
@ -177,6 +177,7 @@
|
|||
"copy_address": "Kopyahin ang Address",
|
||||
"copy_id": "Kopyahin ang ID",
|
||||
"copyWalletConnectLink": "Kopyahin ang link ng WalletConnect mula sa dApp at i-paste dito",
|
||||
"corrupted_seed_notice": "Ang mga file para sa pitaka na ito ay nasira at hindi mabubuksan. Mangyaring tingnan ang parirala ng binhi, i -save ito, at ibalik ang pitaka.\n\nKung ang halaga ay walang laman, kung gayon ang binhi ay hindi ma -recover nang tama.",
|
||||
"countries": "Mga bansa",
|
||||
"create_account": "Lumikha ng Account",
|
||||
"create_backup": "Lumikha ng backup",
|
||||
|
|
|
@ -177,6 +177,7 @@
|
|||
"copy_address": "Adresi kopyala",
|
||||
"copy_id": "ID'yi kopyala",
|
||||
"copyWalletConnectLink": "WalletConnect bağlantısını dApp'ten kopyalayıp buraya yapıştırın",
|
||||
"corrupted_seed_notice": "Bu cüzdanın dosyaları bozuk ve açılamıyor. Lütfen tohum ifadesini görüntüleyin, kaydedin ve cüzdanı geri yükleyin.\n\nDeğer boşsa, tohum doğru bir şekilde geri kazanılamadı.",
|
||||
"countries": "Ülkeler",
|
||||
"create_account": "Hesap oluştur",
|
||||
"create_backup": "Yedek oluştur",
|
||||
|
|
|
@ -177,6 +177,7 @@
|
|||
"copy_address": "Cкопіювати адресу",
|
||||
"copy_id": "Скопіювати ID",
|
||||
"copyWalletConnectLink": "Скопіюйте посилання WalletConnect із dApp і вставте сюди",
|
||||
"corrupted_seed_notice": "Файли для цього гаманця пошкоджені і не можуть бути відкриті. Перегляньте насіннєву фразу, збережіть її та відновіть гаманець.\n\nЯкщо значення порожнє, то насіння не могло бути правильно відновленим.",
|
||||
"countries": "Країни",
|
||||
"create_account": "Створити обліковий запис",
|
||||
"create_backup": "Створити резервну копію",
|
||||
|
|
|
@ -177,6 +177,7 @@
|
|||
"copy_address": "ایڈریس کاپی کریں۔",
|
||||
"copy_id": "کاپی ID",
|
||||
"copyWalletConnectLink": "dApp ﮯﺳ WalletConnect ۔ﮟﯾﺮﮐ ﭧﺴﯿﭘ ﮞﺎﮩﯾ ﺭﻭﺍ ﮟﯾﺮﮐ ﯽﭘﺎﮐ ﻮﮐ ﮏﻨﻟ",
|
||||
"corrupted_seed_notice": "اس پرس کے لئے فائلیں خراب ہیں اور کھولنے سے قاصر ہیں۔ براہ کرم بیج کے فقرے کو دیکھیں ، اسے بچائیں ، اور بٹوے کو بحال کریں۔\n\nاگر قیمت خالی ہے ، تو بیج صحیح طور پر بازیافت کرنے سے قاصر تھا۔",
|
||||
"countries": "ممالک",
|
||||
"create_account": "اکاؤنٹ بنائیں",
|
||||
"create_backup": "بیک اپ بنائیں",
|
||||
|
|
|
@ -176,6 +176,7 @@
|
|||
"copy_address": "Sao chép Địa chỉ",
|
||||
"copy_id": "Sao chép ID",
|
||||
"copyWalletConnectLink": "Sao chép liên kết WalletConnect từ dApp và dán vào đây",
|
||||
"corrupted_seed_notice": "Các tệp cho ví này bị hỏng và không thể mở. Vui lòng xem cụm từ hạt giống, lưu nó và khôi phục ví.\n\nNếu giá trị trống, thì hạt giống không thể được phục hồi chính xác.",
|
||||
"countries": "Quốc gia",
|
||||
"create_account": "Tạo tài khoản",
|
||||
"create_backup": "Tạo sao lưu",
|
||||
|
|
|
@ -177,6 +177,7 @@
|
|||
"copy_address": "Ṣẹ̀dà àdírẹ́sì",
|
||||
"copy_id": "Ṣẹ̀dà àmì ìdánimọ̀",
|
||||
"copyWalletConnectLink": "Daakọ ọna asopọ WalletConnect lati dApp ki o si lẹẹmọ nibi",
|
||||
"corrupted_seed_notice": "Awọn faili fun apamọwọ yii jẹ ibajẹ ati pe ko lagbara lati ṣii. Jọwọ wo ọrọ iseda, fipamọ rẹ, ki o mu apamọwọ naa pada.\n\nTi iye ba ṣofo, lẹhinna irugbin naa ko lagbara lati gba pada ni deede.",
|
||||
"countries": "Awọn orilẹ-ede",
|
||||
"create_account": "Dá àkáǹtì",
|
||||
"create_backup": "Ṣẹ̀dà nípamọ́",
|
||||
|
|
|
@ -177,6 +177,7 @@
|
|||
"copy_address": "复制地址",
|
||||
"copy_id": "复制ID",
|
||||
"copyWalletConnectLink": "从 dApp 复制 WalletConnect 链接并粘贴到此处",
|
||||
"corrupted_seed_notice": "该钱包的文件被损坏,无法打开。请查看种子短语,保存并恢复钱包。\n\n如果该值为空,则种子无法正确恢复。",
|
||||
"countries": "国家",
|
||||
"create_account": "创建账户",
|
||||
"create_backup": "创建备份",
|
||||
|
|
|
@ -8,7 +8,7 @@ if [[ ! -d "monero_c" ]];
|
|||
then
|
||||
git clone https://github.com/mrcyjanek/monero_c --branch master
|
||||
cd monero_c
|
||||
git checkout d72c15f4339791a7bbdf17e9d827b7b56ca144e4
|
||||
git checkout c41c4dad9aa5003a914cfb2c528c76386f952665
|
||||
git reset --hard
|
||||
git submodule update --init --force --recursive
|
||||
./apply_patches.sh monero
|
||||
|
|
|
@ -14,7 +14,6 @@ list(APPEND FLUTTER_PLUGIN_LIST
|
|||
)
|
||||
|
||||
list(APPEND FLUTTER_FFI_PLUGIN_LIST
|
||||
sp_scanner
|
||||
)
|
||||
|
||||
set(PLUGIN_BUNDLED_LIBRARIES)
|
||||
|
|
Loading…
Reference in a new issue