From c3b07c84a604afe9e7eb568c3de6e7f5bc8fb301 Mon Sep 17 00:00:00 2001 From: LeanBitLab <245915690+LeanBitLab@users.noreply.github.com> Date: Wed, 7 Oct 2026 08:15:12 +0000 Subject: [PATCH] =?UTF-8?q?=E2=9A=A1=20Bolt:=20[performance=20improvement]?= =?UTF-8?q?=20Pre-compile=20regex=20properties?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Extracted dynamic `.toRegex()` calls into `private val` top-level properties across several Kotlin files. This avoids recompiling the same regular expression objects on every invocation. --- .../keyboard_parser/LocaleKeyboardInfos.kt | 12 ++++++---- .../latin/EmojiAltPhysicalKeyDetector.kt | 4 +++- .../keyboard/latin/sound/SoundPackImporter.kt | 9 +++++--- .../keyboard/latin/utils/LayoutUtils.kt | 4 +++- .../preferences/BackupRestorePreference.kt | 22 +++++++++++++------ .../LoadHandwritingPluginPreference.kt | 5 +++-- .../preferences/LoadOcrPluginPreference.kt | 5 +++-- .../LoadOfflineAiPluginPreference.kt | 5 +++-- .../LoadTranslationPluginPreference.kt | 5 +++-- .../settings/screens/VoiceSettingsScreen.kt | 5 +++-- 10 files changed, 50 insertions(+), 26 deletions(-) diff --git a/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/LocaleKeyboardInfos.kt b/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/LocaleKeyboardInfos.kt index 1ae440de3..ded474c58 100644 --- a/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/LocaleKeyboardInfos.kt +++ b/app/src/main/java/helium314/keyboard/keyboard/internal/keyboard_parser/LocaleKeyboardInfos.kt @@ -67,7 +67,6 @@ class LocaleKeyboardInfos(dataStream: InputStream?, locale: Locale) { if (stream == null) return stream.reader().use { reader -> var mode = READER_MODE_NONE - val colonSpaceRegex = ":\\s+".toRegex() reader.forEachLine { l -> val line = l.trim() if (line.isEmpty()) return@forEachLine @@ -257,9 +256,9 @@ private fun getCurrencyKey(locale: Locale): Pair> { return euro if (locale.toString().matches(euroLocales)) return euro - if (locale.language.matches("ca|eu|lb|mt|pms".toRegex())) + if (locale.language.matches(euroLanguagesRegex)) return euro - if (locale.language.matches("ak|dag|ee|fa|gaa|ha|he|ig|iw|lo|ko|km|mn|ne|si|th|uk|vi|yo".toRegex())) + if (locale.language.matches(otherLanguagesRegex)) return genericCurrencyKey(getCurrency(locale)) if (locale.language == "hy") return dram @@ -271,7 +270,7 @@ private fun getCurrencyKey(locale: Locale): Pair> { return genericCurrencyKey(getCurrency(locale)) if (locale.country != "IN" && locale.language == "ta") return genericCurrencyKey("௹") - if (locale.country == "IN" || locale.language.matches("hi|kn|ml|mr|ta|te|gu".toRegex())) + if (locale.country == "IN" || locale.language.matches(inLanguagesRegex)) return rupee if (locale.country == "GB") return pound @@ -325,6 +324,11 @@ private val dollar = "$" to listOf("£", "¢", "€", "¥", "₱") private val euroCountries = "AD|AT|BE|BG|HR|CY|CZ|DA|EE|FI|FR|DE|GR|HU|IE|IT|XK|LV|LT|LU|MT|MO|ME|NL|PL|PT|RO|SM|SK|SI|ES|VA".toRegex() private val euroLocales = "bg|ca|cs|da|de|el|en|es|et|eu|fi|fr|ga|gl|hr|hu|it|lb|lt|lv|mt|nl|pl|pt|ro|sk|sl|sq|sr|sv".toRegex() +private val colonSpaceRegex = ":\\s+".toRegex() +private val euroLanguagesRegex = "ca|eu|lb|mt|pms".toRegex() +private val otherLanguagesRegex = "ak|dag|ee|fa|gaa|ha|he|ig|iw|lo|ko|km|mn|ne|si|th|uk|vi|yo".toRegex() +private val inLanguagesRegex = "hi|kn|ml|mr|ta|te|gu".toRegex() + const val POPUP_KEYS_ALL = "all" const val POPUP_KEYS_MORE = "more" const val POPUP_KEYS_MAIN = "main" diff --git a/app/src/main/java/helium314/keyboard/latin/EmojiAltPhysicalKeyDetector.kt b/app/src/main/java/helium314/keyboard/latin/EmojiAltPhysicalKeyDetector.kt index b6600350c..12e6b755d 100644 --- a/app/src/main/java/helium314/keyboard/latin/EmojiAltPhysicalKeyDetector.kt +++ b/app/src/main/java/helium314/keyboard/latin/EmojiAltPhysicalKeyDetector.kt @@ -130,7 +130,7 @@ class EmojiAltPhysicalKeyDetector(resources: Resources) { val values = resources.getStringArray(resourceId) if (values != null) { for (i in values.indices) { - val valuePair = values[i].split(",".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray() + val valuePair = values[i].split(commaRegex).dropLastWhile { it.isEmpty() }.toTypedArray() if (valuePair.size != 2) { Log.w(TAG, "Expected 2 integers in $name[$i] : ${values[i]}") } @@ -148,3 +148,5 @@ class EmojiAltPhysicalKeyDetector(resources: Resources) { } } } + +private val commaRegex = ",".toRegex() diff --git a/app/src/main/java/helium314/keyboard/latin/sound/SoundPackImporter.kt b/app/src/main/java/helium314/keyboard/latin/sound/SoundPackImporter.kt index 654c74175..b9b9eb3d7 100644 --- a/app/src/main/java/helium314/keyboard/latin/sound/SoundPackImporter.kt +++ b/app/src/main/java/helium314/keyboard/latin/sound/SoundPackImporter.kt @@ -46,7 +46,7 @@ object SoundPackImporter { } fun getPackDir(context: Context, packId: String): File { - val cleanId = packId.replace("[^a-zA-Z0-9._-]".toRegex(), "_") + val cleanId = packId.replace(filenameAllowedCharsRegex, "_") return File(getSoundPacksDir(context), cleanId) } @@ -225,7 +225,7 @@ object SoundPackImporter { ): String? { val ext = originalName.substringAfterLast(".", "ogg").lowercase() val rawName = originalName.substringBeforeLast(".") - val cleanId = "custom_${rawName.replace("[^a-zA-Z0-9_-]".toRegex(), "_").lowercase()}_${System.currentTimeMillis() % 10000}" + val cleanId = "custom_${rawName.replace(packIdAllowedCharsRegex, "_").lowercase()}_${System.currentTimeMillis() % 10000}" val displayName = customName?.takeIf { it.isNotBlank() } ?: rawName val packDir = getPackDir(context, cleanId) packDir.mkdirs() @@ -300,7 +300,7 @@ object SoundPackImporter { val finalId = if (manifest != null) { manifest.id } else { - val baseName = zipFile.nameWithoutExtension.replace("[^a-zA-Z0-9_-]".toRegex(), "_").lowercase() + val baseName = zipFile.nameWithoutExtension.replace(packIdAllowedCharsRegex, "_").lowercase() "custom_${baseName}_${System.currentTimeMillis() % 10000}" } @@ -505,3 +505,6 @@ object SoundPackImporter { return uri.lastPathSegment } } + +private val filenameAllowedCharsRegex = "[^a-zA-Z0-9._-]".toRegex() +private val packIdAllowedCharsRegex = "[^a-zA-Z0-9_-]".toRegex() diff --git a/app/src/main/java/helium314/keyboard/latin/utils/LayoutUtils.kt b/app/src/main/java/helium314/keyboard/latin/utils/LayoutUtils.kt index 3e455b10a..d4c172c92 100644 --- a/app/src/main/java/helium314/keyboard/latin/utils/LayoutUtils.kt +++ b/app/src/main/java/helium314/keyboard/latin/utils/LayoutUtils.kt @@ -63,5 +63,7 @@ object LayoutUtils { } fun getSimpleRowStrings(layoutContent: String): List = - layoutContent.replace("\r\n", "\n").split("\\n\\s*\\n".toRegex()).filter { it.isNotBlank() } + layoutContent.replace("\r\n", "\n").split(doubleNewlineRegex).filter { it.isNotBlank() } } + +private val doubleNewlineRegex = "\\n\\s*\\n".toRegex() diff --git a/app/src/main/java/helium314/keyboard/settings/preferences/BackupRestorePreference.kt b/app/src/main/java/helium314/keyboard/settings/preferences/BackupRestorePreference.kt index 5ca72d27a..73acb5504 100644 --- a/app/src/main/java/helium314/keyboard/settings/preferences/BackupRestorePreference.kt +++ b/app/src/main/java/helium314/keyboard/settings/preferences/BackupRestorePreference.kt @@ -502,14 +502,22 @@ private const val PREFS_FILE_NAME = "preferences.json" private const val PROTECTED_PREFS_FILE_NAME = "protected_preferences.json" private const val FLOATING_KEYBOARD_PREFS_FILE_NAME = "floating_keyboard_preferences.json" +private val blacklistsRegex = "blacklists${File.separator}.*\\.txt".toRegex() +private val layoutsRegex = "layouts${File.separator}.*${LayoutUtilsCustom.CUSTOM_LAYOUT_PREFIX}+\\..{0,4}".toRegex() +private val dictsRegex = "dicts${File.separator}.*${File.separator}.*user\\.dict".toRegex() +private val historyDictRegex = "UserHistoryDictionary.*${File.separator}UserHistoryDictionary.*\\.(body|header)".toRegex() +private val bgImgRegex = "custom_background_image.*".toRegex() +private val fontRegex = "custom_font".toRegex() +private val emojiFontRegex = "custom_emoji_font".toRegex() + private val backupFilePatterns by lazy { listOf( - "blacklists${File.separator}.*\\.txt".toRegex(), - "layouts${File.separator}.*${LayoutUtilsCustom.CUSTOM_LAYOUT_PREFIX}+\\..{0,4}".toRegex(), // can't expect a period at the end, as this would break restoring older backups - "dicts${File.separator}.*${File.separator}.*user\\.dict".toRegex(), - "UserHistoryDictionary.*${File.separator}UserHistoryDictionary.*\\.(body|header)".toRegex(), - "custom_background_image.*".toRegex(), - "custom_font".toRegex(), - "custom_emoji_font".toRegex(), + blacklistsRegex, + layoutsRegex, // can't expect a period at the end, as this would break restoring older backups + dictsRegex, + historyDictRegex, + bgImgRegex, + fontRegex, + emojiFontRegex, ) } enum class BackupCategory { diff --git a/app/src/main/java/helium314/keyboard/settings/preferences/LoadHandwritingPluginPreference.kt b/app/src/main/java/helium314/keyboard/settings/preferences/LoadHandwritingPluginPreference.kt index 793b290e9..1948755db 100644 --- a/app/src/main/java/helium314/keyboard/settings/preferences/LoadHandwritingPluginPreference.kt +++ b/app/src/main/java/helium314/keyboard/settings/preferences/LoadHandwritingPluginPreference.kt @@ -90,8 +90,7 @@ fun LoadHandwritingPluginPreference( conn.connect() if (conn.responseCode == 200) { val response = conn.inputStream.bufferedReader().use { it.readText() } - val regex = "\"tag_name\"\\s*:\\s*\"([^\"]+)\"".toRegex() - val match = regex.find(response) + val match = tagNameRegex.find(response) if (match != null) { val tag = match.groupValues[1] remoteVersion = tag @@ -320,6 +319,8 @@ private fun isUpdateAvailable(local: String, remote: String): Boolean { return false } +private val tagNameRegex = "\"tag_name\"\\s*:\\s*\"([^\"]+)\"".toRegex() + private fun buildLanguageEntries(context: Context): List> { val sysLocale = context.resources.configuration.locales[0] val locales = java.util.Locale.getAvailableLocales() diff --git a/app/src/main/java/helium314/keyboard/settings/preferences/LoadOcrPluginPreference.kt b/app/src/main/java/helium314/keyboard/settings/preferences/LoadOcrPluginPreference.kt index 30145334c..ee66d235a 100644 --- a/app/src/main/java/helium314/keyboard/settings/preferences/LoadOcrPluginPreference.kt +++ b/app/src/main/java/helium314/keyboard/settings/preferences/LoadOcrPluginPreference.kt @@ -93,8 +93,7 @@ fun LoadOcrPluginPreference( conn.connect() if (conn.responseCode == 200) { val response = conn.inputStream.bufferedReader().use { it.readText() } - val regex = "\"tag_name\"\\s*:\\s*\"([^\"]+)\"".toRegex() - val match = regex.find(response) + val match = tagNameRegex.find(response) if (match != null) { remoteVersion = match.groupValues[1] } @@ -321,3 +320,5 @@ private fun isUpdateAvailable(local: String, remote: String): Boolean { } return false } + +private val tagNameRegex = "\"tag_name\"\\s*:\\s*\"([^\"]+)\"".toRegex() diff --git a/app/src/main/java/helium314/keyboard/settings/preferences/LoadOfflineAiPluginPreference.kt b/app/src/main/java/helium314/keyboard/settings/preferences/LoadOfflineAiPluginPreference.kt index 840bee190..898296c0f 100644 --- a/app/src/main/java/helium314/keyboard/settings/preferences/LoadOfflineAiPluginPreference.kt +++ b/app/src/main/java/helium314/keyboard/settings/preferences/LoadOfflineAiPluginPreference.kt @@ -87,8 +87,7 @@ fun LoadOfflineAiPluginPreference( conn.connect() if (conn.responseCode == 200) { val response = conn.inputStream.bufferedReader().use { it.readText() } - val regex = "\"tag_name\"\\s*:\\s*\"([^\"]+)\"".toRegex() - val match = regex.find(response) + val match = tagNameRegex.find(response) if (match != null) { val tag = match.groupValues[1] remoteVersion = tag @@ -318,3 +317,5 @@ private fun isUpdateAvailable(local: String, remote: String): Boolean { } return false } + +private val tagNameRegex = "\"tag_name\"\\s*:\\s*\"([^\"]+)\"".toRegex() diff --git a/app/src/main/java/helium314/keyboard/settings/preferences/LoadTranslationPluginPreference.kt b/app/src/main/java/helium314/keyboard/settings/preferences/LoadTranslationPluginPreference.kt index bbfa854eb..43a60b93e 100644 --- a/app/src/main/java/helium314/keyboard/settings/preferences/LoadTranslationPluginPreference.kt +++ b/app/src/main/java/helium314/keyboard/settings/preferences/LoadTranslationPluginPreference.kt @@ -94,8 +94,7 @@ fun LoadTranslationPluginPreference( conn.connect() if (conn.responseCode == 200) { val response = conn.inputStream.bufferedReader().use { it.readText() } - val regex = "\"tag_name\"\\s*:\\s*\"([^\"]+)\"".toRegex() - val match = regex.find(response) + val match = tagNameRegex.find(response) if (match != null) { val tag = match.groupValues[1] remoteVersion = tag @@ -323,6 +322,8 @@ private fun isUpdateAvailable(local: String, remote: String): Boolean { return false } +private val tagNameRegex = "\"tag_name\"\\s*:\\s*\"([^\"]+)\"".toRegex() + @Composable fun TranslationModePreference() { val ctx = LocalContext.current diff --git a/app/src/main/java/helium314/keyboard/settings/screens/VoiceSettingsScreen.kt b/app/src/main/java/helium314/keyboard/settings/screens/VoiceSettingsScreen.kt index 1283f3c6e..8d760afcd 100644 --- a/app/src/main/java/helium314/keyboard/settings/screens/VoiceSettingsScreen.kt +++ b/app/src/main/java/helium314/keyboard/settings/screens/VoiceSettingsScreen.kt @@ -150,8 +150,7 @@ fun VoiceSettingsScreen( conn.connect() if (conn.responseCode == 200) { val response = conn.inputStream.bufferedReader().use { it.readText() } - val regex = "\"tag_name\"\\s*:\\s*\"([^\"]+)\"".toRegex() - val match = regex.find(response) + val match = tagNameRegex.find(response) if (match != null) { val tag = match.groupValues[1] remoteVersion = tag @@ -842,6 +841,8 @@ private fun isUpdateAvailable(local: String, remote: String): Boolean { return false } +private val tagNameRegex = "\"tag_name\"\\s*:\\s*\"([^\"]+)\"".toRegex() + fun createVoiceSettings(context: Context): List = listOf( Setting( key = VoiceConstants.PREF_VOICE_PROVIDER,