diff --git a/.gitignore b/.gitignore index 8e8f30452..d0a35f04a 100644 --- a/.gitignore +++ b/.gitignore @@ -108,3 +108,5 @@ scripts/ # local.properties build.log .androidide +BUILD_GUIDE.md +.github/workflows/ diff --git a/composite-builds/build-deps-common/settings.gradle.kts b/composite-builds/build-deps-common/settings.gradle.kts index 1439f7d66..05d3b0281 100644 --- a/composite-builds/build-deps-common/settings.gradle.kts +++ b/composite-builds/build-deps-common/settings.gradle.kts @@ -21,13 +21,13 @@ enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS") pluginManagement { repositories { - maven { url = uri("https://maven.aliyun.com/repository/gradle-plugin") } - maven { url = uri("https://maven.aliyun.com/repository/central") } - maven { url = uri("https://maven.aliyun.com/repository/google") } - gradlePluginPortal() google() mavenCentral() + maven { url = uri("https://maven.aliyun.com/repository/gradle-plugin") } + maven { url = uri("https://maven.aliyun.com/repository/central") } + maven { url = uri("https://maven.aliyun.com/repository/google") } + maven { url = uri("https://maven.aliyun.com/repository/public") } } } @@ -35,6 +35,7 @@ dependencyResolutionManagement { repositories { maven { url = uri("https://maven.aliyun.com/repository/central") } maven { url = uri("https://maven.aliyun.com/repository/google") } + maven { url = uri("https://maven.aliyun.com/repository/public") } google() mavenCentral() diff --git a/composite-builds/build-deps/settings.gradle.kts b/composite-builds/build-deps/settings.gradle.kts index 23b082a9a..94febef46 100644 --- a/composite-builds/build-deps/settings.gradle.kts +++ b/composite-builds/build-deps/settings.gradle.kts @@ -23,20 +23,21 @@ pluginManagement { includeBuild("../build-logic") repositories { - // maven { url = uri("https://maven.aliyun.com/repository/gradle-plugin") } - // maven { url = uri("https://maven.aliyun.com/repository/central") } - // maven { url = uri("https://maven.aliyun.com/repository/google") } - gradlePluginPortal() google() mavenCentral() + maven { url = uri("https://maven.aliyun.com/repository/gradle-plugin") } + maven { url = uri("https://maven.aliyun.com/repository/central") } + maven { url = uri("https://maven.aliyun.com/repository/google") } + maven { url = uri("https://maven.aliyun.com/repository/public") } } } dependencyResolutionManagement { repositories { - // maven { url = uri("https://maven.aliyun.com/repository/central") } - // maven { url = uri("https://maven.aliyun.com/repository/google") } + maven { url = uri("https://maven.aliyun.com/repository/central") } + maven { url = uri("https://maven.aliyun.com/repository/google") } + maven { url = uri("https://maven.aliyun.com/repository/public") } google() mavenCentral() } diff --git a/composite-builds/build-logic/plugins/src/main/java/com/tom/rv2ide/plugins/conf/AndroidModuleConf.kt b/composite-builds/build-logic/plugins/src/main/java/com/tom/rv2ide/plugins/conf/AndroidModuleConf.kt index 859087322..36ec70e56 100644 --- a/composite-builds/build-logic/plugins/src/main/java/com/tom/rv2ide/plugins/conf/AndroidModuleConf.kt +++ b/composite-builds/build-logic/plugins/src/main/java/com/tom/rv2ide/plugins/conf/AndroidModuleConf.kt @@ -39,7 +39,7 @@ import org.gradle.api.provider.Provider * For example, if the base version code of the IDE is 270 (for v2.7.0), then for arm64-v8a flavor, * the version code will be `100 * 270 + 1` i.e. `27001` */ -internal val flavorsAbis = mapOf("arm64-v8a" to 0, "armeabi-v7a" to 0) +internal val flavorsAbis = mapOf("arm64-v8a" to 0, "armeabi-v7a" to 1) fun Project.configureAndroidModule(coreLibDesugDep: Provider) { val isAppModule = plugins.hasPlugin("com.android.application") @@ -121,7 +121,7 @@ fun Project.configureAndroidModule(coreLibDesugDep: Provider "arm64-v8a" - variantName.contains("armeabi") || variantName.contains("arm7") -> "armeabi-v7a" - else -> { - // This should not happen with our configuration - throw IllegalStateException( - "Could not determine ABI for variant: $variantName. Expected arm64-v8a or armeabi-v7a." - ) - } - } - } - - if (archSuffix !in listOf("arm64-v8a", "armeabi-v7a")) { - throw IllegalStateException( - "Unsupported architecture: $archSuffix. Only arm64-v8a and armeabi-v7a are supported." - ) - } + ?: "universal" val appName = "android-code-studio" val fileName = diff --git a/core/app/src/main/baseline-prof.txt b/core/app/src/main/baseline-prof.txt new file mode 100644 index 000000000..e69de29bb diff --git a/core/app/src/main/java/com/tom/rv2ide/actions/editor/ExtractAction.kt b/core/app/src/main/java/com/tom/rv2ide/actions/editor/ExtractAction.kt index 958f74228..71a8e20ad 100644 --- a/core/app/src/main/java/com/tom/rv2ide/actions/editor/ExtractAction.kt +++ b/core/app/src/main/java/com/tom/rv2ide/actions/editor/ExtractAction.kt @@ -209,13 +209,13 @@ class ExtractAction(private val context: Context, override val order: Int) : Bas val moduleNames = modules.map { it.name }.toTypedArray() MaterialAlertDialogBuilder(context) - .setTitle("Select Module") + .setTitle(context.getString(R.string.atc_select_module)) .setItems(moduleNames) { dialog, which -> val selectedModule = modules[which] onModuleSelected(selectedModule) dialog.dismiss() } - .setNegativeButton("Cancel") { dialog, _ -> dialog.dismiss() } + .setNegativeButton(context.getString(R.string.action_cancel)) { dialog, _ -> dialog.dismiss() } .show() } } diff --git a/core/app/src/main/java/com/tom/rv2ide/actions/etc/TextActionMenuAction.kt b/core/app/src/main/java/com/tom/rv2ide/actions/etc/TextActionMenuAction.kt index 28ad87e30..da48b7f6f 100644 --- a/core/app/src/main/java/com/tom/rv2ide/actions/etc/TextActionMenuAction.kt +++ b/core/app/src/main/java/com/tom/rv2ide/actions/etc/TextActionMenuAction.kt @@ -25,7 +25,8 @@ import com.tom.rv2ide.actions.ActionData import com.tom.rv2ide.actions.ActionItem import com.tom.rv2ide.actions.ActionMenu import com.tom.rv2ide.actions.EditorActivityAction -import com.tom.rv2ide.R +import com.tom.rv2ide.R +import com.tom.rv2ide.resources.R as ResR import com.tom.rv2ide.utils.TextTransformers import io.github.rosemoe.sora.widget.CodeEditor import org.slf4j.LoggerFactory @@ -102,7 +103,7 @@ class ConvertToUppercaseAction(context: Context, override val order: Int) : Edit } init { - label = "Convert to uppercase" + label = context.getString(ResR.string.action_convert_to_uppercase) icon = ContextCompat.getDrawable(context, R.drawable.ic_uppercase) } @@ -128,7 +129,7 @@ class ConvertToLowercaseAction(context: Context, override val order: Int) : Edit override var requiresUIThread = true init { - label = "Convert to lowercase" + label = context.getString(ResR.string.action_convert_to_lowercase) icon = ContextCompat.getDrawable(context, R.drawable.ic_lowercase) } @@ -147,7 +148,7 @@ class DeleteLineAction(context: Context, override val order: Int) : EditorActivi override var requiresUIThread = true init { - label = "Delete line" + label = context.getString(ResR.string.action_delete_line) icon = ContextCompat.getDrawable(context, R.drawable.ic_delete) } @@ -166,7 +167,7 @@ class DuplicateLineAction(context: Context, override val order: Int) : EditorAct override var requiresUIThread = true init { - label = "Duplicate line" + label = context.getString(ResR.string.action_duplicate_line) icon = ContextCompat.getDrawable(context, R.drawable.ic_duplicate) } @@ -185,7 +186,7 @@ class CopyLineAction(private val context: Context, override val order: Int) : Ed override var requiresUIThread = true init { - label = "Copy line" + label = context.getString(ResR.string.action_copy_line) icon = ContextCompat.getDrawable(context, R.drawable.ic_copy) } @@ -195,7 +196,7 @@ class CopyLineAction(private val context: Context, override val order: Int) : Ed return false } TextTransformers(editor).copyLine() - Toast.makeText(context, "Copied to clipboard", Toast.LENGTH_SHORT).show() + Toast.makeText(context, ResR.string.msg_copied_to_clipboard, Toast.LENGTH_SHORT).show() return true } } @@ -205,7 +206,7 @@ class CommentLineAction(context: Context, override val order: Int) : EditorActiv override var requiresUIThread = true init { - label = "Comment line" + label = context.getString(ResR.string.action_comment_line) icon = ContextCompat.getDrawable(context, R.drawable.ic_comment) } @@ -224,7 +225,7 @@ class MoveLineUpAction(context: Context, override val order: Int) : EditorActivi override var requiresUIThread = true init { - label = "Move line up" + label = context.getString(ResR.string.action_move_line_up) icon = ContextCompat.getDrawable(context, R.drawable.ic_move_line_up) } @@ -243,7 +244,7 @@ class MoveLineDownAction(context: Context, override val order: Int) : EditorActi override var requiresUIThread = true init { - label = "Move line down" + label = context.getString(ResR.string.action_move_line_down) icon = ContextCompat.getDrawable(context, R.drawable.ic_move_line_down) } @@ -262,7 +263,7 @@ class InsertLineAboveAction(context: Context, override val order: Int) : EditorA override var requiresUIThread = true init { - label = "Insert line above" + label = context.getString(ResR.string.action_insert_line_above) icon = ContextCompat.getDrawable(context, R.drawable.ic_insert_line_above) } @@ -281,7 +282,7 @@ class InsertLineBelowAction(context: Context, override val order: Int) : EditorA override var requiresUIThread = true init { - label = "Insert line below" + label = context.getString(ResR.string.action_insert_line_below) icon = ContextCompat.getDrawable(context, R.drawable.ic_insert_line_below) } @@ -300,7 +301,7 @@ class SelectLineAction(context: Context, override val order: Int) : EditorActivi override var requiresUIThread = true init { - label = "Select line" + label = context.getString(ResR.string.action_select_line) icon = ContextCompat.getDrawable(context, R.drawable.ic_select_line) } @@ -319,7 +320,7 @@ class TrimTrailingWhitespaceAction(private val context: Context, override val or override var requiresUIThread = true init { - label = "Trim trailing whitespace" + label = context.getString(ResR.string.action_trim_trailing_whitespace) icon = ContextCompat.getDrawable(context, R.drawable.ic_trim_trailing_whitespace) } @@ -329,7 +330,7 @@ class TrimTrailingWhitespaceAction(private val context: Context, override val or return false } TextTransformers(editor).trimTrailingWhitespace() - Toast.makeText(context, "Trailing whitespace removed", Toast.LENGTH_SHORT).show() + Toast.makeText(context, ResR.string.msg_trailing_whitespace_removed, Toast.LENGTH_SHORT).show() return true } } @@ -339,7 +340,7 @@ class IndentLineAction(context: Context, override val order: Int) : EditorActivi override var requiresUIThread = true init { - label = "Indent line" + label = context.getString(ResR.string.action_indent_line) icon = ContextCompat.getDrawable(context, R.drawable.ic_indent_line) } @@ -358,7 +359,7 @@ class UnindentLineAction(context: Context, override val order: Int) : EditorActi override var requiresUIThread = true init { - label = "Unindent line" + label = context.getString(ResR.string.action_unindent_line) icon = ContextCompat.getDrawable(context, R.drawable.ic_unindent_line) } @@ -377,7 +378,7 @@ class JoinLinesAction(context: Context, override val order: Int) : EditorActivit override var requiresUIThread = true init { - label = "Join lines" + label = context.getString(ResR.string.action_join_lines) icon = ContextCompat.getDrawable(context, R.drawable.ic_join_lines) } @@ -396,7 +397,7 @@ class ClearAllAction(private val context: Context, override val order: Int) : Ed override var requiresUIThread = true init { - label = "Clear all" + label = context.getString(ResR.string.action_clear_all) icon = ContextCompat.getDrawable(context, R.drawable.ic_clear_all) } @@ -408,13 +409,13 @@ class ClearAllAction(private val context: Context, override val order: Int) : Ed val activity = data.requireActivity() MaterialAlertDialogBuilder(activity) - .setTitle("Clear All") - .setMessage("Are you sure you want to clear all text? This action cannot be undone.") - .setPositiveButton("Clear") { _, _ -> + .setTitle(ResR.string.title_clear_all) + .setMessage(ResR.string.msg_clear_all_confirm) + .setPositiveButton(ResR.string.btn_clear) { _, _ -> TextTransformers(editor).clearAll() - Toast.makeText(context, "Editor cleared", Toast.LENGTH_SHORT).show() + Toast.makeText(context, ResR.string.msg_editor_cleared, Toast.LENGTH_SHORT).show() } - .setNegativeButton("Cancel", null) + .setNegativeButton(android.R.string.cancel, null) .show() return true diff --git a/core/app/src/main/java/com/tom/rv2ide/actions/sidebar/AIAgentSidebarAction.kt b/core/app/src/main/java/com/tom/rv2ide/actions/sidebar/AIAgentSidebarAction.kt index 09a4121f0..890082d3b 100644 --- a/core/app/src/main/java/com/tom/rv2ide/actions/sidebar/AIAgentSidebarAction.kt +++ b/core/app/src/main/java/com/tom/rv2ide/actions/sidebar/AIAgentSidebarAction.kt @@ -41,7 +41,7 @@ class AIAgentSidebarAction(context: Context, override val order: Int) : Abstract init { label = context.getString(R.string.ai_agent_title) - subtitle = "v0.1-preview" + subtitle = context.getString(R.string.ai_agent_version) icon = ContextCompat.getDrawable(context, R.drawable.ic_ai_agent) iconRes = R.drawable.ic_ai_agent } diff --git a/core/app/src/main/java/com/tom/rv2ide/activities/AssetStudioActivity.kt b/core/app/src/main/java/com/tom/rv2ide/activities/AssetStudioActivity.kt index b5d21b42b..89b8a2ae7 100644 --- a/core/app/src/main/java/com/tom/rv2ide/activities/AssetStudioActivity.kt +++ b/core/app/src/main/java/com/tom/rv2ide/activities/AssetStudioActivity.kt @@ -74,9 +74,9 @@ class AssetStudioActivity : EdgeToEdgeIDEActivity() { isXmlMode = true updatePreview() if (selectedXmlDrawable != null) { - Toast.makeText(this, "Icon imported from Material Icons", Toast.LENGTH_SHORT).show() + Toast.makeText(this, getString(R.string.asset_studio_icon_imported), Toast.LENGTH_SHORT).show() } else { - Toast.makeText(this, "Failed to load vector from selection", Toast.LENGTH_SHORT) + Toast.makeText(this, getString(R.string.asset_studio_load_vector_failed), Toast.LENGTH_SHORT) .show() } } @@ -96,7 +96,7 @@ class AssetStudioActivity : EdgeToEdgeIDEActivity() { isXmlMode = false updatePreview() } catch (e: Exception) { - Toast.makeText(this, "Error loading image: ${e.message}", Toast.LENGTH_SHORT).show() + Toast.makeText(this, getString(R.string.asset_studio_error_loading_image, e.message), Toast.LENGTH_SHORT).show() } } } @@ -112,14 +112,14 @@ class AssetStudioActivity : EdgeToEdgeIDEActivity() { val inputStream = contentResolver.openInputStream(uri) val xmlContent = inputStream?.bufferedReader()?.use { it.readText() } if (xmlContent != null) { - Toast.makeText(this, "XML content length: ${xmlContent.length}", Toast.LENGTH_SHORT) + Toast.makeText(this, getString(R.string.asset_studio_xml_content_length, xmlContent.length), Toast.LENGTH_SHORT) .show() selectedXmlDrawable = loadVectorDrawableFromXml(xmlContent) selectedImage = null isXmlMode = true updatePreview() if (selectedXmlDrawable != null) { - Toast.makeText(this, "XML loaded successfully", Toast.LENGTH_SHORT).show() + Toast.makeText(this, getString(R.string.asset_studio_xml_loaded), Toast.LENGTH_SHORT).show() } else { Toast.makeText( this, @@ -129,10 +129,10 @@ class AssetStudioActivity : EdgeToEdgeIDEActivity() { .show() } } else { - Toast.makeText(this, "Failed to read XML content", Toast.LENGTH_SHORT).show() + Toast.makeText(this, getString(R.string.asset_studio_xml_read_failed), Toast.LENGTH_SHORT).show() } } catch (e: Exception) { - Toast.makeText(this, "Error loading XML: ${e.message}", Toast.LENGTH_SHORT).show() + Toast.makeText(this, getString(R.string.asset_studio_error_loading_xml, e.message), Toast.LENGTH_SHORT).show() } } } @@ -843,15 +843,15 @@ class AssetStudioActivity : EdgeToEdgeIDEActivity() { if (isXmlMode && selectedXmlDrawable != null) { binding.previewImageView.setImageDrawable(selectedXmlDrawable) - Toast.makeText(this, "XML Preview updated", Toast.LENGTH_SHORT).show() + Toast.makeText(this, getString(R.string.asset_studio_xml_preview_updated), Toast.LENGTH_SHORT).show() } else { selectedImage?.let { bitmap -> val transformedBitmap = applyImageTransformations(bitmap) binding.previewImageView.setImageBitmap(transformedBitmap) - Toast.makeText(this, "Image Preview updated", Toast.LENGTH_SHORT).show() + Toast.makeText(this, getString(R.string.asset_studio_image_preview_updated), Toast.LENGTH_SHORT).show() } ?: run { - Toast.makeText(this, "Please select an image or XML file first", Toast.LENGTH_SHORT) + Toast.makeText(this, getString(R.string.asset_studio_select_image_first), Toast.LENGTH_SHORT) .show() } } @@ -885,7 +885,7 @@ class AssetStudioActivity : EdgeToEdgeIDEActivity() { private fun showMaterialIconsImportDialog() { val options = arrayOf("Browse in app", "Paste Vector XML") AlertDialog.Builder(this) - .setTitle("Material Icons") + .setTitle(getString(R.string.asset_studio_material_icons)) .setItems(options) { dialog, which -> when (which) { 0 -> { @@ -915,9 +915,9 @@ class AssetStudioActivity : EdgeToEdgeIDEActivity() { ) } AlertDialog.Builder(this) - .setTitle("Import Vector XML") + .setTitle(getString(R.string.asset_studio_import_vector)) .setView(input) - .setPositiveButton("Import") { d, _ -> + .setPositiveButton(getString(R.string.action_import)) { d, _ -> val xml = input.text?.toString()?.trim() if (!xml.isNullOrEmpty()) { selectedXmlDrawable = loadVectorDrawableFromXml(xml) @@ -925,9 +925,9 @@ class AssetStudioActivity : EdgeToEdgeIDEActivity() { isXmlMode = true updatePreview() if (selectedXmlDrawable != null) { - Toast.makeText(this, "Vector imported", Toast.LENGTH_SHORT).show() + Toast.makeText(this, getString(R.string.asset_studio_vector_imported), Toast.LENGTH_SHORT).show() } else { - Toast.makeText(this, "Failed to parse vector XML", Toast.LENGTH_SHORT).show() + Toast.makeText(this, getString(R.string.asset_studio_parse_vector_failed), Toast.LENGTH_SHORT).show() } } d.dismiss() @@ -940,9 +940,9 @@ class AssetStudioActivity : EdgeToEdgeIDEActivity() { val locations = arrayOf("drawable", "mipmap") var selected = 0 AlertDialog.Builder(this) - .setTitle("Save to") + .setTitle(getString(R.string.asset_studio_save_to)) .setSingleChoiceItems(locations, selected) { _, which -> selected = which } - .setPositiveButton("Generate") { dialog, _ -> + .setPositiveButton(getString(R.string.action_generate)) { dialog, _ -> val useMipmap = (selected == 1) generateToLocation(sourceBitmap, iconName, useMipmap) dialog.dismiss() @@ -955,7 +955,7 @@ class AssetStudioActivity : EdgeToEdgeIDEActivity() { try { val projectDir = com.tom.rv2ide.projects.IProjectManager.getInstance().projectDirPath if (projectDir == null) { - Toast.makeText(this, "No project opened", Toast.LENGTH_SHORT).show() + Toast.makeText(this, getString(R.string.asset_studio_no_project), Toast.LENGTH_SHORT).show() return } val resDir = java.io.File(projectDir, "app/src/main/res") @@ -988,10 +988,10 @@ class AssetStudioActivity : EdgeToEdgeIDEActivity() { generatedCount++ } - Toast.makeText(this, "Generated $generatedCount icons in res/$base-*", Toast.LENGTH_LONG) + Toast.makeText(this, getString(R.string.asset_studio_generated_icons, generatedCount, base), Toast.LENGTH_LONG) .show() } catch (e: Exception) { - Toast.makeText(this, "Error generating icons: ${e.message}", Toast.LENGTH_SHORT).show() + Toast.makeText(this, getString(R.string.asset_studio_generate_error, e.message), Toast.LENGTH_SHORT).show() } } @@ -1004,7 +1004,7 @@ class AssetStudioActivity : EdgeToEdgeIDEActivity() { selectedImage } if (sourceBitmap == null) { - Toast.makeText(this, "Please select an image or XML file first", Toast.LENGTH_SHORT).show() + Toast.makeText(this, getString(R.string.asset_studio_select_image_first), Toast.LENGTH_SHORT).show() return } promptSaveLocationAndGenerate(sourceBitmap, iconName) diff --git a/core/app/src/main/java/com/tom/rv2ide/activities/FileBrowserActivity.kt b/core/app/src/main/java/com/tom/rv2ide/activities/FileBrowserActivity.kt index f6e045bc3..71ac5ab70 100644 --- a/core/app/src/main/java/com/tom/rv2ide/activities/FileBrowserActivity.kt +++ b/core/app/src/main/java/com/tom/rv2ide/activities/FileBrowserActivity.kt @@ -48,7 +48,7 @@ class FileBrowserActivity : EdgeToEdgeIDEActivity() { if (isGranted) { loadFileBrowserFragment() } else { - Toast.makeText(this, "Permission denied to read storage", Toast.LENGTH_SHORT).show() + Toast.makeText(this, getString(R.string.file_permission_denied), Toast.LENGTH_SHORT).show() } } @@ -58,7 +58,7 @@ class FileBrowserActivity : EdgeToEdgeIDEActivity() { if (Environment.isExternalStorageManager()) { loadFileBrowserFragment() } else { - Toast.makeText(this, "Permission denied to manage storage", Toast.LENGTH_SHORT).show() + Toast.makeText(this, getString(R.string.file_permission_manage_denied), Toast.LENGTH_SHORT).show() } } } diff --git a/core/app/src/main/java/com/tom/rv2ide/activities/IDEConfigurations.kt b/core/app/src/main/java/com/tom/rv2ide/activities/IDEConfigurations.kt index 8fce2ec3c..cef7c87f1 100644 --- a/core/app/src/main/java/com/tom/rv2ide/activities/IDEConfigurations.kt +++ b/core/app/src/main/java/com/tom/rv2ide/activities/IDEConfigurations.kt @@ -118,10 +118,10 @@ class IDEConfigurations : EdgeToEdgeIDEActivity() { lifecycleScope.launch(Dispatchers.IO) { try { } catch (e: TimeoutCancellationException) { - withContext(Dispatchers.Main) { flashError("Request timed out") } + withContext(Dispatchers.Main) { flashError(getString(R.string.msg_request_timed_out)) } } catch (e: Exception) { withContext(Dispatchers.Main) { - flashError("An error occurred: ${e.message}") + flashError(getString(R.string.msg_an_error_occurred, e.message)) } e.printStackTrace() } @@ -157,8 +157,8 @@ class IDEConfigurations : EdgeToEdgeIDEActivity() { private fun setUpDropdown() { val dropdown = findViewById(R.id.ndks_dropdown) val cmake_dropdown = findViewById(R.id.cmake_dropdown) - dropdown.setText("Loading versions...", false) - cmake_dropdown.setText("Loading versions...", false) + dropdown.setText(getString(R.string.loading_versions), false) + cmake_dropdown.setText(getString(R.string.loading_versions), false) val cpuArch = getCpuArchitecture() val architecture: AcsCommandInterface.Architecture = @@ -167,7 +167,7 @@ class IDEConfigurations : EdgeToEdgeIDEActivity() { "arm64-v8a" -> AcsCommandInterface.Architecture.ARM64_V8A "x86_64" -> AcsCommandInterface.Architecture.X86_64 else -> { - flashError("Unsupported architecture: $cpuArch") + flashError(getString(R.string.msg_unsupported_arch, cpuArch)) return } } @@ -238,12 +238,12 @@ class IDEConfigurations : EdgeToEdgeIDEActivity() { } } } else { - dropdown.setText("No versions available", false) - flashError("No NDK versions found in the repository") + dropdown.setText(getString(R.string.no_versions_available), false) + flashError(getString(R.string.msg_no_ndk_versions)) } } else { - dropdown.setText("Failed to load", false) - flashError("Failed to fetch versions: ${versionsResult.errorOutput}") + dropdown.setText(getString(R.string.failed_to_load), false) + flashError(getString(R.string.msg_failed_to_fetch_versions, versionsResult.errorOutput)) } // Process CMake versions @@ -295,18 +295,18 @@ class IDEConfigurations : EdgeToEdgeIDEActivity() { } } } else { - cmake_dropdown.setText("No versions available", false) - flashError("No CMake versions found in the repository") + cmake_dropdown.setText(getString(R.string.no_versions_available), false) + flashError(getString(R.string.msg_no_cmake_versions)) } } else { - cmake_dropdown.setText("Failed to load", false) - flashError("Failed to fetch versions: ${cmakeVersionsResult.errorOutput}") + cmake_dropdown.setText(getString(R.string.failed_to_load), false) + flashError(getString(R.string.msg_failed_to_fetch_versions, cmakeVersionsResult.errorOutput)) } } } catch (e: Exception) { withContext(Dispatchers.Main) { - dropdown.setText("Error loading", false) - flashError("Error fetching versions: ${e.message}") + dropdown.setText(getString(R.string.error_loading), false) + flashError(getString(R.string.msg_error_fetching_versions, e.message)) } e.printStackTrace() } diff --git a/core/app/src/main/java/com/tom/rv2ide/activities/PreferencesActivity.kt b/core/app/src/main/java/com/tom/rv2ide/activities/PreferencesActivity.kt index 82ff92ffc..f4f66c8f3 100644 --- a/core/app/src/main/java/com/tom/rv2ide/activities/PreferencesActivity.kt +++ b/core/app/src/main/java/com/tom/rv2ide/activities/PreferencesActivity.kt @@ -87,9 +87,9 @@ class PreferencesActivity : EdgeToEdgeIDEActivity() { } } - Toast.makeText(this, "Font copied successfully: $fileName", Toast.LENGTH_SHORT).show() + Toast.makeText(this, getString(R.string.pref_font_copy_success, fileName), Toast.LENGTH_SHORT).show() } catch (e: Exception) { - Toast.makeText(this, "Error copying font: ${e.message}", Toast.LENGTH_LONG).show() + Toast.makeText(this, getString(R.string.pref_font_copy_error, e.message), Toast.LENGTH_LONG).show() } } } diff --git a/core/app/src/main/java/com/tom/rv2ide/activities/ReviewChangesActivity.kt b/core/app/src/main/java/com/tom/rv2ide/activities/ReviewChangesActivity.kt index db0de2568..ed06eba1c 100644 --- a/core/app/src/main/java/com/tom/rv2ide/activities/ReviewChangesActivity.kt +++ b/core/app/src/main/java/com/tom/rv2ide/activities/ReviewChangesActivity.kt @@ -53,7 +53,7 @@ class ReviewChangesActivity : AppCompatActivity() { setSupportActionBar(toolbar) supportActionBar?.apply { setDisplayHomeAsUpEnabled(true) - title = "Review Changes" + title = getString(R.string.review_changes) } toolbar.setNavigationOnClickListener { setResult(RESULT_CANCELED) diff --git a/core/app/src/main/java/com/tom/rv2ide/activities/editor/BaseEditorActivity.kt b/core/app/src/main/java/com/tom/rv2ide/activities/editor/BaseEditorActivity.kt index efd084d6e..cfa86a91e 100644 --- a/core/app/src/main/java/com/tom/rv2ide/activities/editor/BaseEditorActivity.kt +++ b/core/app/src/main/java/com/tom/rv2ide/activities/editor/BaseEditorActivity.kt @@ -732,9 +732,9 @@ override fun onApplySystemBarInsets(insets: Insets) { val setup = Setup(this) setup.scanProjectForLanguageServers(ProjectManagerImpl.getInstance().projectDir) { isSuccessfullyInstalled -> if (isSuccessfullyInstalled) { - flashSuccess("Installation succeeded") + flashSuccess(R.string.msg_installation_succeeded) if (!editorViewModel.isInitializing) { - flashInfo("Reinitializing project...") + flashInfo(R.string.msg_reinitializing_project) (this as? ProjectHandlerActivity)?.initializeProject() } } @@ -1174,14 +1174,14 @@ override fun onApplySystemBarInsets(insets: Insets) { private fun showNdkNotInstalledDialog(context: Context, onDismiss: () -> Unit = {}) { MaterialAlertDialogBuilder(context) - .setTitle("NDK Not Found") + .setTitle(getString(R.string.native_error_title)) .setMessage( "A compatible NDK (version 28.2.13676358) is not installed.\n\n" + "Native code features will be disabled for this project.\n\n" + "To enable native development, please install NDK version 28.2.13676358 " + "open a terminal then run: 'idesetup -y -c -wn'." ) - .setPositiveButton("OK") { dialog, _ -> + .setPositiveButton(getString(R.string.lsp_ok_button)) { dialog, _ -> dialog.dismiss() onDismiss() } diff --git a/core/app/src/main/java/com/tom/rv2ide/activities/editor/ProjectHandlerActivity.kt b/core/app/src/main/java/com/tom/rv2ide/activities/editor/ProjectHandlerActivity.kt index 338a929db..77732c0be 100644 --- a/core/app/src/main/java/com/tom/rv2ide/activities/editor/ProjectHandlerActivity.kt +++ b/core/app/src/main/java/com/tom/rv2ide/activities/editor/ProjectHandlerActivity.kt @@ -607,37 +607,37 @@ fun initializeProject(buildVariants: Map) { } val builder = newMaterialDialogBuilder(this) - builder.setTitle("Project Setup Failed") + builder.setTitle(getString(R.string.project_setup_failed)) builder.setMessage( "The project could not be initialized properly.\n\n$errorMessage\n\nFull error details have been copied to clipboard.\n\nYou can try:\n• Update top level build.gradle\n• Syncing the project again\n• Checking if all required files are present\n• Restarting the IDE" ) builder.setIcon(R.drawable.ic_error) builder.setCancelable(false) - builder.setPositiveButton("Retry") { dialog, _ -> + builder.setPositiveButton(getString(R.string.action_retry)) { dialog, _ -> dialog.dismiss() if (!isFinishing && !isDestroyed) { initializeProject() } } - builder.setNegativeButton("Close Project") { dialog, _ -> + builder.setNegativeButton(getString(R.string.title_close_project)) { dialog, _ -> dialog.dismiss() if (!isFinishing && !isDestroyed) { confirmProjectClose() } } - builder.setNeutralButton("View Error") { dialog, _ -> + builder.setNeutralButton(getString(R.string.project_view_error)) { dialog, _ -> if (isFinishing || isDestroyed) { return@setNeutralButton } val errorBuilder = newMaterialDialogBuilder(this) - errorBuilder.setTitle("Full Error Details") + errorBuilder.setTitle(getString(R.string.full_error_details)) errorBuilder.setMessage(fullErrorDetails) - errorBuilder.setPositiveButton("OK") { d, _ -> d.dismiss() } - errorBuilder.setNeutralButton("Copy Again") { d, _ -> + errorBuilder.setPositiveButton(getString(R.string.lsp_ok_button)) { d, _ -> d.dismiss() } + errorBuilder.setNeutralButton(getString(R.string.project_copy_again)) { d, _ -> try { val clipboard = getSystemService(CLIPBOARD_SERVICE) as android.content.ClipboardManager val clip = android.content.ClipData.newPlainText("Project Setup Error", fullErrorDetails) diff --git a/core/app/src/main/java/com/tom/rv2ide/adapters/BuildVariantsAdapter.kt b/core/app/src/main/java/com/tom/rv2ide/adapters/BuildVariantsAdapter.kt index d2d3f044d..576420907 100644 --- a/core/app/src/main/java/com/tom/rv2ide/adapters/BuildVariantsAdapter.kt +++ b/core/app/src/main/java/com/tom/rv2ide/adapters/BuildVariantsAdapter.kt @@ -137,9 +137,9 @@ class BuildVariantsAdapter( dialogBinding.compileSdk.setText(variantInfo.compileSdk?.toString() ?: "") MaterialAlertDialogBuilder(context) - .setTitle("Edit ${variantInfo.projectPath}") + .setTitle(context.getString(R.string.build_edit_variant, variantInfo.projectPath)) .setView(dialogBinding.root) - .setPositiveButton("Save") { _, _ -> + .setPositiveButton(context.getString(R.string.action_save)) { _, _ -> val updatedInfo = variantInfo.copy( versionName = dialogBinding.versionName.text?.toString()?.takeIf { it.isNotEmpty() }, versionCode = dialogBinding.versionCode.text?.toString()?.toIntOrNull(), @@ -153,7 +153,7 @@ class BuildVariantsAdapter( viewModel.updateModuleConfig(variantInfo.projectPath, updatedInfo) } - .setNegativeButton("Cancel", null) + .setNegativeButton(context.getString(R.string.action_cancel), null) .show() } } \ No newline at end of file diff --git a/core/app/src/main/java/com/tom/rv2ide/adapters/FileModificationAdapter.kt b/core/app/src/main/java/com/tom/rv2ide/adapters/FileModificationAdapter.kt index 6c02b8826..962127bda 100644 --- a/core/app/src/main/java/com/tom/rv2ide/adapters/FileModificationAdapter.kt +++ b/core/app/src/main/java/com/tom/rv2ide/adapters/FileModificationAdapter.kt @@ -48,12 +48,12 @@ class FileModificationAdapter : RecyclerView.Adapter { - holder.fileStatus.text = "Modifying..." + holder.fileStatus.text = holder.itemView.context.getString(R.string.file_mod_modifying) holder.progressIndicator.visibility = View.VISIBLE holder.statusIcon.visibility = View.GONE } Status.SUCCESS -> { - holder.fileStatus.text = "Modified successfully" + holder.fileStatus.text = holder.itemView.context.getString(R.string.file_mod_success) holder.progressIndicator.visibility = View.GONE holder.statusIcon.visibility = View.VISIBLE holder.statusIcon.setImageResource(android.R.drawable.ic_menu_save) @@ -62,7 +62,7 @@ class FileModificationAdapter : RecyclerView.Adapter { - holder.fileStatus.text = "Failed to modify" + holder.fileStatus.text = holder.itemView.context.getString(R.string.file_mod_failed) holder.progressIndicator.visibility = View.GONE holder.statusIcon.visibility = View.VISIBLE holder.statusIcon.setImageResource(android.R.drawable.ic_delete) diff --git a/core/app/src/main/java/com/tom/rv2ide/app/IDEApplication.kt b/core/app/src/main/java/com/tom/rv2ide/app/IDEApplication.kt index ecacdb0c5..01a491414 100644 --- a/core/app/src/main/java/com/tom/rv2ide/app/IDEApplication.kt +++ b/core/app/src/main/java/com/tom/rv2ide/app/IDEApplication.kt @@ -61,7 +61,8 @@ import com.tom.rv2ide.utils.Environment import com.tom.rv2ide.utils.MemoryManager import com.tom.rv2ide.utils.RecyclableObjectPool import com.tom.rv2ide.utils.VMUtils -import com.tom.rv2ide.utils.flashError +import com.tom.rv2ide.utils.flashError +import com.tom.rv2ide.resources.R import com.tom.rv2ide.utils.MemoryProfiler import io.github.mohammedbaqernull.seasonal.SeasonalEffects import io.github.miyazkaori.silentinstaller.SilentInstaller @@ -179,7 +180,7 @@ class IDEApplication : TermuxApplication() { startActivity(intent) } catch (th: Throwable) { log.error("Unable to start activity to show changelog", th) - flashError("Unable to start activity") + flashError(R.string.msg_unable_to_start_activity) } } diff --git a/core/app/src/main/java/com/tom/rv2ide/artificial/dialogs/AIPermissionDialog.kt b/core/app/src/main/java/com/tom/rv2ide/artificial/dialogs/AIPermissionDialog.kt index 85411b82d..4b7f2efec 100644 --- a/core/app/src/main/java/com/tom/rv2ide/artificial/dialogs/AIPermissionDialog.kt +++ b/core/app/src/main/java/com/tom/rv2ide/artificial/dialogs/AIPermissionDialog.kt @@ -42,17 +42,17 @@ class AIPermissionDialog(private val context: Context) { onDeny: () -> Unit ) { MaterialAlertDialogBuilder(context) - .setTitle("AI File Write Permission") - .setMessage("AI wants to write to:\n$fileName\n\nAllow this action?") - .setPositiveButton("Allow") { dialog, _ -> + .setTitle(context.getString(R.string.ai_file_write_title)) + .setMessage(context.getString(R.string.ai_file_write_message, fileName)) + .setPositiveButton(context.getString(R.string.action_allow)) { dialog, _ -> onConfirm() dialog.dismiss() } - .setNegativeButton("Deny") { dialog, _ -> + .setNegativeButton(context.getString(R.string.action_deny)) { dialog, _ -> onDeny() dialog.dismiss() } - .setNeutralButton("Always Allow") { dialog, _ -> + .setNeutralButton(context.getString(R.string.action_always_allow)) { dialog, _ -> permissionManager.setRequireConfirmation(false) onConfirm() dialog.dismiss() @@ -77,16 +77,16 @@ class AIPermissionDialog(private val context: Context) { autoBackupCheckbox.isChecked = permissionManager.isAutoBackupEnabled() MaterialAlertDialogBuilder(context) - .setTitle("AI Permissions") + .setTitle(context.getString(R.string.ai_permissions_title)) .setView(view) - .setPositiveButton("Save") { dialog, _ -> + .setPositiveButton(context.getString(R.string.action_save)) { dialog, _ -> permissionManager.setFileWriteEnabled(enableWriteCheckbox.isChecked) permissionManager.setRequireConfirmation(requireConfirmationCheckbox.isChecked) permissionManager.setAutoBackup(autoBackupCheckbox.isChecked) onSettingsChanged() dialog.dismiss() } - .setNegativeButton("Cancel") { dialog, _ -> + .setNegativeButton(context.getString(R.string.action_cancel)) { dialog, _ -> dialog.dismiss() } .show() diff --git a/core/app/src/main/java/com/tom/rv2ide/artificial/dialogs/ProviderSwitchDialog.kt b/core/app/src/main/java/com/tom/rv2ide/artificial/dialogs/ProviderSwitchDialog.kt index ba36746ba..d6f5c0dbf 100644 --- a/core/app/src/main/java/com/tom/rv2ide/artificial/dialogs/ProviderSwitchDialog.kt +++ b/core/app/src/main/java/com/tom/rv2ide/artificial/dialogs/ProviderSwitchDialog.kt @@ -21,6 +21,7 @@ import android.content.Context import android.content.SharedPreferences import com.google.android.material.dialog.MaterialAlertDialogBuilder import android.preference.PreferenceManager +import com.tom.rv2ide.R /* * @author Mohammed-baqer-null @ https://github.com/Mohammed-baqer-null @@ -55,23 +56,23 @@ class ProviderSwitchDialog(private val context: Context) { val providerNames = availableProviders.map { it.second }.toTypedArray() MaterialAlertDialogBuilder(context) - .setTitle("⚠️ Provider Error") + .setTitle(context.getString(R.string.ai_provider_error)) .setMessage( "Current Provider: $currentProvider\n\n" + "Error: $errorMessage\n\n" + "Available providers: ${availableProviders.size}\n\n" + "Would you like to switch to another provider?" ) - .setPositiveButton("Switch Manually") { dialog, _ -> + .setPositiveButton(context.getString(R.string.ai_switch_manually)) { dialog, _ -> dialog.dismiss() showProviderSelectionDialog(availableProviders, onProviderSelected) } - .setNegativeButton("Enable Auto-Switch") { dialog, _ -> + .setNegativeButton(context.getString(R.string.ai_enable_auto_switch)) { dialog, _ -> setAutoSwitch(true) onEnableAutoSwitch() dialog.dismiss() } - .setNeutralButton("Cancel") { dialog, _ -> + .setNeutralButton(context.getString(R.string.action_cancel)) { dialog, _ -> dialog.dismiss() } .setCancelable(false) @@ -86,12 +87,12 @@ class ProviderSwitchDialog(private val context: Context) { val providerIds = availableProviders.map { it.first } MaterialAlertDialogBuilder(context) - .setTitle("Select Provider") + .setTitle(context.getString(R.string.ai_select_provider)) .setItems(providerNames) { dialog, which -> onProviderSelected(providerIds[which]) dialog.dismiss() } - .setNegativeButton("Cancel") { dialog, _ -> + .setNegativeButton(context.getString(R.string.action_cancel)) { dialog, _ -> dialog.dismiss() } .show() @@ -99,7 +100,7 @@ class ProviderSwitchDialog(private val context: Context) { private fun showNoProvidersAvailableDialog(errorMessage: String) { MaterialAlertDialogBuilder(context) - .setTitle("❌ No Providers Available") + .setTitle(context.getString(R.string.ai_no_providers)) .setMessage( "Error: $errorMessage\n\n" + "Unfortunately, there are no other providers available with valid API keys.\n\n" + @@ -108,7 +109,7 @@ class ProviderSwitchDialog(private val context: Context) { "2. Verify account quotas\n" + "3. Try again later" ) - .setPositiveButton("OK") { dialog, _ -> + .setPositiveButton(context.getString(R.string.action_ok)) { dialog, _ -> dialog.dismiss() } .show() @@ -120,17 +121,17 @@ class ProviderSwitchDialog(private val context: Context) { reason: String ): MaterialAlertDialogBuilder { return MaterialAlertDialogBuilder(context) - .setTitle("🔄 Auto-Switched Provider") + .setTitle(context.getString(R.string.ai_auto_switched)) .setMessage( "Switched from: $fromProvider\n" + "Switched to: $toProvider\n\n" + "Reason: $reason\n\n" + "Auto-switch is enabled. You can disable it in settings." ) - .setPositiveButton("OK") { dialog, _ -> + .setPositiveButton(context.getString(R.string.action_ok)) { dialog, _ -> dialog.dismiss() } - .setNegativeButton("Disable Auto-Switch") { dialog, _ -> + .setNegativeButton(context.getString(R.string.ai_disable_auto_switch)) { dialog, _ -> setAutoSwitch(false) dialog.dismiss() } diff --git a/core/app/src/main/java/com/tom/rv2ide/experimental/assetstudio/m3icons/ColorPickerDialog.kt b/core/app/src/main/java/com/tom/rv2ide/experimental/assetstudio/m3icons/ColorPickerDialog.kt index 2e1b91c65..dfd02534c 100644 --- a/core/app/src/main/java/com/tom/rv2ide/experimental/assetstudio/m3icons/ColorPickerDialog.kt +++ b/core/app/src/main/java/com/tom/rv2ide/experimental/assetstudio/m3icons/ColorPickerDialog.kt @@ -179,13 +179,13 @@ object ColorPickerDialog { } MaterialAlertDialogBuilder(context) - .setTitle("Select Color") + .setTitle(context.getString(R.string.asset_studio_select_color)) .setView(dialogView) - .setPositiveButton("OK") { dialog, _ -> + .setPositiveButton(context.getString(R.string.action_ok)) { dialog, _ -> onColorSelected(currentColor, selectedDynamicColor) dialog.dismiss() } - .setNegativeButton("Cancel", null) + .setNegativeButton(context.getString(R.string.action_cancel), null) .show() } } \ No newline at end of file diff --git a/core/app/src/main/java/com/tom/rv2ide/experimental/assetstudio/m3icons/CopyDialogHandler.kt b/core/app/src/main/java/com/tom/rv2ide/experimental/assetstudio/m3icons/CopyDialogHandler.kt index 715c646e7..917ec177d 100644 --- a/core/app/src/main/java/com/tom/rv2ide/experimental/assetstudio/m3icons/CopyDialogHandler.kt +++ b/core/app/src/main/java/com/tom/rv2ide/experimental/assetstudio/m3icons/CopyDialogHandler.kt @@ -48,15 +48,15 @@ object CopyDialogHandler { radioDrawable.isChecked = true MaterialAlertDialogBuilder(context) - .setTitle("Copy to") + .setTitle(context.getString(R.string.asset_studio_copy_to)) .setView(dialogView) - .setPositiveButton("Copy") { dialog, _ -> + .setPositiveButton(context.getString(R.string.action_copy)) { dialog, _ -> val fileName = fileNameInput.text.toString().ifEmpty { icon.name } val destination = if (radioDrawable.isChecked) "drawable" else "mipmap" IconCopier.copyIconToDestination(context, fileName, bitmap, destination, xmlContent) dialog.dismiss() } - .setNegativeButton("Cancel", null) + .setNegativeButton(context.getString(R.string.action_cancel), null) .show() } @@ -78,9 +78,9 @@ object CopyDialogHandler { radioDrawable.isChecked = true MaterialAlertDialogBuilder(context) - .setTitle("Copy to") + .setTitle(context.getString(R.string.asset_studio_copy_to)) .setView(dialogView) - .setPositiveButton("Copy") { dialog, _ -> + .setPositiveButton(context.getString(R.string.action_copy)) { dialog, _ -> val finalFileName = fileNameInput.text.toString().ifEmpty { fileName } val destination = if (radioDrawable.isChecked) "drawable" else "mipmap" IconCopier.copyIconToDestination( @@ -94,7 +94,7 @@ object CopyDialogHandler { ) dialog.dismiss() } - .setNegativeButton("Cancel", null) + .setNegativeButton(context.getString(R.string.action_cancel), null) .show() } } \ No newline at end of file diff --git a/core/app/src/main/java/com/tom/rv2ide/experimental/depsupdater/DependencyAdapter.kt b/core/app/src/main/java/com/tom/rv2ide/experimental/depsupdater/DependencyAdapter.kt index 405a18d9c..4ad4008a2 100644 --- a/core/app/src/main/java/com/tom/rv2ide/experimental/depsupdater/DependencyAdapter.kt +++ b/core/app/src/main/java/com/tom/rv2ide/experimental/depsupdater/DependencyAdapter.kt @@ -59,7 +59,7 @@ class DependencyAdapter( when { dependency.hasUpdate && dependency.latestVersion != null -> { - tvUpdateInfo.text = "Update available: ${dependency.latestVersion}" + tvUpdateInfo.text = context.getString(R.string.dep_update_available, dependency.latestVersion) tvUpdateInfo.setTextColor(colorPrimary) tvUpdateInfo.visibility = View.VISIBLE card.setCardBackgroundColor(colorPrimaryContainer) @@ -67,7 +67,7 @@ class DependencyAdapter( card.setOnClickListener { onItemClick(dependency) } } dependency.latestVersion != null && !dependency.latestVersion.startsWith("Error") -> { - tvUpdateInfo.text = "Up to date" + tvUpdateInfo.text = context.getString(R.string.dep_up_to_date) tvUpdateInfo.setTextColor(colorOnSurfaceVariant) tvUpdateInfo.visibility = View.VISIBLE card.setCardBackgroundColor(colorSurface) @@ -83,7 +83,7 @@ class DependencyAdapter( card.setOnClickListener(null) } else -> { - tvUpdateInfo.text = "Not found in repositories" + tvUpdateInfo.text = context.getString(R.string.dep_not_found) tvUpdateInfo.setTextColor(colorTertiary) tvUpdateInfo.visibility = View.VISIBLE card.setCardBackgroundColor(colorTertiaryContainer) diff --git a/core/app/src/main/java/com/tom/rv2ide/experimental/depsupdater/DependencyUpdaterDialog.kt b/core/app/src/main/java/com/tom/rv2ide/experimental/depsupdater/DependencyUpdaterDialog.kt index bf4c97704..238cef062 100644 --- a/core/app/src/main/java/com/tom/rv2ide/experimental/depsupdater/DependencyUpdaterDialog.kt +++ b/core/app/src/main/java/com/tom/rv2ide/experimental/depsupdater/DependencyUpdaterDialog.kt @@ -134,7 +134,7 @@ class DependencyUpdaterDialog( val btnUpdate = warningView.findViewById(R.id.btnUpdate) tvTitle.text = "⚠️ Warning" - tvMessage.text = "You are about to update:\n\n${dependency.group}:${dependency.name}\n${dependency.currentVersion} → ${dependency.latestVersion}\n\nPlease note that newer versions may contain bugs, breaking changes, or be in alpha/beta stage. Always test thoroughly after updating.\n\nDo you want to proceed?" + tvMessage.text = context.getString(R.string.dep_update_single_message, dependency.group, dependency.name, dependency.currentVersion, dependency.latestVersion) val warningDialog = MaterialAlertDialogBuilder(context) .setView(warningView) @@ -162,7 +162,7 @@ class DependencyUpdaterDialog( val btnUpdate = warningView.findViewById(R.id.btnUpdate) tvTitle.text = "⚠️ Warning" - tvMessage.text = "You are about to update ${dependencies.size} dependencies.\n\nPlease note that newer versions may contain bugs, breaking changes, or be in alpha/beta stage. Updating all dependencies at once can introduce compatibility issues.\n\nIt's recommended to update and test dependencies individually.\n\nDo you want to proceed with updating all?" + tvMessage.text = context.getString(R.string.dep_update_all_message, dependencies.size) val warningDialog = MaterialAlertDialogBuilder(context) .setView(warningView) @@ -190,7 +190,7 @@ class DependencyUpdaterDialog( val btnCancel = dialogView.findViewById(R.id.btnCancel) val btnUpdate = dialogView.findViewById(R.id.btnUpdate) - tvConfirmTitle.text = "Confirm Update" + tvConfirmTitle.text = context.getString(R.string.dep_confirm_update) tvConfirmMessage.text = "${dependency.group}:${dependency.name}\n${dependency.currentVersion} → ${dependency.latestVersion}\n\nProceed with update?" val confirmDialog = MaterialAlertDialogBuilder(context) @@ -230,7 +230,7 @@ class DependencyUpdaterDialog( val btnCancel = successView.findViewById(R.id.btnCancel) val btnUpdate = successView.findViewById(R.id.btnUpdate) - tvTitle.text = "Success" + tvTitle.text = context.getString(R.string.dep_success) tvMessage.text = "${dependency.group}:${dependency.name} updated to ${dependency.latestVersion}" btnCancel.visibility = View.GONE btnUpdate.text = "OK" @@ -258,8 +258,8 @@ class DependencyUpdaterDialog( val btnCancel = errorView.findViewById(R.id.btnCancel) val btnUpdate = errorView.findViewById(R.id.btnUpdate) - tvTitle.text = "Error" - tvMessage.text = "Failed to update: ${e.message}" + tvTitle.text = context.getString(R.string.dep_error) + tvMessage.text = context.getString(R.string.dep_update_failed, e.message) btnCancel.visibility = View.GONE btnUpdate.text = "OK" @@ -319,8 +319,8 @@ class DependencyUpdaterDialog( val btnCancel = resultView.findViewById(R.id.btnCancel) val btnUpdate = resultView.findViewById(R.id.btnUpdate) - tvTitle.text = "Update Complete" - tvMessage.text = "Successfully updated: $successCount\nFailed: $failCount" + tvTitle.text = context.getString(R.string.dep_update_complete) + tvMessage.text = context.getString(R.string.dep_update_result, successCount, failCount) btnCancel.visibility = View.GONE btnUpdate.text = "OK" @@ -346,8 +346,8 @@ class DependencyUpdaterDialog( val btnCancel = errorView.findViewById(R.id.btnCancel) val btnUpdate = errorView.findViewById(R.id.btnUpdate) - tvTitle.text = "Error" - tvMessage.text = "Failed to update dependencies: ${e.message}" + tvTitle.text = context.getString(R.string.dep_error) + tvMessage.text = context.getString(R.string.dep_update_all_failed, e.message) btnCancel.visibility = View.GONE btnUpdate.text = "OK" diff --git a/core/app/src/main/java/com/tom/rv2ide/fragments/BranchesFragment.kt b/core/app/src/main/java/com/tom/rv2ide/fragments/BranchesFragment.kt index 105f84ce8..108412f15 100644 --- a/core/app/src/main/java/com/tom/rv2ide/fragments/BranchesFragment.kt +++ b/core/app/src/main/java/com/tom/rv2ide/fragments/BranchesFragment.kt @@ -93,7 +93,7 @@ class BranchesFragment : Fragment() { viewModel.currentBranch.observe(viewLifecycleOwner) { branch -> currentBranch = branch - binding.textCurrentBranch.text = "Current: $branch" + binding.textCurrentBranch.text = getString(R.string.git_current_branch, branch) adapter.notifyDataSetChanged() } @@ -120,33 +120,33 @@ class BranchesFragment : Fragment() { val editText = dialogView.findViewById(R.id.editTextBranchName) MaterialAlertDialogBuilder(requireContext()) - .setTitle("Create New Branch") + .setTitle(getString(R.string.git_create_new_branch)) .setView(dialogView) - .setPositiveButton("Create") { _, _ -> + .setPositiveButton(getString(R.string.git_create_action)) { _, _ -> val branchName = editText.text.toString().trim() if (branchName.isNotBlank()) { viewModel.createBranch(branchName) } else { - Snackbar.make(binding.root, "Branch name cannot be empty", Snackbar.LENGTH_SHORT).show() + Snackbar.make(binding.root, getString(R.string.git_branch_name_empty), Snackbar.LENGTH_SHORT).show() } } - .setNegativeButton("Cancel", null) + .setNegativeButton(getString(R.string.cancel), null) .show() } private fun showDeleteConfirmation(branch: String) { if (branch == currentBranch) { - Snackbar.make(binding.root, "Cannot delete current branch", Snackbar.LENGTH_SHORT).show() + Snackbar.make(binding.root, getString(R.string.git_cannot_delete_current_branch), Snackbar.LENGTH_SHORT).show() return } MaterialAlertDialogBuilder(requireContext()) - .setTitle("Delete Branch") - .setMessage("Are you sure you want to delete branch '$branch'?") - .setPositiveButton("Delete") { _, _ -> + .setTitle(getString(R.string.git_delete_branch)) + .setMessage(getString(R.string.git_delete_branch_message, branch)) + .setPositiveButton(getString(R.string.git_delete_action)) { _, _ -> viewModel.deleteBranch(branch) } - .setNegativeButton("Cancel", null) + .setNegativeButton(getString(R.string.cancel), null) .show() } diff --git a/core/app/src/main/java/com/tom/rv2ide/fragments/ChangesFragment.kt b/core/app/src/main/java/com/tom/rv2ide/fragments/ChangesFragment.kt index c683ac7bc..6eb1c12e0 100644 --- a/core/app/src/main/java/com/tom/rv2ide/fragments/ChangesFragment.kt +++ b/core/app/src/main/java/com/tom/rv2ide/fragments/ChangesFragment.kt @@ -74,19 +74,19 @@ class ChangesFragment : Fragment() { val editText = dialogView.findViewById(R.id.editTextCommitMessage) MaterialAlertDialogBuilder(requireContext()) - .setTitle("Commit Changes") + .setTitle(getString(R.string.git_commit_changes)) .setView(dialogView) - .setPositiveButton("Commit") { _, _ -> + .setPositiveButton(getString(R.string.git_commit_action)) { _, _ -> val message = editText.text.toString() if (message.isNotBlank()) { val author = prefsManager.getGitUserName() val email = prefsManager.getGitUserEmail() viewModel.commit(message, author, email) } else { - Snackbar.make(binding.root, "Commit message cannot be empty", Snackbar.LENGTH_SHORT).show() + Snackbar.make(binding.root, getString(R.string.git_commit_message_empty), Snackbar.LENGTH_SHORT).show() } } - .setNegativeButton("Cancel", null) + .setNegativeButton(getString(R.string.cancel), null) .show() } @@ -142,12 +142,12 @@ class ChangesFragment : Fragment() { private fun showDiscardConfirmation(filePath: String) { MaterialAlertDialogBuilder(requireContext()) - .setTitle("Discard Changes") - .setMessage("Are you sure you want to discard changes in $filePath? This cannot be undone.") - .setPositiveButton("Discard") { _, _ -> + .setTitle(getString(R.string.git_discard_changes)) + .setMessage(getString(R.string.git_discard_changes_message, filePath)) + .setPositiveButton(getString(R.string.git_discard_action)) { _, _ -> viewModel.discardChanges(filePath) } - .setNegativeButton("Cancel", null) + .setNegativeButton(getString(R.string.cancel), null) .show() } diff --git a/core/app/src/main/java/com/tom/rv2ide/fragments/ChatFragment.kt b/core/app/src/main/java/com/tom/rv2ide/fragments/ChatFragment.kt index b8a6e8897..e500aa928 100644 --- a/core/app/src/main/java/com/tom/rv2ide/fragments/ChatFragment.kt +++ b/core/app/src/main/java/com/tom/rv2ide/fragments/ChatFragment.kt @@ -223,14 +223,14 @@ class ChatFragment( val success = aiAgent.setProjectRoot(userRootProject) if (success) { - statusText.text = "Project loaded successfully" + statusText.text = getString(R.string.chat_project_loaded) showSnackbar("✦ Project loaded: ${userRootProject.substringAfterLast("/")}") } else { - statusText.text = "Failed to load project" + statusText.text = getString(R.string.chat_project_load_failed) showSnackbar("✗ Project not found or invalid path") } } catch (e: Exception) { - statusText.text = "Error loading project" + statusText.text = getString(R.string.chat_project_load_error) showSnackbar("Error: ${e.message}") } } @@ -390,7 +390,7 @@ class ChatFragment( aiAgent.clearConversation() promptInput.text?.clear() - statusText.text = "Conversation cleared. Ready for new request." + statusText.text = getString(R.string.chat_conversation_cleared) fileModificationList.visibility = View.GONE summaryCard.visibility = View.GONE fileModificationAdapter.clear() diff --git a/core/app/src/main/java/com/tom/rv2ide/fragments/FileBrowserDialogFragment.kt b/core/app/src/main/java/com/tom/rv2ide/fragments/FileBrowserDialogFragment.kt index 8f58442ca..2b3f1fd46 100644 --- a/core/app/src/main/java/com/tom/rv2ide/fragments/FileBrowserDialogFragment.kt +++ b/core/app/src/main/java/com/tom/rv2ide/fragments/FileBrowserDialogFragment.kt @@ -277,7 +277,7 @@ class FileBrowserDialogFragment : DialogFragment() { val destinationFile = File(destinationDir, sourceFile.name) if (!sourceFile.exists()) { - Toast.makeText(requireContext(), "Source file doesn't exist", Toast.LENGTH_SHORT).show() + Toast.makeText(requireContext(), getString(R.string.file_source_not_exist), Toast.LENGTH_SHORT).show() return } @@ -359,7 +359,7 @@ class FileBrowserDialogFragment : DialogFragment() { val destinationFile = File(destinationDir, sourceFile.name) if (!sourceFile.exists()) { - Toast.makeText(requireContext(), "Source file doesn't exist", Toast.LENGTH_SHORT).show() + Toast.makeText(requireContext(), getString(R.string.file_source_not_exist), Toast.LENGTH_SHORT).show() return } @@ -482,19 +482,19 @@ class FileBrowserDialogFragment : DialogFragment() { val file = File(path) if (!file.exists()) { - Toast.makeText(requireContext(), "Directory doesn't exist: ${file.name}", Toast.LENGTH_SHORT).show() + Toast.makeText(requireContext(), getString(R.string.file_dir_not_exist, file.name), Toast.LENGTH_SHORT).show() return } if (!file.canRead()) { - Toast.makeText(requireContext(), "Cannot read directory: ${file.name}", Toast.LENGTH_SHORT).show() + Toast.makeText(requireContext(), getString(R.string.file_dir_cannot_read, file.name), Toast.LENGTH_SHORT).show() return } val filesAndFolders = file.listFiles() if (filesAndFolders == null) { - Toast.makeText(requireContext(), "Cannot access folder", Toast.LENGTH_SHORT).show() + Toast.makeText(requireContext(), getString(R.string.file_cannot_access_folder), Toast.LENGTH_SHORT).show() return } diff --git a/core/app/src/main/java/com/tom/rv2ide/fragments/FileBrowserFragment.kt b/core/app/src/main/java/com/tom/rv2ide/fragments/FileBrowserFragment.kt index 95ddead4f..d1f710365 100644 --- a/core/app/src/main/java/com/tom/rv2ide/fragments/FileBrowserFragment.kt +++ b/core/app/src/main/java/com/tom/rv2ide/fragments/FileBrowserFragment.kt @@ -308,10 +308,10 @@ class FileBrowserFragment : Fragment() { } MaterialAlertDialogBuilder(requireContext()) - .setTitle("Enter Custom Extension") - .setMessage("Enter file extension without the dot") + .setTitle(getString(R.string.file_custom_extension_title)) + .setMessage(getString(R.string.file_custom_extension_message)) .setView(input) - .setPositiveButton("Apply") { _, _ -> + .setPositiveButton(getString(R.string.action_apply)) { _, _ -> val extension = input.text.toString().trim() if (extension.isNotEmpty()) { filterPrefs.activeExtensions.add(ExtensionFilter.CUSTOM) @@ -319,7 +319,7 @@ class FileBrowserFragment : Fragment() { applyFilters() } } - .setNegativeButton("Cancel", null) + .setNegativeButton(getString(R.string.action_cancel), null) .show() } @@ -370,7 +370,7 @@ class FileBrowserFragment : Fragment() { fileAdapter.updateData(filteredList) if (filteredList.isEmpty()) { - Toast.makeText(requireContext(), "No files match the filters", Toast.LENGTH_SHORT).show() + Toast.makeText(requireContext(), getString(R.string.file_no_match), Toast.LENGTH_SHORT).show() } } @@ -443,15 +443,15 @@ class FileBrowserFragment : Fragment() { } MaterialAlertDialogBuilder(requireContext()) - .setTitle("Rename") - .setMessage("Enter new name for ${fileItem.name}") + .setTitle(getString(R.string.file_rename_title)) + .setMessage(getString(R.string.file_rename_message, fileItem.name)) .setView(input) - .setPositiveButton("Rename") { _, _ -> + .setPositiveButton(getString(R.string.action_rename)) { _, _ -> val newName = input.text.toString().trim() if (newName.isNotEmpty() && newName != fileItem.name) { renameFile(fileItem, newName) } else if (newName.isEmpty()) { - Toast.makeText(requireContext(), "Name cannot be empty", Toast.LENGTH_SHORT).show() + Toast.makeText(requireContext(), getString(R.string.file_name_empty), Toast.LENGTH_SHORT).show() } } .setNegativeButton("Cancel", null) @@ -465,15 +465,15 @@ class FileBrowserFragment : Fragment() { val newFile = File(oldFile.parent, newName) if (newFile.exists()) { - Toast.makeText(requireContext(), "A file with this name already exists", Toast.LENGTH_SHORT).show() + Toast.makeText(requireContext(), getString(R.string.file_name_exists), Toast.LENGTH_SHORT).show() return } if (oldFile.renameTo(newFile)) { - Toast.makeText(requireContext(), "Renamed successfully", Toast.LENGTH_SHORT).show() + Toast.makeText(requireContext(), getString(R.string.file_renamed_success), Toast.LENGTH_SHORT).show() listFiles(currentPath) } else { - Toast.makeText(requireContext(), "Failed to rename", Toast.LENGTH_SHORT).show() + Toast.makeText(requireContext(), getString(R.string.file_renamed_failed), Toast.LENGTH_SHORT).show() } } @@ -481,7 +481,7 @@ class FileBrowserFragment : Fragment() { val clipboard = requireContext().getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager val clip = ClipData.newPlainText("File Path", fileItem.path) clipboard.setPrimaryClip(clip) - Toast.makeText(requireContext(), "Path copied to clipboard", Toast.LENGTH_SHORT).show() + Toast.makeText(requireContext(), getString(R.string.file_path_copied), Toast.LENGTH_SHORT).show() } private fun showDeleteConfirmation(fileItem: FileItem) { @@ -493,12 +493,12 @@ class FileBrowserFragment : Fragment() { } MaterialAlertDialogBuilder(requireContext()) - .setTitle("Delete $fileType") + .setTitle(getString(R.string.file_delete_title, fileType)) .setMessage(message) - .setPositiveButton("Delete") { _, _ -> + .setPositiveButton(getString(R.string.action_delete)) { _, _ -> deleteFile(fileItem) } - .setNegativeButton("Cancel", null) + .setNegativeButton(getString(R.string.action_cancel), null) .show() } @@ -506,10 +506,10 @@ class FileBrowserFragment : Fragment() { val file = File(fileItem.path) if (file.deleteRecursively()) { - Toast.makeText(requireContext(), "Deleted successfully", Toast.LENGTH_SHORT).show() + Toast.makeText(requireContext(), getString(R.string.file_deleted_success), Toast.LENGTH_SHORT).show() listFiles(currentPath) } else { - Toast.makeText(requireContext(), "Failed to delete", Toast.LENGTH_SHORT).show() + Toast.makeText(requireContext(), getString(R.string.file_deleted_failed), Toast.LENGTH_SHORT).show() } } @@ -562,7 +562,7 @@ class FileBrowserFragment : Fragment() { val filesAndFolders = file.listFiles() if (filesAndFolders == null) { - Toast.makeText(requireContext(), "Cannot access this folder", Toast.LENGTH_SHORT).show() + Toast.makeText(requireContext(), getString(R.string.file_cannot_access), Toast.LENGTH_SHORT).show() return } diff --git a/core/app/src/main/java/com/tom/rv2ide/fragments/HistoryAdapter.kt b/core/app/src/main/java/com/tom/rv2ide/fragments/HistoryAdapter.kt index 7fc3f9ca9..0ead5a07d 100644 --- a/core/app/src/main/java/com/tom/rv2ide/fragments/HistoryAdapter.kt +++ b/core/app/src/main/java/com/tom/rv2ide/fragments/HistoryAdapter.kt @@ -48,7 +48,7 @@ class HistoryAdapter : RecyclerView.Adapter() historyTitle.text = "$status $fileName" historyTime.text = dateFormat.format(Date(item.timestamp)) - historyDetails.text = "Attempt #${item.attemptNumber} - ${if (item.success) "Success" else "Failed"}" + historyDetails.text = itemView.context.getString(R.string.history_attempt, item.attemptNumber, if (item.success) itemView.context.getString(R.string.dep_success) else itemView.context.getString(R.string.dep_error)) // Set icon tint based on success/failure val colorRes = if (item.success) { diff --git a/core/app/src/main/java/com/tom/rv2ide/fragments/InitFragment.kt b/core/app/src/main/java/com/tom/rv2ide/fragments/InitFragment.kt index eb6cd950b..9f099652f 100644 --- a/core/app/src/main/java/com/tom/rv2ide/fragments/InitFragment.kt +++ b/core/app/src/main/java/com/tom/rv2ide/fragments/InitFragment.kt @@ -84,7 +84,7 @@ class InitFragment : Fragment() { // Repository is ready, MainActivity will handle navigation } RepositoryStatus.ERROR -> { - Snackbar.make(binding.root, "Failed to initialize repository", Snackbar.LENGTH_LONG).show() + Snackbar.make(binding.root, getString(R.string.git_init_failed), Snackbar.LENGTH_LONG).show() } else -> {} } @@ -142,17 +142,17 @@ class InitFragment : Fragment() { editText.setText("main") MaterialAlertDialogBuilder(requireContext()) - .setTitle("Initialize Repository") - .setMessage("Initialize a new Git repository at:\n${GCProperties.userProject}\n\nChoose initial branch name:") + .setTitle(getString(R.string.git_initialize_repo)) + .setMessage(getString(R.string.git_initialize_repo_message, GCProperties.userProject)) .setView(dialogView) - .setPositiveButton("Initialize") { _, _ -> + .setPositiveButton(getString(R.string.git_initialize_action)) { _, _ -> val branchName = editText.text.toString().trim() val finalBranchName = if (branchName.isBlank()) "main" else branchName createGitIgnoreAndOthers() viewModel.initializeRepository(GCProperties.userProject, finalBranchName) } - .setNegativeButton("Cancel", null) + .setNegativeButton(getString(R.string.cancel), null) .show() } @@ -163,10 +163,10 @@ class InitFragment : Fragment() { val editTextPassword = dialogView.findViewById(R.id.editTextClonePassword) MaterialAlertDialogBuilder(requireContext()) - .setTitle("Clone Repository") - .setMessage("Clone to: ${GCProperties.userProject}") + .setTitle(getString(R.string.git_clone_repository)) + .setMessage(getString(R.string.git_clone_to, GCProperties.userProject)) .setView(dialogView) - .setPositiveButton("Clone") { _, _ -> + .setPositiveButton(getString(R.string.git_clone_action)) { _, _ -> val url = editTextUrl.text.toString() val username = editTextUsername.text.toString().takeIf { it.isNotBlank() } val password = editTextPassword.text.toString().takeIf { it.isNotBlank() } @@ -174,10 +174,10 @@ class InitFragment : Fragment() { if (url.isNotBlank()) { viewModel.cloneRepository(url, GCProperties.userProject, username, password) } else { - Snackbar.make(binding.root, "URL cannot be empty", Snackbar.LENGTH_SHORT).show() + Snackbar.make(binding.root, getString(R.string.git_url_empty), Snackbar.LENGTH_SHORT).show() } } - .setNegativeButton("Cancel", null) + .setNegativeButton(getString(R.string.cancel), null) .show() } diff --git a/core/app/src/main/java/com/tom/rv2ide/fragments/MainFragment.kt b/core/app/src/main/java/com/tom/rv2ide/fragments/MainFragment.kt index 9604f1f0b..92c5fc788 100644 --- a/core/app/src/main/java/com/tom/rv2ide/fragments/MainFragment.kt +++ b/core/app/src/main/java/com/tom/rv2ide/fragments/MainFragment.kt @@ -81,14 +81,13 @@ class MainFragment : BaseFragment() { companion object { private val log = LoggerFactory.getLogger(MainFragment::class.java) - // Common git clone options - private val COMMON_GIT_OPTIONS = + private val COMMON_GIT_OPTION_FLAGS = listOf( - GitOption("--depth 1", "Shallow clone (faster)"), - GitOption("--single-branch", "Clone single branch only"), - GitOption("--recursive", "Clone with submodules"), - GitOption("--no-tags", "Don't fetch tags"), - GitOption("--bare", "Create bare repository"), + "--depth 1", + "--single-branch", + "--recursive", + "--no-tags", + "--bare", ) } @@ -284,7 +283,7 @@ class MainFragment : BaseFragment() { } private fun showProjectOptionsDialog(project: File, onActionComplete: () -> Unit) { - val options = arrayOf("Backup project", "Delete project", "Rename") + val options = arrayOf(getString(R.string.git_backup_project), getString(R.string.git_delete_project_action), getString(R.string.git_rename_action)) val builder = DialogUtils.newMaterialDialogBuilder(requireContext()) builder.setTitle(project.name) @@ -444,11 +443,11 @@ class MainFragment : BaseFragment() { val binding = LayoutDialogProgressBinding.inflate(layoutInflater) binding.message.visibility = View.VISIBLE - binding.message.text = "Backing up project..." + binding.message.text = getString(R.string.git_backing_up_project) binding.progress.isIndeterminate = true - builder.setTitle("Backup in Progress") - builder.setMessage("Creating backup of ${project.name}") + builder.setTitle(getString(R.string.git_backup_in_progress)) + builder.setMessage(getString(R.string.git_creating_backup_of, project.name)) builder.setView(binding.root) builder.setCancelable(false) @@ -483,11 +482,11 @@ class MainFragment : BaseFragment() { dialog.dismiss() val successBuilder = DialogUtils.newMaterialDialogBuilder(requireContext()) - successBuilder.setTitle("Backup Completed") + successBuilder.setTitle(getString(R.string.git_backup_completed)) successBuilder.setMessage( - "Project backed up successfully!\n\nLocation:\n${backupFile.absolutePath}" + getString(R.string.git_backup_success_message, backupFile.absolutePath) ) - successBuilder.setPositiveButton("OK") { d, _ -> + successBuilder.setPositiveButton(getString(R.string.lsp_ok_button)) { d, _ -> d.dismiss() onComplete() } @@ -499,9 +498,9 @@ class MainFragment : BaseFragment() { dialog.dismiss() val errorBuilder = DialogUtils.newMaterialDialogBuilder(requireContext()) - errorBuilder.setTitle("Backup Failed") - errorBuilder.setMessage("Failed to backup project: ${e.localizedMessage}") - errorBuilder.setPositiveButton("OK", null) + errorBuilder.setTitle(getString(R.string.git_backup_failed)) + errorBuilder.setMessage(getString(R.string.git_backup_failed_message, e.localizedMessage)) + errorBuilder.setPositiveButton(getString(R.string.lsp_ok_button), null) errorBuilder.show() } } @@ -527,11 +526,11 @@ class MainFragment : BaseFragment() { val binding = LayoutDialogProgressBinding.inflate(layoutInflater) binding.message.visibility = View.VISIBLE - binding.message.text = "Deleting project..." + binding.message.text = getString(R.string.git_deleting_project) binding.progress.isIndeterminate = true - builder.setTitle("Delete in Progress") - builder.setMessage("Deleting ${project.name}") + builder.setTitle(getString(R.string.git_delete_in_progress)) + builder.setMessage(getString(R.string.git_deleting, project.name)) builder.setView(binding.root) builder.setCancelable(false) @@ -600,12 +599,20 @@ class MainFragment : BaseFragment() { val bottomSheet = BottomSheetDialog(requireContext()) val sheetBinding = BottomsheetGitCloneBinding.inflate(layoutInflater) - COMMON_GIT_OPTIONS.forEach { option -> + val gitOptionDescriptions = mapOf( + "--depth 1" to getString(R.string.git_option_shallow), + "--single-branch" to getString(R.string.git_option_single_branch), + "--recursive" to getString(R.string.git_option_recursive), + "--no-tags" to getString(R.string.git_option_no_tags), + "--bare" to getString(R.string.git_option_bare), + ) + + COMMON_GIT_OPTION_FLAGS.forEach { flag -> val chip = Chip(requireContext()) - chip.text = option.description + chip.text = gitOptionDescriptions[flag] chip.isCheckable = true chip.isCheckedIconVisible = true - chip.tag = option.flag + chip.tag = flag sheetBinding.chipGroup.addView(chip) } diff --git a/core/app/src/main/java/com/tom/rv2ide/fragments/RemotesFragment.kt b/core/app/src/main/java/com/tom/rv2ide/fragments/RemotesFragment.kt index 1899326d7..4eb032ece 100644 --- a/core/app/src/main/java/com/tom/rv2ide/fragments/RemotesFragment.kt +++ b/core/app/src/main/java/com/tom/rv2ide/fragments/RemotesFragment.kt @@ -138,7 +138,7 @@ class RemotesFragment : Fragment() { MaterialAlertDialogBuilder(requireContext()) .setTitle(title) .setMessage(message) - .setPositiveButton("OK", null) + .setPositiveButton(getString(R.string.lsp_ok_button), null) .show() } @@ -152,26 +152,26 @@ class RemotesFragment : Fragment() { } MaterialAlertDialogBuilder(requireContext()) - .setTitle("Add Remote") + .setTitle(getString(R.string.git_add_remote)) .setView(dialogView) - .setPositiveButton("Add") { _, _ -> + .setPositiveButton(getString(R.string.git_add_action)) { _, _ -> val name = editTextName.text.toString().trim() val url = editTextUrl.text.toString().trim() if (name.isNotBlank() && url.isNotBlank()) { viewModel.addRemote(name, url) } else { - showErrorDialog("Invalid Input", "Name and URL cannot be empty") + showErrorDialog(getString(R.string.git_invalid_input), getString(R.string.git_name_url_empty)) } } - .setNegativeButton("Cancel", null) + .setNegativeButton(getString(R.string.cancel), null) .show() } private fun showPushDialog() { val remotesList = adapter.currentList if (remotesList.isEmpty()) { - showErrorDialog("No Remotes", "No remotes configured. Add a remote first.") + showErrorDialog(getString(R.string.git_no_remotes), getString(R.string.git_no_remotes_message)) return } @@ -184,10 +184,10 @@ class RemotesFragment : Fragment() { prefsManager.getPassword()?.let { editTextPassword.setText(it) } MaterialAlertDialogBuilder(requireContext()) - .setTitle("Push to Remote") - .setMessage("Push your commits to ${remotesList[0].name}") + .setTitle(getString(R.string.git_push_to_remote)) + .setMessage(getString(R.string.git_push_message, remotesList[0].name)) .setView(dialogView) - .setPositiveButton("Push") { _, _ -> + .setPositiveButton(getString(R.string.git_push_action)) { _, _ -> val username = editTextUsername.text.toString().takeIf { it.isNotBlank() } val password = editTextPassword.text.toString().takeIf { it.isNotBlank() } @@ -202,8 +202,8 @@ class RemotesFragment : Fragment() { password = password ) } - .setNegativeButton("Cancel", null) - .setNeutralButton("Without credentials") { _, _ -> + .setNegativeButton(getString(R.string.cancel), null) + .setNeutralButton(getString(R.string.git_without_credentials)) { _, _ -> viewModel.push(remoteName = remotesList[0].name) } .show() @@ -212,7 +212,7 @@ class RemotesFragment : Fragment() { private fun showPullDialog() { val remotesList = adapter.currentList if (remotesList.isEmpty()) { - showErrorDialog("No Remotes", "No remotes configured. Add a remote first.") + showErrorDialog(getString(R.string.git_no_remotes), getString(R.string.git_no_remotes_message)) return } @@ -224,10 +224,10 @@ class RemotesFragment : Fragment() { prefsManager.getPassword()?.let { editTextPassword.setText(it) } MaterialAlertDialogBuilder(requireContext()) - .setTitle("Pull from Remote") - .setMessage("Pull changes from ${remotesList[0].name}") + .setTitle(getString(R.string.git_pull_from_remote)) + .setMessage(getString(R.string.git_pull_message, remotesList[0].name)) .setView(dialogView) - .setPositiveButton("Pull") { _, _ -> + .setPositiveButton(getString(R.string.git_pull_action)) { _, _ -> val username = editTextUsername.text.toString().takeIf { it.isNotBlank() } val password = editTextPassword.text.toString().takeIf { it.isNotBlank() } @@ -242,8 +242,8 @@ class RemotesFragment : Fragment() { password = password ) } - .setNegativeButton("Cancel", null) - .setNeutralButton("Without credentials") { _, _ -> + .setNegativeButton(getString(R.string.cancel), null) + .setNeutralButton(getString(R.string.git_without_credentials)) { _, _ -> viewModel.pull(remoteName = remotesList[0].name) } .show() @@ -252,7 +252,7 @@ class RemotesFragment : Fragment() { private fun showFetchDialog() { val remotesList = adapter.currentList if (remotesList.isEmpty()) { - showErrorDialog("No Remotes", "No remotes configured. Add a remote first.") + showErrorDialog(getString(R.string.git_no_remotes), getString(R.string.git_no_remotes_message)) return } @@ -265,10 +265,10 @@ class RemotesFragment : Fragment() { prefsManager.getPassword()?.let { editTextPassword.setText(it) } MaterialAlertDialogBuilder(requireContext()) - .setTitle("Fetch from Remote") - .setMessage("Fetch changes from ${remotesList[0].name}") + .setTitle(getString(R.string.git_fetch_from_remote)) + .setMessage(getString(R.string.git_fetch_message, remotesList[0].name)) .setView(dialogView) - .setPositiveButton("Fetch") { _, _ -> + .setPositiveButton(getString(R.string.git_fetch_action)) { _, _ -> val username = editTextUsername.text.toString().takeIf { it.isNotBlank() } val password = editTextPassword.text.toString().takeIf { it.isNotBlank() } @@ -283,8 +283,8 @@ class RemotesFragment : Fragment() { password = password ) } - .setNegativeButton("Cancel", null) - .setNeutralButton("Without credentials") { _, _ -> + .setNegativeButton(getString(R.string.cancel), null) + .setNeutralButton(getString(R.string.git_without_credentials)) { _, _ -> viewModel.fetch(remoteName = remotesList[0].name) } .show() @@ -292,12 +292,12 @@ class RemotesFragment : Fragment() { private fun showRemoveRemoteConfirmation(remoteName: String) { MaterialAlertDialogBuilder(requireContext()) - .setTitle("Remove Remote") - .setMessage("Are you sure you want to remove remote '$remoteName'?") - .setPositiveButton("Remove") { _, _ -> + .setTitle(getString(R.string.git_remove_remote)) + .setMessage(getString(R.string.git_remove_remote_message, remoteName)) + .setPositiveButton(getString(R.string.git_remove_action)) { _, _ -> viewModel.removeRemote(remoteName) } - .setNegativeButton("Cancel", null) + .setNegativeButton(getString(R.string.cancel), null) .show() } diff --git a/core/app/src/main/java/com/tom/rv2ide/fragments/SettingsFragment.kt b/core/app/src/main/java/com/tom/rv2ide/fragments/SettingsFragment.kt index 859ed1f72..cf426d727 100644 --- a/core/app/src/main/java/com/tom/rv2ide/fragments/SettingsFragment.kt +++ b/core/app/src/main/java/com/tom/rv2ide/fragments/SettingsFragment.kt @@ -65,7 +65,7 @@ class SettingsFragment : Fragment() { binding.switchRememberCredentials.isChecked = prefsManager.shouldRememberCredentials() val hasCredentials = prefsManager.getUsername() != null - binding.textCredentialsStatus.text = if (hasCredentials) "Saved" else "Not saved" + binding.textCredentialsStatus.text = if (hasCredentials) getString(R.string.git_credentials_saved) else getString(R.string.git_credentials_not_saved) } private fun setupButtons() { @@ -77,20 +77,20 @@ class SettingsFragment : Fragment() { prefsManager.setRememberCredentials(isChecked) if (!isChecked) { prefsManager.clearCredentials() - binding.textCredentialsStatus.text = "Not saved" + binding.textCredentialsStatus.text = getString(R.string.git_credentials_not_saved) } } binding.buttonClearCredentials.setOnClickListener { MaterialAlertDialogBuilder(requireContext()) - .setTitle("Clear Credentials") - .setMessage("Are you sure you want to clear saved credentials?") - .setPositiveButton("Clear") { _, _ -> + .setTitle(getString(R.string.git_clear_credentials)) + .setMessage(getString(R.string.git_clear_credentials_message)) + .setPositiveButton(getString(R.string.git_clear_action)) { _, _ -> prefsManager.clearCredentials() - binding.textCredentialsStatus.text = "Not saved" - Snackbar.make(binding.root, "Credentials cleared", Snackbar.LENGTH_SHORT).show() + binding.textCredentialsStatus.text = getString(R.string.git_credentials_not_saved) + Snackbar.make(binding.root, getString(R.string.git_credentials_cleared), Snackbar.LENGTH_SHORT).show() } - .setNegativeButton("Cancel", null) + .setNegativeButton(getString(R.string.cancel), null) .show() } } @@ -104,9 +104,9 @@ class SettingsFragment : Fragment() { editTextEmail.setText(prefsManager.getGitUserEmail()) MaterialAlertDialogBuilder(requireContext()) - .setTitle("Git User Config") + .setTitle(getString(R.string.git_user_config)) .setView(dialogView) - .setPositiveButton("Save") { _, _ -> + .setPositiveButton(getString(R.string.git_save_action)) { _, _ -> val name = editTextName.text.toString().trim() val email = editTextEmail.text.toString().trim() @@ -115,12 +115,12 @@ class SettingsFragment : Fragment() { prefsManager.setGitUserEmail(email) viewModel.setUserConfig(name, email) loadSettings() - Snackbar.make(binding.root, "User config updated", Snackbar.LENGTH_SHORT).show() + Snackbar.make(binding.root, getString(R.string.git_user_config_updated), Snackbar.LENGTH_SHORT).show() } else { - Snackbar.make(binding.root, "Name and email cannot be empty", Snackbar.LENGTH_SHORT).show() + Snackbar.make(binding.root, getString(R.string.git_name_email_empty), Snackbar.LENGTH_SHORT).show() } } - .setNegativeButton("Cancel", null) + .setNegativeButton(getString(R.string.cancel), null) .show() } diff --git a/core/app/src/main/java/com/tom/rv2ide/fragments/sidebar/utils/FileTree/DialogProjectSettings.kt b/core/app/src/main/java/com/tom/rv2ide/fragments/sidebar/utils/FileTree/DialogProjectSettings.kt index af428dc73..a0304cf6d 100644 --- a/core/app/src/main/java/com/tom/rv2ide/fragments/sidebar/utils/FileTree/DialogProjectSettings.kt +++ b/core/app/src/main/java/com/tom/rv2ide/fragments/sidebar/utils/FileTree/DialogProjectSettings.kt @@ -90,11 +90,11 @@ class DialogProjectSettings(private val context: Context) { val binding = LayoutDialogProgressBinding.inflate(LayoutInflater.from(context)) binding.message.visibility = View.VISIBLE - binding.message.text = "Backing up project..." + binding.message.text = context.getString(R.string.project_backing_up) binding.progress.isIndeterminate = true - builder.setTitle("Backup in Progress") - builder.setMessage("Creating backup of ${project.name}") + builder.setTitle(context.getString(R.string.project_backup_in_progress)) + builder.setMessage(context.getString(R.string.project_backup_message, project.name)) builder.setView(binding.root) builder.setCancelable(false) @@ -128,11 +128,11 @@ class DialogProjectSettings(private val context: Context) { progressDialog.dismiss() val successBuilder = DialogUtils.newMaterialDialogBuilder(context) - successBuilder.setTitle("Backup Completed") + successBuilder.setTitle(context.getString(R.string.project_backup_completed)) successBuilder.setMessage( "Project backed up successfully!\n\nLocation:\n${backupFile.absolutePath}" ) - successBuilder.setPositiveButton("OK") { d, _ -> + successBuilder.setPositiveButton(context.getString(R.string.action_ok)) { d, _ -> d.dismiss() onComplete() } @@ -143,9 +143,9 @@ class DialogProjectSettings(private val context: Context) { progressDialog.dismiss() val errorBuilder = DialogUtils.newMaterialDialogBuilder(context) - errorBuilder.setTitle("Backup Failed") - errorBuilder.setMessage("Failed to backup project: ${e.localizedMessage}") - errorBuilder.setPositiveButton("OK", null) + errorBuilder.setTitle(context.getString(R.string.project_backup_failed)) + errorBuilder.setMessage(context.getString(R.string.project_backup_failed_message, e.localizedMessage)) + errorBuilder.setPositiveButton(context.getString(R.string.action_ok), null) errorBuilder.show() } } diff --git a/core/app/src/main/java/com/tom/rv2ide/fragments/sidebar/utils/LiveResponseRenderer.kt b/core/app/src/main/java/com/tom/rv2ide/fragments/sidebar/utils/LiveResponseRenderer.kt index 4d585f166..bca9deb5e 100644 --- a/core/app/src/main/java/com/tom/rv2ide/fragments/sidebar/utils/LiveResponseRenderer.kt +++ b/core/app/src/main/java/com/tom/rv2ide/fragments/sidebar/utils/LiveResponseRenderer.kt @@ -33,6 +33,7 @@ import com.blankj.utilcode.util.ThreadUtils import com.google.android.material.button.MaterialButton import com.google.android.material.card.MaterialCardView import com.google.android.material.textview.MaterialTextView +import com.tom.rv2ide.R import org.slf4j.LoggerFactory /* !! DEPRECATED @@ -301,7 +302,7 @@ class LiveResponseRenderer( val clipboard = context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager val clip = ClipData.newPlainText("code", codeContent.toString()) clipboard.setPrimaryClip(clip) - Toast.makeText(context, "Code copied to clipboard", Toast.LENGTH_SHORT).show() + Toast.makeText(context, context.getString(R.string.file_code_copied), Toast.LENGTH_SHORT).show() } /** Apply basic syntax highlighting based on language */ diff --git a/core/app/src/main/java/com/tom/rv2ide/handlers/EditorBuildEventListener.kt b/core/app/src/main/java/com/tom/rv2ide/handlers/EditorBuildEventListener.kt index 2e55222a3..d112def5f 100644 --- a/core/app/src/main/java/com/tom/rv2ide/handlers/EditorBuildEventListener.kt +++ b/core/app/src/main/java/com/tom/rv2ide/handlers/EditorBuildEventListener.kt @@ -176,14 +176,14 @@ class EditorBuildEventListener : GradleBuildService.EventListener { /** Show dialog when NDK is not installed but required */ private fun showNdkNotInstalledDialog(context: Context, onDismiss: () -> Unit = {}) { MaterialAlertDialogBuilder(context) - .setTitle("NDK Not Found") + .setTitle(context.getString(R.string.ndk_not_found_title)) .setMessage( "A compatible NDK (version 28.2.13676358) is not installed.\n\n" + "Native code features will be disabled for this project.\n\n" + "To enable native development, please install NDK version 28.2.13676358 " + "open a terminal then run: 'idesetup -y -c -wn'." ) - .setPositiveButton("OK") { dialog, _ -> + .setPositiveButton(context.getString(R.string.action_ok)) { dialog, _ -> dialog.dismiss() onDismiss() } diff --git a/core/app/src/main/java/com/tom/rv2ide/handlers/FileTreeActionHandler.kt b/core/app/src/main/java/com/tom/rv2ide/handlers/FileTreeActionHandler.kt index ff3980bc6..0922e9b7f 100644 --- a/core/app/src/main/java/com/tom/rv2ide/handlers/FileTreeActionHandler.kt +++ b/core/app/src/main/java/com/tom/rv2ide/handlers/FileTreeActionHandler.kt @@ -19,6 +19,7 @@ package com.tom.rv2ide.handlers import android.content.Context import androidx.core.view.GravityCompat +import com.tom.rv2ide.R import com.tom.rv2ide.actions.ActionData import com.tom.rv2ide.actions.ActionItem.Location.EDITOR_FILE_TREE import com.tom.rv2ide.actions.ActionMenu @@ -81,7 +82,7 @@ class FileTreeActionHandler : BaseEventHandler() { } if (MB_10 < event.file.length()) { - flashError("File is too big!") + flashError(context.getString(R.string.msg_file_too_big)) log.warn( "Cannot open {} as it is too big. File size: {} bytes", event.file, diff --git a/core/app/src/main/java/com/tom/rv2ide/handlers/system/ICMake.kt b/core/app/src/main/java/com/tom/rv2ide/handlers/system/ICMake.kt index 64ab61141..74362f9dc 100644 --- a/core/app/src/main/java/com/tom/rv2ide/handlers/system/ICMake.kt +++ b/core/app/src/main/java/com/tom/rv2ide/handlers/system/ICMake.kt @@ -126,14 +126,14 @@ class ICMake( when { availableVersions.isEmpty() -> { - Toast.makeText(context, "No CMake versions found to remove", Toast.LENGTH_SHORT).show() + Toast.makeText(context, context.getString(R.string.cmake_no_versions), Toast.LENGTH_SHORT).show() } availableVersions.size == 1 -> { removeCmakeVersion(availableVersions.first()) } else -> { showVersionSelectionDialog( - title = "Select CMake Version to Remove", + title = context.getString(R.string.select_cmake_version_remove), versions = availableVersions, onVersionSelected = { selectedVersion -> removeCmakeVersion(selectedVersion) }, ) @@ -163,7 +163,7 @@ class ICMake( selectedVersion == "Loading versions..." || selectedVersion == "No versions available" ) { - flashError("Please select a CMake version from the dropdown first") + flashError(context.getString(R.string.msg_select_cmake_first)) return } @@ -181,19 +181,19 @@ class ICMake( private fun removeCmakeVersion(version: String) { val utils = IDEUtils() MaterialAlertDialogBuilder(context) - .setTitle("Remove CMake") - .setMessage("Are you sure you want to remove CMake version $version?") - .setPositiveButton("Remove") { dialog, _ -> + .setTitle(context.getString(R.string.cmake_remove_title)) + .setMessage(context.getString(R.string.cmake_remove_message, version)) + .setPositiveButton(context.getString(R.string.action_remove)) { dialog, _ -> if (utils.deleteCMake(context, version)) { - Toast.makeText(context, "Successfully removed CMake $version", Toast.LENGTH_SHORT) + Toast.makeText(context, context.getString(R.string.cmake_removed_success, version), Toast.LENGTH_SHORT) .show() updateStatus() } else { - Toast.makeText(context, "Failed to remove CMake $version", Toast.LENGTH_SHORT).show() + Toast.makeText(context, context.getString(R.string.cmake_removed_failed, version), Toast.LENGTH_SHORT).show() } dialog.dismiss() } - .setNegativeButton("Cancel") { dialog, _ -> dialog.dismiss() } + .setNegativeButton(context.getString(R.string.action_cancel)) { dialog, _ -> dialog.dismiss() } .create() .show() } @@ -210,7 +210,7 @@ class ICMake( onVersionSelected(selectedVersion) dialog.dismiss() } - .setNegativeButton("Cancel") { dialog, _ -> dialog.dismiss() } + .setNegativeButton(context.getString(R.string.action_cancel)) { dialog, _ -> dialog.dismiss() } .create() .show() } @@ -224,7 +224,7 @@ class ICMake( onNegativeClick = { val cpuArch = getCpuArchitecture() if (!listOf("armeabi-v7a", "arm64-v8a", "x86_64").contains(cpuArch)) { - flashError("Unsupported architecture: $cpuArch") + flashError(context.getString(R.string.msg_unsupported_arch, cpuArch)) return@showErrorDialog } @@ -253,13 +253,13 @@ class ICMake( infoFlashbar.dismiss() if (!filenameResult.success) { - flashError("Failed to get package filename: ${filenameResult.errorOutput}") + flashError(context.getString(R.string.msg_failed_get_filename, filenameResult.errorOutput)) return@launch } val filename = filenameResult.output.trim() if (filename.isEmpty()) { - flashError("Empty filename received from manifest") + flashError(context.getString(R.string.msg_empty_filename)) return@launch } @@ -278,7 +278,7 @@ class ICMake( downloadFlashbar.dismiss() if (downloadResult.output.contains("successfully", ignoreCase = true)) { - val successFlash = flashSuccess("Successfully downloaded") + val successFlash = flashSuccess(context.getString(R.string.msg_successfully_downloaded)) lifecycleScope.launch(Dispatchers.IO) { delay(1000) @@ -300,13 +300,13 @@ class ICMake( withContext(Dispatchers.Main) { extractFlashbar.dismiss() - flashSuccess("Installation completed successfully!") + flashSuccess(context.getString(R.string.lsp_installed_summary)) updateStatus() } } catch (e: Exception) { withContext(Dispatchers.Main) { extractFlashbar.dismiss() - flashError("Installation failed: ${e.message}") + flashError(context.getString(R.string.msg_installation_failed_with_error, e.message)) android.util.Log.e("ICMake", "Extraction error", e) } } @@ -317,7 +317,7 @@ class ICMake( } else { showErrorDialog( ctx = context, - title = "Download Failed", + title = context.getString(R.string.lsp_server_error_title), message = "Package verification failed:\n${downloadResult.output}\n${downloadResult.errorOutput}", negativeBtnTitle = "OK", @@ -327,7 +327,7 @@ class ICMake( } catch (e: Exception) { withContext(Dispatchers.Main) { downloadFlashbar.dismiss() - flashError("Download failed: ${e.message}") + flashError(context.getString(R.string.msg_download_failed_with_error, e.message)) e.printStackTrace() } } @@ -335,7 +335,7 @@ class ICMake( } } catch (e: Exception) { infoFlashbar.dismiss() - flashError("Failed to get package info: ${e.message}") + flashError(context.getString(R.string.msg_failed_get_package_info, e.message)) e.printStackTrace() } } diff --git a/core/app/src/main/java/com/tom/rv2ide/handlers/system/INdk.kt b/core/app/src/main/java/com/tom/rv2ide/handlers/system/INdk.kt index c96667cfd..b0bcd2eff 100644 --- a/core/app/src/main/java/com/tom/rv2ide/handlers/system/INdk.kt +++ b/core/app/src/main/java/com/tom/rv2ide/handlers/system/INdk.kt @@ -122,14 +122,14 @@ class INdk( when { availableVersions.isEmpty() -> { - Toast.makeText(context, "No NDK versions found to remove", Toast.LENGTH_SHORT).show() + Toast.makeText(context, context.getString(R.string.ndk_no_versions), Toast.LENGTH_SHORT).show() } availableVersions.size == 1 -> { removeNdkVersion(availableVersions.first()) } else -> { showVersionSelectionDialog( - title = "Select NDK Version to Remove", + title = context.getString(R.string.select_ndk_version_remove), versions = availableVersions, onVersionSelected = { selectedVersion -> removeNdkVersion(selectedVersion) }, ) @@ -159,7 +159,7 @@ class INdk( selectedVersion == "Loading versions..." || selectedVersion == "No versions available" ) { - flashError("Please select ndk version from the dropdown first") + flashError(context.getString(R.string.msg_select_ndk_first)) return } @@ -177,21 +177,21 @@ class INdk( private fun removeNdkVersion(version: String) { val utils = IDEUtils() MaterialAlertDialogBuilder(context) - .setTitle("Remove NDK") - .setMessage("Are you sure you want to remove NDK version $version?") - .setPositiveButton("Remove") { dialog, _ -> + .setTitle(context.getString(R.string.ndk_remove_title)) + .setMessage(context.getString(R.string.ndk_remove_message, version)) + .setPositiveButton(context.getString(R.string.action_remove)) { dialog, _ -> if (utils.deleteNdk(context, version)) { if (version == getVersion()) { prefManager.putBoolean("ndk_installed", false) } - Toast.makeText(context, "Successfully removed NDK $version", Toast.LENGTH_SHORT).show() + Toast.makeText(context, context.getString(R.string.ndk_removed_success, version), Toast.LENGTH_SHORT).show() updateStatus() } else { - Toast.makeText(context, "Failed to remove NDK $version", Toast.LENGTH_SHORT).show() + Toast.makeText(context, context.getString(R.string.ndk_removed_failed, version), Toast.LENGTH_SHORT).show() } dialog.dismiss() } - .setNegativeButton("Cancel") { dialog, _ -> dialog.dismiss() } + .setNegativeButton(context.getString(R.string.action_cancel)) { dialog, _ -> dialog.dismiss() } .create() .show() } @@ -208,7 +208,7 @@ class INdk( onVersionSelected(selectedVersion) dialog.dismiss() } - .setNegativeButton("Cancel") { dialog, _ -> dialog.dismiss() } + .setNegativeButton(context.getString(R.string.action_cancel)) { dialog, _ -> dialog.dismiss() } .create() .show() } @@ -222,7 +222,7 @@ class INdk( onNegativeClick = { val cpuArch = getCpuArchitecture() if (!listOf("armeabi-v7a", "arm64-v8a", "x86_64").contains(cpuArch)) { - flashError("Unsupported architecture: $cpuArch") + flashError(context.getString(R.string.msg_unsupported_arch, cpuArch)) return@showErrorDialog } @@ -251,13 +251,13 @@ class INdk( infoFlashbar.dismiss() if (!filenameResult.success) { - flashError("Failed to get package filename: ${filenameResult.errorOutput}") + flashError(context.getString(R.string.msg_failed_get_filename, filenameResult.errorOutput)) return@launch } val filename = filenameResult.output.trim() if (filename.isEmpty()) { - flashError("Empty filename received from manifest") + flashError(context.getString(R.string.msg_empty_filename)) return@launch } @@ -276,7 +276,7 @@ class INdk( downloadFlashbar.dismiss() if (downloadResult.output.contains("successfully", ignoreCase = true)) { - val successFlash = flashSuccess("Successfully downloaded") + val successFlash = flashSuccess(context.getString(R.string.msg_successfully_downloaded)) lifecycleScope.launch(Dispatchers.IO) { delay(1000) @@ -298,7 +298,7 @@ class INdk( withContext(Dispatchers.Main) { extractFlashbar.dismiss() prefManager.putBoolean("ndk_installed", true) - flashSuccess("Installation completed successfully!") + flashSuccess(context.getString(R.string.lsp_installed_summary)) renameDir(NDK_DIR.absolutePath, "$version") updateNdkBuild(version) updateStatus() @@ -306,7 +306,7 @@ class INdk( } catch (e: Exception) { withContext(Dispatchers.Main) { extractFlashbar.dismiss() - flashError("Installation failed: ${e.message}") + flashError(context.getString(R.string.msg_installation_failed_with_error, e.message)) e.printStackTrace() } } @@ -317,7 +317,7 @@ class INdk( } else { showErrorDialog( ctx = context, - title = "Download Failed", + title = context.getString(R.string.lsp_server_error_title), message = "Package verification failed:\n${downloadResult.output}\n${downloadResult.errorOutput}", negativeBtnTitle = "OK", @@ -327,7 +327,7 @@ class INdk( } catch (e: Exception) { withContext(Dispatchers.Main) { downloadFlashbar.dismiss() - flashError("Download failed: ${e.message}") + flashError(context.getString(R.string.msg_download_failed_with_error, e.message)) e.printStackTrace() } } @@ -335,7 +335,7 @@ class INdk( } } catch (e: Exception) { infoFlashbar.dismiss() - flashError("Failed to get package info: ${e.message}") + flashError(context.getString(R.string.msg_failed_get_package_info, e.message)) e.printStackTrace() } } diff --git a/core/app/src/main/java/com/tom/rv2ide/preferences/aiAgentPrefExts.kt b/core/app/src/main/java/com/tom/rv2ide/preferences/aiAgentPrefExts.kt index fe3c8eb8f..2477d77c4 100644 --- a/core/app/src/main/java/com/tom/rv2ide/preferences/aiAgentPrefExts.kt +++ b/core/app/src/main/java/com/tom/rv2ide/preferences/aiAgentPrefExts.kt @@ -132,15 +132,15 @@ private class GrokApiKey( val dialog = com.google.android.material.dialog .MaterialAlertDialogBuilder(context) - .setTitle("Grok API Key") - .setMessage("Enter your xAI Grok API key") + .setTitle(context.getString(R.string.api_key_grok_title)) + .setMessage(context.getString(R.string.api_key_grok_message)) .setView(editText) - .setPositiveButton("Save") { _, _ -> + .setPositiveButton(context.getString(R.string.action_save)) { _, _ -> val apiKey = editText.text.toString().trim() prefManager.putString("ai_agent_grok_api_key", apiKey) preference.summary = getSummaryText() } - .setNegativeButton("Cancel", null) + .setNegativeButton(context.getString(R.string.action_cancel), null) .create() dialog.show() @@ -186,15 +186,15 @@ private class GeminiApiKey( val dialog = com.google.android.material.dialog .MaterialAlertDialogBuilder(context) - .setTitle("Gemini API Key") - .setMessage("Enter your Google Gemini API key") + .setTitle(context.getString(R.string.api_key_gemini_title)) + .setMessage(context.getString(R.string.api_key_gemini_message)) .setView(editText) - .setPositiveButton("Save") { _, _ -> + .setPositiveButton(context.getString(R.string.action_save)) { _, _ -> val apiKey = editText.text.toString().trim() prefManager.putString("ai_agent_gemini_api_key", apiKey) preference.summary = getSummaryText() } - .setNegativeButton("Cancel", null) + .setNegativeButton(context.getString(R.string.action_cancel), null) .create() dialog.show() @@ -240,15 +240,15 @@ private class DeepseekApiKey( val dialog = com.google.android.material.dialog .MaterialAlertDialogBuilder(context) - .setTitle("Deepseek API Key") - .setMessage("Enter your Deepseek API key") + .setTitle(context.getString(R.string.api_key_deepseek_title)) + .setMessage(context.getString(R.string.api_key_deepseek_message)) .setView(editText) - .setPositiveButton("Save") { _, _ -> + .setPositiveButton(context.getString(R.string.action_save)) { _, _ -> val apiKey = editText.text.toString().trim() prefManager.putString("ai_agent_deepseek_api_key", apiKey) preference.summary = getSummaryText() } - .setNegativeButton("Cancel", null) + .setNegativeButton(context.getString(R.string.action_cancel), null) .create() dialog.show() @@ -294,15 +294,15 @@ private class OpenAIApiKey( val dialog = com.google.android.material.dialog .MaterialAlertDialogBuilder(context) - .setTitle("OpenAI API Key") - .setMessage("Enter your OpenAI API key") + .setTitle(context.getString(R.string.api_key_openai_title)) + .setMessage(context.getString(R.string.api_key_openai_message)) .setView(editText) - .setPositiveButton("Save") { _, _ -> + .setPositiveButton(context.getString(R.string.action_save)) { _, _ -> val apiKey = editText.text.toString().trim() prefManager.putString("ai_agent_openai_api_key", apiKey) preference.summary = getSummaryText() } - .setNegativeButton("Cancel", null) + .setNegativeButton(context.getString(R.string.action_cancel), null) .create() dialog.show() @@ -348,15 +348,15 @@ private class AnthropicApiKey( val dialog = com.google.android.material.dialog .MaterialAlertDialogBuilder(context) - .setTitle("Anthropic API Key") - .setMessage("Enter your Anthropic API key") + .setTitle(context.getString(R.string.api_key_anthropic_title)) + .setMessage(context.getString(R.string.api_key_anthropic_message)) .setView(editText) - .setPositiveButton("Save") { _, _ -> + .setPositiveButton(context.getString(R.string.action_save)) { _, _ -> val apiKey = editText.text.toString().trim() prefManager.putString("ai_agent_anthropic_api_key", apiKey) preference.summary = getSummaryText() } - .setNegativeButton("Cancel", null) + .setNegativeButton(context.getString(R.string.action_cancel), null) .create() dialog.show() diff --git a/core/app/src/main/java/com/tom/rv2ide/preferences/editorPrefExts.kt b/core/app/src/main/java/com/tom/rv2ide/preferences/editorPrefExts.kt index 8604fc314..b6cd870ee 100644 --- a/core/app/src/main/java/com/tom/rv2ide/preferences/editorPrefExts.kt +++ b/core/app/src/main/java/com/tom/rv2ide/preferences/editorPrefExts.kt @@ -419,11 +419,11 @@ private class UseCustomFont( } null -> { EditorPreferences.selectedCustomFont = null - Toast.makeText(preference.context, "Using default font", Toast.LENGTH_SHORT).show() + Toast.makeText(preference.context, preference.context.getString(R.string.pref_using_default_font), Toast.LENGTH_SHORT).show() } else -> { EditorPreferences.selectedCustomFont = entry.data as String - Toast.makeText(preference.context, "Font selected: ${entry.label}", Toast.LENGTH_SHORT).show() + Toast.makeText(preference.context, preference.context.getString(R.string.pref_font_selected, entry.label), Toast.LENGTH_SHORT).show() } } } @@ -442,7 +442,7 @@ private class UseCustomFont( PICK_FONT_REQUEST ) } catch (e: Exception) { - Toast.makeText(preference.context, "Error opening file picker: ${e.message}", Toast.LENGTH_SHORT).show() + Toast.makeText(preference.context, preference.context.getString(R.string.pref_file_picker_error, e.message), Toast.LENGTH_SHORT).show() } } } diff --git a/core/app/src/main/java/com/tom/rv2ide/preferences/generalPrefExts.kt b/core/app/src/main/java/com/tom/rv2ide/preferences/generalPrefExts.kt index 79f8389be..b18bb9741 100644 --- a/core/app/src/main/java/com/tom/rv2ide/preferences/generalPrefExts.kt +++ b/core/app/src/main/java/com/tom/rv2ide/preferences/generalPrefExts.kt @@ -126,7 +126,7 @@ class UiMode( AppRestartDialog.show(preference.context) { restart -> if (restart) { GeneralPreferences.uiMode = (entry?.data as? Int?) ?: AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM - android.widget.Toast.makeText(preference.context, "Restarting...", 0).show() + android.widget.Toast.makeText(preference.context, preference.context.getString(MainR.string.pref_restarting), 0).show() Handler(Looper.getMainLooper()).postDelayed({ AppRestartDialog.restartApp(preference.context) }, 1000) } } @@ -165,7 +165,7 @@ class ThemeSelector( AppRestartDialog.show(preference.context) { restart -> if (restart) { GeneralPreferences.selectedTheme = (entry?.data as? IDETheme?)?.name ?: IDETheme.DEFAULT.name - android.widget.Toast.makeText(preference.context, "Restarting...", 0).show() + android.widget.Toast.makeText(preference.context, preference.context.getString(MainR.string.pref_restarting), 0).show() Handler(Looper.getMainLooper()).postDelayed({ AppRestartDialog.restartApp(preference.context) }, 1000) } } @@ -192,7 +192,7 @@ class Snowfall( AppRestartDialog.show(preference.context) { restart -> if (restart) { GeneralPreferences.snowfallOverlay = newSnowfallValue - android.widget.Toast.makeText(preference.context, "Restarting...", android.widget.Toast.LENGTH_SHORT).show() + android.widget.Toast.makeText(preference.context, preference.context.getString(MainR.string.pref_restarting), android.widget.Toast.LENGTH_SHORT).show() Handler(Looper.getMainLooper()).postDelayed({ AppRestartDialog.restartApp(preference.context) }, 1000) diff --git a/core/app/src/main/java/com/tom/rv2ide/templates/AtcWizardDialog.kt b/core/app/src/main/java/com/tom/rv2ide/templates/AtcWizardDialog.kt index 2a95e15f3..9263763d3 100644 --- a/core/app/src/main/java/com/tom/rv2ide/templates/AtcWizardDialog.kt +++ b/core/app/src/main/java/com/tom/rv2ide/templates/AtcWizardDialog.kt @@ -391,7 +391,7 @@ class AtcWizardDialog : BottomSheetDialogFragment() { val currentIndex = versions.indexOf(Options.OPT_SELECTED_NDK_VERSION).coerceAtLeast(0) MaterialAlertDialogBuilder(ctx) - .setTitle("Select NDK Version") + .setTitle(context?.getString(R.string.atc_select_ndk)) .setSingleChoiceItems(versionLabels, currentIndex) { dialog, which -> val selectedVersion = versions[which] if (Check.validateNdkVersion(selectedVersion)) { @@ -399,10 +399,10 @@ class AtcWizardDialog : BottomSheetDialogFragment() { binding.ndkVersionButton.text = "NDK: $selectedVersion" dialog.dismiss() } else { - Toast.makeText(ctx, "Invalid NDK: $selectedVersion", Toast.LENGTH_SHORT).show() + Toast.makeText(ctx, context?.getString(R.string.atc_invalid_ndk, selectedVersion), Toast.LENGTH_SHORT).show() } } - .setNegativeButton("Cancel", null) + .setNegativeButton(context?.getString(R.string.action_cancel), null) .show() } @@ -413,16 +413,16 @@ class AtcWizardDialog : BottomSheetDialogFragment() { .toTypedArray() MaterialAlertDialogBuilder(ctx) - .setTitle("Select CMake Version") + .setTitle(context?.getString(R.string.atc_select_cmake)) .setSingleChoiceItems(versionLabels, 0) { dialog, which -> val selectedVersion = versions[which] Check.validateCMakeVersion(selectedVersion)?.let { path -> Options.OPT_CMAKE_PATH = path - Toast.makeText(ctx, "CMake $selectedVersion selected", Toast.LENGTH_SHORT).show() + Toast.makeText(ctx, context?.getString(R.string.atc_cmake_selected, selectedVersion), Toast.LENGTH_SHORT).show() dialog.dismiss() - } ?: Toast.makeText(ctx, "Invalid CMake: $selectedVersion", Toast.LENGTH_SHORT).show() + } ?: Toast.makeText(ctx, context?.getString(R.string.atc_invalid_cmake, selectedVersion), Toast.LENGTH_SHORT).show() } - .setNegativeButton("Cancel") { _, _ -> binding.useCMakeSwitch.isChecked = false } + .setNegativeButton(context?.getString(R.string.action_cancel)) { _, _ -> binding.useCMakeSwitch.isChecked = false } .show() } @@ -436,7 +436,7 @@ class AtcWizardDialog : BottomSheetDialogFragment() { .setTitle(title) .setMessage(message) .setPositiveButton(positiveText) { _, _ -> onPositive?.invoke() } - .setNegativeButton("Cancel", null) + .setNegativeButton(context?.getString(R.string.action_cancel), null) .show() } diff --git a/core/app/src/main/java/com/tom/rv2ide/templates/android/BasicActivity.kt b/core/app/src/main/java/com/tom/rv2ide/templates/android/BasicActivity.kt index 50867fca5..c42983d45 100644 --- a/core/app/src/main/java/com/tom/rv2ide/templates/android/BasicActivity.kt +++ b/core/app/src/main/java/com/tom/rv2ide/templates/android/BasicActivity.kt @@ -26,6 +26,7 @@ import com.tom.androidcodestudio.project.manager.SdkVersionHelper import com.tom.androidcodestudio.project.manager.builder.* import com.tom.androidcodestudio.project.manager.builder.module.* import com.tom.androidcodestudio.project.manager.builder.toplevel.* +import com.tom.rv2ide.R import com.tom.rv2ide.templates.* import com.tom.rv2ide.templates.AtcInterface import com.tom.rv2ide.templates.preferences.Options @@ -68,7 +69,7 @@ class BasicActivity : Template { // Show toast on main thread withContext(Dispatchers.Main) { - Toast.makeText(context, "Creating Basic Activity...", Toast.LENGTH_SHORT).show() + Toast.makeText(context, context.getString(R.string.template_creating_basic), Toast.LENGTH_SHORT).show() } val packageHelper = diff --git a/core/app/src/main/java/com/tom/rv2ide/templates/android/BottomNavigationActivity.kt b/core/app/src/main/java/com/tom/rv2ide/templates/android/BottomNavigationActivity.kt index 005df7343..c0a6cceaf 100644 --- a/core/app/src/main/java/com/tom/rv2ide/templates/android/BottomNavigationActivity.kt +++ b/core/app/src/main/java/com/tom/rv2ide/templates/android/BottomNavigationActivity.kt @@ -26,6 +26,7 @@ import com.tom.androidcodestudio.project.manager.SdkVersionHelper import com.tom.androidcodestudio.project.manager.builder.* import com.tom.androidcodestudio.project.manager.builder.module.* import com.tom.androidcodestudio.project.manager.builder.toplevel.* +import com.tom.rv2ide.R import com.tom.rv2ide.templates.* import com.tom.rv2ide.templates.AtcInterface import com.tom.rv2ide.templates.android.navigation.bottom.BottomNavigationSources @@ -74,7 +75,7 @@ class BottomNavigationActivity : Template { // Show toast on main thread withContext(Dispatchers.Main) { - Toast.makeText(context, "Creating Bottom Navigation Activity...", Toast.LENGTH_SHORT) + Toast.makeText(context, context.getString(R.string.template_creating_bottom_nav), Toast.LENGTH_SHORT) .show() } diff --git a/core/app/src/main/java/com/tom/rv2ide/templates/android/ComposeEmptyActivity.kt b/core/app/src/main/java/com/tom/rv2ide/templates/android/ComposeEmptyActivity.kt index cc150b934..a4cfb8865 100644 --- a/core/app/src/main/java/com/tom/rv2ide/templates/android/ComposeEmptyActivity.kt +++ b/core/app/src/main/java/com/tom/rv2ide/templates/android/ComposeEmptyActivity.kt @@ -26,6 +26,7 @@ import com.tom.androidcodestudio.project.manager.SdkVersionHelper import com.tom.androidcodestudio.project.manager.builder.* import com.tom.androidcodestudio.project.manager.builder.module.* import com.tom.androidcodestudio.project.manager.builder.toplevel.* +import com.tom.rv2ide.R import com.tom.rv2ide.templates.* import com.tom.rv2ide.templates.AtcInterface import java.io.File @@ -70,7 +71,7 @@ class ComposeEmptyActivity : Template { // Show toast on main thread withContext(Dispatchers.Main) { - Toast.makeText(context, "Creating Compose Empty Activity...", Toast.LENGTH_SHORT).show() + Toast.makeText(context, context.getString(R.string.template_creating_compose_empty), Toast.LENGTH_SHORT).show() } val packageHelper = diff --git a/core/app/src/main/java/com/tom/rv2ide/templates/android/EmptyActivity.kt b/core/app/src/main/java/com/tom/rv2ide/templates/android/EmptyActivity.kt index 400c77aa2..893824bee 100644 --- a/core/app/src/main/java/com/tom/rv2ide/templates/android/EmptyActivity.kt +++ b/core/app/src/main/java/com/tom/rv2ide/templates/android/EmptyActivity.kt @@ -28,6 +28,7 @@ import com.tom.androidcodestudio.project.manager.builder.module.* import com.tom.androidcodestudio.project.manager.builder.toplevel.* import com.tom.androidcodestudio.project.manager.builder.toplevel.GradleFileType.GROOVY import com.tom.androidcodestudio.project.manager.builder.toplevel.GradleFileType.KTS +import com.tom.rv2ide.R import com.tom.rv2ide.templates.* import com.tom.rv2ide.templates.AtcInterface import com.tom.rv2ide.templates.preferences.Options @@ -70,7 +71,7 @@ class EmptyActivity : Template { // Show toast on main thread withContext(Dispatchers.Main) { - Toast.makeText(context, "Creating Empty Activity...", Toast.LENGTH_SHORT).show() + Toast.makeText(context, context.getString(R.string.template_creating_empty), Toast.LENGTH_SHORT).show() } val packageHelper = diff --git a/core/app/src/main/java/com/tom/rv2ide/templates/android/GameActivity.kt b/core/app/src/main/java/com/tom/rv2ide/templates/android/GameActivity.kt index 0022f9f35..ee1ea51dd 100644 --- a/core/app/src/main/java/com/tom/rv2ide/templates/android/GameActivity.kt +++ b/core/app/src/main/java/com/tom/rv2ide/templates/android/GameActivity.kt @@ -26,6 +26,7 @@ import com.tom.androidcodestudio.project.manager.SdkVersionHelper import com.tom.androidcodestudio.project.manager.builder.* import com.tom.androidcodestudio.project.manager.builder.module.* import com.tom.androidcodestudio.project.manager.builder.toplevel.* +import com.tom.rv2ide.R import com.tom.rv2ide.templates.* import com.tom.rv2ide.templates.AtcInterface import com.tom.rv2ide.templates.android.etc.NativeCpp.Check.getHighestCMakeVersion @@ -80,7 +81,7 @@ class GameActivity : Template { // Show toast on main thread withContext(Dispatchers.Main) { - Toast.makeText(context, "Creating native c++...", Toast.LENGTH_SHORT).show() + Toast.makeText(context, context.getString(R.string.template_creating_native_cpp), Toast.LENGTH_SHORT).show() } val packageHelper = diff --git a/core/app/src/main/java/com/tom/rv2ide/templates/android/NativeCpp.kt b/core/app/src/main/java/com/tom/rv2ide/templates/android/NativeCpp.kt index 86bcf9934..c268e4fd1 100644 --- a/core/app/src/main/java/com/tom/rv2ide/templates/android/NativeCpp.kt +++ b/core/app/src/main/java/com/tom/rv2ide/templates/android/NativeCpp.kt @@ -26,6 +26,7 @@ import com.tom.androidcodestudio.project.manager.SdkVersionHelper import com.tom.androidcodestudio.project.manager.builder.* import com.tom.androidcodestudio.project.manager.builder.module.* import com.tom.androidcodestudio.project.manager.builder.toplevel.* +import com.tom.rv2ide.R import com.tom.rv2ide.templates.* import com.tom.rv2ide.templates.AtcInterface import com.tom.rv2ide.templates.android.cpp.CppSources @@ -76,7 +77,7 @@ class NativeCpp : Template { // Show toast on main thread withContext(Dispatchers.Main) { - Toast.makeText(context, "Creating native c++...", Toast.LENGTH_SHORT).show() + Toast.makeText(context, context.getString(R.string.template_creating_native_cpp), Toast.LENGTH_SHORT).show() } val packageHelper = diff --git a/core/app/src/main/java/com/tom/rv2ide/templates/android/NavigationDrawerActivity.kt b/core/app/src/main/java/com/tom/rv2ide/templates/android/NavigationDrawerActivity.kt index 5adb97406..0374e4e2c 100644 --- a/core/app/src/main/java/com/tom/rv2ide/templates/android/NavigationDrawerActivity.kt +++ b/core/app/src/main/java/com/tom/rv2ide/templates/android/NavigationDrawerActivity.kt @@ -26,6 +26,7 @@ import com.tom.androidcodestudio.project.manager.SdkVersionHelper import com.tom.androidcodestudio.project.manager.builder.* import com.tom.androidcodestudio.project.manager.builder.module.* import com.tom.androidcodestudio.project.manager.builder.toplevel.* +import com.tom.rv2ide.R import com.tom.rv2ide.templates.* import com.tom.rv2ide.templates.AtcInterface import com.tom.rv2ide.templates.android.navigation.drawer.Fragment @@ -74,7 +75,7 @@ class NavigationDrawerActivity : Template { // Show toast on main thread withContext(Dispatchers.Main) { - Toast.makeText(context, "Creating Navigation drawer Activity...", Toast.LENGTH_SHORT) + Toast.makeText(context, context.getString(R.string.template_creating_nav_drawer), Toast.LENGTH_SHORT) .show() } diff --git a/core/app/src/main/java/com/tom/rv2ide/templates/android/NoActivity.kt b/core/app/src/main/java/com/tom/rv2ide/templates/android/NoActivity.kt index 5fe668b3c..abb7c7280 100644 --- a/core/app/src/main/java/com/tom/rv2ide/templates/android/NoActivity.kt +++ b/core/app/src/main/java/com/tom/rv2ide/templates/android/NoActivity.kt @@ -26,6 +26,7 @@ import com.tom.androidcodestudio.project.manager.SdkVersionHelper import com.tom.androidcodestudio.project.manager.builder.* import com.tom.androidcodestudio.project.manager.builder.module.* import com.tom.androidcodestudio.project.manager.builder.toplevel.* +import com.tom.rv2ide.R import com.tom.rv2ide.templates.* import com.tom.rv2ide.templates.AtcInterface import com.tom.rv2ide.templates.preferences.Options @@ -68,7 +69,7 @@ class NoActivity : Template { // Show toast on main thread withContext(Dispatchers.Main) { - Toast.makeText(context, "Creating no Activity...", Toast.LENGTH_SHORT).show() + Toast.makeText(context, context.getString(R.string.template_creating_no_activity), Toast.LENGTH_SHORT).show() } val packageHelper = diff --git a/core/app/src/main/java/com/tom/rv2ide/templates/android/ResponsiveActivity.kt b/core/app/src/main/java/com/tom/rv2ide/templates/android/ResponsiveActivity.kt index b2ff8d857..374b152b8 100644 --- a/core/app/src/main/java/com/tom/rv2ide/templates/android/ResponsiveActivity.kt +++ b/core/app/src/main/java/com/tom/rv2ide/templates/android/ResponsiveActivity.kt @@ -26,6 +26,7 @@ import com.tom.androidcodestudio.project.manager.SdkVersionHelper import com.tom.androidcodestudio.project.manager.builder.* import com.tom.androidcodestudio.project.manager.builder.module.* import com.tom.androidcodestudio.project.manager.builder.toplevel.* +import com.tom.rv2ide.R import com.tom.rv2ide.templates.* import com.tom.rv2ide.templates.AtcInterface import com.tom.rv2ide.templates.android.navigation.responsive.Fragment @@ -74,7 +75,7 @@ class ResponsiveActivity : Template { // Show toast on main thread withContext(Dispatchers.Main) { - Toast.makeText(context, "Creating Responsive activity Activity...", Toast.LENGTH_SHORT) + Toast.makeText(context, context.getString(R.string.template_creating_responsive), Toast.LENGTH_SHORT) .show() } diff --git a/core/app/src/main/res/layout/activity_asset_studio.xml b/core/app/src/main/res/layout/activity_asset_studio.xml index 6871e6563..17f5b2fe5 100644 --- a/core/app/src/main/res/layout/activity_asset_studio.xml +++ b/core/app/src/main/res/layout/activity_asset_studio.xml @@ -76,7 +76,7 @@ @@ -119,7 +119,7 @@ @@ -136,7 +136,7 @@ android:layout_height="wrap_content" android:layout_weight="1" android:layout_marginEnd="8dp" - android:text="Select Image" + android:text="@string/asset_studio_select_image" android:textAppearance="@style/TextAppearance.Material3.LabelLarge" app:icon="@drawable/ic_image" app:iconGravity="textStart" @@ -147,7 +147,7 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" - android:text="Load XML" + android:text="@string/asset_studio_load_xml" android:textAppearance="@style/TextAppearance.Material3.LabelLarge" app:icon="@drawable/ic_code" app:iconGravity="textStart" @@ -159,7 +159,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="12dp" - android:text="Choose an image or XML vector to create app icons" + android:text="@string/asset_studio_choose_source" android:textAppearance="@style/TextAppearance.Material3.BodyMedium" android:textColor="?attr/colorOnSurfaceVariant" /> @@ -184,7 +184,7 @@ @@ -194,7 +194,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="20dp" - android:hint="Icon Name" + android:hint="@string/asset_studio_icon_name_hint" app:startIconDrawable="@drawable/ic_label" style="@style/Widget.Material3.TextInputLayout.OutlinedBox"> @@ -203,7 +203,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:inputType="text" - android:text="ic_my_icon" /> + android:hint="@string/asset_studio_icon_name_hint" /> @@ -211,7 +211,7 @@ @@ -228,7 +228,7 @@ android:id="@+id/circle_shape_button" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="Circle" + android:text="@string/asset_studio_shape_circle" android:checked="true" style="@style/Widget.Material3.Chip.Filter" /> @@ -236,14 +236,14 @@ android:id="@+id/square_shape_button" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="Square" + android:text="@string/asset_studio_shape_square" style="@style/Widget.Material3.Chip.Filter" /> @@ -252,7 +252,7 @@ @@ -278,7 +278,7 @@ android:layout_weight="1" android:layout_marginStart="16dp" android:layout_marginEnd="8dp" - android:text="Choose Color" + android:text="@string/asset_studio_choose_color" android:textAppearance="@style/TextAppearance.Material3.LabelLarge" app:icon="@drawable/ic_palette" app:iconGravity="textStart" @@ -289,7 +289,7 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" - android:text="Custom" + android:text="@string/asset_studio_custom" android:textAppearance="@style/TextAppearance.Material3.LabelLarge" app:icon="@drawable/ic_tune" app:iconGravity="textStart" @@ -310,7 +310,7 @@ @@ -352,7 +352,7 @@ @@ -406,7 +406,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginEnd="12dp" - android:text="Preview" + android:text="@string/asset_studio_preview" android:textAppearance="@style/TextAppearance.Material3.LabelLarge" app:icon="@drawable/ic_visibility" app:iconGravity="textStart" @@ -416,7 +416,7 @@ android:id="@+id/generate_button" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="Generate Icons" + android:text="@string/asset_studio_generate_icons" android:textAppearance="@style/TextAppearance.Material3.LabelLarge" app:icon="@drawable/ic_download" app:iconGravity="textStart" diff --git a/core/app/src/main/res/layout/activity_m3icons.xml b/core/app/src/main/res/layout/activity_m3icons.xml index c8bf0542a..40e19fb18 100644 --- a/core/app/src/main/res/layout/activity_m3icons.xml +++ b/core/app/src/main/res/layout/activity_m3icons.xml @@ -12,7 +12,7 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:layout_margin="16dp" - android:hint="Search icons..." + android:hint="@string/hint_search_icons" app:startIconDrawable="@android:drawable/ic_menu_search" style="@style/Widget.Material3.TextInputLayout.OutlinedBox" app:layout_constraintEnd_toEndOf="parent" diff --git a/core/app/src/main/res/layout/activity_review_changes.xml b/core/app/src/main/res/layout/activity_review_changes.xml index a6320e840..ded3a181c 100644 --- a/core/app/src/main/res/layout/activity_review_changes.xml +++ b/core/app/src/main/res/layout/activity_review_changes.xml @@ -46,7 +46,7 @@ @@ -78,7 +78,7 @@ @@ -110,7 +110,7 @@ @@ -137,7 +137,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginEnd="8dp" - android:text="Cancel" + android:text="@string/cancel" app:icon="@drawable/ic_clear" style="@style/Widget.Material3.Button.OutlinedButton" /> @@ -145,7 +145,7 @@ android:id="@+id/applyBtn" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="Apply Changes" + android:text="@string/review_apply_changes" app:icon="@drawable/ic_check" /> diff --git a/core/app/src/main/res/layout/bottomsheet_project_list.xml b/core/app/src/main/res/layout/bottomsheet_project_list.xml index cc1dbeec6..9afb13e6d 100644 --- a/core/app/src/main/res/layout/bottomsheet_project_list.xml +++ b/core/app/src/main/res/layout/bottomsheet_project_list.xml @@ -29,7 +29,7 @@ android:layout_height="wrap_content" android:contentDescription="@string/browse_other_location" app:icon="@drawable/ic_folder" - android:text="import project" + android:text="@string/import_project" app:iconGravity="textStart" /> diff --git a/core/app/src/main/res/layout/cmake_layout.xml b/core/app/src/main/res/layout/cmake_layout.xml index e7cf56c72..521ced7e7 100644 --- a/core/app/src/main/res/layout/cmake_layout.xml +++ b/core/app/src/main/res/layout/cmake_layout.xml @@ -54,7 +54,7 @@ app:icon="@drawable/download" style="@style/Widget.Material3.Button.TonalButton" app:backgroundTint="?attr/colorSurfaceContainerHigh" - android:text="Download" /> + android:text="@string/action_download" /> @@ -17,27 +17,27 @@ android:id="@+id/enableWriteCheckbox" android:layout_width="match_parent" android:layout_height="wrap_content" - android:text="Enable AI file writing" + android:text="@string/ai_enable_file_writing" android:layout_marginBottom="8dp"/> diff --git a/core/app/src/main/res/layout/dialog_branch_name.xml b/core/app/src/main/res/layout/dialog_branch_name.xml index d5550c49c..2a0d944e9 100644 --- a/core/app/src/main/res/layout/dialog_branch_name.xml +++ b/core/app/src/main/res/layout/dialog_branch_name.xml @@ -9,7 +9,7 @@ @@ -33,7 +33,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="8dp" - android:hint="Username" + android:hint="@string/git_username_hint" style="@style/Widget.Material3.TextInputLayout.OutlinedBox"> diff --git a/core/app/src/main/res/layout/dialog_color_picker.xml b/core/app/src/main/res/layout/dialog_color_picker.xml index 8eb7b7263..346f9ae0d 100644 --- a/core/app/src/main/res/layout/dialog_color_picker.xml +++ b/core/app/src/main/res/layout/dialog_color_picker.xml @@ -42,7 +42,7 @@ @@ -72,7 +72,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="20dp" - android:hint="Hex Color (e.g., #FF6200EE)" + android:hint="@string/hint_hex_color" app:startIconDrawable="@drawable/ic_palette" style="@style/Widget.Material3.TextInputLayout.OutlinedBox"> @@ -90,7 +90,7 @@ @@ -114,7 +114,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginEnd="12dp" - android:text="Cancel" + android:text="@string/cancel" android:textAppearance="@style/TextAppearance.Material3.LabelLarge" style="@style/Widget.Material3.Button.TextButton" /> @@ -122,7 +122,7 @@ android:id="@+id/apply_color_button" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="Apply" + android:text="@string/action_apply" android:textAppearance="@style/TextAppearance.Material3.LabelLarge" style="@style/Widget.Material3.Button" /> diff --git a/core/app/src/main/res/layout/dialog_commit.xml b/core/app/src/main/res/layout/dialog_commit.xml index 9c1eddc59..a91b97f0b 100644 --- a/core/app/src/main/res/layout/dialog_commit.xml +++ b/core/app/src/main/res/layout/dialog_commit.xml @@ -9,7 +9,7 @@ diff --git a/core/app/src/main/res/layout/dialog_credentials.xml b/core/app/src/main/res/layout/dialog_credentials.xml index 10b7662f6..757acc148 100644 --- a/core/app/src/main/res/layout/dialog_credentials.xml +++ b/core/app/src/main/res/layout/dialog_credentials.xml @@ -11,7 +11,7 @@ @@ -43,5 +43,5 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="8dp" - android:text="Remember credentials"/> + android:text="@string/git_remember_credentials"/> diff --git a/core/app/src/main/res/layout/dialog_deps_progress.xml b/core/app/src/main/res/layout/dialog_deps_progress.xml index 793794855..c25a90412 100644 --- a/core/app/src/main/res/layout/dialog_deps_progress.xml +++ b/core/app/src/main/res/layout/dialog_deps_progress.xml @@ -9,7 +9,7 @@ android:id="@+id/tvProgressTitle" android:layout_width="match_parent" android:layout_height="wrap_content" - android:text="Updating Dependencies" + android:text="@string/updating_dependencies" android:textAppearance="@style/TextAppearance.Material3.HeadlineSmall" android:textColor="?attr/colorOnSurface" android:layout_marginBottom="8dp" /> @@ -18,7 +18,7 @@ android:id="@+id/tvProgressMessage" android:layout_width="match_parent" android:layout_height="wrap_content" - android:text="Please wait..." + android:text="@string/please_wait" android:textAppearance="@style/TextAppearance.Material3.BodyMedium" android:textColor="?attr/colorOnSurfaceVariant" android:layout_marginBottom="16dp" /> diff --git a/core/app/src/main/res/layout/dialog_edit_module_config.xml b/core/app/src/main/res/layout/dialog_edit_module_config.xml index 3fb23c3c6..fd04a90ce 100644 --- a/core/app/src/main/res/layout/dialog_edit_module_config.xml +++ b/core/app/src/main/res/layout/dialog_edit_module_config.xml @@ -27,7 +27,7 @@ style="@style/Widget.Material3.TextInputLayout.OutlinedBox" android:layout_width="match_parent" android:layout_height="wrap_content" - android:hint="Version Name"> + android:hint="@string/hint_version_name"> + android:hint="@string/hint_version_code"> + android:hint="@string/hint_min_sdk"> + android:hint="@string/hint_target_sdk"> + android:hint="@string/hint_compile_sdk"> @@ -42,7 +42,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="16dp" - android:hint="File name" + android:hint="@string/file_name" style="@style/Widget.Material3.TextInputLayout.OutlinedBox"> @@ -95,7 +95,7 @@ android:id="@+id/colorPickerButton" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="Change" + android:text="@string/action_change" style="@style/Widget.Material3.Button.TonalButton" /> @@ -110,7 +110,7 @@ android:id="@+id/cancelButton" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="Cancel" + android:text="@string/cancel" android:layout_marginEnd="8dp" style="@style/Widget.Material3.Button.TextButton" /> @@ -118,7 +118,7 @@ android:id="@+id/saveButton" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="Save & Copy" + android:text="@string/save_and_copy" style="@style/Widget.Material3.Button" /> diff --git a/core/app/src/main/res/layout/dialog_loading.xml b/core/app/src/main/res/layout/dialog_loading.xml index c8cfa3bc5..a1eafeb2f 100644 --- a/core/app/src/main/res/layout/dialog_loading.xml +++ b/core/app/src/main/res/layout/dialog_loading.xml @@ -20,7 +20,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="16dp" - android:text="Loading..." + android:text="@string/msg_loading" android:textAppearance="?attr/textAppearanceBodyLarge" android:textAlignment="center" /> diff --git a/core/app/src/main/res/layout/dialog_local_llm_config.xml b/core/app/src/main/res/layout/dialog_local_llm_config.xml index 9b262be83..74ae9d48e 100644 --- a/core/app/src/main/res/layout/dialog_local_llm_config.xml +++ b/core/app/src/main/res/layout/dialog_local_llm_config.xml @@ -11,7 +11,7 @@ @@ -19,7 +19,7 @@ @@ -28,14 +28,14 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:inputType="textUri" - android:text="http://localhost:1234" /> + android:hint="@string/hint_llm_base_url" /> @@ -44,7 +44,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:inputType="text" - android:text="local-model" /> + android:hint="@string/hint_llm_model_name" /> @@ -58,7 +58,7 @@ android:id="@+id/cancelButton" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="Cancel" + android:text="@string/cancel" android:layout_marginEnd="8dp" style="@style/Widget.Material3.Button.TextButton" /> @@ -66,7 +66,7 @@ android:id="@+id/saveButton" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="Save" + android:text="@string/git_save_action" style="@style/Widget.Material3.Button" /> diff --git a/core/app/src/main/res/layout/dialog_progress.xml b/core/app/src/main/res/layout/dialog_progress.xml index e9491f6c2..09b72b64e 100644 --- a/core/app/src/main/res/layout/dialog_progress.xml +++ b/core/app/src/main/res/layout/dialog_progress.xml @@ -17,7 +17,7 @@ android:id="@+id/textProgressMessage" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="Please wait..." + android:text="@string/please_wait" android:textSize="16sp" android:textColor="?android:textColorPrimary" android:layout_marginTop="16dp"/> diff --git a/core/app/src/main/res/layout/dialog_project_settings.xml b/core/app/src/main/res/layout/dialog_project_settings.xml index 40f64f68f..5144a80d2 100644 --- a/core/app/src/main/res/layout/dialog_project_settings.xml +++ b/core/app/src/main/res/layout/dialog_project_settings.xml @@ -17,7 +17,7 @@ android:textSize="18sp" android:fontFamily="sans-serif-bold" android:textStyle="bold" - android:text="Project settings" /> + android:text="@string/idepref_general_projectConfig" /> + android:text="@string/git_backup_project" /> diff --git a/core/app/src/main/res/layout/dialog_push_pull.xml b/core/app/src/main/res/layout/dialog_push_pull.xml index 2f0df36f2..f971e681a 100644 --- a/core/app/src/main/res/layout/dialog_push_pull.xml +++ b/core/app/src/main/res/layout/dialog_push_pull.xml @@ -10,7 +10,7 @@ @@ -18,7 +18,7 @@ diff --git a/core/app/src/main/res/layout/dialog_update_confirm.xml b/core/app/src/main/res/layout/dialog_update_confirm.xml index 29a5a07cf..8879972d2 100644 --- a/core/app/src/main/res/layout/dialog_update_confirm.xml +++ b/core/app/src/main/res/layout/dialog_update_confirm.xml @@ -14,7 +14,7 @@ android:id="@+id/tvConfirmTitle" android:layout_width="match_parent" android:layout_height="wrap_content" - android:text="Update Dependency" + android:text="@string/update_dependency" android:textAppearance="@style/TextAppearance.Material3.HeadlineSmall" android:layout_marginBottom="16dp" /> @@ -36,7 +36,7 @@ style="@style/Widget.Material3.Button.TextButton" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="Cancel" + android:text="@string/cancel" android:layout_marginEnd="8dp" /> + android:text="@string/lsp_update_button" /> diff --git a/core/app/src/main/res/layout/dialog_user_config.xml b/core/app/src/main/res/layout/dialog_user_config.xml index 2edc9072d..e707bb342 100644 --- a/core/app/src/main/res/layout/dialog_user_config.xml +++ b/core/app/src/main/res/layout/dialog_user_config.xml @@ -9,7 +9,7 @@ @@ -34,7 +34,7 @@ android:id="@+id/modelDropdownLayout" android:layout_width="match_parent" android:layout_height="wrap_content" - android:hint="Model / Agent" + android:hint="@string/ai_model_hint" android:layout_marginBottom="24dp" app:startIconDrawable="@drawable/ic_code" style="@style/Widget.Material3.TextInputLayout.OutlinedBox.ExposedDropdownMenu"> @@ -65,13 +65,13 @@ @@ -106,13 +106,13 @@ @@ -137,7 +137,7 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" - android:text="Provider:" + android:text="@string/ai_provider_label" android:textAppearance="?attr/textAppearanceBodyMedium" android:textColor="?attr/colorOnSurfaceVariant" /> @@ -145,7 +145,7 @@ android:id="@+id/currentProviderText" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="Not set" + android:text="@string/not_set" android:textAppearance="?attr/textAppearanceBodyMedium" /> @@ -160,7 +160,7 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" - android:text="Model:" + android:text="@string/ai_model_label" android:textAppearance="?attr/textAppearanceBodyMedium" android:textColor="?attr/colorOnSurfaceVariant" /> @@ -168,10 +168,10 @@ android:id="@+id/currentModelText" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="Not set" + android:text="@string/not_set" android:textAppearance="?attr/textAppearanceBodyMedium" /> - + diff --git a/core/app/src/main/res/layout/fragment_artificial.xml b/core/app/src/main/res/layout/fragment_artificial.xml index 8d9b5f8aa..c38ce6f2f 100644 --- a/core/app/src/main/res/layout/fragment_artificial.xml +++ b/core/app/src/main/res/layout/fragment_artificial.xml @@ -65,7 +65,7 @@ android:layout_height="wrap_content" android:layout_gravity="bottom|end" android:layout_margin="16dp" - android:text="Undo" + android:text="@string/undo" android:visibility="gone" app:icon="@drawable/ic_undo" style="@style/Widget.Material3.ExtendedFloatingActionButton.Primary" /> diff --git a/core/app/src/main/res/layout/fragment_asset_studio.xml b/core/app/src/main/res/layout/fragment_asset_studio.xml index 9f4d488d5..4a257faf9 100644 --- a/core/app/src/main/res/layout/fragment_asset_studio.xml +++ b/core/app/src/main/res/layout/fragment_asset_studio.xml @@ -127,7 +127,7 @@ android:id="@+id/m3IconsBtn" android:layout_width="match_parent" android:layout_height="wrap_content" - android:text="M3 Icons" + android:text="@string/asset_studio_m3_icons" style="@style/Widget.Material3.Button.OutlinedButton" /> @@ -161,7 +161,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="8dp" - android:text="No recent assets" + android:text="@string/asset_studio_no_recent" android:textAppearance="@style/TextAppearance.Material3.BodyMedium" android:textColor="?attr/colorOnSurfaceVariant" /> diff --git a/core/app/src/main/res/layout/fragment_branches.xml b/core/app/src/main/res/layout/fragment_branches.xml index 07fc51eb8..8bb157a4f 100644 --- a/core/app/src/main/res/layout/fragment_branches.xml +++ b/core/app/src/main/res/layout/fragment_branches.xml @@ -27,7 +27,7 @@ android:id="@+id/textCurrentBranch" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="Current: main" + android:text="@string/git_current_branch_default" android:textSize="16sp" android:textStyle="bold" android:gravity="center_vertical"/> @@ -36,7 +36,7 @@ android:id="@+id/buttonRefresh" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="Refresh" + android:text="@string/action_refresh" app:icon="@android:drawable/ic_popup_sync" style="@style/Widget.Material3.Button.TextButton"/> @@ -57,6 +57,6 @@ android:layout_height="wrap_content" android:layout_gravity="bottom|end" android:layout_margin="16dp" - android:text="New Branch" + android:text="@string/git_create_new_branch" app:icon="@android:drawable/ic_input_add"/> \ No newline at end of file diff --git a/core/app/src/main/res/layout/fragment_changes.xml b/core/app/src/main/res/layout/fragment_changes.xml index b2dc71aef..310efce8b 100644 --- a/core/app/src/main/res/layout/fragment_changes.xml +++ b/core/app/src/main/res/layout/fragment_changes.xml @@ -34,7 +34,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="4dp" - android:text="Stage All" + android:text="@string/git_stage_all" app:icon="@drawable/ic_add" style="@style/Widget.Material3.Button.TonalButton"/> @@ -43,14 +43,14 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="4dp" - android:text="Refresh" + android:text="@string/action_refresh" app:icon="@drawable/ic_sync" style="@style/Widget.Material3.Button.OutlinedButton"/> @@ -71,7 +71,7 @@ android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" - android:text="No changes detected" + android:text="@string/git_no_changes" android:gravity="center" android:textSize="16sp" android:textColor="?android:textColorSecondary" diff --git a/core/app/src/main/res/layout/fragment_chat.xml b/core/app/src/main/res/layout/fragment_chat.xml index 9c0a96d95..f4a1a7679 100644 --- a/core/app/src/main/res/layout/fragment_chat.xml +++ b/core/app/src/main/res/layout/fragment_chat.xml @@ -18,7 +18,7 @@ android:id="@+id/promptLayout" android:layout_width="match_parent" android:layout_height="wrap_content" - android:hint="What would you like me to do?" + android:hint="@string/ai_agent_chat_hint" android:layout_marginBottom="16dp" app:startIconDrawable="@drawable/ic_ai" style="@style/Widget.Material3.TextInputLayout.OutlinedBox"> @@ -46,7 +46,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginEnd="8dp" - android:text="Clear" + android:text="@string/action_clear" app:icon="@drawable/ic_clear" style="@style/Widget.Material3.Button.OutlinedButton" /> @@ -54,7 +54,7 @@ android:id="@+id/executeBtn" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="Send" + android:text="@string/ai_agent_send" app:icon="@drawable/ic_send" /> @@ -98,7 +98,7 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" - android:text="Status" + android:text="@string/server_status_title" android:textAppearance="?attr/textAppearanceBodyLarge" /> @@ -147,7 +147,7 @@ diff --git a/core/app/src/main/res/layout/fragment_editor_sidebar.xml b/core/app/src/main/res/layout/fragment_editor_sidebar.xml index 2ce856bdf..61f1c4393 100644 --- a/core/app/src/main/res/layout/fragment_editor_sidebar.xml +++ b/core/app/src/main/res/layout/fragment_editor_sidebar.xml @@ -17,7 +17,7 @@ android:id="@+id/title" android:layout_width="match_parent" android:layout_height="wrap_content" - android:text="File Tree" + android:text="@string/msg_file_tree" android:textSize="18sp" android:textStyle="bold" android:paddingLeft="16dp" /> diff --git a/core/app/src/main/res/layout/fragment_file_browser.xml b/core/app/src/main/res/layout/fragment_file_browser.xml index 8a96e1c22..73d0e9c72 100644 --- a/core/app/src/main/res/layout/fragment_file_browser.xml +++ b/core/app/src/main/res/layout/fragment_file_browser.xml @@ -20,7 +20,7 @@ app:icon="@drawable/ic_arrow_back" app:cornerRadius="6dp" android:layout_marginStart="8dp" - android:text="Goto my project" /> + android:text="@string/goto_my_project" /> diff --git a/core/app/src/main/res/layout/fragment_history.xml b/core/app/src/main/res/layout/fragment_history.xml index b48147032..af722885e 100644 --- a/core/app/src/main/res/layout/fragment_history.xml +++ b/core/app/src/main/res/layout/fragment_history.xml @@ -26,7 +26,7 @@ @@ -35,7 +35,7 @@ android:id="@+id/buttonRefresh" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="Refresh" + android:text="@string/action_refresh" app:icon="@android:drawable/ic_popup_sync" style="@style/Widget.Material3.Button.TextButton"/> @@ -54,7 +54,7 @@ android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" - android:text="No commits yet" + android:text="@string/git_no_commits" android:gravity="center" android:textSize="16sp" android:textColor="?android:textColorSecondary" diff --git a/core/app/src/main/res/layout/fragment_init.xml b/core/app/src/main/res/layout/fragment_init.xml index 77bdf646c..189d2c6ec 100644 --- a/core/app/src/main/res/layout/fragment_init.xml +++ b/core/app/src/main/res/layout/fragment_init.xml @@ -22,7 +22,7 @@ android:id="@+id/textTitle" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="No Repository Found" + android:text="@string/git_no_repo_found" android:textSize="24sp" android:textStyle="bold" android:textColor="?android:textColorPrimary" @@ -36,7 +36,7 @@ android:id="@+id/textSubtitle" android:layout_width="0dp" android:layout_height="wrap_content" - android:text="Initialize a new repository, clone an existing one, or open an existing repository" + android:text="@string/git_init_description" android:textSize="16sp" android:textColor="?android:textColorSecondary" android:gravity="center" @@ -70,7 +70,7 @@ android:id="@+id/buttonInitRepo" android:layout_width="match_parent" android:layout_height="60dp" - android:text="Initialize Repository" + android:text="@string/git_initialize_repo" android:textSize="16sp" app:icon="@drawable/ic_add" app:iconGravity="start" @@ -81,7 +81,7 @@ android:layout_width="match_parent" android:layout_height="60dp" android:layout_marginTop="12dp" - android:text="Clone Repository" + android:text="@string/git_clone_repository" android:textSize="16sp" app:icon="@drawable/ic_download" app:iconGravity="start" @@ -92,7 +92,7 @@ android:layout_width="match_parent" android:layout_height="60dp" android:layout_marginTop="12dp" - android:text="Open Existing Repository" + android:text="@string/git_open_existing_repo" android:textSize="16sp" app:icon="@drawable/ic_open" app:iconGravity="start" diff --git a/core/app/src/main/res/layout/fragment_remotes.xml b/core/app/src/main/res/layout/fragment_remotes.xml index c45b24948..ecda21a96 100644 --- a/core/app/src/main/res/layout/fragment_remotes.xml +++ b/core/app/src/main/res/layout/fragment_remotes.xml @@ -32,7 +32,7 @@ @@ -40,7 +40,7 @@ android:id="@+id/buttonRefresh" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="Refresh" + android:text="@string/action_refresh" app:icon="@drawable/ic_sync" style="@style/Widget.Material3.Button.TextButton"/> @@ -54,7 +54,7 @@ android:id="@+id/buttonPush" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="Push" + android:text="@string/git_push_action" android:textSize="14sp" android:layout_margin="4dp" app:icon="@drawable/ic_publish" @@ -66,7 +66,7 @@ android:id="@+id/buttonPull" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="Pull" + android:text="@string/git_pull_action" android:textSize="14sp" android:layout_margin="4dp" app:icon="@drawable/ic_downpull" @@ -78,7 +78,7 @@ android:id="@+id/buttonFetch" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="Fetch" + android:text="@string/git_fetch_action" android:layout_margin="4dp" android:textSize="14sp" app:icon="@drawable/ic_sync" @@ -93,7 +93,7 @@ android:id="@+id/emptyStateText" android:layout_width="match_parent" android:layout_height="wrap_content" - android:text="No remotes configured\nAdd a remote to push/pull changes" + android:text="@string/git_no_remotes_configured" android:textSize="16sp" android:textColor="?android:textColorSecondary" android:gravity="center" @@ -115,7 +115,7 @@ android:layout_height="wrap_content" android:layout_gravity="bottom|end" android:layout_margin="16dp" - android:text="Add Remote" + android:text="@string/git_add_remote" app:elevation="0dp" app:icon="@drawable/ic_add"/> \ No newline at end of file diff --git a/core/app/src/main/res/layout/fragment_settings.xml b/core/app/src/main/res/layout/fragment_settings.xml index 74e940103..66fe6a727 100644 --- a/core/app/src/main/res/layout/fragment_settings.xml +++ b/core/app/src/main/res/layout/fragment_settings.xml @@ -27,7 +27,7 @@ @@ -42,7 +42,7 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" - android:text="Name:" + android:text="@string/git_name_label" android:textSize="14sp" android:textColor="?android:textColorSecondary"/> @@ -51,7 +51,7 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="2" - android:text="User" + android:text="@string/git_user_default" android:textSize="14sp" android:textColor="?android:textColorPrimary" android:textStyle="bold"/> @@ -67,7 +67,7 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" - android:text="Email:" + android:text="@string/git_email_label" android:textSize="14sp" android:textColor="?android:textColorSecondary"/> @@ -76,7 +76,7 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="2" - android:text="user@example.com" + android:text="@string/git_email_default" android:textSize="14sp" android:textColor="?android:textColorPrimary" android:textStyle="bold"/> @@ -87,7 +87,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="16dp" - android:text="Edit User Config" + android:text="@string/git_edit_user_config" style="@style/Widget.Material3.Button.TonalButton"/> @@ -108,7 +108,7 @@ @@ -129,14 +129,14 @@ @@ -158,7 +158,7 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" - android:text="Status:" + android:text="@string/git_status_label" android:textSize="14sp" android:textColor="?android:textColorSecondary"/> @@ -167,7 +167,7 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="2" - android:text="Not saved" + android:text="@string/git_credentials_not_saved" android:textSize="14sp" android:textColor="?android:textColorPrimary" android:textStyle="bold"/> @@ -178,7 +178,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="16dp" - android:text="Clear Saved Credentials" + android:text="@string/git_clear_credentials" style="@style/Widget.Material3.Button.OutlinedButton"/> diff --git a/core/app/src/main/res/layout/fragment_terminal.xml b/core/app/src/main/res/layout/fragment_terminal.xml index 3c808020f..5aa8ab5f9 100644 --- a/core/app/src/main/res/layout/fragment_terminal.xml +++ b/core/app/src/main/res/layout/fragment_terminal.xml @@ -47,7 +47,7 @@ @@ -66,7 +66,7 @@ style="@style/Widget.Material3.Button.TonalButton" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="Initialize Terminal" + android:text="@string/terminal_create_first" app:icon="@android:drawable/ic_input_add" app:cornerRadius="8dp" /> diff --git a/core/app/src/main/res/layout/fragment_terminal_sec_settings.xml b/core/app/src/main/res/layout/fragment_terminal_sec_settings.xml index ce52da1a0..2b8bbc6a1 100644 --- a/core/app/src/main/res/layout/fragment_terminal_sec_settings.xml +++ b/core/app/src/main/res/layout/fragment_terminal_sec_settings.xml @@ -27,7 +27,7 @@ @@ -35,7 +35,7 @@ @@ -77,7 +77,7 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" - android:text="Hide extra keys toolbar" + android:text="@string/terminal_hide_extra_keys" android:textSize="14sp" /> diff --git a/core/app/src/main/res/layout/item_ai_file_change.xml b/core/app/src/main/res/layout/item_ai_file_change.xml index 4dd427023..5bbed969c 100644 --- a/core/app/src/main/res/layout/item_ai_file_change.xml +++ b/core/app/src/main/res/layout/item_ai_file_change.xml @@ -35,7 +35,7 @@ android:id="@+id/fileName" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="MainActivity.kt" + android:text="@string/ai_file_example_name" android:textAppearance="?attr/textAppearanceBodyLarge" android:textStyle="bold" /> @@ -43,7 +43,7 @@ android:id="@+id/fileStatus" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="Modified" + android:text="@string/ai_file_modified" android:textAppearance="?attr/textAppearanceBodySmall" android:layout_marginTop="4dp" /> @@ -51,7 +51,7 @@ android:id="@+id/filePath" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="/path/to/file" + android:text="@string/ai_file_example_path" android:textAppearance="?attr/textAppearanceBodySmall" android:textColor="?attr/colorOnSurfaceVariant" android:layout_marginTop="2dp" diff --git a/core/app/src/main/res/layout/item_branch.xml b/core/app/src/main/res/layout/item_branch.xml index 3e80e5c1f..4f780e8ac 100644 --- a/core/app/src/main/res/layout/item_branch.xml +++ b/core/app/src/main/res/layout/item_branch.xml @@ -30,7 +30,7 @@ android:id="@+id/buttonCheckout" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="Checkout" + android:text="@string/git_checkout" android:textSize="12sp" android:layout_marginEnd="4dp" style="@style/Widget.Material3.Button.TonalButton"/> @@ -39,7 +39,7 @@ android:id="@+id/buttonDelete" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="Delete" + android:text="@string/delete" android:textSize="12sp" style="@style/Widget.Material3.Button.OutlinedButton"/> diff --git a/core/app/src/main/res/layout/item_commit.xml b/core/app/src/main/res/layout/item_commit.xml index 6a54b125c..ba06077a3 100644 --- a/core/app/src/main/res/layout/item_commit.xml +++ b/core/app/src/main/res/layout/item_commit.xml @@ -18,7 +18,7 @@ android:id="@+id/textCommitMessage" android:layout_width="match_parent" android:layout_height="wrap_content" - android:text="Initial commit" + android:text="@string/git_initial_commit_example" android:textSize="16sp" android:textStyle="bold" android:textColor="?android:textColorPrimary"/> @@ -50,7 +50,7 @@ android:id="@+id/textCommitDate" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="Jan 01, 2024 12:00" + android:text="@string/git_date_example" android:textSize="12sp" android:textColor="?android:textColorSecondary"/> @@ -59,7 +59,7 @@ android:id="@+id/textCommitAuthor" android:layout_width="match_parent" android:layout_height="wrap_content" - android:text="Author Name" + android:text="@string/git_author_example" android:textSize="14sp" android:textColor="?android:textColorSecondary" android:layout_marginTop="4dp"/> diff --git a/core/app/src/main/res/layout/item_file.xml b/core/app/src/main/res/layout/item_file.xml index fb1a967b8..9d721e5ed 100644 --- a/core/app/src/main/res/layout/item_file.xml +++ b/core/app/src/main/res/layout/item_file.xml @@ -35,7 +35,7 @@ android:layout_height="wrap_content" android:layout_weight="1" android:layout_marginStart="16dp" - android:text="File Name" + android:text="@string/file_name" android:textSize="16sp" android:textColor="?attr/colorOnSurface" android:fontFamily="sans-serif-medium" diff --git a/core/app/src/main/res/layout/item_file_change.xml b/core/app/src/main/res/layout/item_file_change.xml index 4589ad85f..c7b79407b 100644 --- a/core/app/src/main/res/layout/item_file_change.xml +++ b/core/app/src/main/res/layout/item_file_change.xml @@ -56,7 +56,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="4dp" - android:text="Stage" + android:text="@string/git_stage" android:textSize="12sp" style="@style/Widget.Material3.Button.TonalButton"/> @@ -65,7 +65,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="4dp" - android:text="Unstage" + android:text="@string/git_unstage" android:textSize="12sp" style="@style/Widget.Material3.Button.OutlinedButton"/> @@ -74,7 +74,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="4dp" - android:text="Discard" + android:text="@string/git_discard_action" android:textSize="12sp" style="@style/Widget.Material3.Button.OutlinedButton"/> diff --git a/core/app/src/main/res/layout/item_file_modification.xml b/core/app/src/main/res/layout/item_file_modification.xml index 08eb17b47..984496c57 100644 --- a/core/app/src/main/res/layout/item_file_modification.xml +++ b/core/app/src/main/res/layout/item_file_modification.xml @@ -43,7 +43,7 @@ android:id="@+id/fileName" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="file_name.kt" + android:text="@string/ai_file_example_name" android:textAppearance="?attr/textAppearanceBodyMedium" android:textStyle="bold" /> @@ -51,7 +51,7 @@ android:id="@+id/fileStatus" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="Modifying..." + android:text="@string/ai_file_modifying" android:textAppearance="?attr/textAppearanceBodySmall" android:textColor="?attr/colorOnSurfaceVariant" /> diff --git a/core/app/src/main/res/layout/item_history.xml b/core/app/src/main/res/layout/item_history.xml index 527a5d9de..f249dd03b 100644 --- a/core/app/src/main/res/layout/item_history.xml +++ b/core/app/src/main/res/layout/item_history.xml @@ -39,7 +39,7 @@ android:id="@+id/historyTitle" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="Created MainActivity.kt" + android:text="@string/git_history_example_action" android:textAppearance="?attr/textAppearanceBodyLarge" android:textStyle="bold" /> @@ -47,7 +47,7 @@ android:id="@+id/historyTime" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="2 minutes ago" + android:text="@string/git_history_example_time" android:textAppearance="?attr/textAppearanceBodySmall" android:textColor="?attr/colorOnSurfaceVariant" /> @@ -60,7 +60,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="8dp" - android:text="Modified 3 files" + android:text="@string/git_history_example_files" android:textAppearance="?attr/textAppearanceBodyMedium" /> diff --git a/core/app/src/main/res/layout/item_project.xml b/core/app/src/main/res/layout/item_project.xml index 8d9b7fd49..53a53dc85 100644 --- a/core/app/src/main/res/layout/item_project.xml +++ b/core/app/src/main/res/layout/item_project.xml @@ -28,7 +28,7 @@ android:layout_weight="1" android:textSize="16sp" android:textStyle="bold" - android:text="Project Name" /> + android:text="@string/project_name" /> diff --git a/core/app/src/main/res/layout/item_remote.xml b/core/app/src/main/res/layout/item_remote.xml index ad1b08c11..2b3b7f2f8 100644 --- a/core/app/src/main/res/layout/item_remote.xml +++ b/core/app/src/main/res/layout/item_remote.xml @@ -25,7 +25,7 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" - android:text="origin" + android:text="@string/git_remote_origin" android:textSize="18sp" android:textStyle="bold" android:textColor="?android:textColorPrimary"/> @@ -34,7 +34,7 @@ android:id="@+id/buttonRemove" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="Remove" + android:text="@string/git_remove_action" android:textSize="12sp" style="@style/Widget.Material3.Button.OutlinedButton"/> @@ -43,7 +43,7 @@ android:id="@+id/textRemoteUrl" android:layout_width="match_parent" android:layout_height="wrap_content" - android:text="https://github.com/user/repo.git" + android:hint="@string/git_remote_url_hint" android:textSize="14sp" android:textColor="?android:textColorSecondary" android:layout_marginTop="8dp" diff --git a/core/app/src/main/res/layout/layout_build_variant_item.xml b/core/app/src/main/res/layout/layout_build_variant_item.xml index 5f5395f1c..38482c754 100644 --- a/core/app/src/main/res/layout/layout_build_variant_item.xml +++ b/core/app/src/main/res/layout/layout_build_variant_item.xml @@ -42,7 +42,7 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginTop="8dp" - android:hint="Build Variant" + android:hint="@string/title_build_variants" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/module_name"> @@ -61,7 +61,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="4dp" - android:text="Edit Version & SDK" + android:text="@string/edit_version_and_sdk" app:icon="@drawable/ic_edit" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/variant_name_layout" /> diff --git a/core/app/src/main/res/layout/m3icons_dialog_color_picker.xml b/core/app/src/main/res/layout/m3icons_dialog_color_picker.xml index 4d0e4d8b7..67ab647ab 100644 --- a/core/app/src/main/res/layout/m3icons_dialog_color_picker.xml +++ b/core/app/src/main/res/layout/m3icons_dialog_color_picker.xml @@ -28,7 +28,7 @@ @@ -42,7 +42,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="16dp" - android:hint="Hex Color" + android:hint="@string/hint_hex_color_short" style="@style/Widget.Material3.TextInputLayout.OutlinedBox"> @@ -73,7 +73,7 @@ @@ -88,7 +88,7 @@ @@ -103,7 +103,7 @@ diff --git a/core/app/src/main/res/layout/ndk_layout.xml b/core/app/src/main/res/layout/ndk_layout.xml index a449a0981..28fec7d57 100644 --- a/core/app/src/main/res/layout/ndk_layout.xml +++ b/core/app/src/main/res/layout/ndk_layout.xml @@ -53,7 +53,7 @@ app:icon="@drawable/download" style="@style/Widget.Material3.Button.TonalButton" app:backgroundTint="?attr/colorSurfaceContainerHigh" - android:text="Download" /> + android:text="@string/action_download" /> + + 资源工作室 + Drawable 与图标制作工具 + 启动工作室 + 创建 Drawable + 创建图标 + 导入图片 + 最近资源 + 快捷操作 + res/drawable + 打开完整的资源工作室界面 + + 子模块创建器 + 为您的项目创建新的子模块 + 模块配置 + 编程语言 + Kotlin + Java + 输入模块名称(如:feature、utils) + 模块名称有效 + 模块名称无效 + 创建模块 + 模块 \'%1$s\' 创建成功! + 创建模块失败:%1$s + 关于子模块 + 子模块帮助您将项目组织成更小、更易管理的组件。每个模块可以拥有自己的依赖项和构建配置。 + + 终端 + 终端 + 新建终端 + 关闭终端 + 暂无终端会话 + 当前没有打开的终端会话,创建一个新会话以开始使用。 + 创建终端 + + 编辑 + + + 移除 NDK + 确定要移除 NDK 版本 %1$s 吗? + 没有找到可移除的 NDK 版本 + 成功移除 NDK %1$s + 移除 NDK %1$s 失败 + 未找到 NDK + + + 移除 CMake + 确定要移除 CMake 版本 %1$s 吗? + 没有找到可移除的 CMake 版本 + 成功移除 CMake %1$s + 移除 CMake %1$s 失败 + + + 移除 + 取消 + 确定 + 保存 + 应用 + 删除 + 重命名 + 复制 + 允许 + 拒绝 + 始终允许 + + + 图标已从 Material Icons 导入 + 无法从选择中加载矢量图 + 加载图片出错:%1$s + XML 内容长度:%1$d + XML 加载成功 + 读取 XML 内容失败 + 加载 XML 出错:%1$s + XML 预览已更新 + 图片预览已更新 + 请先选择图片或 XML 文件 + 矢量图已导入 + 解析矢量 XML 失败 + 未打开项目 + 已在 res/%2$s-* 中生成 %1$d 个图标 + 生成图标出错:%1$s + 选择颜色 + 复制到 + + + 选择 NDK 版本 + 选择 CMake 版本 + 无效的 NDK:%1$s + 已选择 CMake %1$s + 无效的 CMake:%1$s + 选择模块 + + + ⚠️ 提供商错误 + 手动切换 + 启用自动切换 + 选择提供商 + ❌ 无可用提供商 + 🔄 已自动切换提供商 + 禁用自动切换 + AI 文件写入权限 + AI 请求写入文件:\n%1$s\n\n是否允许此操作? + AI 权限 + + + Grok API 密钥 + 输入您的 xAI Grok API 密钥 + Gemini API 密钥 + 输入您的 Google Gemini API 密钥 + Deepseek API 密钥 + 输入您的 Deepseek API 密钥 + OpenAI API 密钥 + 输入您的 OpenAI API 密钥 + Anthropic API 密钥 + 输入您的 Anthropic API 密钥 + + + 输入自定义扩展名 + 输入文件扩展名(不含点号) + 重命名 + 输入 %1$s 的新名称 + 删除 %1$s + 没有匹配的文件 + 名称不能为空 + 同名文件已存在 + 重命名成功 + 重命名失败 + 路径已复制到剪贴板 + 删除成功 + 删除失败 + 无法访问此文件夹 + 源文件不存在 + 目录不存在:%1$s + 无法读取目录:%1$s + 无法访问文件夹 + 读取存储权限被拒绝 + 管理存储权限被拒绝 + 代码已复制到剪贴板 + + + 正在重启… + 使用默认字体 + 已选择字体:%1$s + 字体复制成功:%1$s + 复制字体出错:%1$s + 打开文件选择器出错:%1$s + + + 正在备份 + 正在创建 %1$s 的备份 + 备份完成 + 备份失败 + 项目备份失败:%1$s + 正在备份项目… + + + 编辑 %1$s + + + 有更新可用:%1$s + 已是最新 + 在仓库中未找到 + 确认更新 + 您即将更新:\n\n%1$s:%2$s\n%3$s → %4$s\n\n请注意,较新版本可能包含错误、破坏性更改或处于 alpha/beta 阶段。更新后请务必充分测试。\n\n是否继续? + 您即将更新 %1$d 个依赖项。\n\n请注意,较新版本可能包含错误、破坏性更改或处于 alpha/beta 阶段。一次性更新所有依赖项可能会导致兼容性问题。\n\n建议逐个更新和测试依赖项。\n\n是否继续更新全部? + 成功 + 错误 + 更新失败:%1$s + 更新完成 + 成功更新:%1$d\n失败:%2$d + 更新依赖项失败:%1$s + + + 正在修改… + 修改成功 + 修改失败 + + + 项目加载成功 + 项目加载失败 + 加载项目出错 + 对话已清除。可以发送新请求。 + + + 第 %1$d 次尝试 - %2$s + + + 正在创建底部导航 Activity… + 正在创建响应式 Activity… + 正在创建导航抽屉 Activity… + 正在创建无 Activity 项目… + 正在创建原生 C++ 项目… + 正在创建 Compose 空 Activity… + 正在创建基本 Activity… + 正在创建空 Activity… + + + 查看错误 + 重新复制 + + diff --git a/core/app/src/main/res/values/strings.xml b/core/app/src/main/res/values/strings.xml index fe0aaba35..2313dc73c 100644 --- a/core/app/src/main/res/values/strings.xml +++ b/core/app/src/main/res/values/strings.xml @@ -59,6 +59,167 @@ Edit + + Remove NDK + Are you sure you want to remove NDK version %1$s? + No NDK versions found to remove + Successfully removed NDK %1$s + Failed to remove NDK %1$s + NDK Not Found + + Remove CMake + Are you sure you want to remove CMake version %1$s? + No CMake versions found to remove + Successfully removed CMake %1$s + Failed to remove CMake %1$s + + + Remove + Cancel + OK + Save + Apply + Delete + Rename + Copy + Allow + Deny + Always Allow + + + Icon imported from Material Icons + Failed to load vector from selection + Error loading image: %1$s + XML content length: %1$d + XML loaded successfully + Failed to read XML content + Error loading XML: %1$s + XML Preview updated + Image Preview updated + Please select an image or XML file first + Vector imported + Failed to parse vector XML + No project opened + Generated %1$d icons in res/%2$s-* + Error generating icons: %1$s + Select Color + Copy to + + + Select NDK Version + Select CMake Version + Invalid NDK: %1$s + CMake %1$s selected + Invalid CMake: %1$s + Select Module + + + ⚠️ Provider Error + Switch Manually + Enable Auto-Switch + Select Provider + ❌ No Providers Available + 🔄 Auto-Switched Provider + Disable Auto-Switch + AI File Write Permission + AI wants to write to:\n%1$s\n\nAllow this action? + AI Permissions + + + Grok API Key + Enter your xAI Grok API key + Gemini API Key + Enter your Google Gemini API key + Deepseek API Key + Enter your Deepseek API key + OpenAI API Key + Enter your OpenAI API key + Anthropic API Key + Enter your Anthropic API key + + + Enter Custom Extension + Enter file extension without the dot + Rename + Enter new name for %1$s + Delete %1$s + No files match the filters + Name cannot be empty + A file with this name already exists + Renamed successfully + Failed to rename + Path copied to clipboard + Deleted successfully + Failed to delete + Cannot access this folder + Source file doesn\'t exist + Directory doesn\'t exist: %1$s + Cannot read directory: %1$s + Cannot access folder + Permission denied to read storage + Permission denied to manage storage + Code copied to clipboard + + + Restarting… + Using default font + Font selected: %1$s + Font copied successfully: %1$s + Error copying font: %1$s + Error opening file picker: %1$s + + + Backup in Progress + Creating backup of %1$s + Backup Completed + Backup Failed + Failed to backup project: %1$s + Backing up project… + + + Edit %1$s + + + Update available: %1$s + Up to date + Not found in repositories + Confirm Update + You are about to update:\n\n%1$s:%2$s\n%3$s → %4$s\n\nPlease note that newer versions may contain bugs, breaking changes, or be in alpha/beta stage. Always test thoroughly after updating.\n\nDo you want to proceed? + You are about to update %1$d dependencies.\n\nPlease note that newer versions may contain bugs, breaking changes, or be in alpha/beta stage. Updating all dependencies at once can introduce compatibility issues.\n\nIt\'s recommended to update and test dependencies individually.\n\nDo you want to proceed with updating all? + Success + Error + Failed to update: %1$s + Update Complete + Successfully updated: %1$d\nFailed: %2$d + Failed to update dependencies: %1$s + + + Modifying… + Modified successfully + Failed to modify + + + Project loaded successfully + Failed to load project + Error loading project + Conversation cleared. Ready for new request. + + + Attempt #%1$d - %2$s + + + Creating Bottom Navigation Activity… + Creating Responsive Activity… + Creating Navigation Drawer Activity… + Creating no Activity… + Creating native c++… + Creating Compose Empty Activity… + Creating Basic Activity… + Creating Empty Activity… + + + View Error + Copy Again \ No newline at end of file diff --git a/core/common/src/main/java/com/tom/rv2ide/utils/FlashbarActivityUtils.kt b/core/common/src/main/java/com/tom/rv2ide/utils/FlashbarActivityUtils.kt index 2d709b851..6930c8ef9 100644 --- a/core/common/src/main/java/com/tom/rv2ide/utils/FlashbarActivityUtils.kt +++ b/core/common/src/main/java/com/tom/rv2ide/utils/FlashbarActivityUtils.kt @@ -44,6 +44,17 @@ val COLOR_SUCCESS = Color.parseColor("#4CAF50") val COLOR_ERROR = Color.parseColor("#f44336") const val COLOR_INFO = Color.DKGRAY +private var currentFlashbar: Flashbar? = null + +private fun dismissCurrentFlashbar() { + currentFlashbar?.let { + if (it.isShowing()) { + it.dismiss() + } + } + currentFlashbar = null +} + @JvmOverloads fun Activity.flashbarBuilder( gravity: Flashbar.Gravity = TOP, @@ -107,6 +118,7 @@ fun Activity.flashProgress( configure: (Flashbar.Builder.() -> Unit)? = null, action: (Flashbar) -> R, ): R { + dismissCurrentFlashbar() val builder = flashbarBuilder(gravity = TOP, duration = DURATION_INDEFINITE) .showProgress(Flashbar.ProgressPosition.LEFT) @@ -114,13 +126,16 @@ fun Activity.flashProgress( configure?.invoke(builder) val flashbar = builder.build() + currentFlashbar = flashbar flashbar.show() return action(flashbar) } fun Flashbar.Builder.showOnUiThread(): Flashbar { + dismissCurrentFlashbar() val flashbar = build() + currentFlashbar = flashbar flashbar.showOnUiThread() return flashbar } diff --git a/core/resources/src/main/res/values-ar-rSA/strings.xml b/core/resources/src/main/res/values-ar-rSA/strings.xml index 2c9746c90..71f7c92ab 100644 --- a/core/resources/src/main/res/values-ar-rSA/strings.xml +++ b/core/resources/src/main/res/values-ar-rSA/strings.xml @@ -412,115 +412,6 @@ فشلت في تنفيذ الإجراء. تمكين مرسل السجلات. عند التعطيل، لن يتم عرض سجلات التطبيقات في AndroidIDE. - Build variants - Apply - Discard - Failed to fetch build variants - Choose application - Selected build variant not found - Disconnect log senders - Begin long select - Sticky scroll - Show the current scope at the top while scrolling the editor. - Launch app after installation - If enabled, the IDE will (without confirmation) launch the application right after it is installed. - Run options - Cannot run application. Unable to determine package name. - Cannot run application. No application modules found in project. - Launch app - Experimental - You are using %1$s variant of AndroidIDE on a %2$s device. This configuration may work, but it\'ll result in reduced performance and possible security vulnerabilities. Please avoid using this configuration whenever possible. - Pin line numbers - Whether the editor should pin line number panel when scrolled horizontally. - Blue Wave - Sunny Glow - Material You - Language - Select a language for AndroidIDE. - System Default - Project directory is not accessible - Selected file is not a directory - Project directory does not exist - A file save operation is already in progress! - SDK Installation - Install the development tools - The development tools must be installed for the IDE to work. Clicking the done button will open terminal to install the tools. To install, follow the instructions here.

Or read the documentation]]>.
- Welcome - Learn, build, launch. All on your Android. - Grant - Storage - Required to access project files. - Allow installing APKs built with AndroidIDE. - Install packages - Permissions - AndroidIDE requires the following permissions - Please grant the permissions to continue. - It seems you\'re offline. Check your internet connection. - Heads up! You\'re using cellular data. - Heads up! You\'re on a metered network. - Disable background data restriction to avoid installation failures. - Unable to create terminal session - Automatic installation - Manual installation - Android SDK version - JDK version - Install Git - Install OpenSSH - Cannot create session. New sessions are disabled! - Install location error - Unsupported user - Socials - Contributors - Top community contributors. - GitHub Contributors - Crowdin Translators - Misc - Contribute - It\'s not just an IDE, it\'s a community. Contribute code, ideas, and passion to AndroidIDE. - No application available to handle intent. - Open source licenses - View open source licenses. - JDK version - Currently selected: %1$s (requires restart if changed) - لا توجد تحديثات متاحة - فشل التحقق من وجود تحديثات - فشل تحميل سجل التغييرات - خطأ في جلب سجل التغييرات - لم يتم العثور على تحديث متوافق لجهازك - فشل التنزيل - فشل التنزيل: %s - فشل التثبيت - لا يمكن فتح المتصفح - تحديث متاح - تنزيل - عرض في المتصفح - لاحقًا - إلغاء - جاري تنزيل التحديث - الإصدار الجديد %s متاح! - بنية الجهاز: %s - رمز الإصدار المستهدف: %d - المتغيرات المتاحة: %s - جاري التحضير للتنزيل... - %d ميجابايت / %d ميجابايت - يرجى تمكين 'تثبيت التطبيقات غير المعروفة' والمحاولة مرة أخرى - خطأ HTTP: %d - خطأ في جلب معلومات التحديث - خطأ في تحليل معلومات التحديث - الإصدار الحالي: %d، الإصدار المتاح: %d للبنية: %s - لم يتم العثور على متغير متوافق للبنية: %s - الحزمة غير موجودة - ABIs المدعومة: %s - لم يتم العثور على بنية معروفة، سيتم الرجوع إلى armeabi-v7a - بنية الجهاز: %s - لم يتم العثور على تطابق تام لـ %s، جاري تجربة البدائل - استخدام armeabi-v7a كبديل لـ arm64-v8a - استخدام x86 كبديل لـ x86_64 - لم يتم العثور على تطابق تام للبنية، سيتم استخدام أول متغير متاح - خطأ في تنزيل APK - خطأ في تنزيل APK - خطأ في تثبيت APK - خطأ في فتح المتصفح متغيرات البناء تطبيق تجاهل diff --git a/core/resources/src/main/res/values-zh-rCN/strings.xml b/core/resources/src/main/res/values-zh-rCN/strings.xml index 07507b808..03b1e58aa 100644 --- a/core/resources/src/main/res/values-zh-rCN/strings.xml +++ b/core/resources/src/main/res/values-zh-rCN/strings.xml @@ -196,6 +196,10 @@ 项目更名成功 项目重命名失败 + IDE 配置 + 为此项目添加 C++ 模板 + C++ 项目 + 启用构建输出 在编辑器中显示构建输出 @@ -573,7 +577,7 @@ 导入类 生成 setter/getter 添加“throws” - 注释此行 + 注释行 创建缺失方法 转为块 生成构造函数 @@ -1004,4 +1008,258 @@ 好的 无法安装更新:%s 重试 + + + 提交更改 + 提交 + 提交信息不能为空 + 放弃更改 + 您确定要放弃 %1$s 中的更改吗?此操作无法撤消。 + 放弃 + 已保存 + 未保存 + 清除凭据 + 您确定要清除已保存的凭据吗? + 清除 + 凭据已清除 + Git 用户配置 + 保存 + 用户配置已更新 + 用户名和邮箱不能为空 + 添加远程仓库 + 添加 + 输入无效 + 名称和 URL 不能为空 + 无远程仓库 + 未配置远程仓库,请先添加一个远程仓库。 + 推送到远程仓库 + 将提交推送到 %1$s + 推送 + 不使用凭据 + 从远程仓库拉取 + 从 %1$s 拉取更改 + 拉取 + 从远程仓库获取 + 从 %1$s 获取更改 + 获取 + 移除远程仓库 + 您确定要移除远程仓库 \'%1$s\' 吗? + 移除 + 操作失败 + %1$s 失败 + 当前:%1$s + 创建新分支 + 创建 + 分支名称不能为空 + 无法删除当前分支 + 删除分支 + 您确定要删除分支 \'%1$s\' 吗? + 删除 + 初始化仓库失败 + 初始化仓库 + 在以下位置初始化新的 Git 仓库:\n%1$s\n\n选择初始分支名称: + 初始化 + 克隆仓库 + 克隆到:%1$s + 克隆 + URL 不能为空 + 备份项目 + 正在备份项目… + 备份进行中 + 正在创建 %1$s 的备份 + 备份完成 + 项目备份成功!\n\n位置:\n%1$s + 备份失败 + 备份项目失败:%1$s + 正在删除项目… + 删除进行中 + 正在删除 %1$s + 浅克隆(更快) + 仅克隆单个分支 + 包含子模块克隆 + 不获取标签 + 创建裸仓库 + 删除项目 + 重命名 + origin + https://github.com/user/repo.git + 摘要 + 待修改的文件 + 代码预览 + 应用更改 + 前往我的项目 + 凭据(可选) + 用户名 + 密码/令牌 + 下载 + 当前颜色 + 十六进制颜色(如 #FF6200EE) + 颜色预设 + 编辑版本和 SDK + 创建了 MainActivity.kt + 2 分钟前 + 修改了 3 个文件 + 配置本地大语言模型 + 基础 URL + http://localhost:1234 + 模型名称 + local-model + 提交历史 + 刷新 + 暂无提交 + 未找到仓库 + 初始化一个新仓库、克隆已有仓库或打开现有仓库 + 打开现有仓库 + 全部暂存 + 未检测到更改 + 提交信息 + 您想让我做什么? + 图标名称 + 用户邮箱 + 十六进制颜色 + 搜索图标… + AI 提供商 + 模型/代理 + 分支名称 + 正在加载版本… + 暂无可用版本 + 加载失败 + 加载出错 + 请求超时 + 仓库中未找到 NDK 版本 + 仓库中未找到 CMake 版本 + 项目设置失败 + 重试 + 完整错误详情 + Material 图标 + 导入矢量 XML + 导入 + 保存到 + 生成 + 选择要移除的 CMake 版本 + 选择要移除的 NDK 版本 + 请先从下拉菜单中选择 CMake 版本 + 请先从下拉菜单中选择 NDK 版本 + 不支持的架构:%s + 获取包文件名失败:%s + 从清单中收到空文件名 + 下载成功 + 安装失败:%s + 下载失败:%s + 获取包信息失败:%s + 文件太大! + 权限被拒绝 + v0.1-preview + 审查更改 + + MainActivity.kt + 已修改 + /path/to/file + 导入项目 + 外观 + 文字大小 + 隐藏额外按键工具栏 + 正在修改… + AI 文件写入权限 + 启用 AI 文件写入 + 写入前需要确认 + 写入前自动备份文件 + 警告:启用文件写入允许 AI 修改您的项目文件。应用前请务必审查更改。 + 更新依赖 + 版本名称 + 版本号 + 最低 SDK + 目标 SDK + 编译 SDK + 远程仓库名称(如 origin) + 远程仓库 URL + /path/to/project + 名称: + 用户 + 邮箱: + user@example.com + 编辑用户配置 + 凭据 + 记住凭据 + 保存推送/拉取的用户名和密码 + 状态: + 状态 + 随时为您提供帮助 + 修改摘要 + 预览 + 来源 + 选择图片 + 加载 XML + 选择图片或 XML 矢量图来创建应用图标 + 图标设置 + 形状 + 圆形 + 方形 + 圆角 + 背景颜色 + 选择颜色 + 自定义 + 前景缩放 + 圆角 + 生成图标 + 当前:main + 动态取色 + 透明度 + 红色 + 绿色 + 蓝色 + 远程操作 + 未配置远程仓库\n添加远程仓库以推送/拉取更改 + 暂存 + 取消暂存 + 初始提交 + 2024年1月1日 12:00 + 作者名称 + 自动切换提供商 + 出错时自动切换提供商 + 代码补全 + 启用 AI 驱动的代码建议 + 提供商: + 未设置 + 模型: + 目标位置 + 编辑图标 + 颜色 + 更改 + 保存并复制 + M3 图标 + 暂无最近资源 + 正在更新依赖 + 加载中… + 检出 + 未找到所选构建变体 + 无法运行应用,无法确定包名 + 安装失败:%s + 安装成功 + 正在重新初始化项目… + 发生错误:%s + 获取版本失败:%s + 获取版本出错:%s + 无法启动活动 + 转换为大写 + 转换为小写 + 删除行 + 复制行 + 复制行内容 + 上移一行 + 下移一行 + 在上方插入行 + 在下方插入行 + 选择行 + 去除行尾空白 + 增加缩进 + 减少缩进 + 合并行 + 全部清除 + 全部清除 + 确定要清除所有文本吗?此操作无法撤销。 + 清除 + 已复制到剪贴板 + 已去除行尾空白 + 编辑器已清空 diff --git a/core/resources/src/main/res/values/strings.xml b/core/resources/src/main/res/values/strings.xml index 128414093..b167672b3 100644 --- a/core/resources/src/main/res/values/strings.xml +++ b/core/resources/src/main/res/values/strings.xml @@ -1043,4 +1043,258 @@ This AI agent is designed to assist you in developing Android applications direc OK Failed to install update: %s Retry + + + Commit Changes + Commit + Commit message cannot be empty + Discard Changes + Are you sure you want to discard changes in %1$s? This cannot be undone. + Discard + Saved + Not saved + Clear Credentials + Are you sure you want to clear saved credentials? + Clear + Credentials cleared + Git User Config + Save + User config updated + Name and email cannot be empty + Add Remote + Add + Invalid Input + Name and URL cannot be empty + No Remotes + No remotes configured. Add a remote first. + Push to Remote + Push your commits to %1$s + Push + Without credentials + Pull from Remote + Pull changes from %1$s + Pull + Fetch from Remote + Fetch changes from %1$s + Fetch + Remove Remote + Are you sure you want to remove remote \'%1$s\'? + Remove + Operation Failed + %1$s Failed + Current: %1$s + Create New Branch + Create + Branch name cannot be empty + Cannot delete current branch + Delete Branch + Are you sure you want to delete branch \'%1$s\'? + Delete + Failed to initialize repository + Initialize Repository + Initialize a new Git repository at:\n%1$s\n\nChoose initial branch name: + Initialize + Clone Repository + Clone to: %1$s + Clone + URL cannot be empty + Backup project + Backing up project… + Backup in Progress + Creating backup of %1$s + Backup Completed + Project backed up successfully!\n\nLocation:\n%1$s + Backup Failed + Failed to backup project: %1$s + Deleting project… + Delete in Progress + Deleting %1$s + Shallow clone (faster) + Clone single branch only + Clone with submodules + Don\'t fetch tags + Create bare repository + Delete project + Rename + origin + https://github.com/user/repo.git + Summary + Files to be Modified + Code Preview + Apply Changes + Go to My Project + Credentials (Optional) + Username + Password/Token + Download + Current Color + Hex Color (e.g., #FF6200EE) + Color Presets + Edit Version & SDK + Created MainActivity.kt + 2 minutes ago + Modified 3 files + Configure Local LLM + Base URL + http://localhost:1234 + Model Name + local-model + Commit History + Refresh + No commits yet + No Repository Found + Initialize a new repository, clone an existing one, or open an existing repository + Open Existing Repository + Stage All + No changes detected + Commit message + What would you like me to do? + Icon Name + User Email + Hex Color + Search icons… + AI Provider + Model / Agent + Branch name + Loading versions… + No versions available + Failed to load + Error loading + Request timed out + No NDK versions found in the repository + No CMake versions found in the repository + Project Setup Failed + Retry + Full Error Details + Material Icons + Import Vector XML + Import + Save to + Generate + Select CMake Version to Remove + Select NDK Version to Remove + Please select a CMake version from the dropdown first + Please select an NDK version from the dropdown first + Unsupported architecture: %s + Failed to get package filename: %s + Empty filename received from manifest + Successfully downloaded + Installation failed: %s + Download failed: %s + Failed to get package info: %s + File is too big! + Permission denied + v0.1-preview + Review Changes + + MainActivity.kt + Modified + /path/to/file + Import project + Appearance + Text Size + Hide extra keys toolbar + Modifying… + AI File Write Permissions + Enable AI file writing + Require confirmation before writing + Auto backup files before writing + Warning: Enabling file writing allows AI to modify your project files. Always review changes before applying. + Update Dependency + Version Name + Version Code + Min SDK + Target SDK + Compile SDK + Remote name (e.g., origin) + Remote URL + /path/to/project + Name: + User + Email: + user@example.com + Edit User Config + Credentials + Remember credentials + Save username and password for push/pull + Status: + Status + Ready to assist you + Modification Summary + Preview + Source + Select Image + Load XML + Choose an image or XML vector to create app icons + Icon Settings + Shape + Circle + Square + Rounded + Background Color + Choose Color + Custom + Foreground Scale + Rounded Corners + Generate Icons + Current: main + Dynamic Color + Alpha + Red + Green + Blue + Remote Operations + No remotes configured\nAdd a remote to push/pull changes + Stage + Unstage + Initial commit + Jan 01, 2024 12:00 + Author Name + Auto-Switch Provider + Automatically switch provider on errors + Code Completion + Enable AI-powered code suggestions + Provider: + Not set + Model: + Destination + Edit Icon + Color + Change + Save & Copy + M3 Icons + No recent assets + Updating Dependencies + Loading… + Checkout + Selected build variant not found + Cannot run application. Unable to determine package name. + Install failure: %s + Installation succeeded + Reinitializing project… + An error occurred: %s + Failed to fetch versions: %s + Error fetching versions: %s + Unable to start activity + Convert to uppercase + Convert to lowercase + Delete line + Duplicate line + Copy line + Move line up + Move line down + Insert line above + Insert line below + Select line + Trim trailing whitespace + Indent line + Unindent line + Join lines + Clear all + Clear All + Are you sure you want to clear all text? This action cannot be undone. + Clear + Copied to clipboard + Trailing whitespace removed + Editor cleared diff --git a/editor/impl/src/main/java/com/tom/rv2ide/lsp/clang/ClangLanguageServer.kt b/editor/impl/src/main/java/com/tom/rv2ide/lsp/clang/ClangLanguageServer.kt new file mode 100644 index 000000000..6a04797cb --- /dev/null +++ b/editor/impl/src/main/java/com/tom/rv2ide/lsp/clang/ClangLanguageServer.kt @@ -0,0 +1,74 @@ +package com.tom.rv2ide.lsp.clang + +import android.content.Context +import com.tom.rv2ide.lsp.api.ILanguageClient +import com.tom.rv2ide.lsp.api.ILanguageServer +import com.tom.rv2ide.lsp.api.IServerSettings +import com.tom.rv2ide.lsp.models.CodeFormatResult +import com.tom.rv2ide.lsp.models.CompletionParams +import com.tom.rv2ide.lsp.models.CompletionResult +import com.tom.rv2ide.lsp.models.DefinitionParams +import com.tom.rv2ide.lsp.models.DefinitionResult +import com.tom.rv2ide.lsp.models.DiagnosticResult +import com.tom.rv2ide.lsp.models.ExpandSelectionParams +import com.tom.rv2ide.lsp.models.FormatCodeParams +import com.tom.rv2ide.lsp.models.ReferenceParams +import com.tom.rv2ide.lsp.models.ReferenceResult +import com.tom.rv2ide.lsp.models.SignatureHelp +import com.tom.rv2ide.lsp.models.SignatureHelpParams +import com.tom.rv2ide.models.Range +import com.tom.rv2ide.projects.IWorkspace +import java.nio.file.Path + +class ClangLanguageServer(private val context: Context) : ILanguageServer { + + override val serverId: String = SERVER_ID + + override var client: ILanguageClient? = null + private set + + companion object { + const val SERVER_ID = "ide.lsp.clang" + } + + override fun shutdown() { + } + + override fun connectClient(client: ILanguageClient?) { + this.client = client + } + + override fun applySettings(settings: IServerSettings?) { + } + + override fun setupWorkspace(workspace: IWorkspace) { + } + + override fun complete(params: CompletionParams?): CompletionResult { + return CompletionResult.EMPTY + } + + override suspend fun findReferences(params: ReferenceParams): ReferenceResult { + return ReferenceResult(emptyList()) + } + + override suspend fun findDefinition(params: DefinitionParams): DefinitionResult { + return DefinitionResult(emptyList()) + } + + override suspend fun expandSelection(params: ExpandSelectionParams): Range { + return params.selection + } + + override suspend fun signatureHelp(params: SignatureHelpParams): SignatureHelp { + return SignatureHelp(emptyList(), -1, -1) + } + + override suspend fun analyze(file: Path): DiagnosticResult { + return DiagnosticResult.NO_UPDATE + } + + override fun formatCode(params: FormatCodeParams?): CodeFormatResult { + return CodeFormatResult(false, mutableListOf()) + } +} diff --git a/external/logwire/build.gradle.kts b/external/logwire/build.gradle.kts index 511fb84df..125ddedac 100644 --- a/external/logwire/build.gradle.kts +++ b/external/logwire/build.gradle.kts @@ -27,13 +27,13 @@ android { } compileOptions { - sourceCompatibility = JavaVersion.VERSION_11 - targetCompatibility = JavaVersion.VERSION_11 + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 } buildFeatures { aidl = true } - kotlinOptions { jvmTarget = "11" } + kotlinOptions { jvmTarget = "17" } } dependencies { diff --git a/gradle.properties b/gradle.properties index a2f173530..0b5abaad5 100755 --- a/gradle.properties +++ b/gradle.properties @@ -9,14 +9,15 @@ # When configured, Gradle will run in incubating parallel mode. # This option should only be used with decoupled projects. More details, visit # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects -# org.gradle.parallel=true +# org.gradle.parallel=false #Wed Feb 02 13:50:55 IST 2022 -org.gradle.jvmargs=-Xmx4096M \ - -Dkotlin.daemon.jvm.options\="-Xmx4096M" \ +org.gradle.jvmargs=-Xmx3g \ -XX:+HeapDumpOnOutOfMemoryError \ + -XX:+UseParallelGC \ --add-opens java.base/java.lang=ALL-UNNAMED \ --add-opens java.base/java.util=ALL-UNNAMED \ - --add-opens java.base/java.io=ALL-UNNAMED + --add-opens java.base/java.io=ALL-UNNAMED \ + -Dkotlin.daemon.jvm.options="-Xmx1500m" android.useAndroidX=true android.enableJetifier=false android.jetifier.ignorelist=common-30.2.2.jar @@ -27,6 +28,13 @@ android.nonTransitiveRClass=false systemProp.https.protocols=TLSv1,TLSv1.1,TLSv1.2 org.gradle.caching=true # org.gradle.configuration-cache=true -org.gradle.parallel=true -org.gradle.daemon=true -android.r8.version=8.6.17 \ No newline at end of file +org.gradle.parallel=false +org.gradle.daemon=true +org.gradle.workers.max=1 +android.r8.version=8.6.17 +systemProp.http.proxyHost=127.0.0.1 +systemProp.http.proxyPort=18080 +systemProp.https.proxyHost=127.0.0.1 +systemProp.https.proxyPort=18080 +org.gradle.java.home=/root/.local/share/mise/installs/java/17.0.2 +systemProp.http.nonProxyHosts=localhost|127.0.0.1|*.svc|*.cluster.local|::1 diff --git a/logging/logsender/src/main/res/values-zh-rCN/strings.xml b/logging/logsender/src/main/res/values-zh-rCN/strings.xml new file mode 100644 index 000000000..ea165150d --- /dev/null +++ b/logging/logsender/src/main/res/values-zh-rCN/strings.xml @@ -0,0 +1,5 @@ + + + 无法绑定到 AndroidIDE + 退出 + diff --git a/settings.gradle.kts b/settings.gradle.kts index da74386eb..d957fa1bc 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -28,6 +28,10 @@ pluginManagement { gradlePluginPortal() google() mavenCentral() + maven { url = uri("https://maven.aliyun.com/repository/gradle-plugin") } + maven { url = uri("https://maven.aliyun.com/repository/central") } + maven { url = uri("https://maven.aliyun.com/repository/google") } + maven { url = uri("https://maven.aliyun.com/repository/public") } } } @@ -68,6 +72,9 @@ dependencyResolutionManagement { repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) repositories { mavenLocal() + maven { url = uri("https://maven.aliyun.com/repository/central") } + maven { url = uri("https://maven.aliyun.com/repository/google") } + maven { url = uri("https://maven.aliyun.com/repository/public") } google() mavenCentral() maven { url = uri("https://jitpack.io") } diff --git a/tooling/builder-model-impl/src/main/java/com/tom/rv2ide/builder/model/IDESyncIssue.kt b/tooling/builder-model-impl/src/main/java/com/tom/rv2ide/builder/model/IDESyncIssue.kt index 989cfd09a..45287c0f6 100644 --- a/tooling/builder-model-impl/src/main/java/com/tom/rv2ide/builder/model/IDESyncIssue.kt +++ b/tooling/builder-model-impl/src/main/java/com/tom/rv2ide/builder/model/IDESyncIssue.kt @@ -17,40 +17,21 @@ package com.tom.rv2ide.builder.model -import com.android.build.gradle.options.StringOption.AAPT2_FROM_MAVEN_OVERRIDE import com.android.builder.model.v2.ide.SyncIssue -/** - * Sync issue model for AndroidIDE. - * - * @author Akash Yadav - */ +private const val AAPT2_FROM_MAVEN_OVERRIDE_PROPERTY = "android.aapt2FromMavenOverride" + interface IDESyncIssue : SyncIssue { companion object { - /** - * Indicates that the Android Gradle Plugin that is being used by the project is too new for - * AndroidIDE. Data is `projectAgpVersion:maxAgpVersion`. - */ const val TYPE_AGP_VERSION_TOO_NEW = -1 - - // Note: When adding new types, decrement the version by 1 - // The types that are defined in SyncIssue class have their values starting at 0 and incremented - // by 1 when new types are added. So, we could never know what is the latest type's value } } -/** - * Checks whether this [SyncIssue] should be ignored and not reported to the user. - * - * @return Whether the issue can be ignored. - */ fun SyncIssue.shouldBeIgnored(): Boolean { if (this.type != SyncIssue.TYPE_UNSUPPORTED_PROJECT_OPTION_USE) { return false } - // AndroidIDE sets android.aapt2FromMavenOverride in order to use a custom AAPT2 that is - // compatible with Android - return AAPT2_FROM_MAVEN_OVERRIDE.propertyName == this.data + return AAPT2_FROM_MAVEN_OVERRIDE_PROPERTY == this.data } diff --git a/utilities/flashbar/src/main/java/com/tom/rv2ide/flashbar/FlashbarContainerView.kt b/utilities/flashbar/src/main/java/com/tom/rv2ide/flashbar/FlashbarContainerView.kt index 7ce7f522f..a5b433a98 100644 --- a/utilities/flashbar/src/main/java/com/tom/rv2ide/flashbar/FlashbarContainerView.kt +++ b/utilities/flashbar/src/main/java/com/tom/rv2ide/flashbar/FlashbarContainerView.kt @@ -285,14 +285,21 @@ internal class FlashbarContainerView(context: Context) : RelativeLayout(context) private fun dismissInternal(event: DismissEvent) { if (isBarShowing) { - // Flashbar is currently being shown - // but a dismissal has been requested - // take this into account and dismiss flashbar afterwards earlyDismissalRequested = true return } - if (isBarDismissing || !isBarShown) { + if (isBarDismissing) { + return + } + + if (!isBarShown) { + removeCallbacks(dismissRunnable) + (parent as? ViewGroup)?.removeView(this@FlashbarContainerView) + isBarShowing = false + isBarShown = false + isBarDismissing = false + onBarDismissListener?.onDismissed(parentFlashbar, event) return } diff --git a/xml/utils/src/main/java/com/tom/rv2ide/xml/internal/versions/ApiVersionsParser.kt b/xml/utils/src/main/java/com/tom/rv2ide/xml/internal/versions/ApiVersionsParser.kt index 7f792ecfe..4baf5b8c3 100644 --- a/xml/utils/src/main/java/com/tom/rv2ide/xml/internal/versions/ApiVersionsParser.kt +++ b/xml/utils/src/main/java/com/tom/rv2ide/xml/internal/versions/ApiVersionsParser.kt @@ -89,7 +89,7 @@ open class ApiVersionsParser { private fun consumeStartElement(event: StartElement) { when (event.name.localPart) { - TAG_API -> apiVersion = event.getAttributeByName(QName("version")).value.toInt() + TAG_API -> apiVersion = event.getAttributeByName(QName("version")).value.toDouble().toInt() TAG_CLASS -> consumeClass(event) TAG_FIELD -> consumeMember(event, TAG_FIELD) TAG_METHOD -> consumeMember(event, TAG_METHOD) @@ -172,9 +172,9 @@ open class ApiVersionsParser { when (attribute.name.localPart) { ATTR_NAME -> name = attribute.value - ATTR_SIN -> since = attribute.value.toInt() - ATTR_DEPR -> deprecated = attribute.value.toInt() - ATTR_REM -> removed = attribute.value.toInt() + ATTR_SIN -> since = attribute.value.toDouble().toInt() + ATTR_DEPR -> deprecated = attribute.value.toDouble().toInt() + ATTR_REM -> removed = attribute.value.toDouble().toInt() } }