diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/browser/BrowserMultiColumnAdapter.kt b/AnkiDroid/src/main/java/com/ichi2/anki/browser/BrowserMultiColumnAdapter.kt index 4f59798181c3..8c2e6641a8bf 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/browser/BrowserMultiColumnAdapter.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/browser/BrowserMultiColumnAdapter.kt @@ -198,8 +198,14 @@ class BrowserMultiColumnAdapter( try { val (row, isSelected) = viewModel.transformBrowserRow(id) - holder.firstColumn = row.getCells(0).text - holder.secondColumn = row.getCells(1).text + + // PERF: removeSounds only needs to be performed on QUESTION/ANSWER columns + fun renderColumn(columnIndex: Int): String = removeSounds( + input = row.getCells(columnIndex).text, + showMediaFilenames = viewModel.showMediaFilenames + ) + holder.firstColumn = renderColumn(0) + holder.secondColumn = renderColumn(1) holder.setIsSelected(isSelected) holder.setColor(backendColorToColor(row.color)) holder.setIsDeleted(false) @@ -238,6 +244,17 @@ class BrowserMultiColumnAdapter( } companion object { + private val mediaFilenameRegex = Regex("\uD83D\uDD09(.*?)\uD83D\uDD09") // ๐Ÿ”‰(.*?)๐Ÿ”‰ + + /** + * Strips instances of '๐Ÿ”‰filename.mp3๐Ÿ”‰' if [showMediaFilenames] is not set + */ + @VisibleForTesting + fun removeSounds(input: String, showMediaFilenames: Boolean): String { + if (showMediaFilenames) return input + return mediaFilenameRegex.replace(input, "") + } + private const val DEFAULT_FONT_SIZE_RATIO = 100 @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/browser/CardBrowserViewModel.kt b/AnkiDroid/src/main/java/com/ichi2/anki/browser/CardBrowserViewModel.kt index 628ec2e9103b..e75dc488b138 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/browser/CardBrowserViewModel.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/browser/CardBrowserViewModel.kt @@ -98,6 +98,8 @@ class CardBrowserViewModel( private val manualInit: Boolean = false ) : ViewModel(), SharedPreferencesProvider by preferences { + val showMediaFilenames = sharedPrefs().getBoolean("card_browser_show_media_filenames", false) + /** A job which ensures that parallel searches do not occur */ var searchJob: Job? = null private set diff --git a/AnkiDroid/src/test/java/com/ichi2/anki/CardBrowserTest.kt b/AnkiDroid/src/test/java/com/ichi2/anki/CardBrowserTest.kt index 657ff4069093..8337780f47fe 100644 --- a/AnkiDroid/src/test/java/com/ichi2/anki/CardBrowserTest.kt +++ b/AnkiDroid/src/test/java/com/ichi2/anki/CardBrowserTest.kt @@ -41,6 +41,7 @@ import com.ichi2.anki.browser.CardBrowserColumn.QUESTION import com.ichi2.anki.browser.CardBrowserColumn.SFLD import com.ichi2.anki.browser.CardBrowserColumn.TAGS import com.ichi2.anki.browser.CardBrowserViewModel +import com.ichi2.anki.browser.CardBrowserViewModelTest import com.ichi2.anki.browser.CardOrNoteId import com.ichi2.anki.common.utils.isRunningAsUnitTest import com.ichi2.anki.dialogs.DeckSelectionDialog @@ -1055,7 +1056,7 @@ class CardBrowserTest : RobolectricTest() { } val question = card.getColumnHeaderText(CardBrowserColumn.QUESTION) - assertThat(question, equalTo("\uD83D\uDCACTest\uD83D\uDCAC")) + assertThat(question, equalTo(CardBrowserViewModelTest.EXPECTED_TTS)) } @Test diff --git a/AnkiDroid/src/test/java/com/ichi2/anki/browser/BrowserMultiColumnAdapterTest.kt b/AnkiDroid/src/test/java/com/ichi2/anki/browser/BrowserMultiColumnAdapterTest.kt new file mode 100644 index 000000000000..f3fbc94aab81 --- /dev/null +++ b/AnkiDroid/src/test/java/com/ichi2/anki/browser/BrowserMultiColumnAdapterTest.kt @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2024 David Allison + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free Software + * Foundation; either version 3 of the License, or (at your option) any later + * version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ + +package com.ichi2.anki.browser + +import org.hamcrest.MatcherAssert.assertThat +import org.hamcrest.Matchers.equalTo +import org.junit.Test + +/** + * Tests for [BrowserMultiColumnAdapter] + */ +class BrowserMultiColumnAdapterTest { + + @Test + fun `sound without filenames`() { + val text = BrowserMultiColumnAdapter.removeSounds(EXPECTED_SOUND, showMediaFilenames = false) + assertThat("sound filename stripped", text, equalTo("")) + } + + @Test + fun `tts not affected`() { + val text = BrowserMultiColumnAdapter.removeSounds(TTS, showMediaFilenames = false) + assertThat("unchanged", text, equalTo(TTS)) + } + + @Test + fun `sound with filenames`() { + val text = BrowserMultiColumnAdapter.removeSounds(EXPECTED_SOUND, showMediaFilenames = true) + assertThat("unchanged", text, equalTo(EXPECTED_SOUND)) + } + + companion object { + const val EXPECTED_SOUND = CardBrowserViewModelTest.EXPECTED_SOUND + const val TTS = CardBrowserViewModelTest.EXPECTED_TTS + } +} diff --git a/AnkiDroid/src/test/java/com/ichi2/anki/browser/CardBrowserViewModelTest.kt b/AnkiDroid/src/test/java/com/ichi2/anki/browser/CardBrowserViewModelTest.kt index abff313d8c6d..4fa5ce56a58a 100644 --- a/AnkiDroid/src/test/java/com/ichi2/anki/browser/CardBrowserViewModelTest.kt +++ b/AnkiDroid/src/test/java/com/ichi2/anki/browser/CardBrowserViewModelTest.kt @@ -16,6 +16,7 @@ package com.ichi2.anki.browser +import androidx.core.content.edit import androidx.test.ext.junit.runners.AndroidJUnit4 import app.cash.turbine.TurbineTestContext import app.cash.turbine.test @@ -728,6 +729,31 @@ class CardBrowserViewModelTest : JvmTest() { } } + @Test + fun `sound tags regression test`() { + addNoteUsingBasicModel("[sound:david.mp3]") + + showMediaFilenamesPreference = false + + BrowserColumnCollection.update(AnkiDroidApp.sharedPreferencesProvider.sharedPrefs(), CardsOrNotes.CARDS) { + it[0] = QUESTION + return@update true + } + + runViewModelTest { + waitForSearchResults() + val (row, _) = this.transformBrowserRow(this.cards.single()) + val question = row.getCells(0) + assertThat(question.text, equalTo(EXPECTED_SOUND)) + } + } + + private var showMediaFilenamesPreference: Boolean + get() = AnkiDroidApp.sharedPreferencesProvider.sharedPrefs().getBoolean("card_browser_show_media_filenames", false) + set(value) = AnkiDroidApp.sharedPreferencesProvider.sharedPrefs().edit { + putBoolean("card_browser_show_media_filenames", value) + } + private fun runViewModelNotesTest( notes: Int = 0, manualInit: Boolean = true, @@ -777,6 +803,10 @@ class CardBrowserViewModelTest : JvmTest() { } companion object { + + const val EXPECTED_SOUND = "\uD83D\uDD09david.mp3\uD83D\uDD09" + const val EXPECTED_TTS = "\uD83D\uDCACTest\uD83D\uDCAC" + private suspend fun viewModel( lastDeckId: DeckId? = null, intent: CardBrowserLaunchOptions? = null,