mirror of
https://github.com/vitorpamplona/amethyst.git
synced 2026-10-05 11:18:24 +00:00
fix: re-escape the strings copied back to Android res, port the catalog filter test
aapt and compose-resources do not share escaping rules, so a key moved back to res/values needs its apostrophes escaped again or the resource merge fails with "Invalid unicode escape sequence in string". This is the inverse of what tools/strings-migrate/fix_escapes.py does on the way out; a value Android wrapped in quotes to protect whitespace, and a bare @string/ alias, are left alone. SettingsCatalogFilterTest used bare Ints as stand-in resource handles; it now uses real catalog entries and still supplies their text through the injected lookup, which is the point of the filter taking one. :quartz, :commons, :commonsUI and :amethyst unit tests all pass. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AXvKXakvup4inNFfAhhr4L
This commit is contained in:
@@ -169,7 +169,7 @@
|
||||
<string name="always_on_notif_connecting">Connexion aux relais de boîte de réception…</string>
|
||||
<string name="always_on_notif_title">Notifications Amethyst actives</string>
|
||||
<string name="call_ongoing">Appels</string>
|
||||
<string name="call_ongoing_description">Notification d'appel en cours</string>
|
||||
<string name="call_ongoing_description">Notification d\'appel en cours</string>
|
||||
<string name="call_with">Appel avec %1$s</string>
|
||||
<string name="call_hangup">Raccrocher</string>
|
||||
<string name="reaction">Réaction</string>
|
||||
@@ -178,7 +178,7 @@
|
||||
<string name="voice_reply">Réponse vocale</string>
|
||||
<string name="private_message">Message privé</string>
|
||||
<string name="nest_notification_broadcasting">Nest — En direct</string>
|
||||
<string name="nest_notification_channel_description">Maintient l'audio actif pendant qu'une salle est ouverte.</string>
|
||||
<string name="nest_notification_channel_description">Maintient l\'audio actif pendant qu\'une salle est ouverte.</string>
|
||||
<string name="nest_notification_listening">Nest connecté</string>
|
||||
<string name="nest_notification_stop">Arrêter</string>
|
||||
<string name="nest_notification_text">Appuyer pour revenir.</string>
|
||||
|
||||
@@ -185,7 +185,7 @@
|
||||
<string name="always_on_notif_connecting">Connexion aux relais de boîte de réception…</string>
|
||||
<string name="always_on_notif_title">Notifications Amethyst actives</string>
|
||||
<string name="call_ongoing">Appels</string>
|
||||
<string name="call_ongoing_description">Notification d'appel en cours</string>
|
||||
<string name="call_ongoing_description">Notification d\'appel en cours</string>
|
||||
<string name="call_with">Appel avec %1$s</string>
|
||||
<string name="call_hangup">Raccrocher</string>
|
||||
<string name="pow_time_left_soon">à tout moment maintenant</string>
|
||||
@@ -205,7 +205,7 @@
|
||||
<string name="pow_kind_report">Signaler</string>
|
||||
<string name="private_message">Message privé</string>
|
||||
<string name="nest_notification_broadcasting">Nest — En direct</string>
|
||||
<string name="nest_notification_channel_description">Maintient l'audio actif pendant qu'une salle est ouverte.</string>
|
||||
<string name="nest_notification_channel_description">Maintient l\'audio actif pendant qu\'une salle est ouverte.</string>
|
||||
<string name="nest_notification_listening">Nest connecté</string>
|
||||
<string name="nest_notification_stop">Arrêter</string>
|
||||
<string name="nest_notification_text">Appuyer pour revenir.</string>
|
||||
|
||||
@@ -2316,7 +2316,7 @@
|
||||
<string name="always_on_notif_connecting">Connexion aux relais de boîte de réception…</string>
|
||||
<string name="always_on_notif_title">Notifications Amethyst actives</string>
|
||||
<string name="call_ongoing">Appels</string>
|
||||
<string name="call_ongoing_description">Notification d'appel en cours</string>
|
||||
<string name="call_ongoing_description">Notification d\'appel en cours</string>
|
||||
<string name="call_with">Appel avec %1$s</string>
|
||||
<string name="call_hangup">Raccrocher</string>
|
||||
<string name="reaction">Réaction</string>
|
||||
@@ -2327,7 +2327,7 @@
|
||||
<string name="private_message">Message privé</string>
|
||||
<string name="nest_notification_broadcasting">Nest — En direct</string>
|
||||
<string name="nest_notification_channel">Nests</string>
|
||||
<string name="nest_notification_channel_description">Maintient l'audio actif pendant qu'une salle est ouverte.</string>
|
||||
<string name="nest_notification_channel_description">Maintient l\'audio actif pendant qu\'une salle est ouverte.</string>
|
||||
<string name="nest_notification_listening">Nest connecté</string>
|
||||
<string name="nest_notification_stop">Arrêter</string>
|
||||
<string name="nest_notification_text">Appuyer pour revenir.</string>
|
||||
|
||||
@@ -176,7 +176,7 @@
|
||||
<string name="voice_post">Post vocale</string>
|
||||
<string name="voice_reply">Risposta vocale</string>
|
||||
<string name="private_message">Messaggio privato</string>
|
||||
<string name="nest_notification_channel_description">Mantiene l'audio attivo mentre una stanza è aperta.</string>
|
||||
<string name="nest_notification_channel_description">Mantiene l\'audio attivo mentre una stanza è aperta.</string>
|
||||
<string name="nest_notification_listening">Nest connesso</string>
|
||||
<string name="nest_notification_stop">Ferma</string>
|
||||
<string name="nest_notification_text">Tocca per tornare.</string>
|
||||
@@ -195,7 +195,7 @@
|
||||
<string name="napplet_cap_theme">Tema</string>
|
||||
<string name="napplet_cap_notify">Notifiche</string>
|
||||
<string name="napplet_cap_inc">Messaggistica</string>
|
||||
<string name="muted_button">Mutato. Clicca per riattivare l'audio</string>
|
||||
<string name="muted_button">Mutato. Clicca per riattivare l\'audio</string>
|
||||
<string name="mute_button">Audio acceso. Clicca per disattivarlo</string>
|
||||
<string name="play">Riproduci</string>
|
||||
<string name="pause">Pausa</string>
|
||||
|
||||
@@ -158,16 +158,16 @@
|
||||
because android:label on the manifest entry can only reference @string/. -->
|
||||
<!-- My Fitness: the signed-in user's own training summary. Android resource because
|
||||
NavBarItemDef labels are R.string ids. -->
|
||||
<string name="always_on_notif_channel_description">Gerçek zamanlı bildirimler için gelen kutusu relay'lerinize bağlantıları etkin tutar</string>
|
||||
<string name="always_on_notif_channel_description">Gerçek zamanlı bildirimler için gelen kutusu relay\'lerinize bağlantıları etkin tutar</string>
|
||||
<plurals name="always_on_notif_connected">
|
||||
<item quantity="one">%1$d gelen kutusu relay'ine bağlandı</item>
|
||||
<item quantity="other">%1$d gelen kutusu relay'ine bağlandı</item>
|
||||
<item quantity="one">%1$d gelen kutusu relay\'ine bağlandı</item>
|
||||
<item quantity="other">%1$d gelen kutusu relay\'ine bağlandı</item>
|
||||
</plurals>
|
||||
<plurals name="always_on_notif_connected_foreground">
|
||||
<item quantity="one">%1$d relay'e bağlandı</item>
|
||||
<item quantity="other">%1$d relay'e bağlandı</item>
|
||||
<item quantity="one">%1$d relay\'e bağlandı</item>
|
||||
<item quantity="other">%1$d relay\'e bağlandı</item>
|
||||
</plurals>
|
||||
<string name="always_on_notif_connecting">Gelen kutusu relay'lerine bağlanılıyor…</string>
|
||||
<string name="always_on_notif_connecting">Gelen kutusu relay\'lerine bağlanılıyor…</string>
|
||||
<string name="always_on_notif_title">Amethyst Bildirimleri Etkin</string>
|
||||
<string name="call_ongoing">Aramalar</string>
|
||||
<string name="call_ongoing_description">Devam eden arama bildirimi</string>
|
||||
@@ -191,7 +191,7 @@
|
||||
<string name="call_unmute">Sesi Aç</string>
|
||||
<string name="napplet_cap_identity">Kimlik</string>
|
||||
<string name="napplet_cap_keys">Klavye eylemleri</string>
|
||||
<string name="napplet_cap_relay">relay'ler</string>
|
||||
<string name="napplet_cap_relay">relay\'ler</string>
|
||||
<string name="napplet_cap_storage">Depolama</string>
|
||||
<string name="napplet_cap_value">Ödemeler</string>
|
||||
<string name="napplet_cap_resource">Ağ</string>
|
||||
|
||||
@@ -2881,16 +2881,16 @@
|
||||
|
||||
|
||||
|
||||
<string name="always_on_notif_channel_description">Gerçek zamanlı bildirimler için gelen kutusu relay'lerinize bağlantıları etkin tutar</string>
|
||||
<string name="always_on_notif_channel_description">Gerçek zamanlı bildirimler için gelen kutusu relay\'lerinize bağlantıları etkin tutar</string>
|
||||
<plurals name="always_on_notif_connected">
|
||||
<item quantity="one">%1$d gelen kutusu relay'ine bağlandı</item>
|
||||
<item quantity="other">%1$d gelen kutusu relay'ine bağlandı</item>
|
||||
<item quantity="one">%1$d gelen kutusu relay\'ine bağlandı</item>
|
||||
<item quantity="other">%1$d gelen kutusu relay\'ine bağlandı</item>
|
||||
</plurals>
|
||||
<plurals name="always_on_notif_connected_foreground">
|
||||
<item quantity="one">%1$d relay'e bağlandı</item>
|
||||
<item quantity="other">%1$d relay'e bağlandı</item>
|
||||
<item quantity="one">%1$d relay\'e bağlandı</item>
|
||||
<item quantity="other">%1$d relay\'e bağlandı</item>
|
||||
</plurals>
|
||||
<string name="always_on_notif_connecting">Gelen kutusu relay'lerine bağlanılıyor…</string>
|
||||
<string name="always_on_notif_connecting">Gelen kutusu relay\'lerine bağlanılıyor…</string>
|
||||
<string name="always_on_notif_title">Amethyst Bildirimleri Etkin</string>
|
||||
<string name="call_ongoing">Aramalar</string>
|
||||
<string name="call_ongoing_description">Devam eden arama bildirimi</string>
|
||||
@@ -2915,7 +2915,7 @@
|
||||
<string name="call_unmute">Sesi Aç</string>
|
||||
<string name="napplet_cap_identity">Kimlik</string>
|
||||
<string name="napplet_cap_keys">Klavye eylemleri</string>
|
||||
<string name="napplet_cap_relay">relay'ler</string>
|
||||
<string name="napplet_cap_relay">relay\'ler</string>
|
||||
<string name="napplet_cap_storage">Depolama</string>
|
||||
<string name="napplet_cap_value">Ödemeler</string>
|
||||
<string name="napplet_cap_resource">Ağ</string>
|
||||
|
||||
@@ -158,7 +158,7 @@
|
||||
because android:label on the manifest entry can only reference @string/. -->
|
||||
<!-- My Fitness: the signed-in user's own training summary. Android resource because
|
||||
NavBarItemDef labels are R.string ids. -->
|
||||
<string name="always_on_notif_channel_description">Підтримує активні з'єднання з вашими inbox relay для сповіщень у реальному часі</string>
|
||||
<string name="always_on_notif_channel_description">Підтримує активні з\'єднання з вашими inbox relay для сповіщень у реальному часі</string>
|
||||
<plurals name="always_on_notif_connected">
|
||||
<item quantity="one">Підключено до %1$d inbox relay</item>
|
||||
<item quantity="few">Підключено до %1$d inbox relay</item>
|
||||
|
||||
@@ -2640,7 +2640,7 @@
|
||||
|
||||
|
||||
|
||||
<string name="always_on_notif_channel_description">Підтримує активні з'єднання з вашими inbox relay для сповіщень у реальному часі</string>
|
||||
<string name="always_on_notif_channel_description">Підтримує активні з\'єднання з вашими inbox relay для сповіщень у реальному часі</string>
|
||||
<plurals name="always_on_notif_connected">
|
||||
<item quantity="one">Підключено до %1$d inbox relay</item>
|
||||
<item quantity="few">Підключено до %1$d inbox relay</item>
|
||||
|
||||
@@ -160,18 +160,18 @@
|
||||
NavBarItemDef labels are R.string ids. -->
|
||||
<string name="always_on_notif_channel_description">Real vaqtli bildirishnomalar uchun kirish relaylaringizga ulanishni faol saqlaydi</string>
|
||||
<plurals name="always_on_notif_connected">
|
||||
<item quantity="one">%1$d kirish relay'iga ulangan</item>
|
||||
<item quantity="other">%1$d kirish relay'lariga ulangan</item>
|
||||
<item quantity="one">%1$d kirish relay\'iga ulangan</item>
|
||||
<item quantity="other">%1$d kirish relay\'lariga ulangan</item>
|
||||
</plurals>
|
||||
<plurals name="always_on_notif_connected_foreground">
|
||||
<item quantity="one">%1$d relay'ga ulangan</item>
|
||||
<item quantity="other">%1$d relay'larga ulangan</item>
|
||||
<item quantity="one">%1$d relay\'ga ulangan</item>
|
||||
<item quantity="other">%1$d relay\'larga ulangan</item>
|
||||
</plurals>
|
||||
<string name="always_on_notif_connecting">Kirish relaylariga ulanilmoqda…</string>
|
||||
<string name="always_on_notif_title">Amethyst Bildirishnomalari Faol</string>
|
||||
<string name="call_ongoing">Qo'ng'iroqlar</string>
|
||||
<string name="call_ongoing_description">Davom etayotgan qo'ng'iroq bildirishномаsi</string>
|
||||
<string name="call_with">%1$s bilan qo'ng'iroq</string>
|
||||
<string name="call_ongoing">Qo\'ng\'iroqlar</string>
|
||||
<string name="call_ongoing_description">Davom etayotgan qo\'ng\'iroq bildirishномаsi</string>
|
||||
<string name="call_with">%1$s bilan qo\'ng\'iroq</string>
|
||||
<string name="call_hangup">Tugatish</string>
|
||||
<string name="reaction">Reaksiya</string>
|
||||
<string name="boost">Targʻib qilish</string>
|
||||
@@ -180,20 +180,20 @@
|
||||
<string name="private_message">Shaxsiy Xabar</string>
|
||||
<string name="nest_notification_broadcasting">Nest — Jonli</string>
|
||||
<string name="nest_notification_channel">Nestlar</string>
|
||||
<string name="nest_notification_channel_description">Xona ochiq bo'lganda audio ijrosini davom ettiradi.</string>
|
||||
<string name="nest_notification_channel_description">Xona ochiq bo\'lganda audio ijrosini davom ettiradi.</string>
|
||||
<string name="nest_notification_listening">Nest ulandi</string>
|
||||
<string name="nest_notification_stop">To'xtatish</string>
|
||||
<string name="nest_notification_stop">To\'xtatish</string>
|
||||
<string name="nest_notification_text">Qaytish uchun bosing.</string>
|
||||
<string name="nest_leave">Chiqish</string>
|
||||
<string name="nest_mute">Ovozni o'chirish</string>
|
||||
<string name="nest_mute">Ovozni o\'chirish</string>
|
||||
<string name="nest_unmute">Ovozni yoqish</string>
|
||||
<string name="call_mute">Ovozni o'chirish</string>
|
||||
<string name="call_mute">Ovozni o\'chirish</string>
|
||||
<string name="call_unmute">Ovozni yoqish</string>
|
||||
<string name="napplet_cap_identity">Shaxsiyat</string>
|
||||
<string name="napplet_cap_keys">Klaviatura amallari</string>
|
||||
<string name="napplet_cap_relay">Relaylar</string>
|
||||
<string name="napplet_cap_storage">Saqlash</string>
|
||||
<string name="napplet_cap_value">To'lovlar</string>
|
||||
<string name="napplet_cap_value">To\'lovlar</string>
|
||||
<string name="napplet_cap_resource">Tarmoq</string>
|
||||
<string name="napplet_cap_upload">Yuklamalar</string>
|
||||
<string name="napplet_cap_theme">Mavzu</string>
|
||||
|
||||
+37
-20
@@ -20,25 +20,42 @@
|
||||
*/
|
||||
package com.vitorpamplona.amethyst.ui.screen.loggedIn.settings
|
||||
|
||||
import com.vitorpamplona.amethyst.commons.resources.Res
|
||||
import com.vitorpamplona.amethyst.commons.resources.account_settings
|
||||
import com.vitorpamplona.amethyst.commons.resources.backup_keys
|
||||
import com.vitorpamplona.amethyst.commons.resources.danger_zone
|
||||
import com.vitorpamplona.amethyst.commons.resources.relays
|
||||
import com.vitorpamplona.amethyst.commons.resources.settings_section_appearance
|
||||
import com.vitorpamplona.amethyst.commons.resources.theme
|
||||
import org.jetbrains.compose.resources.StringResource
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Test
|
||||
|
||||
class SettingsCatalogFilterTest {
|
||||
// Real catalog entries stand in for the rows, but their text comes from this map:
|
||||
// filterSettings takes its lookup as a parameter precisely so the filter itself
|
||||
// stays Compose-free, and resolving a StringResource for real would need a runtime.
|
||||
private val accountCategory = Res.string.account_settings
|
||||
private val dangerCategory = Res.string.danger_zone
|
||||
private val relayEntry = Res.string.relays
|
||||
private val uiEntry = Res.string.settings_section_appearance
|
||||
private val backupEntry = Res.string.backup_keys
|
||||
private val uiKeywords = Res.string.theme
|
||||
|
||||
private val strings =
|
||||
mapOf(
|
||||
100 to "Account Settings",
|
||||
200 to "Danger Zone",
|
||||
1 to "Relay Setup",
|
||||
2 to "UI Preferences",
|
||||
3 to "Backup Keys",
|
||||
20 to "dark mode, theme, font size",
|
||||
accountCategory to "Account Settings",
|
||||
dangerCategory to "Danger Zone",
|
||||
relayEntry to "Relay Setup",
|
||||
uiEntry to "UI Preferences",
|
||||
backupEntry to "Backup Keys",
|
||||
uiKeywords to "dark mode, theme, font size",
|
||||
)
|
||||
|
||||
private fun entry(
|
||||
titleRes: StringResource,
|
||||
keywordsRes: Int? = null,
|
||||
keywordsRes: StringResource? = null,
|
||||
isDanger: Boolean = false,
|
||||
) = SettingsEntry(
|
||||
titleRes = titleRes,
|
||||
@@ -51,17 +68,17 @@ class SettingsCatalogFilterTest {
|
||||
private val catalog =
|
||||
listOf(
|
||||
SettingsCategory(
|
||||
titleRes = 100,
|
||||
titleRes = accountCategory,
|
||||
entries =
|
||||
listOf(
|
||||
entry(1),
|
||||
entry(2, keywordsRes = 20),
|
||||
entry(relayEntry),
|
||||
entry(uiEntry, keywordsRes = uiKeywords),
|
||||
),
|
||||
),
|
||||
SettingsCategory(
|
||||
titleRes = 200,
|
||||
titleRes = dangerCategory,
|
||||
isDanger = true,
|
||||
entries = listOf(entry(3, isDanger = true)),
|
||||
entries = listOf(entry(backupEntry, isDanger = true)),
|
||||
),
|
||||
)
|
||||
|
||||
@@ -89,30 +106,30 @@ class SettingsCatalogFilterTest {
|
||||
fun titleMatchIsCaseInsensitive() {
|
||||
val result = run("relay")
|
||||
assertEquals(1, result.size)
|
||||
assertEquals(100, result[0].titleRes)
|
||||
assertEquals(accountCategory, result[0].titleRes)
|
||||
assertEquals(1, result[0].entries.size)
|
||||
assertEquals(1, result[0].entries[0].titleRes)
|
||||
assertEquals(relayEntry, result[0].entries[0].titleRes)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun keywordMatchSurfacesEntryWhoseTitleDoesNotMatch() {
|
||||
val result = run("dark mode")
|
||||
assertEquals(1, result.size)
|
||||
assertEquals(2, result[0].entries[0].titleRes) // UI Preferences, matched via keywords
|
||||
assertEquals(uiEntry, result[0].entries[0].titleRes) // UI Preferences, matched via keywords
|
||||
}
|
||||
|
||||
@Test
|
||||
fun categoryTitleMatchSurfacesWholeCategory() {
|
||||
val result = run("account")
|
||||
assertEquals(1, result.size)
|
||||
assertEquals(100, result[0].titleRes)
|
||||
assertEquals(accountCategory, result[0].titleRes)
|
||||
assertEquals(2, result[0].entries.size) // both rows shown because the category name matched
|
||||
}
|
||||
|
||||
@Test
|
||||
fun categoryWithNoMatchesIsDropped() {
|
||||
val result = run("relay")
|
||||
assertTrue(result.none { it.titleRes == 200 })
|
||||
assertTrue(result.none { it.titleRes == dangerCategory })
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -131,8 +148,8 @@ class SettingsCatalogFilterTest {
|
||||
@Test
|
||||
fun prefixOfAWordMatches() {
|
||||
// "rel" is a prefix of "Relay" (title); "the" is a prefix of "theme" (keyword).
|
||||
assertEquals(1, run("rel")[0].entries[0].titleRes)
|
||||
assertEquals(2, run("the")[0].entries[0].titleRes)
|
||||
assertEquals(relayEntry, run("rel")[0].entries[0].titleRes)
|
||||
assertEquals(uiEntry, run("the")[0].entries[0].titleRes)
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -143,7 +160,7 @@ class SettingsCatalogFilterTest {
|
||||
|
||||
@Test
|
||||
fun everyQueryTermMustPrefixSomeWord() {
|
||||
assertEquals(2, run("dark size")[0].entries[0].titleRes) // both terms hit UI Preferences
|
||||
assertEquals(uiEntry, run("dark size")[0].entries[0].titleRes) // both terms hit UI Preferences
|
||||
assertTrue(run("dark zzz").isEmpty()) // second term matches nothing
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user