From 6cd56beada52dcc3009ca8b36b6a30b6340182ef Mon Sep 17 00:00:00 2001 From: John Trujillo Date: Mon, 20 Jul 2026 16:10:04 -0500 Subject: [PATCH 1/2] fix(ai-assistant): resolve file picker crashes and secure API key - Fix file picker empty state and `BadTokenException` by using the correct project context (`IdeProjectService`) and moving I/O off the main thread. - Secure Gemini API key with hardware-backed Keystore encryption (including legacy migration) and add a show/hide toggle. - Improve UI by replacing emoji markers with vector drawables and extracting hardcoded strings to `strings.xml`. --- .../fragments/AiSettingsFragment.kt | 65 ++++- .../aiassistant/fragments/ChatFragment.kt | 13 +- .../fragments/FilePickerDialogFragment.kt | 267 ++++++++++++------ .../aiassistant/security/SecureApiKeyStore.kt | 114 ++++++++ .../viewmodel/AiSettingsViewModel.kt | 27 +- .../src/main/res/drawable/ic_check.xml | 10 + .../src/main/res/drawable/ic_file.xml | 10 + .../src/main/res/drawable/ic_folder.xml | 10 + .../src/main/res/drawable/ic_visibility.xml | 10 + .../main/res/drawable/ic_visibility_off.xml | 10 + .../src/main/res/layout/item_file_picker.xml | 34 +++ .../res/layout/layout_settings_gemini_api.xml | 30 +- ai-assistant/src/main/res/values/strings.xml | 16 ++ .../plugins/aicore/GeminiBackend.kt | 5 +- .../plugins/aicore/SecureApiKeyStore.kt | 114 ++++++++ 15 files changed, 615 insertions(+), 120 deletions(-) create mode 100644 ai-assistant/src/main/kotlin/com/itsaky/androidide/plugins/aiassistant/security/SecureApiKeyStore.kt create mode 100644 ai-assistant/src/main/res/drawable/ic_check.xml create mode 100644 ai-assistant/src/main/res/drawable/ic_file.xml create mode 100644 ai-assistant/src/main/res/drawable/ic_folder.xml create mode 100644 ai-assistant/src/main/res/drawable/ic_visibility.xml create mode 100644 ai-assistant/src/main/res/drawable/ic_visibility_off.xml create mode 100644 ai-assistant/src/main/res/layout/item_file_picker.xml create mode 100644 ai-core/src/main/kotlin/com/itsaky/androidide/plugins/aicore/SecureApiKeyStore.kt diff --git a/ai-assistant/src/main/kotlin/com/itsaky/androidide/plugins/aiassistant/fragments/AiSettingsFragment.kt b/ai-assistant/src/main/kotlin/com/itsaky/androidide/plugins/aiassistant/fragments/AiSettingsFragment.kt index 83c285c1..8c0686a4 100644 --- a/ai-assistant/src/main/kotlin/com/itsaky/androidide/plugins/aiassistant/fragments/AiSettingsFragment.kt +++ b/ai-assistant/src/main/kotlin/com/itsaky/androidide/plugins/aiassistant/fragments/AiSettingsFragment.kt @@ -5,6 +5,8 @@ import android.content.Context import android.content.Intent import android.net.Uri import android.os.Bundle +import android.text.method.HideReturnsTransformationMethod +import android.text.method.PasswordTransformationMethod import android.view.LayoutInflater import android.view.View import android.view.ViewGroup @@ -290,6 +292,7 @@ class AiSettingsFragment : DialogFragment() { private fun setupGeminiApiUi(view: View) { val apiKeyLayout = view.findViewById(R.id.gemini_api_key_layout) val apiKeyInput = view.findViewById(R.id.gemini_api_key_input) + val toggleVisibilityButton = view.findViewById(R.id.btn_toggle_api_key_visibility) val saveButton = view.findViewById