Cache region display-name lookups used by currency search

matchesCurrencySearch() re-derives a country name for every currency
on every keystroke; region codes don't change during a session, so
this was redoing the same locale lookups repeatedly — worst on web,
where each lookup constructs a fresh Intl.DisplayNames instance.
Caches by region code instead, including null results (regions the
platform doesn't recognize), so each code's lookup happens once ever.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FXcrACM5sok3M1KQJ8kByy
This commit is contained in:
2026-09-10 12:35:39 +03:00
co-authored by Claude Sonnet 5
parent 293c822c86
commit 3bdf320f5c
@@ -17,14 +17,25 @@ fun matchesCurrencySearch(info: CurrencyInfo, query: String): Boolean {
} }
} }
// Region codes are static for the life of the app (they don't depend on [query]), but
// [matchesCurrencySearch] re-derives a name for every currency on every keystroke — caching here
// turns that back into a one-time-per-region-code cost. A plain Map (not getOrPut) since a cached
// null result — a region [regionDisplayName] doesn't recognize — must stay cached rather than
// being retried every time, which getOrPut would do for a null value.
private val regionDisplayNameCache = mutableMapOf<String, String?>()
/** /**
* A localized display name for ISO 3166-1 alpha-2 [regionCode] (e.g. "Canada"), or null if the * A localized display name for ISO 3166-1 alpha-2 [regionCode] (e.g. "Canada"), or null if the
* platform doesn't recognize it. "EU" is handled directly since it's not a real ISO 3166-1 * platform doesn't recognize it. "EU" is handled directly since it's not a real ISO 3166-1
* country code — it's [issuingCountryCodes]' own stand-in for EUR's region/flag — and platform * country code — it's [issuingCountryCodes]' own stand-in for EUR's region/flag — and platform
* locale data doesn't reliably resolve it to a name the way it does real country codes. * locale data doesn't reliably resolve it to a name the way it does real country codes.
*/ */
private fun localizedRegionName(regionCode: String): String? = private fun localizedRegionName(regionCode: String): String? {
if (regionCode == "EU") "European Union" else regionDisplayName(regionCode) if (regionCode in regionDisplayNameCache) return regionDisplayNameCache[regionCode]
val name = if (regionCode == "EU") "European Union" else regionDisplayName(regionCode)
regionDisplayNameCache[regionCode] = name
return name
}
/** The current platform's localized display name for ISO 3166-1 alpha-2 [regionCode], if known. */ /** The current platform's localized display name for ISO 3166-1 alpha-2 [regionCode], if known. */
expect fun regionDisplayName(regionCode: String): String? expect fun regionDisplayName(regionCode: String): String?