Cw 858 ledger enhancements ()

* feat: Redesign HW Account select screen

* fix: Avoid "Bluetooth disabled" Exception on dispose of HW Connection screen

* feat: Proceed on Ledger Modal is not dismissible by tapping out

* feat: Gracefully ignore errors thrown by monero ledger keep alive function

* feat: Close a monero ledger wallet on wallet change

* fix: Leave connect screen without connecting
This commit is contained in:
Konstantin Ullrich 2025-02-18 23:23:03 +01:00 committed by GitHub
parent 99338a0532
commit 9d6f985a59
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
36 changed files with 79 additions and 32 deletions

View file

@ -56,14 +56,12 @@ void enableLedgerExchange(monero.wallet ptr, LedgerConnection connection) {
void keepAlive(LedgerConnection connection) {
if (connection.connectionType == ConnectionType.ble) {
_ledgerKeepAlive = Timer.periodic(Duration(seconds: 10), (_) async {
try {
UniversalBle.setNotifiable(
connection.device.id,
connection.device.deviceInfo.serviceId,
connection.device.deviceInfo.notifyCharacteristicKey,
BleInputProperty.notification,
);
} catch (_) {}
UniversalBle.setNotifiable(
connection.device.id,
connection.device.deviceInfo.serviceId,
connection.device.deviceInfo.notifyCharacteristicKey,
BleInputProperty.notification,
).onError((_, __) async {});
});
}
}

View file

@ -179,6 +179,23 @@ abstract class MoneroWalletBase extends WalletBase<MoneroBalance,
@override
Future<void> close({bool shouldCleanup = false}) async {
if (isHardwareWallet) {
disableLedgerExchange();
final currentWalletDirPath = await pathForWalletDir(name: name, type: type);
if (openedWalletsByPath["$currentWalletDirPath/$name"] != null) {
printV("closing wallet");
final wmaddr = wmPtr.address;
final waddr = openedWalletsByPath["$currentWalletDirPath/$name"]!.address;
await Isolate.run(() {
monero.WalletManager_closeWallet(
Pointer.fromAddress(wmaddr), Pointer.fromAddress(waddr), true);
});
openedWalletsByPath.remove("$currentWalletDirPath/$name");
wptr = null;
printV("wallet closed");
}
}
_listener?.stop();
_onAccountChangeReaction?.reaction.dispose();
_onTxHistoryChangeReaction?.reaction.dispose();

View file

@ -67,6 +67,7 @@ void startAuthenticationStateChange(
alertTitle: S.of(context).proceed_on_device,
alertContent: S.of(context).proceed_on_device_description,
buttonText: S.of(context).cancel,
alertBarrierDismissible: false,
buttonAction: () => Navigator.of(context).pop()),
);
await loadCurrentWallet();

View file

@ -190,6 +190,7 @@ class _MoneroHardwareWalletOptionsFormState
alertTitle: S.of(context).proceed_on_device,
alertContent: S.of(context).proceed_on_device_description,
buttonText: S.of(context).cancel,
alertBarrierDismissible: false,
buttonAction: () => Navigator.of(context).pop(),
),
);

View file

@ -147,7 +147,7 @@ class _SelectHardwareWalletAccountFormState extends State<SelectHardwareWalletAc
child: Container(
width: double.infinity,
child: Text(
"Available accounts",
S.of(context).select_hw_account_below,
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w500,
@ -159,6 +159,7 @@ class _SelectHardwareWalletAccountFormState extends State<SelectHardwareWalletAc
Observer(
builder: (context) => Column(
children: _walletHardwareRestoreVM.availableAccounts.map((acc) {
final address = acc.address;
return Padding(
padding: EdgeInsets.only(top: 10),
@ -170,7 +171,7 @@ class _SelectHardwareWalletAccountFormState extends State<SelectHardwareWalletAc
width: 24,
),
text:
"${address.substring(0, 6)}...${address.substring(address.length - 6)}",
"${acc.accountIndex} - ${address.substring(0, 6)}...${address.substring(address.length - 6)}",
showTrailingIcon: false,
height: 54,
isSelected: _walletHardwareRestoreVM.selectedAccount == acc,

View file

@ -599,6 +599,7 @@ class SendPage extends BasePage {
alertTitle: S.of(context).proceed_on_device,
alertContent: S.of(context).proceed_on_device_description,
buttonText: S.of(context).cancel,
alertBarrierDismissible: false,
buttonAction: () {
sendViewModel.state = InitialExecutionState();
Navigator.of(context).pop();

View file

@ -31,8 +31,6 @@ import 'package:cw_core/wallet_type.dart';
import 'package:flutter/material.dart';
import 'package:flutter_mobx/flutter_mobx.dart';
import '../../../themes/extensions/dashboard_page_theme.dart';
class WalletListPage extends BasePage {
WalletListPage({
required this.walletListViewModel,
@ -506,23 +504,28 @@ class WalletListBodyState extends State<WalletListBody> {
final requireHardwareWalletConnection = widget.walletListViewModel
.requireHardwareWalletConnection(wallet);
if (requireHardwareWalletConnection) {
bool didConnect = false;
await Navigator.of(context).pushNamed(
Routes.connectDevices,
arguments: ConnectDevicePageParams(
walletType: WalletType.monero,
onConnectDevice: (context, ledgerVM) async {
monero!.setGlobalLedgerConnection(ledgerVM.connection);
didConnect = true;
Navigator.of(context).pop();
},
),
);
if (!didConnect) return;
showPopUp<void>(
context: context,
builder: (BuildContext context) => AlertWithOneAction(
alertTitle: S.of(context).proceed_on_device,
alertContent: S.of(context).proceed_on_device_description,
buttonText: S.of(context).cancel,
alertBarrierDismissible: false,
buttonAction: () => Navigator.of(context).pop()),
);
}

View file

@ -16,7 +16,6 @@ import 'package:cw_core/utils/print_verbose.dart';
import 'package:cw_core/wallet_base.dart';
import 'package:cw_core/wallet_type.dart';
import 'package:flutter/widgets.dart';
import 'package:ledger_flutter_plus/ledger_flutter_plus.dart' as sdk;
import 'package:mobx/mobx.dart';
import 'package:permission_handler/permission_handler.dart';
@ -61,20 +60,21 @@ abstract class LedgerViewModelBase with Store {
bool bleIsEnabled = false;
bool _bleIsInitialized = false;
Future<void> _initBLE() async {
if (bleIsEnabled && !_bleIsInitialized) {
ledgerPlusBLE = sdk.LedgerInterface.ble(
onPermissionRequest: (_) async {
Map<Permission, PermissionStatus> statuses = await [
Permission.bluetoothScan,
Permission.bluetoothConnect,
Permission.bluetoothAdvertise,
].request();
onPermissionRequest: (_) async {
Map<Permission, PermissionStatus> statuses = await [
Permission.bluetoothScan,
Permission.bluetoothConnect,
Permission.bluetoothAdvertise,
].request();
return statuses.values.where((status) => status.isDenied).isEmpty;
},
bleOptions:
sdk.BluetoothOptions(maxScanDuration: Duration(minutes: 5)));
return statuses.values.where((status) => status.isDenied).isEmpty;
},
bleOptions: sdk.BluetoothOptions(maxScanDuration: Duration(minutes: 5)),
);
_bleIsInitialized = true;
}
}
@ -92,10 +92,8 @@ abstract class LedgerViewModelBase with Store {
Stream<sdk.LedgerDevice> scanForUsbDevices() => ledgerPlusUSB.scan();
Future<void> stopScanning() async {
await ledgerPlusBLE.stopScanning();
if (!Platform.isIOS) {
await ledgerPlusUSB.stopScanning();
}
if (_bleIsInitialized) await ledgerPlusBLE.stopScanning();
if (!Platform.isIOS) await ledgerPlusUSB.stopScanning();
}
Future<void> connectLedger(sdk.LedgerDevice device, WalletType type) async {
@ -112,8 +110,8 @@ abstract class LedgerViewModelBase with Store {
: ledgerPlusUSB;
if (_connectionChangeSubscription == null) {
_connectionChangeSubscription = ledger.deviceStateChanges
.listen(_connectionChangeListener);
_connectionChangeSubscription =
ledger.deviceStateChanges.listen(_connectionChangeListener);
}
_connection = await ledger.connect(device);
@ -125,8 +123,7 @@ abstract class LedgerViewModelBase with Store {
bool _isConnecting = true;
WalletType? _connectingWalletType;
void _connectionChangeListener(
sdk.BleConnectionState event, ) {
void _connectionChangeListener(sdk.BleConnectionState event) {
printV('Ledger Device State Changed: $event');
if (event == sdk.BleConnectionState.disconnected && !_isConnecting) {
_connection = null;

View file

@ -668,6 +668,7 @@
"select_backup_file": "حدد ملف النسخ الاحتياطي",
"select_buy_provider_notice": "حدد مزود شراء أعلاه. يمكنك تخطي هذه الشاشة عن طريق تعيين مزود شراء الافتراضي في إعدادات التطبيق.",
"select_destination": ".ﻲﻃﺎﻴﺘﺣﻻﺍ ﺦﺴﻨﻟﺍ ﻒﻠﻣ ﺔﻬﺟﻭ ﺪﻳﺪﺤﺗ ءﺎﺟﺮﻟﺍ",
"select_hw_account_below": "الرجاء تحديد حساب الاستعادة أدناه:",
"select_sell_provider_notice": ".ﻖﻴﺒﻄﺘﻟﺍ ﺕﺍﺩﺍﺪﻋﺇ ﻲﻓ ﻚﺑ ﺹﺎﺨﻟﺍ ﻲﺿﺍﺮﺘﻓﻻﺍ ﻊﻴﺒﻟﺍ ﺩﻭﺰﻣ ﻦﻴﻴﻌﺗ ﻖﻳﺮﻃ ﻦﻋ ﺔﺷﺎﺸﻟﺍ ﻩﺬﻫ ﻲﻄﺨﺗ",
"select_your_country": "الرجاء تحديد بلدك",
"sell": "بيع",

View file

@ -668,6 +668,7 @@
"select_backup_file": "Избор на резервно копие",
"select_buy_provider_notice": "Изберете доставчик на покупка по -горе. Можете да пропуснете този екран, като зададете вашия доставчик по подразбиране по подразбиране в настройките на приложението.",
"select_destination": "Моля, изберете дестинация за архивния файл.",
"select_hw_account_below": "Моля, изберете кой акаунт да възстановите по -долу:",
"select_sell_provider_notice": "Изберете доставчик на продажба по-горе. Можете да пропуснете този екран, като зададете своя доставчик на продажба по подразбиране в настройките на приложението.",
"select_your_country": "Моля, изберете вашата страна",
"sell": "Продаване",

View file

@ -668,6 +668,7 @@
"select_backup_file": "Vybrat soubor se zálohou",
"select_buy_provider_notice": "Vyberte výše uvedeného poskytovatele nákupu. Tuto obrazovku můžete přeskočit nastavením výchozího poskytovatele nákupu v nastavení aplikace.",
"select_destination": "Vyberte cíl pro záložní soubor.",
"select_hw_account_below": "Níže vyberte, který účet chcete obnovit:",
"select_sell_provider_notice": "Výše vyberte poskytovatele prodeje. Tuto obrazovku můžete přeskočit nastavením výchozího poskytovatele prodeje v nastavení aplikace.",
"select_your_country": "Vyberte prosím svou zemi",
"sell": "Prodat",

View file

@ -669,6 +669,7 @@
"select_backup_file": "Sicherungsdatei auswählen",
"select_buy_provider_notice": "Wählen Sie oben einen Anbieter kaufen. Sie können diese Seite überspringen, indem Sie Ihren Standard-Kaufanbieter in den App-Einstellungen festlegen.",
"select_destination": "Bitte wählen Sie das Ziel für die Sicherungsdatei aus.",
"select_hw_account_below": "Bitte wählen Sie unten, welches Konto unten wiederhergestellt werden soll:",
"select_sell_provider_notice": "Wählen Sie oben einen Verkaufsanbieter aus. Sie können diesen Bildschirm überspringen, indem Sie in den App-Einstellungen Ihren Standard-Verkaufsanbieter festlegen.",
"select_your_country": "Bitte wählen Sie Ihr Land aus",
"sell": "Verkaufen",
@ -1001,4 +1002,4 @@
"you_will_get": "Konvertieren zu",
"you_will_send": "Konvertieren von",
"yy": "YY"
}
}

View file

@ -669,6 +669,7 @@
"select_backup_file": "Select backup file",
"select_buy_provider_notice": "Select a buy provider above. You can skip this screen by setting your default buy provider in app settings.",
"select_destination": "Please select destination for the backup file.",
"select_hw_account_below": "Please select which account to restore below:",
"select_sell_provider_notice": "Select a sell provider above. You can skip this screen by setting your default sell provider in app settings.",
"select_your_country": "Please select your country",
"sell": "Sell",

View file

@ -669,6 +669,7 @@
"select_backup_file": "Seleccionar archivo de respaldo",
"select_buy_provider_notice": "Selecciona un proveedor de compra arriba. Puede omitir esta pantalla configurando su proveedor de compra predeterminado en la configuración de la aplicación.",
"select_destination": "Selecciona el destino del archivo de copia de seguridad.",
"select_hw_account_below": "Seleccione qué cuenta restaurar a continuación:",
"select_sell_provider_notice": "Selecciona un proveedor de venta arriba. Puede omitir esta pantalla configurando su proveedor de venta predeterminado en la configuración de la aplicación.",
"select_your_country": "Seleccione su país",
"sell": "Vender",

View file

@ -668,6 +668,7 @@
"select_backup_file": "Sélectionnez le fichier de sauvegarde",
"select_buy_provider_notice": "Sélectionnez un fournisseur d'achat ci-dessus. Vous pouvez ignorer cet écran en définissant votre fournisseur d'achat par défaut dans les paramètres de l'application.",
"select_destination": "Veuillez sélectionner la destination du fichier de sauvegarde.",
"select_hw_account_below": "Veuillez sélectionner le compte à restaurer ci-dessous:",
"select_sell_provider_notice": "Sélectionnez un fournisseur de vente ci-dessus. Vous pouvez ignorer cet écran en définissant votre fournisseur de vente par défaut dans les paramètres de l'application.",
"select_your_country": "Veuillez sélectionner votre pays",
"sell": "Vendre",

View file

@ -670,6 +670,7 @@
"select_backup_file": "Zaɓi fayil ɗin madadin",
"select_buy_provider_notice": "Zaɓi mai ba da kyauta a sama. Zaka iya tsallake wannan allon ta hanyar saita mai ba da isasshen busasshen mai ba da isasshen busasshiyar saiti.",
"select_destination": "Da fatan za a zaɓi wurin da za a yi wa madadin fayil ɗin.",
"select_hw_account_below": "Da fatan za a zabi wanda asusun zai gyara a ƙasa:",
"select_sell_provider_notice": "Zaɓi mai bada siyarwa a sama. Kuna iya tsallake wannan allon ta saita mai bada siyar da ku a cikin saitunan app.",
"select_your_country": "Da fatan za a zabi ƙasarku",
"sell": "sayar",

View file

@ -670,6 +670,7 @@
"select_backup_file": "बैकअप फ़ाइल का चयन करें",
"select_buy_provider_notice": "ऊपर एक खरीद प्रदाता का चयन करें। आप इस स्क्रीन को ऐप सेटिंग्स में अपना डिफ़ॉल्ट बाय प्रदाता सेट करके छोड़ सकते हैं।",
"select_destination": "कृपया बैकअप फ़ाइल के लिए गंतव्य का चयन करें।",
"select_hw_account_below": "कृपया नीचे पुनर्स्थापित करने के लिए कौन सा खाता चुनें:",
"select_sell_provider_notice": "ऊपर एक विक्रय प्रदाता का चयन करें। आप ऐप सेटिंग में अपना डिफ़ॉल्ट विक्रय प्रदाता सेट करके इस स्क्रीन को छोड़ सकते हैं।",
"select_your_country": "कृपया अपने देश का चयन करें",
"sell": "बेचना",

View file

@ -668,6 +668,7 @@
"select_backup_file": "Odaberite datoteku sigurnosne kopije",
"select_buy_provider_notice": "Odaberite gornji davatelj kupnje. Ovaj zaslon možete preskočiti postavljanjem zadanog davatelja usluga kupnje u postavkama aplikacija.",
"select_destination": "Odaberite odredište za datoteku sigurnosne kopije.",
"select_hw_account_below": "Molimo odaberite koji će se račun vratiti u nastavku:",
"select_sell_provider_notice": "Gore odaberite pružatelja usluga prodaje. Ovaj zaslon možete preskočiti postavljanjem zadanog pružatelja usluga prodaje u postavkama aplikacije.",
"select_your_country": "Odaberite svoju zemlju",
"sell": "Prodavati",

View file

@ -668,6 +668,7 @@
"select_backup_file": "Ընտրել կրկնօրինակ ֆայլ",
"select_buy_provider_notice": "Ընտրեք գնման մատակարարը վերևում։ Դուք կարող եք բաց թողնել այս էկրանը ձեր լռելայն գնման մատակարարը հավելվածի կարգավորումներում սահմանելով",
"select_destination": "Խնդրում ենք ընտրել կրկնօրինակ ֆայլի նպատակակետը",
"select_hw_account_below": "Խնդրում ենք ընտրել, թե որ հաշիվն է վերականգնել հետեւյալը.",
"select_sell_provider_notice": "Ընտրեք վաճառքի մատակարարը վերևում։ Դուք կարող եք բաց թողնել այս էկրանը ձեր լռելայն վաճառքի մատակարարը հավելվածի կարգավորումներում սահմանելով",
"select_your_country": "Խնդրում ենք ընտրել ձեր երկիրը",
"sell": "Ծախել",

View file

@ -671,6 +671,7 @@
"select_backup_file": "Pilih file cadangan",
"select_buy_provider_notice": "Pilih penyedia beli di atas. Anda dapat melewatkan layar ini dengan mengatur penyedia pembelian default Anda di pengaturan aplikasi.",
"select_destination": "Silakan pilih tujuan untuk file cadangan.",
"select_hw_account_below": "Pilih akun mana yang akan dikembalikan di bawah ini:",
"select_sell_provider_notice": "Pilih penyedia jual di atas. Anda dapat melewati layar ini dengan mengatur penyedia penjualan default Anda di pengaturan aplikasi.",
"select_your_country": "Pilih negara Anda",
"sell": "Jual",

View file

@ -670,6 +670,7 @@
"select_backup_file": "Seleziona file di backup",
"select_buy_provider_notice": "Seleziona un fornitore di acquisto sopra. È possibile saltare questa schermata impostando il provider di acquisto predefinito nelle impostazioni dell'app.",
"select_destination": "Seleziona la destinazione per il file di backup.",
"select_hw_account_below": "Seleziona quale account ripristina di seguito:",
"select_sell_provider_notice": "Seleziona un fornitore di vendita sopra. Puoi saltare questa schermata impostando il tuo fornitore di vendita predefinito nelle impostazioni dell'app.",
"select_your_country": "Seleziona il tuo paese",
"sell": "Vendere",

View file

@ -669,6 +669,7 @@
"select_backup_file": "バックアップファイルを選択",
"select_buy_provider_notice": "上記の購入プロバイダーを選択してください。デフォルトの購入プロバイダーをアプリ設定で設定して、この画面をスキップできます。",
"select_destination": "バックアップファイルの保存先を選択してください。",
"select_hw_account_below": "以下に復元するアカウントを選択してください。",
"select_sell_provider_notice": "上記の販売プロバイダーを選択してください。アプリ設定でデフォルトの販売プロバイダーを設定することで、この画面をスキップできます。",
"select_your_country": "あなたの国を選択してください",
"sell": "売る",

View file

@ -668,6 +668,7 @@
"select_backup_file": "백업 파일 선택",
"select_buy_provider_notice": "위의 구매 제공자를 선택하십시오. 앱 설정에서 기본 구매 제공자를 설정 하여이 화면을 건너 뛸 수 있습니다.",
"select_destination": "백업 파일의 대상을 선택하십시오.",
"select_hw_account_below": "아래를 복원 할 계정을 선택하십시오.",
"select_sell_provider_notice": "위에서 판매 공급자를 선택하세요. 앱 설정에서 기본 판매 공급자를 설정하면 이 화면을 건너뛸 수 있습니다.",
"select_your_country": "국가를 선택하십시오",
"sell": "팔다",

View file

@ -668,6 +668,7 @@
"select_backup_file": "အရန်ဖိုင်ကို ရွေးပါ။",
"select_buy_provider_notice": "အပေါ်ကဝယ်သူတစ် ဦး ကိုရွေးချယ်ပါ။ သင်၏ default 0 ယ်သူအား app settings တွင် setting လုပ်ခြင်းဖြင့်ဤ screen ကိုကျော်သွားနိုင်သည်။",
"select_destination": "အရန်ဖိုင်အတွက် ဦးတည်ရာကို ရွေးပါ။",
"select_hw_account_below": "အောက်ဖော်ပြပါမည်သည့်အကောင့်ကိုရွေးပါ။",
"select_sell_provider_notice": "အထက်ဖော်ပြပါ အရောင်းဝန်ဆောင်မှုပေးသူကို ရွေးပါ။ အက်ပ်ဆက်တင်များတွင် သင်၏မူလရောင်းချပေးသူကို သတ်မှတ်ခြင်းဖြင့် ဤစခရင်ကို ကျော်နိုင်သည်။",
"select_your_country": "ကျေးဇူးပြု. သင့်နိုင်ငံကိုရွေးချယ်ပါ",
"sell": "ရောင်း",

View file

@ -668,6 +668,7 @@
"select_backup_file": "Selecteer een back-upbestand",
"select_buy_provider_notice": "Selecteer hierboven een koopprovider. U kunt dit scherm overslaan door uw standaard kopenprovider in te stellen in app -instellingen.",
"select_destination": "Selecteer de bestemming voor het back-upbestand.",
"select_hw_account_below": "Selecteer welk account u hieronder moet herstellen:",
"select_sell_provider_notice": "Selecteer hierboven een verkoopaanbieder. U kunt dit scherm overslaan door uw standaardverkoopprovider in te stellen in de app-instellingen.",
"select_your_country": "Selecteer uw land",
"sell": "Verkopen",

View file

@ -668,6 +668,7 @@
"select_backup_file": "Wybierz plik kopii zapasowej",
"select_buy_provider_notice": "Wybierz powyższe dostawcę zakupu. Możesz pominąć ten ekran, ustawiając domyślnego dostawcę zakupu w ustawieniach aplikacji.",
"select_destination": "Wybierz miejsce docelowe dla pliku kopii zapasowej.",
"select_hw_account_below": "Wybierz, które konto przywrócić poniżej:",
"select_sell_provider_notice": "Wybierz dostawcę sprzedaży powyżej. Możesz pominąć ten ekran, ustawiając domyślnego dostawcę sprzedaży w ustawieniach aplikacji.",
"select_your_country": "Wybierz swój kraj",
"sell": "Sprzedać",

View file

@ -670,6 +670,7 @@
"select_backup_file": "Selecione o arquivo de backup",
"select_buy_provider_notice": "Selecione um provedor de compra acima. Você pode pular esta tela definindo seu provedor de compra padrão nas configurações de aplicativos.",
"select_destination": "Selecione o destino para o arquivo de backup.",
"select_hw_account_below": "Selecione qual conta para restaurar abaixo:",
"select_sell_provider_notice": "Selecione um fornecedor de venda acima. Você pode pular esta tela definindo seu provedor de venda padrão nas configurações do aplicativo.",
"select_your_country": "Selecione seu país",
"sell": "Vender",

View file

@ -669,6 +669,7 @@
"select_backup_file": "Выберите файл резервной копии",
"select_buy_provider_notice": "Выберите поставщика покупки выше. Вы можете пропустить этот экран, установив поставщика покупки по умолчанию в настройках приложения.",
"select_destination": "Пожалуйста, выберите место для файла резервной копии.",
"select_hw_account_below": "Пожалуйста, выберите, какую учетную запись восстановить ниже:",
"select_sell_provider_notice": "Выберите поставщика услуг продажи выше. Вы можете пропустить этот экран, установив поставщика услуг продаж по умолчанию в настройках приложения.",
"select_your_country": "Пожалуйста, выберите свою страну",
"sell": "Продавать",

View file

@ -668,6 +668,7 @@
"select_backup_file": "เลือกไฟล์สำรอง",
"select_buy_provider_notice": "เลือกผู้ให้บริการซื้อด้านบน คุณสามารถข้ามหน้าจอนี้ได้โดยการตั้งค่าผู้ให้บริการซื้อเริ่มต้นในการตั้งค่าแอป",
"select_destination": "โปรดเลือกปลายทางสำหรับไฟล์สำรอง",
"select_hw_account_below": "กรุณาเลือกบัญชีที่จะกู้คืนด้านล่าง:",
"select_sell_provider_notice": "เลือกผู้ให้บริการการขายด้านบน คุณสามารถข้ามหน้าจอนี้ได้โดยการตั้งค่าผู้ให้บริการการขายเริ่มต้นในการตั้งค่าแอป",
"select_your_country": "กรุณาเลือกประเทศของคุณ",
"sell": "ขาย",

View file

@ -668,6 +668,7 @@
"select_backup_file": "Piliin ang backup na file",
"select_buy_provider_notice": "Pumili ng provider ng pagbili sa itaas. Maaari mong laktawan ang screen na ito sa pamamagitan ng pagtatakda ng iyong default na provider ng pagbili sa mga setting ng app.",
"select_destination": "Mangyaring piliin ang patutunguhan para sa backup na file.",
"select_hw_account_below": "Mangyaring piliin kung aling account ang ibabalik sa ibaba:",
"select_sell_provider_notice": "Pumili ng provider ng nagbebenta sa itaas. Maaari mong laktawan ang screen na ito sa pamamagitan ng pagtatakda ng iyong default na sell provider sa mga setting ng app.",
"select_your_country": "Mangyaring piliin ang iyong bansa",
"sell": "Ibenta",

View file

@ -668,6 +668,7 @@
"select_backup_file": "Yedek dosyası seç",
"select_buy_provider_notice": "Yukarıda bir satın alma sağlayıcısı seçin. App ayarlarında varsayılan satın alma sağlayıcınızı ayarlayarak bu ekranı atlayabilirsiniz.",
"select_destination": "Lütfen yedekleme dosyası için hedef seçin.",
"select_hw_account_below": "Lütfen aşağıda hangi hesabı geri yükleyeceğinizi seçin:",
"select_sell_provider_notice": "Yukarıdan bir satış sağlayıcısı seçin. Uygulama ayarlarında varsayılan satış sağlayıcınızı ayarlayarak bu ekranı atlayabilirsiniz.",
"select_your_country": "Lütfen ülkenizi seçin",
"sell": "Satış",

View file

@ -669,6 +669,7 @@
"select_backup_file": "Виберіть файл резервної копії",
"select_buy_provider_notice": "Виберіть постачальника купівлі вище. Ви можете пропустити цей екран, встановивши свого постачальника купівлі за замовчуванням у налаштуваннях додатків.",
"select_destination": "Виберіть місце призначення для файлу резервної копії.",
"select_hw_account_below": "Виберіть, який рахунок відновити нижче:",
"select_sell_provider_notice": "Виберіть вище постачальника послуг продажу. Ви можете пропустити цей екран, встановивши постачальника послуг продажу за умовчанням у налаштуваннях програми.",
"select_your_country": "Будь ласка, виберіть свою країну",
"sell": "Продати",

View file

@ -670,6 +670,7 @@
"select_backup_file": "بیک اپ فائل کو منتخب کریں۔",
"select_buy_provider_notice": "اوپر خریدنے والا خریدنے والا منتخب کریں۔ آپ ایپ کی ترتیبات میں اپنے پہلے سے طے شدہ خریدنے والے کو ترتیب دے کر اس اسکرین کو چھوڑ سکتے ہیں۔",
"select_destination": "۔ﮟﯾﺮﮐ ﺏﺎﺨﺘﻧﺍ ﺎﮐ ﻝﺰﻨﻣ ﮯﯿﻟ ﮯﮐ ﻞﺋﺎﻓ ﭖﺍ ﮏﯿﺑ ﻡﺮﮐ ﮦﺍﺮﺑ",
"select_hw_account_below": "براہ کرم ذیل میں کون سا اکاؤنٹ بحال کرنا ہے منتخب کریں:",
"select_sell_provider_notice": "۔ﮟﯿﮨ ﮯﺘﮑﺳ ﮌﻮﮭﭼ ﻮﮐ ﻦﯾﺮﮑﺳﺍ ﺱﺍ ﺮﮐ ﮮﺩ ﺐﯿﺗﺮﺗ ﻮﮐ ﮦﺪﻨﻨﮐ ﻢﮨﺍﺮﻓ ﻞﯿﺳ ﭧﻟﺎﻔﯾﮈ ﮯﻨﭘﺍ ﮟﯿﻣ ﺕﺎﺒ",
"select_your_country": "براہ کرم اپنے ملک کو منتخب کریں",
"sell": "بیچنا",

View file

@ -667,6 +667,7 @@
"select_backup_file": "Chọn tệp sao lưu",
"select_buy_provider_notice": "Chọn nhà cung cấp mua ở trên. Bạn có thể bỏ qua màn hình này bằng cách thiết lập nhà cung cấp mua mặc định trong cài đặt ứng dụng.",
"select_destination": "Vui lòng chọn đích cho tệp sao lưu.",
"select_hw_account_below": "Vui lòng chọn tài khoản nào để khôi phục bên dưới:",
"select_sell_provider_notice": "Chọn nhà cung cấp bán ở trên. Bạn có thể bỏ qua màn hình này bằng cách thiết lập nhà cung cấp bán mặc định trong cài đặt ứng dụng.",
"select_your_country": "Vui lòng chọn quốc gia của bạn",
"sell": "Bán",

View file

@ -669,6 +669,7 @@
"select_backup_file": "Select backup file",
"select_buy_provider_notice": "Yan olupese Ra loke. O le skii iboju yii nipa ṣiṣeto olupese rẹ ni awọn eto App.",
"select_destination": "Jọwọ yan ibi ti o nlo fun faili afẹyinti.",
"select_hw_account_below": "Jọwọ yan iru iroyin lati mu pada ni isalẹ:",
"select_sell_provider_notice": "Yan olupese ti o ta loke. O le foju iboju yii nipa tito olupese iṣẹ tita aiyipada rẹ ni awọn eto app.",
"select_your_country": "Jọwọ yan orilẹ-ede rẹ",
"sell": "Tà",

View file

@ -668,6 +668,7 @@
"select_backup_file": "选择备份文件",
"select_buy_provider_notice": "在上面选择买入提供商。您可以通过在应用程序设置中设置默认的购买提供商来跳过此屏幕。",
"select_destination": "请选择备份文件的目的地。",
"select_hw_account_below": "请在下面选择要还原的帐户:",
"select_sell_provider_notice": "选择上面的销售提供商。您可以通过在应用程序设置中设置默认销售提供商来跳过此屏幕。",
"select_your_country": "请选择你的国家",
"sell": "卖",