Skip to content

Commit

Permalink
Fix incorrect translation names after download
Browse files Browse the repository at this point in the history
After downloading a fresh translation, the names typically show
something like x.db instead of the translation name. This fixes it by
updating the cache of translations when translations are updated.
  • Loading branch information
ahmedre committed Jan 26, 2025
1 parent d03ac75 commit addd70c
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,26 +10,43 @@ import com.quran.labs.androidquran.common.TranslationMetadata
import com.quran.labs.androidquran.database.TranslationsDBAdapter
import com.quran.labs.androidquran.model.translation.TranslationModel
import com.quran.labs.androidquran.presenter.Presenter
import com.quran.labs.androidquran.presenter.translationlist.TranslationListPresenter
import com.quran.labs.androidquran.util.QuranSettings
import com.quran.labs.androidquran.util.TranslationUtil
import com.quran.mobile.translation.model.LocalTranslation
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.async
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.withContext
import timber.log.Timber

open class BaseTranslationPresenter<T : Any> internal constructor(
private val translationModel: TranslationModel,
private val translationsAdapter: TranslationsDBAdapter,
private val translationUtil: TranslationUtil,
private val quranInfo: QuranInfo
private val quranInfo: QuranInfo,
translationListPresenter: TranslationListPresenter,
) : Presenter<T> {
private val translationMap: MutableMap<String, LocalTranslation> = HashMap()
private val scope = MainScope()

var translationScreen: T? = null

init {
translationListPresenter.translations()
.onEach { translations ->
Timber.w("BaseTranslationListPresenter emit with ${translations.size}")
updateTranslationsMap(translations)
onAvailableTranslationsChanged(translations)
}
.launchIn(scope)
}

suspend fun getVerses(
getArabic: Boolean,
translationsFileNames: List<String>,
Expand Down Expand Up @@ -184,15 +201,32 @@ open class BaseTranslationPresenter<T : Any> internal constructor(
return texts
}

open fun onAvailableTranslationsChanged(localTranslations: List<LocalTranslation>) {
}

suspend fun updateTranslationsMap(localTranslations: List<LocalTranslation>) {
// mutate on the main thread only to avoid contention
withContext(Dispatchers.Main.immediate) {
localTranslations.associateBy { it.filename }.let {
translationMap.clear()
translationMap.putAll(it)
}
}
}

private suspend fun getTranslationMap(): Map<String, LocalTranslation> {
val currentTranslationMap = translationMap
return withContext(Dispatchers.IO) {
if (currentTranslationMap.isEmpty()) {
val updatedTranslations = translationsAdapter.getTranslations()
.map { it.associateBy { it.filename } }
.first()
translationMap.clear()
translationMap.putAll(updatedTranslations)

// only mutate on the main thread
withContext(Dispatchers.Main) {
translationMap.clear()
translationMap.putAll(updatedTranslations)
}
updatedTranslations
} else {
currentTranslationMap
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,6 @@ import com.quran.labs.androidquran.util.QuranSettings
import com.quran.labs.androidquran.util.TranslationUtil
import com.quran.mobile.translation.model.LocalTranslation
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.withContext
import javax.inject.Inject

Expand All @@ -24,21 +21,11 @@ class InlineTranslationPresenter @Inject constructor(
translationListPresenter: TranslationListPresenter,
quranInfo: QuranInfo
) : BaseTranslationPresenter<InlineTranslationPresenter.TranslationScreen>(
translationModel, dbAdapter, translationUtil, quranInfo
translationModel, dbAdapter, translationUtil, quranInfo, translationListPresenter
) {
private val scope = MainScope()
private var cachedTranslations = emptyList<LocalTranslation>()
private var lastVerseRange: VerseRange? = null

init {
translationListPresenter.translations()
.onEach { translations ->
cachedTranslations = translations
translationScreen?.onTranslationsUpdated(translations)
}
.launchIn(scope)
}

suspend fun refresh(verseRange: VerseRange) {
val ayahHasBeenChanged = verseRange != lastVerseRange
val result = withContext(Dispatchers.IO) {
Expand All @@ -54,6 +41,12 @@ class InlineTranslationPresenter @Inject constructor(
what.onTranslationsUpdated(translations)
}

override fun onAvailableTranslationsChanged(localTranslations: List<LocalTranslation>) {
super.onAvailableTranslationsChanged(localTranslations)
cachedTranslations = localTranslations
translationScreen?.onTranslationsUpdated(localTranslations)
}

interface TranslationScreen {
fun setVerses(translations: Array<LocalTranslation>, verses: List<QuranAyahInfo>, ayahHasBeenChanged: Boolean)
fun onTranslationsUpdated(translations: List<LocalTranslation>)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import com.quran.data.di.QuranPageScope
import com.quran.labs.androidquran.common.QuranAyahInfo
import com.quran.labs.androidquran.database.TranslationsDBAdapter
import com.quran.labs.androidquran.model.translation.TranslationModel
import com.quran.labs.androidquran.presenter.translationlist.TranslationListPresenter
import com.quran.labs.androidquran.util.QuranSettings
import com.quran.labs.androidquran.util.TranslationUtil
import com.quran.mobile.translation.model.LocalTranslation
Expand All @@ -18,11 +19,12 @@ class TranslationPresenter @Inject internal constructor(
private val quranSettings: QuranSettings,
translationsAdapter: TranslationsDBAdapter,
translationUtil: TranslationUtil,
translationListPresenter: TranslationListPresenter,
private val quranInfo: QuranInfo,
private val pages: IntArray
) :
BaseTranslationPresenter<TranslationPresenter.TranslationScreen>(
translationModel, translationsAdapter, translationUtil, quranInfo
translationModel, translationsAdapter, translationUtil, quranInfo, translationListPresenter
) {

suspend fun refresh() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,14 @@ import com.quran.labs.androidquran.database.TranslationsDBAdapter
import com.quran.labs.androidquran.model.translation.TranslationModel
import com.quran.labs.androidquran.pages.data.madani.MadaniDataSource
import com.quran.labs.androidquran.presenter.Presenter
import com.quran.labs.androidquran.presenter.translationlist.TranslationListPresenter
import com.quran.labs.androidquran.util.TranslationUtil
import com.quran.mobile.translation.model.LocalTranslation
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.test.UnconfinedTestDispatcher
import kotlinx.coroutines.test.resetMain
import kotlinx.coroutines.test.setMain
import org.junit.After
import org.junit.Before
import org.junit.Test
import org.mockito.Mockito
Expand All @@ -19,8 +25,11 @@ class BaseTranslationPresenterTest {

private lateinit var presenter: BaseTranslationPresenter<TestPresenter>

private val testDispatcher = UnconfinedTestDispatcher()

@Before
fun setupTest() {
Dispatchers.setMain(testDispatcher)
presenter = BaseTranslationPresenter(
Mockito.mock(TranslationModel::class.java),
Mockito.mock(TranslationsDBAdapter::class.java),
Expand All @@ -29,10 +38,16 @@ class BaseTranslationPresenterTest {
return TranslationMetadata(quranText.sura, quranText.ayah, quranText.text, translationId)
}
},
QuranInfo(MadaniDataSource())
QuranInfo(MadaniDataSource()),
Mockito.mock(TranslationListPresenter::class.java)
)
}

@After
fun tearDown() {
Dispatchers.resetMain()
}

@Test
fun testGetTranslationNames() {
val databases = listOf("one.db", "two.db")
Expand Down

0 comments on commit addd70c

Please sign in to comment.