diff --git a/AGENTS.md b/AGENTS.md index fba2b9e4..e3028b9f 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -60,6 +60,7 @@ See `CLAUDE.md` for the key-files table (verified accurate against the current t - ktlint `android_studio` code style (`.editorconfig`); star imports effectively disabled; trailing commas allowed; `@Composable` functions exempt from the function-naming rule. Run `ktlintFormat` rather than hand-formatting. - Translations live in `app/src/main/res/values-/strings.xml`; `MissingTranslation` lint is intentionally disabled and the shipped locales are pinned by `androidResources.localeFilters` in `app/build.gradle.kts`. +- **Always translate string resources.** Whenever you add or change a string in `app/src/main/res/values/strings.xml`, add the translated entry to **every** existing `app/src/main/res/values-*/strings.xml` locale file in the same change (list them with `ls app/src/main/res | grep '^values-'`, ignoring `values-night`). Do not ship English placeholders in locale files — write the actual translation, matching the existing tone/registers of that file. Escape apostrophes as `\'` in languages that use them (e.g. French, Italian, Turkish), exactly like neighboring entries. - Git hooks (`git-hooks/pre-commit`, `pre-push`) are auto-installed by the root `build.gradle.kts` `installGitHook` task wired into `:app` `preBuild`. Do not rely on them as a substitute for running checks directly. ## Codex Web / cloud setup 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 bd5b6ed1..7aa60c10 100644 --- a/app/src/main/java/com/greenart7c3/nostrsigner/ui/SecurityScreen.kt +++ b/app/src/main/java/com/greenart7c3/nostrsigner/ui/SecurityScreen.kt @@ -8,6 +8,8 @@ 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.foundation.layout.size +import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Surface import androidx.compose.material3.Switch @@ -27,6 +29,7 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import androidx.navigation.NavController import com.greenart7c3.nostrsigner.Amber +import com.greenart7c3.nostrsigner.AmberLog import com.greenart7c3.nostrsigner.LocalPreferences import com.greenart7c3.nostrsigner.R import com.greenart7c3.nostrsigner.ui.components.AmberButton @@ -52,11 +55,31 @@ fun SecurityScreen( val setupPin by remember { mutableStateOf(Amber.instance.settings.usePin) } var privacyMode by remember { mutableStateOf(Amber.instance.settings.privacyMode) } var requireUnlockedDevice by remember { mutableStateOf(Amber.instance.settings.requireUnlockedDevice) } + var requireUnlockedDeviceUpdating by remember { mutableStateOf(false) } var biometricsIndex by remember { mutableIntStateOf(Amber.instance.settings.biometricsTimeType.screenCode) } val scope = rememberCoroutineScope() val context = LocalContext.current + fun toggleRequireUnlockedDevice(enabled: Boolean) { + requireUnlockedDevice = enabled + requireUnlockedDeviceUpdating = true + // Use the application-scoped IOScope, not the + // composition scope: key rotation must complete + // even if the user leaves the screen/app, or + // stored secrets could be left inaccessible. + Amber.instance.applicationIOScope.launch(Dispatchers.IO) { + try { + LocalPreferences.updateRequireUnlockedDevice(context, enabled) + } catch (e: Exception) { + AmberLog.e(Amber.TAG, "Error toggling require unlocked device", e) + } finally { + // Re-sync the toggle with the persisted setting (reverts on failure) + requireUnlockedDevice = Amber.instance.settings.requireUnlockedDevice + requireUnlockedDeviceUpdating = false + } + } + } Surface( modifier.fillMaxSize(), color = MaterialTheme.colorScheme.background, @@ -129,16 +152,8 @@ fun SecurityScreen( modifier = Modifier .fillMaxWidth() .padding(horizontal = 8.dp, vertical = 4.dp) - .clickable { - val newValue = !requireUnlockedDevice - requireUnlockedDevice = newValue - // Use the application-scoped IOScope, not the - // composition scope: key rotation must complete - // even if the user leaves the screen/app, or - // stored secrets could be left inaccessible. - Amber.instance.applicationIOScope.launch(Dispatchers.IO) { - LocalPreferences.updateRequireUnlockedDevice(context, newValue) - } + .clickable(enabled = !requireUnlockedDeviceUpdating) { + toggleRequireUnlockedDevice(!requireUnlockedDevice) }, ) { Column(modifier = Modifier.weight(1f)) { @@ -148,14 +163,32 @@ fun SecurityScreen( style = MaterialTheme.typography.bodySmall, color = Color.Gray, ) + if (requireUnlockedDeviceUpdating) { + Row( + horizontalArrangement = Arrangement.spacedBy(8.dp), + verticalAlignment = Alignment.CenterVertically, + ) { + CircularProgressIndicator( + modifier = Modifier.size(16.dp), + strokeWidth = 2.dp, + ) + Text( + text = stringResource(R.string.require_unlocked_device_updating), + style = MaterialTheme.typography.bodySmall, + ) + } + Text( + text = stringResource(R.string.require_unlocked_device_do_not_close), + style = MaterialTheme.typography.bodySmall, + color = MaterialTheme.colorScheme.error, + ) + } } Switch( checked = requireUnlockedDevice, + enabled = !requireUnlockedDeviceUpdating, onCheckedChange = { enabled -> - requireUnlockedDevice = enabled - Amber.instance.applicationIOScope.launch(Dispatchers.IO) { - LocalPreferences.updateRequireUnlockedDevice(context, enabled) - } + toggleRequireUnlockedDevice(enabled) }, ) } diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 55eed1cf..d9d6a763 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -864,6 +864,8 @@ Nach neuen Versionen suchen Entsperrtes Gerät für den Schlüsselzugriff anfordern Wenn aktiviert, kann der Keystore-Schlüssel zum Entschlüsseln Ihrer gespeicherten Kontoschlüssel nicht verwendet werden, während das Gerät gesperrt ist. Dies verhindert, dass Code, der im Amber-Prozess ausgeführt wird, Ihre Schlüssel entschlüsselt, während der Bildschirm gesperrt ist. Hinweis: Dies deaktiviert die Hintergrund-NIP-46-Signierung, während das Gerät gesperrt ist. Das Umschalten erfordert eine erneute Verschlüsselung aller gespeicherten Schlüssel. + Alle gespeicherten Schlüssel werden neu verschlüsselt… + Schließen Sie die App nicht und sperren Sie den Bildschirm nicht, bis dies abgeschlossen ist. Unsicheres (Klartext, ws://) Relay über das öffentliche Internet legt NIP-46-Metadaten und Chiffretext für Netzwerkbeobachter offen. Bevorzugen Sie wss://, oder verwenden Sie ws:// nur für .onion / lokale Netzwerk-Relays. Verbinde mit Tor: %1$d%% Tor-Verbindung fehlgeschlagen diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index d0ee6651..5354758d 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -867,6 +867,8 @@ Buscar nuevas versiones Requerir dispositivo desbloqueado para acceder a la clave Cuando está habilitado, la clave de Keystore utilizada para descifrar las claves de su cuenta almacenadas no se puede usar mientras el dispositivo está bloqueado. Esto evita que cualquier código que se ejecute en el proceso de Amber descifre sus claves mientras la pantalla está bloqueada. Nota: esto deshabilita la firma NIP-46 en segundo plano mientras el dispositivo está bloqueado. Cambiar esto requiere volver a cifrar todas las claves almacenadas. + Recifrando todas las claves almacenadas… + No cierres la aplicación ni bloquees la pantalla hasta que esto termine. Un relay inseguro (texto plano, ws://) a través de la Internet pública expone los metadatos y el texto cifrado de NIP-46 a los observadores de la red. Prefiera wss://, o use ws:// solo para relays .onion / de red local. Conectando a Tor: %1$d%% Conexión a Tor fallida diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index fe823b9b..1b3853c5 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -864,6 +864,8 @@ Rechercher de nouvelles versions Exiger un appareil déverrouillé pour l\'accès aux clés Une fois activée, la clé Keystore utilisée pour déchiffrer les clés de votre compte stockées ne peut pas être utilisée lorsque l\'appareil est verrouillé. Cela empêche tout code s\'exécutant dans le processus d\'Amber de déchiffrer vos clés lorsque l\'écran est verrouillé. Remarque : cela désactive la signature NIP-46 en arrière-plan lorsque l\'appareil est verrouillé. L\'activation de cette option nécessite le rechiffrement de toutes les clés stockées. + Rechiffrement de toutes les clés stockées… + Ne fermez pas l\'application et ne verrouillez pas l\'écran tant que ce n\'est pas terminé. Un relais non sécurisé (texte clair, ws://) sur l\'Internet public expose les métadonnées et le texte chiffré NIP-46 aux observateurs du réseau. Préférez wss://, ou utilisez ws:// uniquement pour les relais .onion / réseau local. Connexion à Tor : %1$d%% Échec de la connexion à Tor diff --git a/app/src/main/res/values-in/strings.xml b/app/src/main/res/values-in/strings.xml index 85daba02..7ee9f0ce 100644 --- a/app/src/main/res/values-in/strings.xml +++ b/app/src/main/res/values-in/strings.xml @@ -867,6 +867,8 @@ Periksa versi baru Wajibkan perangkat tidak terkunci untuk akses kunci Saat diaktifkan, kunci Keystore yang digunakan untuk mendekripsi kunci akun yang Anda simpan tidak dapat digunakan saat perangkat terkunci. Ini mencegah kode apa pun yang berjalan di proses Amber mendekripsi kunci Anda saat layar terkunci. Catatan: ini menonaktifkan penandatanganan NIP-46 di latar belakang saat perangkat terkunci. Mengalihkan ini memerlukan enkripsi ulang semua kunci yang disimpan. + Mengenkripsi ulang semua kunci yang disimpan… + Jangan menutup aplikasi atau mengunci layar sampai proses ini selesai. Relay yang tidak aman (teks biasa, ws://) melalui internet publik mengekspos metadata dan teks sandi NIP-46 ke pengamat jaringan. Pilih wss://, atau gunakan ws:// hanya untuk relay .onion / jaringan lokal. Menghubungkan ke Tor: %1$d%% Koneksi Tor gagal diff --git a/app/src/main/res/values-it-rIT/strings.xml b/app/src/main/res/values-it-rIT/strings.xml index 7ee564ee..8d7cee8b 100644 --- a/app/src/main/res/values-it-rIT/strings.xml +++ b/app/src/main/res/values-it-rIT/strings.xml @@ -867,6 +867,8 @@ Controlla nuove versioni Richiedi dispositivo sbloccato per l\'accesso alle chiavi Se abilitato, la chiave Keystore utilizzata per decrittografare le chiavi del tuo account memorizzate non può essere utilizzata mentre il dispositivo è bloccato. Ciò impedisce a qualsiasi codice in esecuzione nel processo di Amber di decrittografare le tue chiavi mentre lo schermo è bloccato. Nota: questo disabilita la firma NIP-46 in background mentre il dispositivo è bloccato. L\'attivazione di questa opzione richiede la ri-crittografia di tutte le chiavi memorizzate. + Ri-crittografia di tutte le chiavi memorizzate in corso… + Non chiudere l\'app e non bloccare lo schermo fino al termine dell\'operazione. Un relay non sicuro (testo in chiaro, ws://) su internet pubblico espone i metadati NIP-46 e il testo cifrato agli osservatori di rete. Preferisci wss://, o usa ws:// solo per relay .onion / di rete locale. Connessione a Tor: %1$d%% Connessione a Tor fallita diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index 78af5619..a147925d 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -843,6 +843,8 @@ 新しいバージョンを確認 キーアクセスにデバイスのロック解除を要求する 有効にすると、保存されたアカウントキーを復号化するために使用されるKeystoreキーは、デバイスがロックされている間は使用できなくなります。これにより、画面がロックされている間にAmberのプロセスで実行されているコードがキーを復号化するのを防ぎます。注:これにより、デバイスがロックされている間、バックグラウンドでのNIP-46署名が無効になります。これを切り替えるには、すべての保存されたキーの再暗号化が必要です。 + 保存されたすべてのキーを再暗号化しています… + 処理が完了するまで、アプリを閉じたり画面をロックしたりしないでください。 公開インターネットを介した安全でない(クリアテキスト、ws://)リレーは、NIP-46のメタデータと暗号文をネットワークオブザーバーにさらします。wss://を優先するか、.onion / ローカルネットワークリレーの場合のみws://を使用してください。 Torに接続中: %1$d%% Torへの接続に失敗しました diff --git a/app/src/main/res/values-ko-rKR/strings.xml b/app/src/main/res/values-ko-rKR/strings.xml index 3e0c623c..1e025585 100644 --- a/app/src/main/res/values-ko-rKR/strings.xml +++ b/app/src/main/res/values-ko-rKR/strings.xml @@ -867,6 +867,8 @@ 새 버전 확인 키 액세스를 위해 잠금 해제된 장치 필요 활성화하면 저장된 계정 키를 복호화하는 데 사용되는 Keystore 키를 장치가 잠겨 있는 동안 사용할 수 없습니다. 이는 화면이 잠겨 있는 동안 Amber 프로세스에서 실행되는 코드가 키를 복호화하는 것을 방지합니다. 참고: 장치가 잠겨 있는 동안 백그라운드 NIP-46 서명이 비활성화됩니다. 이를 전환하려면 저장된 모든 키를 다시 암호화해야 합니다. + 저장된 모든 키를 다시 암호화하는 중… + 완료될 때까지 앱을 닫거나 화면을 잠그지 마세요. 공개 인터넷을 통한 안전하지 않은(일반 텍스트, ws://) 릴레이는 NIP-46 메타데이터와 암호문을 네트워크 관찰자에게 노출합니다. wss://를 선호하거나, .onion / 로컬 네트워크 릴레이에 대해서만 ws://를 사용하십시오. Tor 연결 중: %1$d%% Tor 연결 실패 diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index f18b7dfe..fb96c9c0 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -862,6 +862,8 @@ Verificar novas versões Exigir dispositivo desbloqueado para acesso à chave Quando ativado, a chave do Keystore usada para descriptografar as chaves da sua conta armazenada não pode ser usada enquanto o dispositivo estiver bloqueado. Isso evita que qualquer código em execução no processo do Amber descriptografe suas chaves enquanto a tela estiver bloqueada. Observação: isso desativa a assinatura NIP-46 em segundo plano enquanto o dispositivo estiver bloqueado. Alternar isso requer a criptografia de todas as chaves armazenadas. + Recriptografando todas as chaves armazenadas… + Não feche o aplicativo nem bloqueie a tela até que isso seja concluído. Um relay inseguro (texto simples, ws://) pela internet pública expõe metadados e texto cifrado do NIP-46 a observadores de rede. Prefira wss://, ou use ws:// apenas para relays .onion / de rede local. Conectando ao Tor: %1$d%% Falha na conexão ao Tor diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 41927aeb..b04f8c1b 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -867,6 +867,8 @@ Проверить наличие новых версий Требовать разблокировки устройства для доступа к ключам Если этот параметр включен, ключ Keystore, используемый для расшифровки сохраненных ключей вашей учетной записи, нельзя использовать, пока устройство заблокировано. Это предотвращает расшифровку ваших ключей любым кодом, запущенным в процессе Amber, пока экран заблокирован. Примечание: это отключает фоновую подпись NIP-46, пока устройство заблокировано. Переключение этого параметра требует повторного шифрования всех сохраненных ключей. + Повторное шифрование всех сохраненных ключей… + Не закрывайте приложение и не блокируйте экран, пока процесс не завершится. Незащищенное (открытый текст, ws://) реле через общедоступный Интернет раскрывает метаданные NIP-46 и зашифрованный текст сетевым наблюдателям. Предпочитайте wss:// или используйте ws:// только для реле .onion / локальной сети. Подключение к Tor: %1$d%% Ошибка подключения к Tor diff --git a/app/src/main/res/values-th/strings.xml b/app/src/main/res/values-th/strings.xml index da34c7ce..5aed0b13 100644 --- a/app/src/main/res/values-th/strings.xml +++ b/app/src/main/res/values-th/strings.xml @@ -843,6 +843,8 @@ ตรวจหาเวอร์ชันใหม่ ต้องปลดล็อกอุปกรณ์เพื่อเข้าถึงคีย์ เมื่อเปิดใช้งาน คีย์ Keystore ที่ใช้ในการถอดรหัสคีย์บัญชีที่เก็บไว้ของคุณจะไม่สามารถใช้งานได้ในขณะที่อุปกรณ์ถูกล็อก ซึ่งจะช่วยป้องกันไม่ให้โค้ดใดๆ ที่ทำงานในกระบวนการของ Amber ถอดรหัสคีย์ของคุณในขณะที่หน้าจอถูกล็อก หมายเหตุ: การดำเนินการนี้จะปิดใช้งานการลงนาม NIP-46 ในเบื้องหลังในขณะที่อุปกรณ์ถูกล็อก การสลับการตั้งค่านี้ต้องมีการเข้ารหัสคีย์ที่เก็บไว้ทั้งหมดใหม่ + กำลังเข้ารหัสคีย์ที่เก็บไว้ทั้งหมดใหม่… + อย่าปิดแอปหรือล็อกหน้าจอจนกว่าจะเสร็จสิ้น รีเลย์ที่ไม่ปลอดภัย (ข้อความธรรมดา, ws://) ผ่านอินเทอร์เน็ตสาธารณะจะเปิดเผยข้อมูลเมตาและข้อความไซเฟอร์เท็กซ์ของ NIP-46 ต่อผู้สังเกตการณ์เครือข่าย แนะนำให้ใช้ wss:// หรือใช้ ws:// เฉพาะสำหรับรีเลย์ .onion / เครือข่ายท้องถิ่นเท่านั้น กำลังเชื่อมต่อกับ Tor: %1$d%% การเชื่อมต่อ Tor ล้มเหลว diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml index 6ad8e03d..d8956e9c 100644 --- a/app/src/main/res/values-tr/strings.xml +++ b/app/src/main/res/values-tr/strings.xml @@ -863,6 +863,8 @@ Yeni sürümleri kontrol edin Anahtar erişimi için kilit açılmış cihaz gerektir Etkinleştirildiğinde, kayıtlı hesap anahtarlarınızı çözmek için kullanılan Keystore anahtarı cihaz kilitliyken kullanılamaz. Bu, ekran kilitliyken Amber\'ın sürecinde çalışan herhangi bir kodun anahtarlarınızı çözmesini engeller. Not: Bu, cihaz kilitliyken arka planda NIP-46 imzalama işlemini devre dışı bırakır. Bunu değiştirmek, kayıtlı tüm anahtarların yeniden şifrelenmesini gerektirir. + Kayıtlı tüm anahtarlar yeniden şifreleniyor… + Bu işlem bitene kadar uygulamayı kapatmayın veya ekranı kilitlemeyin. Genel internet üzerindeki güvensiz (açık metin, ws://) röle, NIP-46 meta verilerini ve şifreli metni ağ gözlemcilerine ifşa eder. wss:// tercih edin veya ws://\'yi yalnızca .onion / yerel ağ röleleri için kullanın. Tor\'a bağlanılıyor: %1$d%% Tor bağlantısı başarısız oldu diff --git a/app/src/main/res/values-vi-rVN/strings.xml b/app/src/main/res/values-vi-rVN/strings.xml index cd1b6fd5..814e78d1 100644 --- a/app/src/main/res/values-vi-rVN/strings.xml +++ b/app/src/main/res/values-vi-rVN/strings.xml @@ -843,6 +843,8 @@ Kiểm tra phiên bản mới Yêu cầu mở khóa thiết bị để truy cập khóa Khi được bật, khóa Keystore dùng để giải mã các khóa tài khoản đã lưu của bạn không thể sử dụng được khi thiết bị đang khóa. Điều này ngăn bất kỳ mã nào chạy trong quy trình của Amber giải mã khóa của bạn khi màn hình đang khóa. Lưu ý: điều này sẽ vô hiệu hóa việc ký NIP-46 trong nền khi thiết bị đang khóa. Việc bật/tắt tính năng này yêu cầu mã hóa lại tất cả các khóa đã lưu. + Đang mã hóa lại tất cả các khóa đã lưu… + Không đóng ứng dụng hoặc khóa màn hình cho đến khi quá trình này hoàn tất. Relay không an toàn (văn bản thuần túy, ws://) qua internet công cộng sẽ để lộ siêu dữ liệu NIP-46 và văn bản mã hóa cho những người quan sát mạng. Ưu tiên wss:// hoặc chỉ sử dụng ws:// cho các relay .onion / mạng cục bộ. Đang kết nối với Tor: %1$d%% Kết nối Tor thất bại diff --git a/app/src/main/res/values-zh/strings.xml b/app/src/main/res/values-zh/strings.xml index 2fea9f37..c14bd5df 100644 --- a/app/src/main/res/values-zh/strings.xml +++ b/app/src/main/res/values-zh/strings.xml @@ -848,6 +848,8 @@ 检查新版本 访问密钥需要解锁设备 启用后,在设备锁定期间,将无法使用用于解密存储的帐户密钥的密钥库密钥。这可以防止在屏幕锁定期间 Amber 进程中运行的任何代码解密您的密钥。注意:这会在设备锁定期间禁用后台 NIP-46 签名。切换此设置需要重新加密所有存储的密钥。 + 正在重新加密所有存储的密钥… + 在此完成之前,请不要关闭应用或锁定屏幕。 通过公共互联网进行的不安全(明文,ws://)中继会将 NIP-46 元数据和密文暴露给网络观察者。建议优先使用 wss://,或仅对 .onion / 本地网络中继使用 ws://。 正在连接到 Tor: %1$d%% Tor 连接失败 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index bb67e3be..d3753149 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -557,6 +557,8 @@ wss://… Require unlocked device for key access When enabled, the Keystore key used to decrypt your stored account keys cannot be used while the device is locked. This prevents any code running in Amber\'s process from decrypting your keys while the screen is locked. Note: this disables background NIP-46 signing while the device is locked. Toggling this requires re-encrypting all stored keys. + Re-encrypting all stored keys… + Do not close the app or lock the screen until this finishes. Insecure (cleartext, ws://) relay over the public internet exposes NIP-46 metadata and ciphertext to network observers. Prefer wss://, or use ws:// only for .onion / local-network relays. "Name can't be empty " Your nsecbunker is ready!