CW-351-Add-option-in-Privacy-settings-to-enable-disable-screenshots (#885)

* add prevent screenshots option * fix prevent screen recording * update localization * Update strings_ja.arb

Serhii committed Apr 20, 2023 at 12:59 UTC f26815efb80a735b12bbf52b4d1e515cb8cb5c13
31 files changed +113 -37
android/app/src/main/java/com/cakewallet/cake_wallet/MainActivity.java
+9 -6
@@ -24,6 +24,7 @@ import java.security.SecureRandom;
24 public class MainActivity extends FlutterFragmentActivity {
25 final String UTILS_CHANNEL = "com.cake_wallet/native_utils";
26 final int UNSTOPPABLE_DOMAIN_MIN_VERSION_SDK = 24;
27 + boolean isAppSecure = false;
28
29 @Override
30 public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {
@@ -56,6 +57,14 @@ public class MainActivity extends FlutterFragmentActivity {
57 handler.post(() -> result.success(""));
58 }
59 break;
60 + case "setIsAppSecure":
61 + isAppSecure = call.argument("isAppSecure");
62 + if (isAppSecure) {
63 + getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE);
64 + } else {
65 + getWindow().clearFlags(WindowManager.LayoutParams.FLAG_SECURE);
66 + }
67 + break;
68 default:
69 handler.post(() -> result.notImplemented());
70 }
@@ -80,10 +89,4 @@ public class MainActivity extends FlutterFragmentActivity {
89 }
90 });
91 }
83 -
84 - @Override
85 - public void onCreate(Bundle savedInstanceState) {
86 - super.onCreate(savedInstanceState);
87 - getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE);
88 - }
92 }
\ No newline at end of file
cw_core/lib/set_app_secure_native.dart new
+6
@@ -0,0 +1,6 @@
1 +import 'package:flutter/services.dart';
2 +
3 +const utils = const MethodChannel('com.cake_wallet/native_utils');
4 +
5 +void setIsAppSecureNative(bool isAppSecure) =>
6 + utils.invokeMethod<Uint8List>('setIsAppSecure', {'isAppSecure': isAppSecure});
cw_monero/example/pubspec.lock
+7 -7
@@ -115,10 +115,10 @@ packages:
115 dependency: transitive
116 description:
117 name: ffi
118 - sha256: "13a6ccf6a459a125b3fcdb6ec73bd5ff90822e071207c663bfd1f70062d51d18"
118 + sha256: a38574032c5f1dd06c4aee541789906c12ccaab8ba01446e800d9c5b79c4a978
119 url: "https://pub.dev"
120 source: hosted
121 - version: "1.2.1"
121 + version: "2.0.1"
122 file:
123 dependency: transitive
124 description:
@@ -277,10 +277,10 @@ packages:
277 dependency: transitive
278 description:
279 name: path_provider_windows
280 - sha256: a34ecd7fb548f8e57321fd8e50d865d266941b54e6c3b7758cf8f37c24116905
280 + sha256: f53720498d5a543f9607db4b0e997c4b5438884de25b0f73098cc2671a51b130
281 url: "https://pub.dev"
282 source: hosted
283 - version: "2.0.7"
283 + version: "2.1.5"
284 platform:
285 dependency: transitive
286 description:
@@ -386,10 +386,10 @@ packages:
386 dependency: transitive
387 description:
388 name: win32
389 - sha256: c0e3a4f7be7dae51d8f152230b86627e3397c1ba8c3fa58e63d44a9f3edc9cef
389 + sha256: a6f0236dbda0f63aa9a25ad1ff9a9d8a4eaaa5012da0dc59d21afdb1dc361ca4
390 url: "https://pub.dev"
391 source: hosted
392 - version: "2.6.1"
392 + version: "3.1.4"
393 xdg_directories:
394 dependency: transitive
395 description:
@@ -399,5 +399,5 @@ packages:
399 source: hosted
400 version: "0.2.0+3"
401 sdks:
402 - dart: ">=2.18.1 <3.0.0"
402 + dart: ">=2.18.1 <4.0.0"
403 flutter: ">=3.0.0"
lib/core/backup_service.dart
+6
@@ -209,6 +209,7 @@ class BackupService {
209 final currentBalanceDisplayMode = data[PreferencesKey.currentBalanceDisplayModeKey] as int?;
210 final currentFiatCurrency = data[PreferencesKey.currentFiatCurrencyKey] as String?;
211 final shouldSaveRecipientAddress = data[PreferencesKey.shouldSaveRecipientAddressKey] as bool?;
212 + final isAppSecure = data[PreferencesKey.isAppSecureKey] as bool?;
213 final currentTransactionPriorityKeyLegacy = data[PreferencesKey.currentTransactionPriorityKeyLegacy] as int?;
214 final allowBiometricalAuthentication = data[PreferencesKey.allowBiometricalAuthenticationKey] as bool?;
215 final currentBitcoinElectrumSererId = data[PreferencesKey.currentBitcoinElectrumSererIdKey] as int?;
@@ -245,6 +246,11 @@ class BackupService {
246 PreferencesKey.shouldSaveRecipientAddressKey,
247 shouldSaveRecipientAddress);
248
249 + if (isAppSecure != null)
250 + await _sharedPreferences.setBool(
251 + PreferencesKey.isAppSecureKey,
252 + isAppSecure);
253 +
254 if (currentTransactionPriorityKeyLegacy != null)
255 await _sharedPreferences.setInt(
256 PreferencesKey.currentTransactionPriorityKeyLegacy,
lib/entities/preferences_key.dart
+1
@@ -9,6 +9,7 @@ class PreferencesKey {
9 static const currentTransactionPriorityKeyLegacy = 'current_fee_priority';
10 static const currentBalanceDisplayModeKey = 'current_balance_display_mode';
11 static const shouldSaveRecipientAddressKey = 'save_recipient_address';
12 + static const isAppSecureKey = 'is_app_secure';
13 static const currentFiatApiModeKey = 'current_fiat_api_mode';
14 static const allowBiometricalAuthenticationKey =
15 'allow_biometrical_authentication';
lib/src/screens/settings/privacy_page.dart
+8
@@ -8,6 +8,7 @@ import 'package:cake_wallet/view_model/settings/choices_list_item.dart';
8 import 'package:cake_wallet/view_model/settings/privacy_settings_view_model.dart';
9 import 'package:flutter/material.dart';
10 import 'package:flutter_mobx/flutter_mobx.dart';
11 +import 'dart:io' show Platform;
12
13 class PrivacyPage extends BasePage {
14 PrivacyPage(this._privacySettingsViewModel);
@@ -48,6 +49,13 @@ class PrivacyPage extends BasePage {
49 onValueChange: (BuildContext _, bool value) {
50 _privacySettingsViewModel.setShouldSaveRecipientAddress(value);
51 }),
52 + if (Platform.isAndroid)
53 + SettingsSwitcherCell(
54 + title: S.current.prevent_screenshots,
55 + value: _privacySettingsViewModel.isAppSecure,
56 + onValueChange: (BuildContext _, bool value) {
57 + _privacySettingsViewModel.setIsAppSecure(value);
58 + }),
59 ],
60 );
61 }),
lib/store/settings_store.dart
+24 -1
@@ -19,6 +19,8 @@ import 'package:cw_core/node.dart';
19 import 'package:cake_wallet/monero/monero.dart';
20 import 'package:cake_wallet/entities/action_list_display_mode.dart';
21 import 'package:cake_wallet/entities/fiat_api_mode.dart';
22 +import 'package:cw_core/set_app_secure_native.dart';
23 +import 'dart:io' show Platform;
24
25 part 'settings_store.g.dart';
26
@@ -31,6 +33,7 @@ abstract class SettingsStoreBase with Store {
33 required FiatCurrency initialFiatCurrency,
34 required BalanceDisplayMode initialBalanceDisplayMode,
35 required bool initialSaveRecipientAddress,
36 + required bool initialAppSecure,
37 required FiatApiMode initialFiatMode,
38 required bool initialAllowBiometricalAuthentication,
39 required ExchangeApiMode initialExchangeStatus,
@@ -53,6 +56,7 @@ abstract class SettingsStoreBase with Store {
56 fiatCurrency = initialFiatCurrency,
57 balanceDisplayMode = initialBalanceDisplayMode,
58 shouldSaveRecipientAddress = initialSaveRecipientAddress,
59 + isAppSecure = initialAppSecure,
60 fiatApiMode = initialFiatMode,
61 allowBiometricalAuthentication = initialAllowBiometricalAuthentication,
62 shouldShowMarketPlaceInDashboard = initialShouldShowMarketPlaceInDashboard,
@@ -119,6 +123,17 @@ abstract class SettingsStoreBase with Store {
123 PreferencesKey.shouldSaveRecipientAddressKey,
124 shouldSaveRecipientAddress));
125
126 + reaction((_) => isAppSecure, (bool isAppSecure) {
127 + sharedPreferences.setBool(PreferencesKey.isAppSecureKey, isAppSecure);
128 + if (Platform.isAndroid) {
129 + setIsAppSecureNative(isAppSecure);
130 + }
131 + });
132 +
133 + if (Platform.isAndroid) {
134 + setIsAppSecureNative(isAppSecure);
135 + }
136 +
137 reaction(
138 (_) => fiatApiMode,
139 (FiatApiMode mode) => sharedPreferences.setInt(
@@ -199,6 +214,9 @@ abstract class SettingsStoreBase with Store {
214 @observable
215 bool shouldSaveRecipientAddress;
216
217 + @observable
218 + bool isAppSecure;
219 +
220 @observable
221 bool allowBiometricalAuthentication;
222
@@ -289,6 +307,8 @@ abstract class SettingsStoreBase with Store {
307 // FIX-ME: Check for which default value we should have here
308 final shouldSaveRecipientAddress =
309 sharedPreferences.getBool(PreferencesKey.shouldSaveRecipientAddressKey) ?? false;
310 + final isAppSecure =
311 + sharedPreferences.getBool(PreferencesKey.isAppSecureKey) ?? false;
312 final currentFiatApiMode = FiatApiMode.deserialize(
313 raw: sharedPreferences
314 .getInt(PreferencesKey.currentFiatApiModeKey) ?? FiatApiMode.enabled.raw);
@@ -316,7 +336,7 @@ abstract class SettingsStoreBase with Store {
336 final pinCodeTimeOutDuration = timeOutDuration != null
337 ? PinCodeRequiredDuration.deserialize(raw: timeOutDuration)
338 : defaultPinCodeTimeOutDuration;
319 -
339 +
340 // If no value
341 if (pinLength == null || pinLength == 0) {
342 pinLength = defaultPinLength;
@@ -367,6 +387,7 @@ abstract class SettingsStoreBase with Store {
387 initialFiatCurrency: currentFiatCurrency,
388 initialBalanceDisplayMode: currentBalanceDisplayMode,
389 initialSaveRecipientAddress: shouldSaveRecipientAddress,
390 + initialAppSecure: isAppSecure,
391 initialFiatMode: currentFiatApiMode,
392 initialAllowBiometricalAuthentication: allowBiometricalAuthentication,
393 initialExchangeStatus: exchangeStatus,
@@ -412,6 +433,8 @@ abstract class SettingsStoreBase with Store {
433 .getInt(PreferencesKey.currentBalanceDisplayModeKey)!);
434 shouldSaveRecipientAddress =
435 sharedPreferences.getBool(PreferencesKey.shouldSaveRecipientAddressKey) ?? shouldSaveRecipientAddress;
436 + isAppSecure =
437 + sharedPreferences.getBool(PreferencesKey.isAppSecureKey) ?? isAppSecure;
438 allowBiometricalAuthentication = sharedPreferences
439 .getBool(PreferencesKey.allowBiometricalAuthenticationKey) ??
440 allowBiometricalAuthentication;
lib/view_model/settings/privacy_settings_view_model.dart
+6
@@ -21,6 +21,9 @@ abstract class PrivacySettingsViewModelBase with Store {
21 @computed
22 FiatApiMode get fiatApiMode => _settingsStore.fiatApiMode;
23
24 + @computed
25 + bool get isAppSecure => _settingsStore.isAppSecure;
26 +
27 @action
28 void setShouldSaveRecipientAddress(bool value) => _settingsStore.shouldSaveRecipientAddress = value;
29
@@ -30,4 +33,7 @@ abstract class PrivacySettingsViewModelBase with Store {
33 @action
34 void setFiatMode(FiatApiMode fiatApiMode) => _settingsStore.fiatApiMode = fiatApiMode;
35
36 + @action
37 + void setIsAppSecure(bool value) => _settingsStore.isAppSecure = value;
38 +
39 }
res/values/strings_ar.arb
+2 -1
@@ -699,5 +699,6 @@
699 "sell_monero_com_alert_content": "بيع Monero غير مدعوم حتى الآن",
700 "error_text_input_below_minimum_limit":" المبلغ أقل من الحد الأدنى",
701 "error_text_input_above_maximum_limit":"المبلغ أكبر من الحد الأقصى",
702 - "show_market_place": "إظهار السوق"
702 + "show_market_place": "إظهار السوق",
703 + "prevent_screenshots": "منع لقطات الشاشة وتسجيل الشاشة"
704 }
res/values/strings_bg.arb
+2 -1
@@ -700,5 +700,6 @@
700 "sell_monero_com_alert_content": "Продажбата на Monero все още не се поддържа",
701 "error_text_input_below_minimum_limit" : "Сумата е по-малко от минималната",
702 "error_text_input_above_maximum_limit" : "Сумата надвишава максималната",
703 - "show_market_place":"Покажи пазар"
703 + "show_market_place":"Покажи пазар",
704 + "prevent_screenshots": "Предотвратете екранни снимки и запис на екрана"
705 }
res/values/strings_cs.arb
+2 -1
@@ -700,5 +700,6 @@
700 "sell_monero_com_alert_content": "Prodej Monero zatím není podporován",
701 "error_text_input_below_minimum_limit" : "Částka je menší než minimální hodnota",
702 "error_text_input_above_maximum_limit" : "Částka je větší než maximální hodnota",
703 - "show_market_place": "Zobrazit trh"
703 + "show_market_place": "Zobrazit trh",
704 + "prevent_screenshots": "Zabránit vytváření snímků obrazovky a nahrávání obrazovky"
705 }
res/values/strings_de.arb
+2 -1
@@ -701,5 +701,6 @@
701 "sell_monero_com_alert_content": "Der Verkauf von Monero wird noch nicht unterstützt",
702 "error_text_input_below_minimum_limit" : "Menge ist unter dem Minimum",
703 "error_text_input_above_maximum_limit" : "Menge ist über dem Maximum",
704 - "show_market_place": "Marktplatz anzeigen"
704 + "show_market_place": "Marktplatz anzeigen",
705 + "prevent_screenshots": "Verhindern Sie Screenshots und Bildschirmaufzeichnungen"
706 }
res/values/strings_en.arb
+2 -1
@@ -701,5 +701,6 @@
701 "sell_monero_com_alert_content": "Selling Monero is not supported yet",
702 "error_text_input_below_minimum_limit" : "Amount is less than the minimum",
703 "error_text_input_above_maximum_limit" : "Amount is more than the maximum",
704 - "show_market_place" :"Show Marketplace"
704 + "show_market_place" :"Show Marketplace",
705 + "prevent_screenshots": "Prevent screenshots and screen recording"
706 }
res/values/strings_es.arb
+2 -1
@@ -701,5 +701,6 @@
701 "sell_monero_com_alert_content": "Aún no se admite la venta de Monero",
702 "error_text_input_below_minimum_limit" : "La cantidad es menos que mínima",
703 "error_text_input_above_maximum_limit" : "La cantidad es más que el máximo",
704 - "show_market_place": "Mostrar mercado"
704 + "show_market_place": "Mostrar mercado",
705 + "prevent_screenshots": "Evitar capturas de pantalla y grabación de pantalla"
706 }
res/values/strings_fr.arb
+2 -1
@@ -701,5 +701,6 @@
701 "sell_monero_com_alert_content": "La vente de Monero n'est pas encore prise en charge",
702 "error_text_input_below_minimum_limit" : "Le montant est inférieur au minimum",
703 "error_text_input_above_maximum_limit" : "Le montant est supérieur au maximum",
704 - "show_market_place" :"Afficher la place de marché"
704 + "show_market_place" :"Afficher la place de marché",
705 + "prevent_screenshots": "Empêcher les captures d'écran et l'enregistrement d'écran"
706 }
res/values/strings_hi.arb
+2 -1
@@ -701,5 +701,6 @@
701 "sell_monero_com_alert_content": "मोनेरो बेचना अभी तक समर्थित नहीं है",
702 "error_text_input_below_minimum_limit" : "राशि न्यूनतम से कम है",
703 "error_text_input_above_maximum_limit" : "राशि अधिकतम से अधिक है",
704 - "show_market_place":"बाज़ार दिखाएँ"
704 + "show_market_place":"बाज़ार दिखाएँ",
705 + "prevent_screenshots": "स्क्रीनशॉट और स्क्रीन रिकॉर्डिंग रोकें"
706 }
res/values/strings_hr.arb
+2 -1
@@ -701,5 +701,6 @@
701 "sell_monero_com_alert_content": "Prodaja Monera još nije podržana",
702 "error_text_input_below_minimum_limit" : "Iznos je manji od minimalnog",
703 "error_text_input_above_maximum_limit" : "Iznos je veći od maskimalnog",
704 - "show_market_place" : "Prikaži tržište"
704 + "show_market_place" : "Prikaži tržište",
705 + "prevent_screenshots": "Spriječite snimke zaslona i snimanje zaslona"
706 }
res/values/strings_id.arb
+2 -1
@@ -682,5 +682,6 @@
682 "sell_monero_com_alert_content": "Menjual Monero belum didukung",
683 "error_text_input_below_minimum_limit" : "Jumlah kurang dari minimal",
684 "error_text_input_above_maximum_limit" : "Jumlah lebih dari maksimal",
685 - "show_market_place": "Tampilkan Pasar"
685 + "show_market_place": "Tampilkan Pasar",
686 + "prevent_screenshots": "Cegah tangkapan layar dan perekaman layar"
687 }
res/values/strings_it.arb
+2 -1
@@ -701,5 +701,6 @@
701 "sell_monero_com_alert_content": "La vendita di Monero non è ancora supportata",
702 "error_text_input_below_minimum_limit" : "L'ammontare è inferiore al minimo",
703 "error_text_input_above_maximum_limit" : "L'ammontare è superiore al massimo",
704 - "show_market_place":"Mostra mercato"
704 + "show_market_place":"Mostra mercato",
705 + "prevent_screenshots": "Impedisci screenshot e registrazione dello schermo"
706 }
res/values/strings_ja.arb
+2 -1
@@ -701,5 +701,6 @@
701 "sell_monero_com_alert_content": "モネロの販売はまだサポートされていません",
702 "error_text_input_below_minimum_limit" : "金額は最小額より少ない",
703 "error_text_input_above_maximum_limit" : "金額は最大値を超えています",
704 - "show_market_place":"マーケットプレイスを表示"
704 + "show_market_place":"マーケットプレイスを表示",
705 + "prevent_screenshots": "スクリーンショットと画面録画を防止する"
706 }
res/values/strings_ko.arb
+2 -1
@@ -701,5 +701,6 @@
701 "sell_monero_com_alert_content": "지원되지 않습니다.",
702 "error_text_input_below_minimum_limit" : "금액이 최소보다 적습니다.",
703 "error_text_input_above_maximum_limit" : "금액이 최대 값보다 많습니다.",
704 - "show_market_place":"마켓플레이스 표시"
704 + "show_market_place":"마켓플레이스 표시",
705 + "prevent_screenshots": "스크린샷 및 화면 녹화 방지"
706 }
res/values/strings_my.arb
+2 -1
@@ -701,5 +701,6 @@
701 "sell_monero_com_alert_content": "Monero ရောင်းချခြင်းကို မပံ့ပိုးရသေးပါ။",
702 "error_text_input_below_minimum_limit" : "ပမာဏသည် အနိမ့်ဆုံးထက်နည်းသည်။",
703 "error_text_input_above_maximum_limit" : "ပမာဏသည် အများဆုံးထက် ပိုများသည်။",
704 - "show_market_place":"စျေးကွက်ကိုပြသပါ။"
704 + "show_market_place":"စျေးကွက်ကိုပြသပါ။",
705 + "prevent_screenshots": "ဖန်သားပြင်ဓာတ်ပုံများနှင့် မျက်နှာပြင်ရိုက်ကူးခြင်းကို တားဆီးပါ။"
706 }
res/values/strings_nl.arb
+2 -1
@@ -701,5 +701,6 @@
701 "sell_monero_com_alert_content": "Het verkopen van Monero wordt nog niet ondersteund",
702 "error_text_input_below_minimum_limit" : "Bedrag is minder dan minimaal",
703 "error_text_input_above_maximum_limit" : "Bedrag is meer dan maximaal",
704 - "show_market_place":"Toon Marktplaats"
704 + "show_market_place":"Toon Marktplaats",
705 + "prevent_screenshots": "Voorkom screenshots en schermopname"
706 }
res/values/strings_pl.arb
+2 -1
@@ -701,5 +701,6 @@
701 "sell_monero_com_alert_content": "Sprzedaż Monero nie jest jeszcze obsługiwana",
702 "error_text_input_below_minimum_limit" : "Kwota jest mniejsza niż minimalna",
703 "error_text_input_above_maximum_limit" : "Kwota jest większa niż maksymalna",
704 - "show_market_place" : "Pokaż rynek"
704 + "show_market_place" : "Pokaż rynek",
705 + "prevent_screenshots": "Zapobiegaj zrzutom ekranu i nagrywaniu ekranu"
706 }
res/values/strings_pt.arb
+2 -1
@@ -700,5 +700,6 @@
700 "sell_monero_com_alert_content": "A venda de Monero ainda não é suportada",
701 "error_text_input_below_minimum_limit" : "O valor é menor que o mínimo",
702 "error_text_input_above_maximum_limit" : "O valor é superior ao máximo",
703 - "show_market_place":"Mostrar mercado"
703 + "show_market_place":"Mostrar mercado",
704 + "prevent_screenshots": "Evite capturas de tela e gravação de tela"
705 }
res/values/strings_ru.arb
+2 -1
@@ -701,5 +701,6 @@
701 "sell_monero_com_alert_content": "Продажа Monero пока не поддерживается",
702 "error_text_input_below_minimum_limit" : "Сумма меньше минимальной",
703 "error_text_input_above_maximum_limit" : "Сумма больше максимальной",
704 - "show_market_place":"Показать торговую площадку"
704 + "show_market_place":"Показать торговую площадку",
705 + "prevent_screenshots": "Предотвратить скриншоты и запись экрана"
706 }
res/values/strings_th.arb
+2 -1
@@ -699,5 +699,6 @@
699 "sell_monero_com_alert_content": "ยังไม่รองรับการขาย Monero",
700 "error_text_input_below_minimum_limit" : "จำนวนเงินน้อยกว่าขั้นต่ำ",
701 "error_text_input_above_maximum_limit" : "จำนวนเงินสูงกว่าค่าสูงสุด",
702 - "show_market_place":"แสดงตลาดกลาง"
702 + "show_market_place":"แสดงตลาดกลาง",
703 + "prevent_screenshots": "ป้องกันภาพหน้าจอและการบันทึกหน้าจอ"
704 }
res/values/strings_tr.arb
+2 -1
@@ -701,5 +701,6 @@
701 "sell_monero_com_alert_content": "Monero satışı henüz desteklenmiyor",
702 "error_text_input_below_minimum_limit" : "Miktar minimumdan daha azdır",
703 "error_text_input_above_maximum_limit" : "Miktar maksimumdan daha fazla",
704 - "show_market_place":"Pazar Yerini Göster"
704 + "show_market_place":"Pazar Yerini Göster",
705 + "prevent_screenshots": "Ekran görüntülerini ve ekran kaydını önleyin"
706 }
res/values/strings_uk.arb
+2 -1
@@ -700,5 +700,6 @@
700 "sell_monero_com_alert_content": "Продаж Monero ще не підтримується",
701 "error_text_input_below_minimum_limit" : "Сума менша мінімальної",
702 "error_text_input_above_maximum_limit" : "Сума більше максимальної",
703 - "show_market_place":"Шоу Ринок"
703 + "show_market_place":"Відображати маркетплейс",
704 + "prevent_screenshots": "Запобігати знімкам екрана та запису екрана"
705 }
res/values/strings_ur.arb
+2 -1
@@ -701,5 +701,6 @@
701 "sell_monero_com_alert_content": "Monero فروخت کرنا ابھی تک تعاون یافتہ نہیں ہے۔",
702 "error_text_input_below_minimum_limit" : "رقم کم از کم سے کم ہے۔",
703 "error_text_input_above_maximum_limit" : "رقم زیادہ سے زیادہ سے زیادہ ہے۔",
704 - "show_market_place":"بازار دکھائیں۔"
704 + "show_market_place":"بازار دکھائیں۔",
705 + "prevent_screenshots": "اسکرین شاٹس اور اسکرین ریکارڈنگ کو روکیں۔"
706 }
res/values/strings_zh.arb
+2 -1
@@ -700,5 +700,6 @@
700 "sell_monero_com_alert_content": "尚不支持出售门罗币",
701 "error_text_input_below_minimum_limit" : "金额小于最小值",
702 "error_text_input_above_maximum_limit" : "金额大于最大值",
703 - "show_market_place" :"显示市场"
703 + "show_market_place" :"显示市场",
704 + "prevent_screenshots": "防止截屏和录屏"
705 }