diff --git a/app/src/main/java/com/greenart7c3/nostrsigner/LocalPreferences.kt b/app/src/main/java/com/greenart7c3/nostrsigner/LocalPreferences.kt index 533dbe4b..466c7eee 100644 --- a/app/src/main/java/com/greenart7c3/nostrsigner/LocalPreferences.kt +++ b/app/src/main/java/com/greenart7c3/nostrsigner/LocalPreferences.kt @@ -67,6 +67,7 @@ private enum class SettingsKeys(val key: String) { UPDATE_CHANNEL("update_channel"), LAST_UPDATE_CHECK_TIME("last_update_check_time"), START_SERVICE_ON_BOOT("start_service_on_boot"), + PRIVACY_MODE("privacy_mode"), WEBDAV_URL("webdav_url"), WEBDAV_USERNAME("webdav_username"), WEBDAV_PASSWORD_ENCRYPTED("webdav_password_encrypted"), @@ -151,6 +152,7 @@ object LocalPreferences { putString(SettingsKeys.LANGUAGE_PREFS.key, settings.language) putStringSet(SettingsKeys.AUTH_WHITELIST.key, settings.authWhitelist.toSet()) putBoolean(SettingsKeys.START_SERVICE_ON_BOOT.key, settings.startServiceOnBoot) + putBoolean(SettingsKeys.PRIVACY_MODE.key, settings.privacyMode) putBoolean(SettingsKeys.RATE_LIMIT_ENABLED.key, settings.rateLimitEnabled) putInt(SettingsKeys.RATE_LIMIT_MAX_PER_WINDOW.key, settings.rateLimitMaxPerWindow) putInt(SettingsKeys.RATE_LIMIT_WINDOW_SECONDS.key, settings.rateLimitWindowSeconds) @@ -306,6 +308,7 @@ object LocalPreferences { UpdateChannel.STABLE }, startServiceOnBoot = getBoolean(SettingsKeys.START_SERVICE_ON_BOOT.key, true), + privacyMode = getBoolean(SettingsKeys.PRIVACY_MODE.key, false), rateLimitEnabled = getBoolean(SettingsKeys.RATE_LIMIT_ENABLED.key, true), rateLimitMaxPerWindow = getInt(SettingsKeys.RATE_LIMIT_MAX_PER_WINDOW.key, 5), rateLimitWindowSeconds = getInt(SettingsKeys.RATE_LIMIT_WINDOW_SECONDS.key, 30), @@ -584,6 +587,30 @@ object LocalPreferences { Amber.instance.settings = loadSettingsFromEncryptedStorage() } + /** + * Toggles privacy mode. When enabled, immediately wipes all existing logs and + * activity history for every account so no previously collected data survives. + * Future writes are blocked at the DAO layer while this setting stays on. + */ + suspend fun updatePrivacyMode(context: Context, enabled: Boolean) { + sharedPrefs(context).edit { + apply { + putBoolean(SettingsKeys.PRIVACY_MODE.key, enabled) + } + } + Amber.instance.settings = loadSettingsFromEncryptedStorage() + if (enabled) { + allSavedAccounts(context).forEach { + try { + Amber.instance.getLogDatabase(it.npub).dao().clearLogs() + Amber.instance.getHistoryDatabase(it.npub).dao().clearHistory() + } catch (e: Exception) { + AmberLog.e(Amber.TAG, "Error wiping data for privacy mode", e) + } + } + } + } + fun updateUpdateCheckFrequency(context: Context, frequency: UpdateCheckFrequency) { sharedPrefs(context).edit { apply { diff --git a/app/src/main/java/com/greenart7c3/nostrsigner/SignerProviderQuery.kt b/app/src/main/java/com/greenart7c3/nostrsigner/SignerProviderQuery.kt index 377d4ae9..1d466dfa 100644 --- a/app/src/main/java/com/greenart7c3/nostrsigner/SignerProviderQuery.kt +++ b/app/src/main/java/com/greenart7c3/nostrsigner/SignerProviderQuery.kt @@ -303,7 +303,7 @@ object SignerProviderQuery { } } catch (e: Exception) { scope.launch { - logDatabase.dao().insertLog( + logDatabase.dao().insertLogIfEnabled( LogEntity( 0, requesterId, @@ -407,7 +407,7 @@ object SignerProviderQuery { } } catch (e: Exception) { scope.launch { - logDatabase.dao().insertLog( + logDatabase.dao().insertLogIfEnabled( LogEntity( 0, requesterId, @@ -507,7 +507,7 @@ object SignerProviderQuery { AmberLog.d(Amber.TAG, "Failed to sign psbt", e) scope.launch { val logDb = Amber.instance.getLogDatabase(account.npub) - logDb.dao().insertLog( + logDb.dao().insertLogIfEnabled( LogEntity( 0, requesterId, @@ -624,7 +624,7 @@ object SignerProviderQuery { scope.launch { LocalPreferences.allSavedAccounts(context).forEach { accInfo -> val database = Amber.instance.getLogDatabase(accInfo.npub) - database.dao().insertLog( + database.dao().insertLogIfEnabled( LogEntity( 0, requesterId, diff --git a/app/src/main/java/com/greenart7c3/nostrsigner/database/HistoryDao.kt b/app/src/main/java/com/greenart7c3/nostrsigner/database/HistoryDao.kt index d5239929..c4146df5 100644 --- a/app/src/main/java/com/greenart7c3/nostrsigner/database/HistoryDao.kt +++ b/app/src/main/java/com/greenart7c3/nostrsigner/database/HistoryDao.kt @@ -97,6 +97,10 @@ interface HistoryDao { @Transaction suspend fun deleteOldHistory(time: Long): Int + @Query("DELETE FROM history") + @Transaction + suspend fun clearHistory() + @Delete @Transaction suspend fun deleteHistory(historyEntity: HistoryEntity) @@ -108,6 +112,7 @@ interface HistoryDao { @Insert(onConflict = OnConflictStrategy.IGNORE) @Transaction suspend fun addHistory(entities: List, npub: String?) { + if (Amber.instance.settings.privacyMode) return try { val localEntities = entities.map { entity -> val permission = Permission(entity.type.toLowerCase(Locale.current), entity.kind) diff --git a/app/src/main/java/com/greenart7c3/nostrsigner/database/LogDao.kt b/app/src/main/java/com/greenart7c3/nostrsigner/database/LogDao.kt index aae1ae33..8fbc4354 100644 --- a/app/src/main/java/com/greenart7c3/nostrsigner/database/LogDao.kt +++ b/app/src/main/java/com/greenart7c3/nostrsigner/database/LogDao.kt @@ -6,6 +6,7 @@ import androidx.room.Delete import androidx.room.Insert import androidx.room.Query import androidx.room.Transaction +import com.greenart7c3.nostrsigner.Amber import kotlinx.coroutines.flow.Flow @Dao @@ -17,6 +18,17 @@ interface LogDao { @Transaction suspend fun insertLog(logEntity: LogEntity) + /** + * Inserts a log entry unless privacy mode is on, in which case the write is + * dropped. All call sites that record non-essential relay/bunker/request + * logs should use this instead of [insertLog]. + */ + @Transaction + suspend fun insertLogIfEnabled(logEntity: LogEntity) { + if (Amber.instance.settings.privacyMode) return + insertLog(logEntity) + } + @Query("SELECT * FROM amber_log ORDER BY time DESC") fun getLogs(): Flow> diff --git a/app/src/main/java/com/greenart7c3/nostrsigner/models/AmberSettings.kt b/app/src/main/java/com/greenart7c3/nostrsigner/models/AmberSettings.kt index 2f5bb2a3..8114f7a9 100644 --- a/app/src/main/java/com/greenart7c3/nostrsigner/models/AmberSettings.kt +++ b/app/src/main/java/com/greenart7c3/nostrsigner/models/AmberSettings.kt @@ -34,6 +34,7 @@ data class AmberSettings( val updateCheckFrequency: UpdateCheckFrequency = UpdateCheckFrequency.DAILY, val updateChannel: UpdateChannel = UpdateChannel.STABLE, val startServiceOnBoot: Boolean = true, + val privacyMode: Boolean = false, val rateLimitEnabled: Boolean = true, val rateLimitMaxPerWindow: Int = 5, val rateLimitWindowSeconds: Int = 30, diff --git a/app/src/main/java/com/greenart7c3/nostrsigner/relays/NostrClientLoggerListener.kt b/app/src/main/java/com/greenart7c3/nostrsigner/relays/NostrClientLoggerListener.kt index 7f54f8c1..646f14d4 100644 --- a/app/src/main/java/com/greenart7c3/nostrsigner/relays/NostrClientLoggerListener.kt +++ b/app/src/main/java/com/greenart7c3/nostrsigner/relays/NostrClientLoggerListener.kt @@ -94,7 +94,7 @@ class NostrClientLoggerListener( scope.launch { val account = LocalPreferences.currentAccount(context) if (account != null) { - Amber.instance.getLogDatabase(account).dao().insertLog( + Amber.instance.getLogDatabase(account).dao().insertLogIfEnabled( LogEntity( id = 0, url = url, @@ -105,7 +105,7 @@ class NostrClientLoggerListener( ) } else { LocalPreferences.allSavedAccounts(context).forEach { - Amber.instance.getLogDatabase(it.npub).dao().insertLog( + Amber.instance.getLogDatabase(it.npub).dao().insertLogIfEnabled( LogEntity( id = 0, url = url, diff --git a/app/src/main/java/com/greenart7c3/nostrsigner/service/BunkerRequestUtils.kt b/app/src/main/java/com/greenart7c3/nostrsigner/service/BunkerRequestUtils.kt index b329f01e..d1f5e862 100644 --- a/app/src/main/java/com/greenart7c3/nostrsigner/service/BunkerRequestUtils.kt +++ b/app/src/main/java/com/greenart7c3/nostrsigner/service/BunkerRequestUtils.kt @@ -82,7 +82,7 @@ object BunkerRequestUtils { if (relays.isEmpty()) { onDone(true) onLoading(false) - Amber.instance.getLogDatabase(account.npub).dao().insertLog( + Amber.instance.getLogDatabase(account.npub).dao().insertLogIfEnabled( LogEntity( id = 0, url = bunkerRequest.localKey, @@ -109,7 +109,7 @@ object BunkerRequestUtils { // plaintext. Record only non-sensitive metadata (id + error status). val sanitizedResponse = "id=${bunkerResponse.id} ${bunkerResponse.error?.let { "error=$it" } ?: "ok"}" relays.forEach { relay -> - Amber.instance.getLogDatabase(account.npub).dao().insertLog( + Amber.instance.getLogDatabase(account.npub).dao().insertLogIfEnabled( LogEntity( id = 0, url = relay.url, diff --git a/app/src/main/java/com/greenart7c3/nostrsigner/service/ClearLogsWorker.kt b/app/src/main/java/com/greenart7c3/nostrsigner/service/ClearLogsWorker.kt index aa3215a8..95815cbd 100644 --- a/app/src/main/java/com/greenart7c3/nostrsigner/service/ClearLogsWorker.kt +++ b/app/src/main/java/com/greenart7c3/nostrsigner/service/ClearLogsWorker.kt @@ -51,7 +51,7 @@ class ClearLogsWorker(appContext: Context, workerParams: WorkerParameters) : Cor dao.updateExpiredPermissions(TimeUtils.now()) val deleted = dao.deleteOldApplications(now / 1000) if (deleted > 0) { - logDao.insertLog( + logDao.insertLogIfEnabled( LogEntity( id = 0, url = "", diff --git a/app/src/main/java/com/greenart7c3/nostrsigner/service/EventNotificationConsumer.kt b/app/src/main/java/com/greenart7c3/nostrsigner/service/EventNotificationConsumer.kt index e0f02029..9b428036 100644 --- a/app/src/main/java/com/greenart7c3/nostrsigner/service/EventNotificationConsumer.kt +++ b/app/src/main/java/com/greenart7c3/nostrsigner/service/EventNotificationConsumer.kt @@ -80,7 +80,7 @@ class EventNotificationConsumer(private val applicationContext: Context) { Amber.instance.applicationIOScope.launch { if (npub != null) { val dao = Amber.instance.getLogDatabase(npub).dao() - dao.insertLog( + dao.insertLogIfEnabled( LogEntity( 0, url, @@ -94,7 +94,7 @@ class EventNotificationConsumer(private val applicationContext: Context) { accounts.forEach { LocalPreferences.loadFromEncryptedStorage(applicationContext, it.npub)?.let { acc -> val dao = Amber.instance.getLogDatabase(acc.npub).dao() - dao.insertLog( + dao.insertLogIfEnabled( LogEntity( 0, url, diff --git a/app/src/main/java/com/greenart7c3/nostrsigner/service/IntentUtils.kt b/app/src/main/java/com/greenart7c3/nostrsigner/service/IntentUtils.kt index be435be1..a6681c3f 100644 --- a/app/src/main/java/com/greenart7c3/nostrsigner/service/IntentUtils.kt +++ b/app/src/main/java/com/greenart7c3/nostrsigner/service/IntentUtils.kt @@ -313,7 +313,7 @@ object IntentUtils { } Amber.instance.applicationIOScope.launch { val database = Amber.instance.getLogDatabase(account.npub) - database.dao().insertLog( + database.dao().insertLogIfEnabled( LogEntity( 0, packageName ?: "", @@ -498,7 +498,7 @@ object IntentUtils { } Amber.instance.applicationIOScope.launch { val database = Amber.instance.getLogDatabase(account.npub) - database.dao().insertLog( + database.dao().insertLogIfEnabled( LogEntity( 0, packageName ?: "", @@ -758,7 +758,7 @@ object IntentUtils { emitInvalid(intent, packageName, "Error parsing intent: ${e.message}", e) Amber.instance.applicationIOScope.launch { LocalPreferences.allSavedAccounts(Amber.instance).forEach { - Amber.instance.getLogDatabase(it.npub).dao().insertLog( + Amber.instance.getLogDatabase(it.npub).dao().insertLogIfEnabled( LogEntity( id = 0, url = "IntentUtils", diff --git a/app/src/main/java/com/greenart7c3/nostrsigner/service/NostrConnectUtils.kt b/app/src/main/java/com/greenart7c3/nostrsigner/service/NostrConnectUtils.kt index 5019433b..f488af34 100644 --- a/app/src/main/java/com/greenart7c3/nostrsigner/service/NostrConnectUtils.kt +++ b/app/src/main/java/com/greenart7c3/nostrsigner/service/NostrConnectUtils.kt @@ -159,7 +159,7 @@ object NostrConnectUtils { } catch (e: Exception) { AmberLog.e(Amber.TAG, e.message, e) Amber.instance.applicationIOScope.launch { - Amber.instance.getLogDatabase(account.npub).dao().insertLog( + Amber.instance.getLogDatabase(account.npub).dao().insertLogIfEnabled( LogEntity( 0, "nostrconnect", diff --git a/app/src/main/java/com/greenart7c3/nostrsigner/ui/SecurityScreen.kt b/app/src/main/java/com/greenart7c3/nostrsigner/ui/SecurityScreen.kt index d1426fc7..b135a125 100644 --- a/app/src/main/java/com/greenart7c3/nostrsigner/ui/SecurityScreen.kt +++ b/app/src/main/java/com/greenart7c3/nostrsigner/ui/SecurityScreen.kt @@ -6,6 +6,7 @@ import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Surface @@ -20,6 +21,8 @@ import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import androidx.navigation.NavController @@ -47,10 +50,12 @@ fun SecurityScreen( ) var enableBiometrics by remember { mutableStateOf(Amber.instance.settings.useAuth) } val setupPin by remember { mutableStateOf(Amber.instance.settings.usePin) } + var privacyMode by remember { mutableStateOf(Amber.instance.settings.privacyMode) } var biometricsIndex by remember { mutableIntStateOf(Amber.instance.settings.biometricsTimeType.screenCode) } val scope = rememberCoroutineScope() + val context = LocalContext.current Surface( modifier.fillMaxSize(), color = MaterialTheme.colorScheme.background, @@ -83,6 +88,39 @@ fun SecurityScreen( ) } + Row( + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically, + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 8.dp, vertical = 4.dp) + .clickable { + val newValue = !privacyMode + privacyMode = newValue + scope.launch(Dispatchers.IO) { + LocalPreferences.updatePrivacyMode(context, newValue) + } + }, + ) { + Column(modifier = Modifier.weight(1f)) { + Text(text = stringResource(R.string.privacy_mode)) + Text( + text = stringResource(R.string.privacy_mode_description), + style = MaterialTheme.typography.bodySmall, + color = Color.Gray, + ) + } + Switch( + checked = privacyMode, + onCheckedChange = { enabled -> + privacyMode = enabled + scope.launch(Dispatchers.IO) { + LocalPreferences.updatePrivacyMode(context, enabled) + } + }, + ) + } + Row( horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.CenterVertically, diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 0e7e078c..8388ae4e 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -221,6 +221,8 @@ Authentifizierung benötigt, um die App zu nutzen Sicherheit Biometrische Daten aktivieren + Datenschutzmodus + Deaktiviert die Protokollierung und Aktivitätsstatistiken. Beim Einschalten werden vorhandene Protokolle und Aktivitätsverläufe gelöscht. Wer soll gefragt werden Jedes Mal Eine Minute diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 072986df..a9340493 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -224,6 +224,8 @@ Autenticación necesaria para usar la aplicación Seguridad Activar biometría + Modo de privacidad + Desactiva el registro de logs y las estadísticas de actividad. Los logs y el historial de actividad existentes se eliminan al activarse. Cuándo pedir Siempre Un minuto diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index f67e6a49..850fa577 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -221,6 +221,8 @@ Authentification nécessaire pour utiliser l\'application Sécurité Activer la biométrie + Mode de confidentialité + Désactive la journalisation et les statistiques d\'activité. Les journaux et l\'historique d\'activité existants sont supprimés lors de l\'activation. Quand demander À chaque fois Une minute diff --git a/app/src/main/res/values-in/strings.xml b/app/src/main/res/values-in/strings.xml index 5515404e..7af0738f 100644 --- a/app/src/main/res/values-in/strings.xml +++ b/app/src/main/res/values-in/strings.xml @@ -224,6 +224,8 @@ Autentikasi diperlukan untuk menggunakan aplikasi Keamanan Aktifkan biometrik + Mode privasi + Menonaktifkan pencatatan log dan statistik aktivitas. Log dan riwayat aktivitas yang ada dihapus saat diaktifkan. Kapan bertanya Setiap kali Satu menit diff --git a/app/src/main/res/values-it-rIT/strings.xml b/app/src/main/res/values-it-rIT/strings.xml index 292aade3..f7f20024 100644 --- a/app/src/main/res/values-it-rIT/strings.xml +++ b/app/src/main/res/values-it-rIT/strings.xml @@ -224,6 +224,8 @@ Autenticazione necessaria per usare l\'app Sicurezza Abilita biometria + Modalità privacy + Disattiva la registrazione dei log e le statistiche di attività. I log e la cronologia delle attività esistenti vengono eliminati quando viene attivata. Quando chiedere Ogni volta Un minuto diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index 850012f8..424ee267 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -200,6 +200,8 @@ アプリを使用するには認証が必要です セキュリティ 生体認証を有効にする + プライバシーモード + ログ記録とアクティビティ統計を無効にします。オンにすると既存のログとアクティビティ履歴が削除されます。 確認のタイミング 毎回 1 分 diff --git a/app/src/main/res/values-ko-rKR/strings.xml b/app/src/main/res/values-ko-rKR/strings.xml index 523047e6..7acebc84 100644 --- a/app/src/main/res/values-ko-rKR/strings.xml +++ b/app/src/main/res/values-ko-rKR/strings.xml @@ -224,6 +224,8 @@ 앱을 사용하려면 인증이 필요합니다 보안 생체 인식 활성화 + 개인정보 보호 모드 + 로깅 및 활동 통계를 비활성화합니다. 켜면 기존 로그 및 활동 기록이 삭제됩니다. 인증 요청 시점 매번 1분 diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index 8e79ba7d..ec212e4c 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -219,6 +219,8 @@ Autenticação necessária para usar o aplicativo Segurança Habilitar biometria + Modo de privacidade + Desativa o registro de logs e estatísticas de atividade. Os logs e o histórico de atividade existentes são excluídos quando ativado. Quando perguntar Sempre Um minuto diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index dc9baf98..fda42fa0 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -224,6 +224,8 @@ Требуется аутентификация для использования приложения Безопасность Включить биометрию + Конфиденциальный режим + Отключает ведение журнала и статистику активности. При включении существующие журналы и история активности удаляются. Когда спрашивать Каждый раз Одна минута diff --git a/app/src/main/res/values-th/strings.xml b/app/src/main/res/values-th/strings.xml index bd8bf8d5..51fa8815 100644 --- a/app/src/main/res/values-th/strings.xml +++ b/app/src/main/res/values-th/strings.xml @@ -200,6 +200,8 @@ ต้องการการยืนยันตัวตนเพื่อใช้แอป ความปลอดภัย เปิดใช้งานไบโอเมตริก + โหมดความเป็นส่วนตัว + ปิดการบันทึกและสถิติการใช้งาน บันทึกและประวัติการใช้งานที่มีอยู่จะถูกลบเมื่อเปิดใช้งาน เมื่อใดที่จะถาม ทุกครั้ง หนึ่งนาที diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml index b7f05531..21452b58 100644 --- a/app/src/main/res/values-tr/strings.xml +++ b/app/src/main/res/values-tr/strings.xml @@ -220,6 +220,8 @@ Uygulamayı kullanmak için kimlik doğrulama gerekli Güvenlik Biyometrik doğrulamayı etkinleştir + Gizlilik modu + Günlük kaydını ve etkinlik istatistiklerini devre dışı bırakır. Açıldığında mevcut günlükler ve etkinlik geçmişi silinir. Ne zaman sorulsun Her zaman Bir dakika diff --git a/app/src/main/res/values-vi-rVN/strings.xml b/app/src/main/res/values-vi-rVN/strings.xml index 287ef45a..f0be7b44 100644 --- a/app/src/main/res/values-vi-rVN/strings.xml +++ b/app/src/main/res/values-vi-rVN/strings.xml @@ -200,6 +200,8 @@ Cần xác thực để sử dụng ứng dụng Bảo mật Bật sinh trắc học + Chế độ riêng tư + Tắt ghi nhật ký và thống kê hoạt động. Nhật ký và lịch sử hoạt động hiện có sẽ bị xóa khi bật. Khi nào hỏi Mỗi lần Một phút diff --git a/app/src/main/res/values-zh/strings.xml b/app/src/main/res/values-zh/strings.xml index 8e443476..3d18f3ec 100644 --- a/app/src/main/res/values-zh/strings.xml +++ b/app/src/main/res/values-zh/strings.xml @@ -205,6 +205,8 @@ 使用应用需要身份验证 安全性 启用生物识别解锁 + 隐私模式 + 禁用日志和活动统计。开启时将删除现有日志和活动历史。 解锁请求 每次 一分钟 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index c3c1883c..58676376 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -248,6 +248,8 @@ Authentication needed to use the app Security Enable biometrics + Privacy mode + Disables logging and activity statistics. Existing logs and activity history are deleted when turned on. When to ask Every time One minute