diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index ca400154ac..92bc54bd1d 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -14,22 +14,22 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout the Code
- uses: actions/checkout@v3
+ uses: actions/checkout@v4
- name: Setup JDK
- uses: actions/setup-java@v3
+ uses: actions/setup-java@v4
with:
distribution: zulu
java-version: 17
- name: Setup Gradle
- uses: gradle/gradle-build-action@v2
+ uses: gradle/gradle-build-action@v3
- name: Build debug APK
run: ./gradlew assembleMadaniDebug
- name: Download Previous Debug APK
- uses: dawidd6/action-download-artifact@v2
+ uses: dawidd6/action-download-artifact@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
workflow: post_merge.yml
@@ -44,7 +44,7 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Upload Apk Diff Results
- uses: actions/upload-artifact@v3
+ uses: actions/upload-artifact@v4
if: success()
with:
name: apk_differences
@@ -56,16 +56,22 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout the code
- uses: actions/checkout@v3
+ uses: actions/checkout@v4
+
+ - name: Setup JDK
+ uses: actions/setup-java@v4
+ with:
+ distribution: zulu
+ java-version: 17
- name: Setup Gradle
- uses: gradle/gradle-build-action@v2
+ uses: gradle/gradle-build-action@v3
- name: Run lint
run: ./gradlew lintMadaniDebug
- name: Upload lint results
- uses: actions/upload-artifact@v3
+ uses: actions/upload-artifact@v4
if: failure()
with:
name: lint_report
@@ -77,16 +83,16 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout the code
- uses: actions/checkout@v3
+ uses: actions/checkout@v4
- name: Setup JDK
- uses: actions/setup-java@v3
+ uses: actions/setup-java@v4
with:
distribution: zulu
java-version: 17
- name: Setup Gradle
- uses: gradle/gradle-build-action@v2
+ uses: gradle/gradle-build-action@v3
- name: Run SqlDelight migration tests
run: ./gradlew verifySqlDelightMigration
@@ -95,7 +101,7 @@ jobs:
run: ./gradlew test -PdisableCrashlytics -PdisableFirebase
- name: Upload test report
- uses: actions/upload-artifact@v3
+ uses: actions/upload-artifact@v4
if: failure()
with:
name: unit_test_report
@@ -107,22 +113,22 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout the Code
- uses: actions/checkout@v3
+ uses: actions/checkout@v4
- name: Setup JDK
- uses: actions/setup-java@v3
+ uses: actions/setup-java@v4
with:
distribution: zulu
java-version: 17
- name: Setup Gradle
- uses: gradle/gradle-build-action@v2
+ uses: gradle/gradle-build-action@v3
- name: Get dependencies list
run: ./gradlew :app:dependencies --configuration madaniReleaseRuntimeClasspath > current_dependencies.txt
- name: Download Previous Dependencies List
- uses: dawidd6/action-download-artifact@v2
+ uses: dawidd6/action-download-artifact@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
workflow: post_merge.yml
@@ -137,7 +143,7 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Upload Dependency Diff Results
- uses: actions/upload-artifact@v3
+ uses: actions/upload-artifact@v4
if: success()
with:
name: dependency_differences
@@ -148,7 +154,7 @@ jobs:
echo ${{ github.event.number }} > pr.txt
- name: Upload PR Number
- uses: actions/upload-artifact@v3
+ uses: actions/upload-artifact@v4
with:
name: pr
path: pr.txt
diff --git a/.github/workflows/post_build.yml b/.github/workflows/post_build.yml
index eddbb735ea..e0a2df6c34 100644
--- a/.github/workflows/post_build.yml
+++ b/.github/workflows/post_build.yml
@@ -13,7 +13,7 @@ jobs:
if: ${{ github.event.workflow_run.conclusion == 'success' }}
steps:
- name: Download PR Number
- uses: dawidd6/action-download-artifact@v2
+ uses: dawidd6/action-download-artifact@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
run_id: ${{ github.event.workflow_run.id }}
@@ -21,7 +21,7 @@ jobs:
name: pr
- name: Download Apk Diff Results
- uses: dawidd6/action-download-artifact@v2
+ uses: dawidd6/action-download-artifact@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
run_id: ${{ github.event.workflow_run.id }}
@@ -36,7 +36,7 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Download Dependency Diff Results
- uses: dawidd6/action-download-artifact@v2
+ uses: dawidd6/action-download-artifact@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
run_id: ${{ github.event.workflow_run.id }}
diff --git a/.github/workflows/post_merge.yml b/.github/workflows/post_merge.yml
index 2fa5781982..cbf51911ec 100644
--- a/.github/workflows/post_merge.yml
+++ b/.github/workflows/post_merge.yml
@@ -15,22 +15,22 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout the Code
- uses: actions/checkout@v3
+ uses: actions/checkout@v4
- name: Setup JDK
- uses: actions/setup-java@v3
+ uses: actions/setup-java@v4
with:
distribution: zulu
java-version: 17
- name: Setup Gradle
- uses: gradle/gradle-build-action@v2
+ uses: gradle/gradle-build-action@v3
- name: Build debug Apk
run: ./gradlew assembleDebug
- name: Upload Debug Apk
- uses: actions/upload-artifact@v3
+ uses: actions/upload-artifact@v4
if: success()
with:
name: latest-apk
@@ -40,7 +40,7 @@ jobs:
run: ./gradlew :app:dependencies --configuration madaniReleaseRuntimeClasspath > dependencies.txt
- name: Upload dependencies list
- uses: actions/upload-artifact@v3
+ uses: actions/upload-artifact@v4
if: success()
with:
name: dependencies
diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md
index 647ffbb993..a801cccb31 100644
--- a/CONTRIBUTORS.md
+++ b/CONTRIBUTORS.md
@@ -41,7 +41,7 @@ Quran Android Contributors
* Turkish by Mehmed Mahmudoglu.
* Turkish updates by [Shuhrat Dehkanov](http://github.com/ozbek).
* Russian by Rinat [Ринат Валеев](https://github.com/Valey).
-* Kurdish by [Goran Gharib Karim](https://github.com/GorranKurd).
+* Kurdish by [Goran Gharib](https://github.com/GoRaN909).
* French by Yasser [yasserkad](http://github.com/yasserkad).
* French updates by [Abdullah ibn Nadjo](https://github.com/abdullahibnnadjo).
* French updates 1441 Ramadan 13 (06/05/2020) [Saïd B](https://github.com/sbou88).
diff --git a/app/build.gradle b/app/build.gradle
index 40b3844ded..9509f1ce48 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -1,9 +1,10 @@
plugins {
- id 'quran.android.application'
+ id "quran.android.application"
id 'org.jetbrains.kotlin.kapt'
id 'org.jetbrains.kotlin.plugin.parcelize'
- id 'net.ltgt.errorprone'
- id 'com.squareup.anvil'
+ alias libs.plugins.ksp
+ alias libs.plugins.errorprone
+ alias libs.plugins.anvil
}
if (getGradle().getStartParameter().getTaskRequests().toString().contains("Release") &&
@@ -16,11 +17,13 @@ android {
namespace 'com.quran.labs.androidquran'
defaultConfig {
- versionCode 3320
- versionName "3.3.2"
+ versionCode 3430
+ versionName "3.4.3"
testInstrumentationRunner "com.quran.labs.androidquran.core.QuranTestRunner"
}
+ buildFeatures.buildConfig = true
+
signingConfigs {
release {
storeFile file(STORE_FILE)
@@ -30,7 +33,7 @@ android {
}
}
- flavorDimensions "pageType"
+ flavorDimensions = ["pageType"]
productFlavors {
madani {
applicationId "com.quran.labs.androidquran"
@@ -58,7 +61,7 @@ android {
}
}
- applicationVariants.all { variant ->
+ applicationVariants.configureEach { variant ->
resValue "string", "authority", applicationId + '.data.QuranDataProvider'
resValue "string", "file_authority", applicationId + '.fileprovider'
if (applicationId.endsWith("debug")) {
@@ -84,12 +87,6 @@ android {
}
}
- lint {
- checkReleaseBuilds true
- enable 'Interoperability'
- lintConfig file('lint.xml')
- }
-
packagingOptions {
resources {
excludes += ['META-INF/*.kotlin_module', 'META-INF/DEPENDENCIES', 'META-INF/INDEX.LIST']
@@ -120,10 +117,12 @@ dependencies {
implementation project(path: ':common:download')
implementation project(path: ':common:networking')
implementation project(path: ':common:pages')
+ implementation project(path: ':common:preference')
implementation project(path: ':common:reading')
implementation project(path: ':common:recitation')
implementation project(path: ':common:search')
implementation project(path: ':common:toolbar')
+ implementation project(path: ':common:translation')
implementation project(path: ':common:upgrade')
implementation project(path: ':common:ui:core')
@@ -131,57 +130,57 @@ dependencies {
implementation project(path: ':feature:downloadmanager')
implementation project(path: ':feature:qarilist')
- implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:${coroutinesVersion}"
- implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:${coroutinesVersion}"
+ implementation libs.kotlinx.coroutines.core
+ implementation libs.kotlinx.coroutines.android
- implementation "com.squareup.retrofit2:retrofit:${retrofitVersion}"
- implementation "com.squareup.retrofit2:converter-moshi:${retrofitVersion}"
+ implementation libs.retrofit
+ implementation libs.converter.moshi
- implementation "androidx.appcompat:appcompat:${androidxAppcompatVersion}"
- implementation "androidx.media:media:${androidxMediaVersion}"
- implementation "androidx.localbroadcastmanager:localbroadcastmanager:${androidxLocalBroadcastVersion}"
- implementation "androidx.preference:preference-ktx:${androidxPreferencesVersion}"
- implementation "androidx.recyclerview:recyclerview:${androidxRecyclerViewVersion}"
- implementation "com.google.android.material:material:${materialComponentsVersion}"
- implementation "androidx.swiperefreshlayout:swiperefreshlayout:${androidxSwipeRefreshVersion}"
+ implementation libs.androidx.appcompat
+ implementation libs.androidx.media
+ implementation libs.androidx.localbroadcastmanager
+ implementation libs.androidx.preference.ktx
+ implementation libs.androidx.recyclerview
+ implementation libs.material
+ implementation libs.androidx.swiperefreshlayout
// okio
- implementation "com.squareup.okio:okio:${okioVersion}"
+ implementation libs.okio
// rx
- implementation 'io.reactivex.rxjava3:rxjava:3.1.6'
- implementation 'io.reactivex.rxjava3:rxandroid:3.0.2'
+ implementation libs.rxjava
+ implementation libs.rxandroid
// dagger
- kapt deps.dagger.apt
- kaptTest deps.dagger.apt
- implementation deps.dagger.runtime
+ kapt libs.dagger.compiler
+ kaptTest libs.dagger.compiler
+ implementation libs.dagger.runtime
// workmanager
- implementation "androidx.work:work-runtime-ktx:${workManagerVersion}"
+ implementation libs.androidx.work.runtime.ktx
- implementation "com.squareup.okio:okio:${okioVersion}"
- implementation "com.squareup.okhttp3:okhttp"
+ implementation libs.okhttp
- implementation "com.squareup.moshi:moshi:${moshiVersion}"
- kapt("com.squareup.moshi:moshi-kotlin-codegen:${moshiVersion}")
+ implementation libs.moshi
+ ksp(libs.moshi.codegen)
- implementation "dev.chrisbanes.insetter:insetter:0.6.1"
- implementation 'com.jakewharton.timber:timber:5.0.1'
- debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.10'
- implementation 'com.google.firebase:firebase-crashlytics:18.3.6'
+ implementation libs.insetter
+ implementation libs.timber
+ debugImplementation libs.leakcanary.android
- testImplementation "junit:junit:${junitVersion}"
- testImplementation "com.google.truth:truth:${truthVersion}"
- testImplementation "org.mockito:mockito-core:${mockitoVersion}"
- testImplementation "com.squareup.okhttp3:mockwebserver"
- testImplementation "androidx.test.ext:junit-ktx:${androidxJunitExtVersion}"
- testImplementation "org.robolectric:robolectric:${robolectricVersion}"
- testImplementation "androidx.test.espresso:espresso-core:${espressoVersion}"
- testImplementation "androidx.test.espresso:espresso-intents:${espressoVersion}"
+ testImplementation libs.junit
+ testImplementation libs.truth
+ testImplementation libs.mockito.core
+ testImplementation libs.okhttp.mockserver
+ testImplementation libs.junit.ktx
+ testImplementation libs.robolectric
+ testImplementation libs.espresso.core
+ testImplementation libs.espresso.intents
+ testImplementation libs.turbine
+ testImplementation libs.kotlinx.coroutines.test
- errorprone 'com.google.errorprone:error_prone_core:2.18.0'
+ errorprone libs.errorprone.core
// Number Picker
- implementation 'io.github.ShawnLin013:number-picker:2.4.13'
+ implementation libs.number.picker
}
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index f7de6f0d36..2a87047ecc 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -13,6 +13,13 @@
+
+
+
+
+
+
+
@@ -152,11 +159,13 @@
+ android:name=".service.QuranDownloadService"
+ android:foregroundServiceType="dataSync"/>
+ android:name=".service.AudioService"
+ android:foregroundServiceType="mediaPlayback">
diff --git a/app/src/main/java/com/quran/labs/androidquran/QuranApplication.kt b/app/src/main/java/com/quran/labs/androidquran/QuranApplication.kt
index 4fea84f191..c3fb985be0 100644
--- a/app/src/main/java/com/quran/labs/androidquran/QuranApplication.kt
+++ b/app/src/main/java/com/quran/labs/androidquran/QuranApplication.kt
@@ -8,7 +8,6 @@ import androidx.work.WorkManager
import com.quran.labs.androidquran.core.worker.QuranWorkerFactory
import com.quran.labs.androidquran.di.component.application.ApplicationComponent
import com.quran.labs.androidquran.di.component.application.DaggerApplicationComponent
-import com.quran.labs.androidquran.di.module.application.ApplicationModule
import com.quran.labs.androidquran.util.QuranSettings
import com.quran.labs.androidquran.util.RecordingLogTree
import com.quran.labs.androidquran.widget.BookmarksWidgetSubscriber
@@ -42,9 +41,8 @@ open class QuranApplication : Application(), QuranApplicationComponentProvider {
}
open fun initializeInjector(): ApplicationComponent {
- return DaggerApplicationComponent.builder()
- .applicationModule(ApplicationModule(this))
- .build()
+ return DaggerApplicationComponent.factory()
+ .generate(this)
}
open fun initializeWorkManager() {
diff --git a/app/src/main/java/com/quran/labs/androidquran/QuranDataActivity.kt b/app/src/main/java/com/quran/labs/androidquran/QuranDataActivity.kt
index d851ee3473..cda14007d4 100644
--- a/app/src/main/java/com/quran/labs/androidquran/QuranDataActivity.kt
+++ b/app/src/main/java/com/quran/labs/androidquran/QuranDataActivity.kt
@@ -12,6 +12,7 @@ import android.os.Bundle
import android.os.Environment
import android.text.TextUtils
import android.widget.Toast
+import androidx.annotation.RequiresApi
import androidx.appcompat.app.AlertDialog
import androidx.core.app.ActivityCompat
import androidx.core.app.ActivityCompat.OnRequestPermissionsResultCallback
@@ -81,6 +82,8 @@ class QuranDataActivity : Activity(), SimpleDownloadListener, OnRequestPermissio
private var quranDataStatus: QuranDataStatus? = null
private var updateDialog: AlertDialog? = null
private var disposable: Disposable? = null
+ private var lastForceValue: Boolean = false
+ private var didCheckPermissions: Boolean = false
private val scope = MainScope()
@@ -141,7 +144,11 @@ class QuranDataActivity : Activity(), SimpleDownloadListener, OnRequestPermissio
Timber.e(ise)
}
}
- checkPermissions()
+
+ if (!didCheckPermissions) {
+ didCheckPermissions = true
+ checkPermissions()
+ }
}
override fun onPause() {
@@ -158,8 +165,7 @@ class QuranDataActivity : Activity(), SimpleDownloadListener, OnRequestPermissio
errorDialog?.dismiss()
errorDialog = null
- updateDialog?.dismiss()
- updateDialog = null
+ hideMigrationDialog()
scope.cancel()
super.onPause()
@@ -238,12 +244,24 @@ class QuranDataActivity : Activity(), SimpleDownloadListener, OnRequestPermissio
permissionsDialog.show()
}
- private fun migrateFromTo(destination: String) {
- val migrationDialog = AlertDialog.Builder(this)
+ private fun showMigrationDialog() {
+ if (updateDialog == null) {
+ val migrationDialog = AlertDialog.Builder(this)
.setView(R.layout.migration_upgrade)
+ .setCancelable(false)
.create()
- updateDialog = migrationDialog
- migrationDialog.show()
+ updateDialog = migrationDialog
+ migrationDialog.show()
+ }
+ }
+
+ private fun hideMigrationDialog() {
+ updateDialog?.dismiss()
+ updateDialog = null
+ }
+
+ private fun migrateFromTo(destination: String) {
+ showMigrationDialog()
scope.launch {
withContext(Dispatchers.IO) {
@@ -257,6 +275,7 @@ class QuranDataActivity : Activity(), SimpleDownloadListener, OnRequestPermissio
}
private fun checkPages() {
+ showMigrationDialog()
quranDataPresenter.checkPages()
}
@@ -268,6 +287,14 @@ class QuranDataActivity : Activity(), SimpleDownloadListener, OnRequestPermissio
quranSettings.setSdcardPermissionsDialogPresented()
}
+ @RequiresApi(Build.VERSION_CODES.TIRAMISU)
+ private fun requestPostNotificationPermission() {
+ ActivityCompat.requestPermissions(
+ this, arrayOf(permission.POST_NOTIFICATIONS),
+ REQUEST_POST_NOTIFICATION_PERMISSIONS
+ )
+ }
+
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array,
@@ -306,6 +333,8 @@ class QuranDataActivity : Activity(), SimpleDownloadListener, OnRequestPermissio
runListViewWithoutPages()
}
}
+ } else if (requestCode == REQUEST_POST_NOTIFICATION_PERMISSIONS) {
+ actuallyDownloadQuranImages(lastForceValue)
}
}
@@ -382,15 +411,13 @@ class QuranDataActivity : Activity(), SimpleDownloadListener, OnRequestPermissio
}
fun onStorageNotAvailable() {
- updateDialog?.dismiss()
- updateDialog = null
+ hideMigrationDialog()
// no storage mounted, nothing we can do...
runListViewWithoutPages()
}
fun onPagesChecked(quranDataStatus: QuranDataStatus) {
- updateDialog?.dismiss()
- updateDialog = null
+ hideMigrationDialog()
this.quranDataStatus = quranDataStatus
if (!quranDataStatus.havePages()) {
@@ -574,15 +601,46 @@ class QuranDataActivity : Activity(), SimpleDownloadListener, OnRequestPermissio
* @param force whether to force the download to restart or not
*/
private fun downloadQuranImages(force: Boolean) {
+ if (PermissionUtil.havePostNotificationPermission(this)) {
+ actuallyDownloadQuranImages(force)
+ } else if (PermissionUtil.canRequestPostNotificationPermission(this)) {
+ val dialog = PermissionUtil.buildPostPermissionDialog(
+ this,
+ onAccept = {
+ lastForceValue = force
+ permissionsDialog = null
+ requestPostNotificationPermission()
+ },
+ onDecline = {
+ permissionsDialog = null
+ actuallyDownloadQuranImages(force)
+ }
+ )
+ permissionsDialog = dialog
+ dialog.show()
+ } else {
+ lastForceValue = force
+ requestPostNotificationPermission()
+ }
+ }
+
+ private fun actuallyDownloadQuranImages(force: Boolean) {
// if any broadcasts were received, then we are already downloading
// so unless we know what we are doing (via force), don't ask the
// service to restart the download
if (downloadReceiver != null && downloadReceiver!!.didReceiveBroadcast() && !force) {
return
}
+
val dataStatus = quranDataStatus
+ if (dataStatus == null) {
+ // we lost the cached data status, so just check again
+ checkPages()
+ return
+ }
+
var url: String
- url = if (dataStatus!!.needPortrait() && !dataStatus.needLandscape()) {
+ url = if (dataStatus.needPortrait() && !dataStatus.needLandscape()) {
// phone (and tablet when upgrading on some devices, ex n10)
quranFileUtils.zipFileUrl
} else if (dataStatus.needLandscape() && !dataStatus.needPortrait()) {
@@ -681,6 +739,7 @@ class QuranDataActivity : Activity(), SimpleDownloadListener, OnRequestPermissio
companion object {
const val PAGES_DOWNLOAD_KEY = "PAGES_DOWNLOAD_KEY"
private const val REQUEST_WRITE_TO_SDCARD_PERMISSIONS = 1
+ private const val REQUEST_POST_NOTIFICATION_PERMISSIONS = 2
private const val QURAN_DIRECTORY_MARKER_FILE = "q4a"
private const val QURAN_HIDDEN_DIRECTORY_MARKER_FILE = ".q4a"
}
diff --git a/app/src/main/java/com/quran/labs/androidquran/bridge/AudioEventPresenterBridge.kt b/app/src/main/java/com/quran/labs/androidquran/bridge/AudioEventPresenterBridge.kt
deleted file mode 100644
index ea3d929f78..0000000000
--- a/app/src/main/java/com/quran/labs/androidquran/bridge/AudioEventPresenterBridge.kt
+++ /dev/null
@@ -1,27 +0,0 @@
-package com.quran.labs.androidquran.bridge
-
-import com.quran.data.model.SuraAyah
-import com.quran.reading.common.AudioEventPresenter
-import kotlinx.coroutines.MainScope
-import kotlinx.coroutines.cancel
-import kotlinx.coroutines.flow.launchIn
-import kotlinx.coroutines.flow.onEach
-
-class AudioEventPresenterBridge constructor(
- audioEventPresenter: AudioEventPresenter,
- onPlaybackAyahChanged: ((SuraAyah?) -> Unit)
-) {
-
- private val scope = MainScope()
- private val audioPlaybackAyahFlow = audioEventPresenter.audioPlaybackAyahFlow
-
- init {
- audioPlaybackAyahFlow
- .onEach { onPlaybackAyahChanged(it) }
- .launchIn(scope)
- }
-
- fun dispose() {
- scope.cancel()
- }
-}
diff --git a/app/src/main/java/com/quran/labs/androidquran/bridge/AudioStatusRepositoryBridge.kt b/app/src/main/java/com/quran/labs/androidquran/bridge/AudioStatusRepositoryBridge.kt
new file mode 100644
index 0000000000..01e150c515
--- /dev/null
+++ b/app/src/main/java/com/quran/labs/androidquran/bridge/AudioStatusRepositoryBridge.kt
@@ -0,0 +1,60 @@
+package com.quran.labs.androidquran.bridge
+
+import com.quran.data.model.SuraAyah
+import com.quran.labs.androidquran.common.audio.model.playback.AudioRequest
+import com.quran.labs.androidquran.common.audio.model.playback.AudioStatus
+import com.quran.labs.androidquran.common.audio.model.playback.PlaybackStatus
+import com.quran.labs.androidquran.common.audio.repository.AudioStatusRepository
+import com.quran.labs.androidquran.view.AudioStatusBar
+import kotlinx.coroutines.MainScope
+import kotlinx.coroutines.cancel
+import kotlinx.coroutines.flow.launchIn
+import kotlinx.coroutines.flow.onEach
+
+class AudioStatusRepositoryBridge(
+ audioStatusRepository: AudioStatusRepository,
+ audioStatusBar: () -> AudioStatusBar,
+ onPlaybackAyahChanged: ((SuraAyah?) -> Unit)
+) {
+
+ private val scope = MainScope()
+ private val audioPlaybackAyahFlow = audioStatusRepository.audioPlaybackFlow
+
+ init {
+ audioPlaybackAyahFlow
+ .onEach { status ->
+ when (status) {
+ is AudioStatus.Playback -> {
+ val statusBar = audioStatusBar()
+ if (status.playbackStatus == PlaybackStatus.PLAYING) {
+ statusBar.switchMode(AudioStatusBar.PLAYING_MODE)
+ if (status.audioRequest.repeatInfo >= -1) {
+ statusBar.setRepeatCount(status.audioRequest.repeatInfo)
+ statusBar.setSpeed(status.audioRequest.playbackSpeed)
+ }
+ } else if (status.playbackStatus == PlaybackStatus.PAUSED) {
+ statusBar.switchMode(AudioStatusBar.PAUSED_MODE)
+ } else if (status.playbackStatus == PlaybackStatus.PREPARING) {
+ statusBar.switchMode(AudioStatusBar.LOADING_MODE)
+ }
+ onPlaybackAyahChanged(status.currentAyah)
+ }
+ AudioStatus.Stopped -> {
+ audioStatusBar().switchMode(AudioStatusBar.STOPPED_MODE)
+ }
+ }
+ }
+ .launchIn(scope)
+ }
+
+ fun audioRequest(): AudioRequest? {
+ return when (val status = audioPlaybackAyahFlow.value) {
+ is AudioStatus.Playback -> status.audioRequest
+ AudioStatus.Stopped -> null
+ }
+ }
+
+ fun dispose() {
+ scope.cancel()
+ }
+}
diff --git a/app/src/main/java/com/quran/labs/androidquran/common/LocalTranslationDisplaySort.kt b/app/src/main/java/com/quran/labs/androidquran/common/LocalTranslationDisplaySort.kt
index 08870eefb2..65413ca1e9 100644
--- a/app/src/main/java/com/quran/labs/androidquran/common/LocalTranslationDisplaySort.kt
+++ b/app/src/main/java/com/quran/labs/androidquran/common/LocalTranslationDisplaySort.kt
@@ -1,5 +1,7 @@
package com.quran.labs.androidquran.common
+import com.quran.mobile.translation.model.LocalTranslation
+
class LocalTranslationDisplaySort : Comparator {
override fun compare(first: LocalTranslation, second: LocalTranslation): Int {
return first.displayOrder.compareTo(second.displayOrder)
diff --git a/app/src/main/java/com/quran/labs/androidquran/common/TranslationMetadata.kt b/app/src/main/java/com/quran/labs/androidquran/common/TranslationMetadata.kt
index 9a7bdfcddf..8ebb582b89 100644
--- a/app/src/main/java/com/quran/labs/androidquran/common/TranslationMetadata.kt
+++ b/app/src/main/java/com/quran/labs/androidquran/common/TranslationMetadata.kt
@@ -1,6 +1,9 @@
package com.quran.labs.androidquran.common
+import android.text.SpannableString
+import android.text.SpannableStringBuilder
import com.quran.data.model.SuraAyah
+import com.quran.labs.androidquran.ui.helpers.TranslationFootnoteHelper
data class TranslationMetadata(
val sura: Int,
@@ -11,4 +14,21 @@ data class TranslationMetadata(
val linkPageNumber: Int? = null,
val ayat: List = emptyList(),
val footnotes: List = emptyList()
-)
+) {
+
+ fun footnoteCognizantText(
+ spannableStringBuilder: SpannableStringBuilder,
+ expandedFootnotes: List,
+ collapsedFootnoteSpannableStyler: ((Int) -> SpannableString),
+ expandedFootnoteSpannableStyler: ((SpannableStringBuilder, Int, Int) -> SpannableStringBuilder)
+ ): CharSequence {
+ return TranslationFootnoteHelper.footnoteCognizantText(
+ text,
+ footnotes,
+ spannableStringBuilder,
+ expandedFootnotes,
+ collapsedFootnoteSpannableStyler,
+ expandedFootnoteSpannableStyler
+ )
+ }
+}
diff --git a/app/src/main/java/com/quran/labs/androidquran/dao/translation/Translation.kt b/app/src/main/java/com/quran/labs/androidquran/dao/translation/Translation.kt
index 1d01051d1a..bb155f5755 100644
--- a/app/src/main/java/com/quran/labs/androidquran/dao/translation/Translation.kt
+++ b/app/src/main/java/com/quran/labs/androidquran/dao/translation/Translation.kt
@@ -14,8 +14,7 @@ data class Translation(val id: Int,
val saveTo: String,
val languageCode: String,
val translator: String? = "",
- @Json(name = "translatorForeign") val translatorNameLocalized: String? = "",
- val displayOrder: Int = -1) {
+ @Json(name = "translatorForeign") val translatorNameLocalized: String? = "") {
fun withSchema(schema: Int) = copy(minimumVersion = schema)
}
diff --git a/app/src/main/java/com/quran/labs/androidquran/dao/translation/TranslationItem.kt b/app/src/main/java/com/quran/labs/androidquran/dao/translation/TranslationItem.kt
index b5ce16c63a..ecb9ef06d7 100644
--- a/app/src/main/java/com/quran/labs/androidquran/dao/translation/TranslationItem.kt
+++ b/app/src/main/java/com/quran/labs/androidquran/dao/translation/TranslationItem.kt
@@ -1,5 +1,7 @@
package com.quran.labs.androidquran.dao.translation
+import com.quran.mobile.translation.model.LocalTranslation
+
data class TranslationItem @JvmOverloads constructor(val translation: Translation,
val localVersion: Int = 0,
val displayOrder: Int = -1) : TranslationRowData {
@@ -16,7 +18,22 @@ data class TranslationItem @JvmOverloads constructor(val translation: Translatio
fun withTranslationRemoved() = this.copy(localVersion = 0)
- fun withTranslationVersion(version: Int) = this.copy(localVersion = version)
-
fun withDisplayOrder(newDisplayOrder: Int) = this.copy(displayOrder = newDisplayOrder)
+
+ fun withLocalVersionAndDisplayOrder(newVersion: Int, displayOrder: Int) = this.copy(localVersion = newVersion, displayOrder = displayOrder)
+
+ fun asLocalTranslation(): LocalTranslation {
+ return LocalTranslation(
+ id = translation.id.toLong(),
+ filename = translation.fileName,
+ name = translation.displayName,
+ translator = translation.translator,
+ translatorForeign = translation.translatorNameLocalized,
+ url = translation.fileUrl,
+ languageCode = translation.languageCode,
+ version = localVersion,
+ minimumVersion = translation.minimumVersion,
+ displayOrder = displayOrder
+ )
+ }
}
diff --git a/app/src/main/java/com/quran/labs/androidquran/dao/translation/TranslationItemDisplaySort.kt b/app/src/main/java/com/quran/labs/androidquran/dao/translation/TranslationItemDisplaySort.kt
deleted file mode 100644
index ec390d7f70..0000000000
--- a/app/src/main/java/com/quran/labs/androidquran/dao/translation/TranslationItemDisplaySort.kt
+++ /dev/null
@@ -1,7 +0,0 @@
-package com.quran.labs.androidquran.dao.translation
-
-class TranslationItemDisplaySort : Comparator {
- override fun compare(first: TranslationItem, second: TranslationItem): Int {
- return first.displayOrder.compareTo(second.displayOrder)
- }
-}
diff --git a/app/src/main/java/com/quran/labs/androidquran/data/AyahInfoDatabaseProvider.kt b/app/src/main/java/com/quran/labs/androidquran/data/AyahInfoDatabaseProvider.kt
index 3b269de87f..30aa919a83 100644
--- a/app/src/main/java/com/quran/labs/androidquran/data/AyahInfoDatabaseProvider.kt
+++ b/app/src/main/java/com/quran/labs/androidquran/data/AyahInfoDatabaseProvider.kt
@@ -3,11 +3,12 @@ package com.quran.labs.androidquran.data
import android.content.Context
import com.quran.data.di.ActivityScope
import com.quran.labs.androidquran.util.QuranFileUtils
+import com.quran.mobile.di.qualifier.ApplicationContext
import javax.inject.Inject
@ActivityScope
class AyahInfoDatabaseProvider @Inject constructor(
- private val context: Context,
+ @ApplicationContext private val context: Context,
private val widthParameter: String,
private val quranFileUtils: QuranFileUtils
) {
diff --git a/app/src/main/java/com/quran/labs/androidquran/data/Constants.kt b/app/src/main/java/com/quran/labs/androidquran/data/Constants.kt
index e398b58dac..2d456e5af9 100644
--- a/app/src/main/java/com/quran/labs/androidquran/data/Constants.kt
+++ b/app/src/main/java/com/quran/labs/androidquran/data/Constants.kt
@@ -98,4 +98,6 @@ object Constants {
const val PREF_CHECKED_PARTIAL_IMAGES = "didCheckPartialImages"
const val PREF_CURRENT_AUDIO_REVISION = "currentAudioRevision"
const val PREF_SURA_TRANSLATED_NAME = "suraTranslatedName"
+ const val PREF_SHOW_SIDELINES = "showSidelines"
+ const val PREF_SHOW_LINE_DIVIDERS = "showLineDividers"
}
diff --git a/app/src/main/java/com/quran/labs/androidquran/data/QuranDataProvider.java b/app/src/main/java/com/quran/labs/androidquran/data/QuranDataProvider.java
deleted file mode 100644
index e7da9e8bb6..0000000000
--- a/app/src/main/java/com/quran/labs/androidquran/data/QuranDataProvider.java
+++ /dev/null
@@ -1,280 +0,0 @@
-package com.quran.labs.androidquran.data;
-
-import android.app.SearchManager;
-import android.content.ContentProvider;
-import android.content.ContentResolver;
-import android.content.ContentValues;
-import android.content.Context;
-import android.content.UriMatcher;
-import android.database.Cursor;
-import android.database.MatrixCursor;
-import android.net.Uri;
-import android.provider.BaseColumns;
-
-import com.quran.data.core.QuranInfo;
-import com.quran.labs.androidquran.BuildConfig;
-import com.quran.labs.androidquran.QuranApplication;
-import com.quran.labs.androidquran.R;
-import com.quran.labs.androidquran.common.LocalTranslation;
-import com.quran.labs.androidquran.database.DatabaseHandler;
-import com.quran.labs.androidquran.database.DatabaseUtils;
-import com.quran.labs.androidquran.database.TranslationsDBAdapter;
-import com.quran.labs.androidquran.util.QuranFileUtils;
-import com.quran.labs.androidquran.util.QuranUtils;
-
-import java.util.List;
-
-import javax.inject.Inject;
-
-import androidx.annotation.NonNull;
-import timber.log.Timber;
-
-public class QuranDataProvider extends ContentProvider {
-
- public static String AUTHORITY = BuildConfig.APPLICATION_ID + ".data.QuranDataProvider";
- public static final Uri SEARCH_URI = Uri.parse("content://" + AUTHORITY + "/quran/search");
-
- public static final String VERSES_MIME_TYPE =
- ContentResolver.CURSOR_DIR_BASE_TYPE + "/vnd.com.quran.labs.androidquran";
- public static final String QURAN_ARABIC_DATABASE = QuranFileConstants.ARABIC_DATABASE;
-
- // UriMatcher stuff
- private static final int SEARCH_VERSES = 0;
- private static final int SEARCH_SUGGEST = 1;
- private static final UriMatcher uriMatcher = buildUriMatcher();
-
- private boolean didInject;
- @Inject QuranDisplayData quranDisplayData;
- @Inject TranslationsDBAdapter translationsDBAdapter;
- @Inject QuranFileUtils quranFileUtils;
- @Inject QuranInfo quranInfo;
-
- private static UriMatcher buildUriMatcher() {
- UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);
- matcher.addURI(AUTHORITY, "quran/search", SEARCH_VERSES);
- matcher.addURI(AUTHORITY, "quran/search/*", SEARCH_VERSES);
- matcher.addURI(AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY, SEARCH_SUGGEST);
- matcher.addURI(AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY + "/*", SEARCH_SUGGEST);
- return matcher;
- }
-
- @Override
- public boolean onCreate() {
- return true;
- }
-
- @Override
- public Cursor query(@NonNull Uri uri, String[] projection, String selection,
- String[] selectionArgs, String sortOrder) {
- Context context = getContext();
- if (!didInject) {
- Context appContext = context == null ? null : context.getApplicationContext();
- if (appContext instanceof QuranApplication) {
- ((QuranApplication) appContext).getApplicationComponent().inject(this);
- didInject = true;
- } else {
- Timber.e("unable to inject QuranDataProvider");
- return null;
- }
- }
-
- Timber.d("uri: %s", uri.toString());
- switch (uriMatcher.match(uri)) {
- case SEARCH_SUGGEST: {
- if (selectionArgs == null) {
- throw new IllegalArgumentException(
- "selectionArgs must be provided for the Uri: " + uri);
- }
-
- return getSuggestions(selectionArgs[0]);
- }
- case SEARCH_VERSES: {
- if (selectionArgs == null) {
- throw new IllegalArgumentException(
- "selectionArgs must be provided for the Uri: " + uri);
- }
-
- return search(selectionArgs[0]);
- }
- default: {
- throw new IllegalArgumentException("Unknown Uri: " + uri);
- }
- }
- }
-
- private Cursor search(String query) {
- return search(query, getAvailableTranslations());
- }
-
- private List getAvailableTranslations() {
- return translationsDBAdapter.getTranslations();
- }
-
- private Cursor getSuggestions(String query) {
- if (query.length() < 3) {
- return null;
- }
-
- final boolean queryIsArabic = QuranUtils.doesStringContainArabic(query);
- final boolean haveArabic = queryIsArabic &&
- quranFileUtils.hasTranslation(getContext(), QURAN_ARABIC_DATABASE);
-
- List translations = getAvailableTranslations();
- if (translations.size() == 0 && (queryIsArabic && !haveArabic)) {
- return null;
- }
-
- int total = translations.size();
- int start = haveArabic ? -1 : 0;
-
- String[] cols = new String[] { BaseColumns._ID,
- SearchManager.SUGGEST_COLUMN_TEXT_1,
- SearchManager.SUGGEST_COLUMN_TEXT_2,
- SearchManager.SUGGEST_COLUMN_INTENT_DATA_ID };
- MatrixCursor mc = new MatrixCursor(cols);
-
- Context context = getContext();
- boolean gotResults = false;
- boolean likelyHaveMoreResults = false;
- for (int i = start; i < total; i++) {
- if (gotResults) {
- continue;
- }
-
- String database;
- if (i < 0) {
- database = QURAN_ARABIC_DATABASE;
- if (!quranFileUtils.hasArabicSearchDatabase()) {
- continue;
- }
- } else {
- LocalTranslation translation = translations.get(i);
- // skip non-arabic databases if the query is in arabic
- if (queryIsArabic || "ar".equals(translation.getLanguageCode())) {
- // skip arabic databases even when the query is in arabic since
- // searching Arabic tafaseer causes a lot of noise on the search
- // results and is confusing.
- continue;
- }
- database = translation.getFilename();
- }
-
- Cursor suggestions = null;
- try {
- suggestions = search(query, database, false);
- if (context != null && suggestions != null && suggestions.moveToFirst()) {
- if (suggestions.getCount() > 5) {
- likelyHaveMoreResults = true;
- }
-
- int results = 0;
- do {
- if (results == 5) {
- break;
- }
- int sura = suggestions.getInt(1);
- int ayah = suggestions.getInt(2);
- int page = quranInfo.getPageFromSuraAyah(sura, ayah);
- String text = suggestions.getString(3);
- String foundText = context.getString(
- R.string.found_in_sura, quranDisplayData.getSuraName(context, sura, false), ayah, page);
-
- gotResults = true;
- MatrixCursor.RowBuilder row = mc.newRow();
- int id = suggestions.getInt(0);
-
- row.add(id);
- row.add(text);
- row.add(foundText);
- row.add(id);
- results++;
- } while (suggestions.moveToNext());
- }
- } finally {
- DatabaseUtils.closeCursor(suggestions);
- }
- }
-
- if (context != null && (queryIsArabic || likelyHaveMoreResults)) {
- mc.addRow(new Object[] {
- -1, context.getString(R.string.search_full_results),
- context.getString(R.string.search_entire_mushaf), -1
- });
- }
- return mc;
- }
-
- private Cursor search(String query, List translations) {
- Timber.d("query: %s", query);
-
- final Context context = getContext();
- final boolean queryIsArabic = QuranUtils.doesStringContainArabic(query);
- final boolean haveArabic = queryIsArabic &&
- quranFileUtils.hasTranslation(context, QURAN_ARABIC_DATABASE);
- if (translations.size() == 0 && (queryIsArabic && !haveArabic)) {
- return null;
- }
-
- int start = haveArabic ? -1 : 0;
- int total = translations.size();
-
- for (int i = start; i < total; i++) {
- String databaseName;
- if (i < 0) {
- databaseName = QURAN_ARABIC_DATABASE;
- } else {
- LocalTranslation translation = translations.get(i);
- // skip non-arabic databases if the query is in arabic
- if (queryIsArabic || "ar".equals(translation.getLanguageCode())) {
- // skip arabic databases always since it's confusing to people for now.
- // in the future, can think of better ways to enable tafseer search.
- continue;
- }
- databaseName = translation.getFilename();
- }
-
- Cursor cursor = search(query, databaseName, true);
- if (cursor != null && cursor.getCount() > 0) {
- return cursor;
- }
- }
- return null;
- }
-
- private Cursor search(String query, String databaseName, boolean wantSnippets) {
- final DatabaseHandler handler =
- DatabaseHandler.getDatabaseHandler(getContext(), databaseName, quranFileUtils);
- return handler.search(query, wantSnippets, QURAN_ARABIC_DATABASE.equals(databaseName));
- }
-
- @Override
- public String getType(@NonNull Uri uri) {
- switch (uriMatcher.match(uri)) {
- case SEARCH_VERSES: {
- return VERSES_MIME_TYPE;
- }
- case SEARCH_SUGGEST: {
- return SearchManager.SUGGEST_MIME_TYPE;
- }
- default: {
- throw new IllegalArgumentException("Unknown URL " + uri);
- }
- }
- }
-
- @Override
- public Uri insert(@NonNull Uri uri, ContentValues values) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public int update(@NonNull Uri uri, ContentValues values, String selection,
- String[] selectionArgs) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public int delete(@NonNull Uri uri, String selection, String[] selectionArgs) {
- throw new UnsupportedOperationException();
- }
-}
diff --git a/app/src/main/java/com/quran/labs/androidquran/data/QuranDataProvider.kt b/app/src/main/java/com/quran/labs/androidquran/data/QuranDataProvider.kt
new file mode 100644
index 0000000000..e8785b7c20
--- /dev/null
+++ b/app/src/main/java/com/quran/labs/androidquran/data/QuranDataProvider.kt
@@ -0,0 +1,261 @@
+package com.quran.labs.androidquran.data
+
+import android.app.SearchManager
+import android.content.ContentProvider
+import android.content.ContentResolver
+import android.content.ContentValues
+import android.content.UriMatcher
+import android.database.Cursor
+import android.database.MatrixCursor
+import android.net.Uri
+import android.provider.BaseColumns
+import com.quran.data.core.QuranInfo
+import com.quran.labs.androidquran.BuildConfig
+import com.quran.labs.androidquran.QuranApplication
+import com.quran.labs.androidquran.R
+import com.quran.labs.androidquran.database.DatabaseHandler.Companion.getDatabaseHandler
+import com.quran.labs.androidquran.database.DatabaseUtils.closeCursor
+import com.quran.labs.androidquran.database.TranslationsDBAdapter
+import com.quran.labs.androidquran.util.QuranFileUtils
+import com.quran.labs.androidquran.util.QuranUtils
+import com.quran.mobile.translation.model.LocalTranslation
+import kotlinx.coroutines.MainScope
+import kotlinx.coroutines.flow.first
+import kotlinx.coroutines.runBlocking
+import timber.log.Timber
+import javax.inject.Inject
+
+class QuranDataProvider : ContentProvider() {
+ private var didInject = false
+
+ @Inject lateinit var quranDisplayData: QuranDisplayData
+ @Inject lateinit var translationsDBAdapter: TranslationsDBAdapter
+ @Inject lateinit var quranFileUtils: QuranFileUtils
+ @Inject lateinit var quranInfo: QuranInfo
+
+ override fun onCreate(): Boolean {
+ return true
+ }
+
+ override fun query(
+ uri: Uri, projection: Array?, selection: String?,
+ selectionArgs: Array?, sortOrder: String?
+ ): Cursor? {
+ val context = context
+ if (!didInject) {
+ val appContext = context?.applicationContext
+ didInject = if (appContext is QuranApplication) {
+ appContext.applicationComponent.inject(this)
+ true
+ } else {
+ Timber.e("unable to inject QuranDataProvider")
+ return null
+ }
+ }
+ Timber.d("uri: %s", uri.toString())
+ return when (uriMatcher.match(uri)) {
+ SEARCH_SUGGEST -> {
+ requireNotNull(selectionArgs) { "selectionArgs must be provided for the Uri: $uri" }
+ getSuggestions(selectionArgs[0])
+ }
+
+ SEARCH_VERSES -> {
+ requireNotNull(selectionArgs) { "selectionArgs must be provided for the Uri: $uri" }
+ search(selectionArgs[0])
+ }
+
+ else -> {
+ throw IllegalArgumentException("Unknown Uri: $uri")
+ }
+ }
+ }
+
+ private fun availableTranslations(): List {
+ return runBlocking { translationsDBAdapter.getTranslations().first() }
+ }
+
+ private fun getSuggestions(query: String): Cursor? {
+ if (query.length < 3) {
+ return null
+ }
+ val queryIsArabic = QuranUtils.doesStringContainArabic(query)
+ val haveArabic = queryIsArabic &&
+ quranFileUtils.hasTranslation(context!!, QURAN_ARABIC_DATABASE)
+ val translations = availableTranslations()
+ if (translations.isEmpty() && queryIsArabic && !haveArabic) {
+ return null
+ }
+ val total = translations.size
+ val start = if (haveArabic) -1 else 0
+ val cols = arrayOf(
+ BaseColumns._ID,
+ SearchManager.SUGGEST_COLUMN_TEXT_1,
+ SearchManager.SUGGEST_COLUMN_TEXT_2,
+ SearchManager.SUGGEST_COLUMN_INTENT_DATA_ID
+ )
+ val mc = MatrixCursor(cols)
+ val context = context
+ var gotResults = false
+ var likelyHaveMoreResults = false
+ for (i in start until total) {
+ if (gotResults) {
+ continue
+ }
+ var database: String
+ if (i < 0) {
+ database = QURAN_ARABIC_DATABASE
+ if (!quranFileUtils.hasArabicSearchDatabase()) {
+ continue
+ }
+ } else {
+ val (_, filename, _, _, _, _, languageCode) = translations[i]
+ // skip non-arabic databases if the query is in arabic
+ if (queryIsArabic || "ar" == languageCode) {
+ // skip arabic databases even when the query is in arabic since
+ // searching Arabic tafaseer causes a lot of noise on the search
+ // results and is confusing.
+ continue
+ }
+ database = filename
+ }
+ var suggestions: Cursor? = null
+ try {
+ suggestions = search(query, database, false)
+ if (context != null && suggestions != null && suggestions.moveToFirst()) {
+ if (suggestions.count > 5) {
+ likelyHaveMoreResults = true
+ }
+ var results = 0
+ do {
+ if (results == 5) {
+ break
+ }
+ val sura = suggestions.getInt(1)
+ val ayah = suggestions.getInt(2)
+ val page = quranInfo.getPageFromSuraAyah(sura, ayah)
+ val text = suggestions.getString(3)
+ val foundText = context.getString(
+ R.string.found_in_sura,
+ quranDisplayData.getSuraName(context, sura, false),
+ ayah,
+ page
+ )
+ gotResults = true
+ val row = mc.newRow()
+ val id = suggestions.getInt(0)
+ row.add(id)
+ row.add(text)
+ row.add(foundText)
+ row.add(id)
+ results++
+ } while (suggestions.moveToNext())
+ }
+ } finally {
+ closeCursor(suggestions)
+ }
+ }
+ if (context != null && (queryIsArabic || likelyHaveMoreResults)) {
+ mc.addRow(
+ arrayOf(
+ -1, context.getString(R.string.search_full_results),
+ context.getString(R.string.search_entire_mushaf), -1
+ )
+ )
+ }
+ return mc
+ }
+
+ private fun search(
+ query: String,
+ translations: List = availableTranslations()
+ ): Cursor? {
+ Timber.d("query: %s", query)
+ val context = context
+ val queryIsArabic = QuranUtils.doesStringContainArabic(query)
+ val haveArabic = queryIsArabic &&
+ quranFileUtils.hasTranslation(context!!, QURAN_ARABIC_DATABASE)
+ if (translations.isEmpty() && queryIsArabic && !haveArabic) {
+ return null
+ }
+ val start = if (haveArabic) -1 else 0
+ val total = translations.size
+ for (i in start until total) {
+ val databaseName: String = if (i < 0) {
+ QURAN_ARABIC_DATABASE
+ } else {
+ val (_, filename, _, _, _, _, languageCode) = translations[i]
+ // skip non-arabic databases if the query is in arabic
+ if (queryIsArabic || "ar" == languageCode) {
+ // skip arabic databases always since it's confusing to people for now.
+ // in the future, can think of better ways to enable tafseer search.
+ continue
+ }
+ filename
+ }
+ val cursor = search(query, databaseName, true)
+ if (cursor != null && cursor.count > 0) {
+ return cursor
+ }
+ }
+ return null
+ }
+
+ private fun search(query: String, databaseName: String, wantSnippets: Boolean): Cursor? {
+ val handler = getDatabaseHandler(context!!, databaseName, quranFileUtils)
+ return handler.search(query, wantSnippets, QURAN_ARABIC_DATABASE == databaseName)
+ }
+
+ override fun getType(uri: Uri): String? {
+ return when (uriMatcher.match(uri)) {
+ SEARCH_VERSES -> {
+ VERSES_MIME_TYPE
+ }
+
+ SEARCH_SUGGEST -> {
+ SearchManager.SUGGEST_MIME_TYPE
+ }
+
+ else -> {
+ throw IllegalArgumentException("Unknown URL $uri")
+ }
+ }
+ }
+
+ override fun insert(uri: Uri, values: ContentValues?): Uri? {
+ throw UnsupportedOperationException()
+ }
+
+ override fun update(
+ uri: Uri, values: ContentValues?, selection: String?,
+ selectionArgs: Array?
+ ): Int {
+ throw UnsupportedOperationException()
+ }
+
+ override fun delete(uri: Uri, selection: String?, selectionArgs: Array?): Int {
+ throw UnsupportedOperationException()
+ }
+
+ companion object {
+ private const val AUTHORITY = BuildConfig.APPLICATION_ID + ".data.QuranDataProvider"
+
+ @JvmField val SEARCH_URI: Uri = Uri.parse("content://$AUTHORITY/quran/search")
+ const val VERSES_MIME_TYPE =
+ ContentResolver.CURSOR_DIR_BASE_TYPE + "/vnd.com.quran.labs.androidquran"
+ const val QURAN_ARABIC_DATABASE = QuranFileConstants.ARABIC_DATABASE
+
+ // UriMatcher stuff
+ private const val SEARCH_VERSES = 0
+ private const val SEARCH_SUGGEST = 1
+ private val uriMatcher = buildUriMatcher()
+
+ private fun buildUriMatcher(): UriMatcher {
+ val matcher = UriMatcher(UriMatcher.NO_MATCH)
+ matcher.addURI(AUTHORITY, "quran/search", SEARCH_VERSES)
+ matcher.addURI(AUTHORITY, "quran/search/*", SEARCH_VERSES)
+ matcher.addURI(AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY, SEARCH_SUGGEST)
+ matcher.addURI(AUTHORITY, SearchManager.SUGGEST_URI_PATH_QUERY + "/*", SEARCH_SUGGEST)
+ return matcher
+ }
+ }
+}
diff --git a/app/src/main/java/com/quran/labs/androidquran/data/QuranDisplayData.kt b/app/src/main/java/com/quran/labs/androidquran/data/QuranDisplayData.kt
index 4d63480edd..76b9cc4f19 100644
--- a/app/src/main/java/com/quran/labs/androidquran/data/QuranDisplayData.kt
+++ b/app/src/main/java/com/quran/labs/androidquran/data/QuranDisplayData.kt
@@ -89,6 +89,15 @@ class QuranDisplayData @Inject constructor(private val quranInfo: QuranInfo): Qu
QuranUtils.getLocalizedNumber(context, quranInfo.getJuzForDisplayFromPage(page)))
}
+ fun getManzilForPage(context: Context, page: Int): String {
+ val manzil = quranInfo.manzilForPage(page)
+ return if (manzil > 0) {
+ context.getString(R.string.comma) + ' ' + context.getString(R.string.manzil_description, QuranUtils.getLocalizedNumber(context, manzil))
+ } else {
+ ""
+ }
+ }
+
fun getSuraAyahString(context: Context, sura: Int, ayah: Int): String {
return getSuraAyahString(context, sura, ayah, R.string.sura_ayah_notification_str)
}
@@ -148,7 +157,7 @@ class QuranDisplayData @Inject constructor(private val quranInfo: QuranInfo): Qu
}
fun safelyGetSuraOnPage(page: Int): Int {
- return if (page < Constants.PAGES_FIRST || page > quranInfo.numberOfPages) {
+ return if (!quranInfo.isValidPage(page)) {
Timber.e(IllegalArgumentException("safelyGetSuraOnPage with page: $page"))
quranInfo.getSuraOnPage(1)
} else {
diff --git a/app/src/main/java/com/quran/labs/androidquran/database/BookmarksDBAdapter.kt b/app/src/main/java/com/quran/labs/androidquran/database/BookmarksDBAdapter.kt
index 35876d9aa4..5cb9596233 100644
--- a/app/src/main/java/com/quran/labs/androidquran/database/BookmarksDBAdapter.kt
+++ b/app/src/main/java/com/quran/labs/androidquran/database/BookmarksDBAdapter.kt
@@ -54,6 +54,17 @@ class BookmarksDBAdapter @Inject constructor(bookmarksDatabase: BookmarksDatabas
}
}
+ fun removeRecentsForPage(page: Int) {
+ lastPageQueries.transaction {
+ val lastPages = lastPageQueries.getLastPages().executeAsList()
+ val lastPagesWithoutPage = lastPages.filter { it.page != page }
+ if (lastPages.size != lastPagesWithoutPage.size) {
+ lastPageQueries.removeLastPages()
+ lastPagesWithoutPage.forEach { addRecentPage(it.page) }
+ }
+ }
+ }
+
fun replaceRecentRangeWithPage(deleteRangeStart: Int, deleteRangeEnd: Int, page: Int) {
val maxPages = Constants.MAX_RECENT_PAGES.toLong()
lastPageQueries.replaceRangeWithPage(deleteRangeStart, deleteRangeEnd, page, maxPages)
@@ -105,6 +116,14 @@ class BookmarksDBAdapter @Inject constructor(bookmarksDatabase: BookmarksDatabas
}
}
+ fun removeBookmarksForPage(page: Int) {
+ val bookmarkId = bookmarkQueries.getBookmarkIdForPage(page).executeAsOneOrNull()
+ if (bookmarkId != null) {
+ bookmarkTagQueries.deleteByBookmarkIds(listOf(bookmarkId))
+ bookmarkQueries.deleteByIds(listOf(bookmarkId))
+ }
+ }
+
fun addBookmarkIfNotExists(sura: Int, ayah: Int, page: Int): Long {
var bookmarkId = getBookmarkId(sura, ayah, page)
if (bookmarkId < 0) {
diff --git a/app/src/main/java/com/quran/labs/androidquran/database/BookmarksDaoImpl.kt b/app/src/main/java/com/quran/labs/androidquran/database/BookmarksDaoImpl.kt
index b6ddd9eaaf..9a026b909b 100644
--- a/app/src/main/java/com/quran/labs/androidquran/database/BookmarksDaoImpl.kt
+++ b/app/src/main/java/com/quran/labs/androidquran/database/BookmarksDaoImpl.kt
@@ -23,6 +23,12 @@ class BookmarksDaoImpl @Inject constructor(
}
}
+ override suspend fun removeBookmarksForPage(page: Int) {
+ withContext(Dispatchers.IO) {
+ bookmarksDBAdapter.removeBookmarksForPage(page)
+ }
+ }
+
override suspend fun recentPages(): List {
return withContext(Dispatchers.IO) {
bookmarksDBAdapter.getRecentPages()
@@ -40,4 +46,10 @@ class BookmarksDaoImpl @Inject constructor(
bookmarksDBAdapter.removeRecentPages()
}
}
+
+ override suspend fun removeRecentsForPage(page: Int) {
+ withContext(Dispatchers.IO) {
+ bookmarksDBAdapter.removeRecentsForPage(page)
+ }
+ }
}
diff --git a/app/src/main/java/com/quran/labs/androidquran/database/DatabaseHandler.kt b/app/src/main/java/com/quran/labs/androidquran/database/DatabaseHandler.kt
index ccb254ea9b..fc2602685d 100644
--- a/app/src/main/java/com/quran/labs/androidquran/database/DatabaseHandler.kt
+++ b/app/src/main/java/com/quran/labs/androidquran/database/DatabaseHandler.kt
@@ -84,7 +84,7 @@ class DatabaseHandler private constructor(
ContextCompat.getColor(context, R.color.translation_highlight) +
"\">"
defaultSearcher = DefaultSearcher(matchString, MATCH_END, ELLIPSES)
- arabicSearcher = ArabicSearcher(defaultSearcher, matchString, MATCH_END, QuranFileConstants.SEARCH_EXTRA_REPLACEMENTS)
+ arabicSearcher = ArabicSearcher(defaultSearcher, matchString, MATCH_END)
// if there's no Quran base directory, there are no databases
val base = quranFileUtils.getQuranDatabaseDirectory(context)
@@ -117,10 +117,6 @@ class DatabaseHandler private constructor(
fun validDatabase(): Boolean = database?.isOpen ?: false
- private fun getVerses(sura: Int, minAyah: Int, maxAyah: Int): Cursor? {
- return getVerses(sura, minAyah, maxAyah, VERSE_TABLE)
- }
-
private fun getProperty(column: String): Int {
var value = 1
if (!validDatabase()) return value
@@ -284,16 +280,6 @@ class DatabaseHandler private constructor(
)
}
- /**
- * @deprecated use {@link #getVerses(VerseRange, int)} instead
- * @param sura the sura
- * @param ayah the ayah
- * @return the result
- */
- fun getVerse(sura: Int, ayah: Int): Cursor? {
- return getVerses(sura, ayah, ayah)
- }
-
fun getVersesByIds(ids: List): Cursor? {
val builder = StringBuilder()
for (i in ids.indices) {
diff --git a/app/src/main/java/com/quran/labs/androidquran/database/TranslationsDBAdapter.kt b/app/src/main/java/com/quran/labs/androidquran/database/TranslationsDBAdapter.kt
index 38924fbd5f..b21b1ca33a 100644
--- a/app/src/main/java/com/quran/labs/androidquran/database/TranslationsDBAdapter.kt
+++ b/app/src/main/java/com/quran/labs/androidquran/database/TranslationsDBAdapter.kt
@@ -1,166 +1,79 @@
package com.quran.labs.androidquran.database
-import android.content.ContentValues
import android.content.Context
-import android.database.Cursor
-import android.database.sqlite.SQLiteDatabase
import android.util.SparseArray
-
-import com.quran.labs.androidquran.common.LocalTranslation
import com.quran.labs.androidquran.dao.translation.TranslationItem
-import com.quran.labs.androidquran.database.TranslationsDBHelper.TranslationsTable
import com.quran.labs.androidquran.util.QuranFileUtils
-
-import java.util.ArrayList
-import java.util.Collections
-import timber.log.Timber
-
-import androidx.annotation.WorkerThread
+import com.quran.mobile.di.qualifier.ApplicationContext
+import com.quran.mobile.translation.data.TranslationsDataSource
+import com.quran.mobile.translation.model.LocalTranslation
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.filterNotNull
+import kotlinx.coroutines.flow.first
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.withContext
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
class TranslationsDBAdapter @Inject constructor(
- private val context: Context,
- adapter: TranslationsDBHelper,
+ @ApplicationContext private val context: Context,
+ private val dataSource: TranslationsDataSource,
private val quranFileUtils: QuranFileUtils
) {
- private val db: SQLiteDatabase = adapter.writableDatabase
-
- @Volatile
- private var cachedTranslations: List? = null
-
- var lastWriteTime: Long = 0
- private set
- fun getTranslationsHash(): SparseArray {
- val result = SparseArray()
- for (item in getTranslations()) {
- result.put(item.id, item)
- }
- return result
+ fun getTranslations(): Flow> {
+ return dataSource.translations()
+ .filterNotNull()
+ .map { translations ->
+ translations.filter { quranFileUtils.hasTranslation(context, it.filename) }
+ }
}
- // intentional, since cachedTranslations can be replaced by another thread, causing the check
- // to be true, but the cached object returned to be null (or to change).
- @WorkerThread
- fun getTranslations(): List {
- // intentional, since cachedTranslations can be replaced by another thread, causing the check
- // to be true, but the cached object returned to be null (or to change).
- val cached = cachedTranslations
- if (!cached.isNullOrEmpty()) {
- return cached
- }
- var items: MutableList = ArrayList()
- var cursor: Cursor? = null
- try {
- cursor = db.query(TranslationsTable.TABLE_NAME,
- null, null, null, null, null,
- TranslationsTable.ID + " ASC")
-
- while (cursor.moveToNext()) {
- val id = cursor.getInt(0)
- val name = cursor.getString(1)
- val translator = cursor.getString(2)
- val translatorForeign = cursor.getString(3)
- val filename = cursor.getString(4)
- val url = cursor.getString(5)
- val languageCode = cursor.getString(6)
- val version = cursor.getInt(7)
- val minimumVersion = cursor.getInt(8)
- val displayOrder = cursor.getInt(9)
-
- if (quranFileUtils.hasTranslation(context, filename)) {
- items.add(
- LocalTranslation(
- id, filename, name, translator,
- translatorForeign, url, languageCode, version, minimumVersion, displayOrder
- )
- )
- }
+ suspend fun translationsHash(): SparseArray {
+ return withContext(Dispatchers.IO) {
+ val result = SparseArray()
+ val translations = getTranslations().first()
+ for (item in translations) {
+ result.put(item.id.toInt(), item)
}
- } finally {
- cursor?.close()
- }
-
- items = Collections.unmodifiableList(items)
- if (items.size > 0) {
- cachedTranslations = items
+ result
}
- return items
}
- fun deleteTranslationByFile(filename: String) {
- db.execSQL("DELETE FROM " + TranslationsTable.TABLE_NAME + " WHERE " +
- TranslationsTable.FILENAME + " = ?", arrayOf(filename))
+ suspend fun deleteTranslationByFileName(filename: String) {
+ dataSource.removeTranslation(filename)
}
- fun writeTranslationUpdates(updates: List): Boolean {
- var result = true
- db.beginTransaction()
+ suspend fun writeTranslationUpdates(updates: List): Boolean {
+ return withContext(Dispatchers.IO) {
+ val (available, unavailable) = updates.partition { it.exists() }
+
+ val needNextOrder = available.any { it.displayOrder == -1 }
+ val nextOrder = if (needNextOrder) {
+ dataSource.maximumDisplayOrder().toInt() + 1
+ } else {
+ (available.maxOfOrNull { it.displayOrder } ?: 0) + 1
+ }
- try {
- var cachedNextOrder = -1
- for (item in updates) {
- if (item.exists()) {
- var displayOrder = 0
- val translation = item.translation
- if (item.displayOrder > -1) {
- displayOrder = item.displayOrder
+ val items = if (needNextOrder) {
+ var nextOrderNumber = nextOrder
+ available.map { item ->
+ if (item.displayOrder == -1) {
+ item.copy(displayOrder = nextOrderNumber++)
} else {
- var cursor: Cursor? = null
- if (cachedNextOrder == -1) {
- try {
- // get next highest display order
- cursor = db.query(
- TranslationsTable.TABLE_NAME, arrayOf(TranslationsTable.DISPLAY_ORDER),
- null, null, null, null,
- TranslationsTable.DISPLAY_ORDER + " DESC",
- "1"
- )
- if (cursor != null && cursor.moveToFirst()) {
- cachedNextOrder = cursor.getInt(0) + 1
- displayOrder = cachedNextOrder++
- }
- } finally {
- cursor?.close()
- }
- } else {
- displayOrder = cachedNextOrder++
- }
+ item
}
-
- val values = ContentValues()
- values.put(TranslationsTable.ID, translation.id)
- values.put(TranslationsTable.NAME, translation.displayName)
- values.put(TranslationsTable.TRANSLATOR, translation.translator)
- values.put(TranslationsTable.TRANSLATOR_FOREIGN,
- translation.translatorNameLocalized)
- values.put(TranslationsTable.FILENAME, translation.fileName)
- values.put(TranslationsTable.URL, translation.fileUrl)
- values.put(TranslationsTable.LANGUAGE_CODE, translation.languageCode)
- values.put(TranslationsTable.VERSION, item.localVersion)
- values.put(TranslationsTable.MINIMUM_REQUIRED_VERSION, translation.minimumVersion)
- values.put(TranslationsTable.DISPLAY_ORDER, displayOrder)
-
- db.replace(TranslationsTable.TABLE_NAME, null, values)
- } else {
- db.delete(TranslationsTable.TABLE_NAME,
- TranslationsTable.ID + " = " + item.translation.id, null)
}
+ } else {
+ available
}
- db.setTransactionSuccessful()
- lastWriteTime = System.currentTimeMillis()
- // clear the cached translations
- cachedTranslations = null
- } catch (e: Exception) {
- result = false
- Timber.d(e, "error writing translation updates")
- } finally {
- db.endTransaction()
- }
+ dataSource.updateTranslations(items.map { it.asLocalTranslation() })
+ dataSource.removeTranslationsById(unavailable.map { it.translation.id.toLong() })
- return result
+ true
+ }
}
}
diff --git a/app/src/main/java/com/quran/labs/androidquran/database/TranslationsDBHelper.kt b/app/src/main/java/com/quran/labs/androidquran/database/TranslationsDBHelper.kt
deleted file mode 100644
index 9f6fa816df..0000000000
--- a/app/src/main/java/com/quran/labs/androidquran/database/TranslationsDBHelper.kt
+++ /dev/null
@@ -1,111 +0,0 @@
-package com.quran.labs.androidquran.database
-
-import android.content.Context
-import android.database.sqlite.SQLiteDatabase
-import android.database.sqlite.SQLiteOpenHelper
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class TranslationsDBHelper @Inject constructor(context: Context) :
- SQLiteOpenHelper(context, DB_NAME, null, DB_VERSION) {
-
- companion object {
- private const val DB_NAME = "translations.db"
- private const val DB_VERSION = 5
- private const val CREATE_TRANSLATIONS_TABLE =
- "CREATE TABLE " + TranslationsTable.TABLE_NAME + "(" +
- TranslationsTable.ID + " integer primary key, " +
- TranslationsTable.NAME + " varchar not null, " +
- TranslationsTable.TRANSLATOR + " varchar, " +
- TranslationsTable.TRANSLATOR_FOREIGN + " varchar, " +
- TranslationsTable.FILENAME + " varchar not null, " +
- TranslationsTable.URL + " varchar, " +
- TranslationsTable.LANGUAGE_CODE + " varchar, " +
- TranslationsTable.VERSION + " integer not null default 0," +
- TranslationsTable.MINIMUM_REQUIRED_VERSION + " integer not null default 0, " +
- TranslationsTable.DISPLAY_ORDER + " integer not null default -1 " +
- ");"
- }
-
- override fun onCreate(db: SQLiteDatabase) {
- db.execSQL(CREATE_TRANSLATIONS_TABLE)
- }
-
- @Suppress("LocalVariableName")
- override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
- if (oldVersion < 4) {
- // a new column is added and columns are re-arranged
- val BACKUP_TABLE = TranslationsTable.TABLE_NAME + "_backup"
- db.beginTransaction()
- try {
- db.execSQL("ALTER TABLE " + TranslationsTable.TABLE_NAME + " RENAME TO " + BACKUP_TABLE)
- db.execSQL(CREATE_TRANSLATIONS_TABLE)
- db.execSQL("INSERT INTO " + TranslationsTable.TABLE_NAME + " (" +
- TranslationsTable.ID + ", " +
- TranslationsTable.NAME + ", " +
- TranslationsTable.TRANSLATOR + ", " +
- (if (oldVersion < 2) "" else (TranslationsTable.TRANSLATOR_FOREIGN + ", ")) +
- TranslationsTable.FILENAME + ", " +
- TranslationsTable.URL + ", " +
- (if (oldVersion < 3) "" else (TranslationsTable.LANGUAGE_CODE + ",")) +
- TranslationsTable.VERSION + ", " +
- TranslationsTable.DISPLAY_ORDER + ") " +
- "SELECT " + TranslationsTable.ID + ", " +
- TranslationsTable.NAME + ", " +
- TranslationsTable.TRANSLATOR + ", " +
- (if (oldVersion < 2) "" else "translator_foreign, ") +
- TranslationsTable.FILENAME + ", " +
- TranslationsTable.URL + ", " +
- (if (oldVersion < 3) "" else (TranslationsTable.LANGUAGE_CODE + ",")) +
- TranslationsTable.VERSION + ", " +
- TranslationsTable.ID +
- " FROM " + BACKUP_TABLE)
- db.execSQL("DROP TABLE $BACKUP_TABLE")
- db.execSQL("UPDATE " + TranslationsTable.TABLE_NAME + " SET " +
- TranslationsTable.MINIMUM_REQUIRED_VERSION + " = 2")
- db.setTransactionSuccessful()
- } finally {
- db.endTransaction()
- }
- } else if (oldVersion < 5) {
- // the v3 and below update also updates to v5.
- // this code is called for updating from v4.
- upgradeToV5(db)
- }
- }
-
- private fun upgradeToV5(db: SQLiteDatabase) {
- // Add display order column and add arbitrary order to existing translations
- db.beginTransaction()
- try {
- db.execSQL("ALTER TABLE "
- + TranslationsTable.TABLE_NAME
- + " ADD COLUMN "
- + TranslationsTable.DISPLAY_ORDER
- + " integer not null default -1"
- )
-
- // for now, set the order to be the translation id
- db.execSQL("UPDATE " + TranslationsTable.TABLE_NAME + " SET " +
- TranslationsTable.DISPLAY_ORDER + " = " + TranslationsTable.ID)
- db.setTransactionSuccessful()
- } finally {
- db.endTransaction()
- }
- }
-
- internal object TranslationsTable {
- const val TABLE_NAME = "translations"
- const val ID = "id"
- const val NAME = "name"
- const val TRANSLATOR = "translator"
- const val TRANSLATOR_FOREIGN = "translatorForeign"
- const val FILENAME = "filename"
- const val URL = "url"
- const val LANGUAGE_CODE = "languageCode"
- const val VERSION = "version"
- const val MINIMUM_REQUIRED_VERSION = "minimumRequiredVersion"
- const val DISPLAY_ORDER = "userDisplayOrder"
- }
-}
diff --git a/app/src/main/java/com/quran/labs/androidquran/database/TranslationsDaoImpl.kt b/app/src/main/java/com/quran/labs/androidquran/database/TranslationsDaoImpl.kt
index b7b694aa86..643910c2a6 100644
--- a/app/src/main/java/com/quran/labs/androidquran/database/TranslationsDaoImpl.kt
+++ b/app/src/main/java/com/quran/labs/androidquran/database/TranslationsDaoImpl.kt
@@ -9,12 +9,13 @@ import com.quran.data.model.bookmark.Bookmark
import com.quran.labs.androidquran.data.QuranDataProvider
import com.quran.labs.androidquran.database.DatabaseHandler.TextType.Companion.TRANSLATION
import com.quran.labs.androidquran.util.QuranFileUtils
+import com.quran.mobile.di.qualifier.ApplicationContext
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import javax.inject.Inject
class TranslationsDaoImpl @Inject constructor(
- private val appContext: Context,
+ @ApplicationContext private val appContext: Context,
private val quranFileUtils: QuranFileUtils,
) : TranslationsDao {
diff --git a/app/src/main/java/com/quran/labs/androidquran/di/component/activity/PagerActivityComponent.kt b/app/src/main/java/com/quran/labs/androidquran/di/component/activity/PagerActivityComponent.kt
index 819648b638..ae983f4bab 100644
--- a/app/src/main/java/com/quran/labs/androidquran/di/component/activity/PagerActivityComponent.kt
+++ b/app/src/main/java/com/quran/labs/androidquran/di/component/activity/PagerActivityComponent.kt
@@ -1,24 +1,28 @@
package com.quran.labs.androidquran.di.component.activity
-import com.quran.data.di.QuranReadingScope
+import android.content.Context
import com.quran.data.di.ActivityScope
+import com.quran.data.di.QuranReadingScope
import com.quran.labs.androidquran.di.component.fragment.QuranPageComponent
import com.quran.labs.androidquran.di.module.activity.PagerActivityModule
import com.quran.labs.androidquran.ui.PagerActivity
import com.quran.labs.androidquran.ui.fragment.AyahPlaybackFragment
import com.quran.labs.androidquran.ui.fragment.AyahTranslationFragment
import com.quran.labs.androidquran.ui.fragment.TagBookmarkFragment
-import com.quran.page.common.toolbar.AyahToolBar
+import com.quran.labs.androidquran.ui.helpers.AyahSelectedListener
import com.quran.mobile.di.QuranReadingActivityComponent
+import com.quran.mobile.di.qualifier.ActivityContext
import com.quran.mobile.feature.qarilist.QariListWrapper
+import com.quran.page.common.toolbar.AyahToolBar
import com.squareup.anvil.annotations.MergeSubcomponent
+import dagger.BindsInstance
import dagger.Subcomponent
@ActivityScope
@MergeSubcomponent(QuranReadingScope::class, modules = [PagerActivityModule::class])
interface PagerActivityComponent : QuranReadingActivityComponent {
// subcomponents
- fun quranPageComponentBuilder(): QuranPageComponent.Builder
+ fun quranPageComponentFactory(): QuranPageComponent.Factory
fun inject(pagerActivity: PagerActivity)
fun inject(ayahToolBar: AyahToolBar)
@@ -29,9 +33,11 @@ interface PagerActivityComponent : QuranReadingActivityComponent {
fun inject(qariListWrapper: QariListWrapper)
- @Subcomponent.Builder
- interface Builder {
- fun withPagerActivityModule(pagerModule: PagerActivityModule): Builder
- fun build(): PagerActivityComponent
+ @Subcomponent.Factory
+ interface Factory {
+ fun generate(
+ @BindsInstance @ActivityContext context: Context,
+ @BindsInstance ayahSelectedListener: AyahSelectedListener
+ ): PagerActivityComponent
}
}
diff --git a/app/src/main/java/com/quran/labs/androidquran/di/component/activity/QuranActivityComponent.kt b/app/src/main/java/com/quran/labs/androidquran/di/component/activity/QuranActivityComponent.kt
index f15c176504..d78ed394c7 100644
--- a/app/src/main/java/com/quran/labs/androidquran/di/component/activity/QuranActivityComponent.kt
+++ b/app/src/main/java/com/quran/labs/androidquran/di/component/activity/QuranActivityComponent.kt
@@ -8,8 +8,8 @@ import dagger.Subcomponent
interface QuranActivityComponent {
fun inject(quranActivity: QuranActivity)
- @Subcomponent.Builder
- interface Builder {
- fun build(): QuranActivityComponent
+ @Subcomponent.Factory
+ interface Factory {
+ fun generate(): QuranActivityComponent
}
}
diff --git a/app/src/main/java/com/quran/labs/androidquran/di/component/application/ApplicationComponent.kt b/app/src/main/java/com/quran/labs/androidquran/di/component/application/ApplicationComponent.kt
index 24726377a5..ca4c740045 100644
--- a/app/src/main/java/com/quran/labs/androidquran/di/component/application/ApplicationComponent.kt
+++ b/app/src/main/java/com/quran/labs/androidquran/di/component/application/ApplicationComponent.kt
@@ -1,5 +1,6 @@
package com.quran.labs.androidquran.di.component.application
+import android.content.Context
import com.quran.analytics.provider.AnalyticsModule
import com.quran.common.networking.NetworkModule
import com.quran.data.di.AppScope
@@ -33,7 +34,10 @@ import com.quran.labs.androidquran.widget.BookmarksWidget
import com.quran.labs.androidquran.widget.BookmarksWidgetListProvider
import com.quran.labs.androidquran.widget.ShowJumpFragmentActivity
import com.quran.mobile.di.QuranApplicationComponent
+import com.quran.mobile.di.qualifier.ApplicationContext
import com.squareup.anvil.annotations.MergeComponent
+import dagger.BindsInstance
+import dagger.Component
import javax.inject.Singleton
@Singleton
@@ -52,8 +56,8 @@ import javax.inject.Singleton
)
interface ApplicationComponent: QuranApplicationComponent {
// subcomponents
- fun pagerActivityComponentBuilder(): PagerActivityComponent.Builder
- fun quranActivityComponentBuilder(): QuranActivityComponent.Builder
+ fun pagerActivityComponentFactory(): PagerActivityComponent.Factory
+ fun quranActivityComponentFactory(): QuranActivityComponent.Factory
// application
fun inject(quranApplication: QuranApplication)
@@ -89,4 +93,9 @@ interface ApplicationComponent: QuranApplicationComponent {
// widgets
fun inject(bookmarksWidgetListProvider: BookmarksWidgetListProvider)
fun inject(bookmarksWidget: BookmarksWidget)
+
+ @Component.Factory
+ interface Factory {
+ fun generate(@BindsInstance @ApplicationContext appContext: Context): ApplicationComponent
+ }
}
diff --git a/app/src/main/java/com/quran/labs/androidquran/di/component/fragment/QuranPageComponent.kt b/app/src/main/java/com/quran/labs/androidquran/di/component/fragment/QuranPageComponent.kt
index 248dfdeed3..e866e5c97a 100644
--- a/app/src/main/java/com/quran/labs/androidquran/di/component/fragment/QuranPageComponent.kt
+++ b/app/src/main/java/com/quran/labs/androidquran/di/component/fragment/QuranPageComponent.kt
@@ -2,24 +2,23 @@ package com.quran.labs.androidquran.di.component.fragment
import com.quran.data.di.QuranPageScope
import com.quran.data.di.QuranReadingPageScope
-import com.quran.data.page.provider.di.QuranPageExtrasComponent
-import com.quran.labs.androidquran.di.module.fragment.QuranPageModule
import com.quran.labs.androidquran.ui.fragment.QuranPageFragment
import com.quran.labs.androidquran.ui.fragment.TabletFragment
import com.quran.labs.androidquran.ui.fragment.TranslationFragment
+import com.quran.mobile.di.QuranReadingPageComponent
import com.squareup.anvil.annotations.MergeSubcomponent
+import dagger.BindsInstance
import dagger.Subcomponent
@QuranPageScope
-@MergeSubcomponent(QuranReadingPageScope::class, modules = [QuranPageModule::class])
-interface QuranPageComponent: QuranPageExtrasComponent {
+@MergeSubcomponent(QuranReadingPageScope::class)
+interface QuranPageComponent: QuranReadingPageComponent {
fun inject(quranPageFragment: QuranPageFragment)
fun inject(tabletFragment: TabletFragment)
fun inject(translationFragment: TranslationFragment)
- @Subcomponent.Builder
- interface Builder {
- fun withQuranPageModule(quranPageModule: QuranPageModule): Builder
- fun build(): QuranPageComponent
+ @Subcomponent.Factory
+ interface Factory {
+ fun generate(@BindsInstance pages: IntArray): QuranPageComponent
}
}
diff --git a/app/src/main/java/com/quran/labs/androidquran/di/module/activity/PagerActivityModule.kt b/app/src/main/java/com/quran/labs/androidquran/di/module/activity/PagerActivityModule.kt
index a3bc1ec752..8f351532ca 100644
--- a/app/src/main/java/com/quran/labs/androidquran/di/module/activity/PagerActivityModule.kt
+++ b/app/src/main/java/com/quran/labs/androidquran/di/module/activity/PagerActivityModule.kt
@@ -1,40 +1,36 @@
package com.quran.labs.androidquran.di.module.activity
+import android.content.Context
import com.quran.data.core.QuranInfo
import com.quran.data.core.QuranPageInfo
import com.quran.data.di.ActivityScope
import com.quran.labs.androidquran.data.QuranDisplayData
-import com.quran.labs.androidquran.ui.PagerActivity
-import com.quran.labs.androidquran.ui.helpers.AyahSelectedListener
import com.quran.labs.androidquran.util.QuranPageInfoImpl
import com.quran.labs.androidquran.util.QuranScreenInfo
import com.quran.labs.androidquran.util.QuranUtils
import com.quran.labs.androidquran.util.TranslationUtil
import com.quran.mobile.di.AyahActionFragmentProvider
+import com.quran.mobile.di.qualifier.ActivityContext
import dagger.Module
import dagger.Provides
import dagger.multibindings.ElementsIntoSet
@Module
-class PagerActivityModule(private val pagerActivity: PagerActivity) {
-
- @Provides
- fun provideAyahSelectedListener(): AyahSelectedListener {
- return pagerActivity
- }
+object PagerActivityModule {
@Provides
fun provideQuranPageInfo(
+ @ActivityContext context: Context,
quranInfo: QuranInfo,
quranDisplayData: QuranDisplayData
): QuranPageInfo {
- return QuranPageInfoImpl(pagerActivity, quranInfo, quranDisplayData)
+ return QuranPageInfoImpl(context, quranInfo, quranDisplayData)
}
@Provides
@ActivityScope
- fun provideImageWidth(screenInfo: QuranScreenInfo): String {
- return if (QuranUtils.isDualPages(pagerActivity, screenInfo)) {
+ fun provideImageWidth(@ActivityContext context: Context, screenInfo: QuranScreenInfo): String {
+ return if (QuranUtils.isDualPages(context, screenInfo)) {
screenInfo.tabletWidthParam
} else {
screenInfo.widthParam
diff --git a/app/src/main/java/com/quran/labs/androidquran/di/module/application/ApplicationModule.kt b/app/src/main/java/com/quran/labs/androidquran/di/module/application/ApplicationModule.kt
index 97f5c0b785..92a0fa55f3 100644
--- a/app/src/main/java/com/quran/labs/androidquran/di/module/application/ApplicationModule.kt
+++ b/app/src/main/java/com/quran/labs/androidquran/di/module/application/ApplicationModule.kt
@@ -1,6 +1,5 @@
package com.quran.labs.androidquran.di.module.application
-import android.app.Application
import android.content.Context
import android.graphics.Point
import android.view.Display
@@ -15,6 +14,7 @@ import com.quran.labs.androidquran.data.QuranFileConstants
import com.quran.labs.androidquran.util.QuranFileUtils
import com.quran.labs.androidquran.util.QuranSettings
import com.quran.labs.androidquran.util.SettingsImpl
+import com.quran.mobile.di.qualifier.ApplicationContext
import com.quran.mobile.di.ExtraPreferencesProvider
import com.quran.mobile.di.ExtraScreenProvider
import dagger.Module
@@ -28,15 +28,10 @@ import javax.inject.Named
import javax.inject.Singleton
@Module
-class ApplicationModule(private val application: Application) {
+object ApplicationModule {
@Provides
- fun provideApplicationContext(): Context {
- return application
- }
-
- @Provides
- fun provideDisplay(appContext: Context): Display {
+ fun provideDisplay(@ApplicationContext appContext: Context): Display {
val w = appContext.getSystemService(Context.WINDOW_SERVICE) as WindowManager
return w.defaultDisplay
}
@@ -58,11 +53,12 @@ class ApplicationModule(private val application: Application) {
@Provides
@Singleton
- fun provideQuranSettings(): QuranSettings {
- return QuranSettings.getInstance(application)
+ fun provideQuranSettings(@ApplicationContext appContext: Context): QuranSettings {
+ return QuranSettings.getInstance(appContext)
}
@Provides
+ @Singleton
fun provideSettings(settingsImpl: SettingsImpl): Settings {
return settingsImpl
}
@@ -94,8 +90,8 @@ class ApplicationModule(private val application: Application) {
}
@Provides
- fun provideCacheDirectory(): File {
- return application.cacheDir
+ fun provideCacheDirectory(@ApplicationContext appContext: Context): File {
+ return appContext.cacheDir
}
@Provides
diff --git a/app/src/main/java/com/quran/labs/androidquran/di/module/fragment/QuranPageModule.kt b/app/src/main/java/com/quran/labs/androidquran/di/module/fragment/QuranPageModule.kt
deleted file mode 100644
index 5a380bda66..0000000000
--- a/app/src/main/java/com/quran/labs/androidquran/di/module/fragment/QuranPageModule.kt
+++ /dev/null
@@ -1,13 +0,0 @@
-package com.quran.labs.androidquran.di.module.fragment
-
-import dagger.Module
-import dagger.Provides
-
-@Module
-class QuranPageModule(private vararg val pages: Int) {
-
- @Provides
- fun providePages(): IntArray {
- return pages
- }
-}
diff --git a/app/src/main/java/com/quran/labs/androidquran/model/bookmark/BookmarkImportExportModel.java b/app/src/main/java/com/quran/labs/androidquran/model/bookmark/BookmarkImportExportModel.java
index c1f491e4e7..9c898b5f2f 100644
--- a/app/src/main/java/com/quran/labs/androidquran/model/bookmark/BookmarkImportExportModel.java
+++ b/app/src/main/java/com/quran/labs/androidquran/model/bookmark/BookmarkImportExportModel.java
@@ -9,6 +9,7 @@
import com.quran.data.model.bookmark.BookmarkData;
import com.quran.labs.androidquran.R;
import com.quran.labs.androidquran.database.BookmarksDBAdapter;
+import com.quran.mobile.di.qualifier.ApplicationContext;
import java.io.File;
import java.io.IOException;
@@ -30,7 +31,7 @@ public class BookmarkImportExportModel {
private final BookmarkModel bookmarkModel;
@Inject
- BookmarkImportExportModel(Context appContext,
+ BookmarkImportExportModel(@ApplicationContext Context appContext,
BookmarkJsonModel model, BookmarkModel bookmarkModel) {
this.appContext = appContext;
this.jsonModel = model;
diff --git a/app/src/main/java/com/quran/labs/androidquran/model/translation/ArabicDatabaseUtils.java b/app/src/main/java/com/quran/labs/androidquran/model/translation/ArabicDatabaseUtils.java
index 54937c461a..dd9a408f97 100644
--- a/app/src/main/java/com/quran/labs/androidquran/model/translation/ArabicDatabaseUtils.java
+++ b/app/src/main/java/com/quran/labs/androidquran/model/translation/ArabicDatabaseUtils.java
@@ -3,15 +3,19 @@
import android.content.Context;
import android.database.Cursor;
+import androidx.annotation.NonNull;
+import androidx.annotation.VisibleForTesting;
+
import com.quran.data.core.QuranInfo;
import com.quran.data.model.QuranText;
+import com.quran.data.model.SuraAyah;
import com.quran.data.model.bookmark.Bookmark;
import com.quran.labs.androidquran.data.QuranDataProvider;
import com.quran.labs.androidquran.data.QuranFileConstants;
-import com.quran.data.model.SuraAyah;
import com.quran.labs.androidquran.database.DatabaseHandler;
import com.quran.labs.androidquran.database.DatabaseUtils;
import com.quran.labs.androidquran.util.QuranFileUtils;
+import com.quran.mobile.di.qualifier.ApplicationContext;
import java.util.ArrayList;
import java.util.HashMap;
@@ -21,8 +25,6 @@
import javax.inject.Inject;
import javax.inject.Singleton;
-import androidx.annotation.NonNull;
-import androidx.annotation.VisibleForTesting;
import io.reactivex.rxjava3.core.Single;
import io.reactivex.rxjava3.schedulers.Schedulers;
@@ -39,7 +41,7 @@ public class ArabicDatabaseUtils {
private DatabaseHandler arabicDatabaseHandler;
@Inject
- ArabicDatabaseUtils(Context context, QuranInfo quranInfo, QuranFileUtils quranFileUtils) {
+ ArabicDatabaseUtils(@ApplicationContext Context context, QuranInfo quranInfo, QuranFileUtils quranFileUtils) {
this.appContext = context;
this.quranInfo = quranInfo;
arabicDatabaseHandler = getArabicDatabaseHandler();
diff --git a/app/src/main/java/com/quran/labs/androidquran/model/translation/TranslationModel.kt b/app/src/main/java/com/quran/labs/androidquran/model/translation/TranslationModel.kt
index 36f99e9757..e1f9317494 100644
--- a/app/src/main/java/com/quran/labs/androidquran/model/translation/TranslationModel.kt
+++ b/app/src/main/java/com/quran/labs/androidquran/model/translation/TranslationModel.kt
@@ -1,25 +1,27 @@
package com.quran.labs.androidquran.model.translation
import android.content.Context
+import com.quran.data.di.ActivityScope
import com.quran.data.model.QuranText
import com.quran.data.model.VerseRange
import com.quran.data.pageinfo.mapper.AyahMapper
import com.quran.labs.androidquran.data.QuranDataProvider
import com.quran.labs.androidquran.database.DatabaseHandler
import com.quran.labs.androidquran.database.DatabaseHandler.TextType
-import com.quran.data.di.ActivityScope
import com.quran.labs.androidquran.util.QuranFileUtils
-import io.reactivex.rxjava3.core.Single
+import com.quran.mobile.di.qualifier.ApplicationContext
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.withContext
import javax.inject.Inject
@ActivityScope
class TranslationModel @Inject internal constructor(
- private val appContext: Context,
+ @ApplicationContext private val appContext: Context,
private val quranFileUtils: QuranFileUtils,
private val ayahMapper: AyahMapper
) {
- fun getArabicFromDatabase(verses: VerseRange): Single> {
+ suspend fun getArabicFromDatabase(verses: VerseRange): List {
return getVersesFromDatabase(
verses,
QuranDataProvider.QURAN_ARABIC_DATABASE,
@@ -28,17 +30,17 @@ class TranslationModel @Inject internal constructor(
)
}
- fun getTranslationFromDatabase(verses: VerseRange, db: String): Single> {
+ suspend fun getTranslationFromDatabase(verses: VerseRange, db: String): List {
return getVersesFromDatabase(verses, db, TextType.TRANSLATION, shouldMap = true)
}
- private fun getVersesFromDatabase(
+ private suspend fun getVersesFromDatabase(
verses: VerseRange,
database: String,
@TextType type: Int,
shouldMap: Boolean = false
- ): Single> {
- return Single.fromCallable {
+ ): List {
+ return withContext(Dispatchers.IO) {
val databaseHandler = DatabaseHandler.getDatabaseHandler(appContext, database, quranFileUtils)
if (shouldMap) {
diff --git a/app/src/main/java/com/quran/labs/androidquran/pageselect/PageSelectPresenter.kt b/app/src/main/java/com/quran/labs/androidquran/pageselect/PageSelectPresenter.kt
index 19e8b43e8d..f0c8c6ee3f 100644
--- a/app/src/main/java/com/quran/labs/androidquran/pageselect/PageSelectPresenter.kt
+++ b/app/src/main/java/com/quran/labs/androidquran/pageselect/PageSelectPresenter.kt
@@ -101,14 +101,33 @@ constructor(
val updatedBookmarks = bookmarksDao.bookmarks()
.map {
val page = it.page
- val (pageSura, pageAyah) = suraAyahFromPage(page)
- val sura = it.sura ?: pageSura
- val ayah = it.ayah ?: pageAyah
+ if (page - 1 >= sourcePageSuraStart.size) {
+ if (it.isPageBookmark()) {
+ // this bookmark is on a page that doesn't exist in the old page type
+ if (destination.suraForPageArray.size > page) {
+ // but it does exist on the new type, so it's ok, let's not re-map
+ it
+ } else {
+ // we can't map it, so let's just put it as the max page number to avoid bad data
+ it.copy(page = sourcePageAyahStart.size - 1)
+ }
+ } else {
+ // ayah bookmark, so let's just map it
+ val sura = requireNotNull(it.sura)
+ val ayah = requireNotNull(it.ayah)
+ val mappedPage = destinationQuranInfo.getPageFromSuraAyah(sura, ayah)
+ it.copy(page = mappedPage)
+ }
+ } else {
+ val (pageSura, pageAyah) = suraAyahFromPage(page)
+ val sura = it.sura ?: pageSura
+ val ayah = it.ayah ?: pageAyah
- val mappedPage = destinationQuranInfo.getPageFromSuraAyah(sura, ayah)
+ val mappedPage = destinationQuranInfo.getPageFromSuraAyah(sura, ayah)
- // we only copy the page because sura and ayah are the same.
- it.copy(page = mappedPage)
+ // we only copy the page because sura and ayah are the same.
+ it.copy(page = mappedPage)
+ }
}
if (updatedBookmarks.isNotEmpty()) {
diff --git a/app/src/main/java/com/quran/labs/androidquran/presenter/QuranImportPresenter.java b/app/src/main/java/com/quran/labs/androidquran/presenter/QuranImportPresenter.java
index 6ee2595f31..72cd13a8f9 100644
--- a/app/src/main/java/com/quran/labs/androidquran/presenter/QuranImportPresenter.java
+++ b/app/src/main/java/com/quran/labs/androidquran/presenter/QuranImportPresenter.java
@@ -6,16 +6,18 @@
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.ParcelFileDescriptor;
+
import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
import androidx.core.app.ActivityCompat;
-import com.quran.labs.androidquran.QuranImportActivity;
import com.quran.data.model.bookmark.BookmarkData;
+import com.quran.labs.androidquran.QuranImportActivity;
import com.quran.labs.androidquran.model.bookmark.BookmarkImportExportModel;
import com.quran.labs.androidquran.model.bookmark.BookmarkModel;
import com.quran.labs.androidquran.service.util.PermissionUtil;
import com.quran.labs.androidquran.util.QuranSettings;
+import com.quran.mobile.di.qualifier.ApplicationContext;
import java.io.FileDescriptor;
import java.io.FileInputStream;
@@ -24,9 +26,9 @@
import javax.inject.Inject;
import javax.inject.Singleton;
+import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
import io.reactivex.rxjava3.core.Maybe;
import io.reactivex.rxjava3.core.Observable;
-import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
import io.reactivex.rxjava3.disposables.CompositeDisposable;
import io.reactivex.rxjava3.observers.DisposableMaybeObserver;
import io.reactivex.rxjava3.schedulers.Schedulers;
@@ -48,7 +50,7 @@ public class QuranImportPresenter implements Presenter {
private QuranImportActivity mCurrentActivity;
@Inject
- QuranImportPresenter(Context appContext,
+ QuranImportPresenter(@ApplicationContext Context appContext,
BookmarkImportExportModel model,
BookmarkModel bookmarkModel) {
mAppContext = appContext;
diff --git a/app/src/main/java/com/quran/labs/androidquran/presenter/audio/AudioPresenter.kt b/app/src/main/java/com/quran/labs/androidquran/presenter/audio/AudioPresenter.kt
index 43536c5264..d9e391c8c8 100644
--- a/app/src/main/java/com/quran/labs/androidquran/presenter/audio/AudioPresenter.kt
+++ b/app/src/main/java/com/quran/labs/androidquran/presenter/audio/AudioPresenter.kt
@@ -5,12 +5,12 @@ import android.content.Intent
import com.quran.data.model.SuraAyah
import com.quran.labs.androidquran.R
import com.quran.labs.androidquran.common.audio.model.QariItem
-import com.quran.labs.androidquran.dao.audio.AudioPathInfo
-import com.quran.labs.androidquran.dao.audio.AudioRequest
+import com.quran.labs.androidquran.common.audio.model.playback.AudioPathInfo
+import com.quran.labs.androidquran.common.audio.model.playback.AudioRequest
import com.quran.labs.androidquran.data.QuranDisplayData
import com.quran.labs.androidquran.presenter.Presenter
import com.quran.labs.androidquran.service.QuranDownloadService
-import com.quran.labs.androidquran.common.audio.model.AudioDownloadMetadata
+import com.quran.labs.androidquran.common.audio.model.download.AudioDownloadMetadata
import com.quran.labs.androidquran.service.util.ServiceIntentHelper
import com.quran.labs.androidquran.ui.PagerActivity
import com.quran.labs.androidquran.util.AudioUtils
@@ -32,6 +32,7 @@ constructor(private val quranDisplayData: QuranDisplayData,
verseRepeat: Int,
rangeRepeat: Int,
enforceRange: Boolean,
+ playbackSpeed: Float,
shouldStream: Boolean) {
val audioPathInfo = getLocalAudioPathInfo(qari)
if (audioPathInfo != null) {
@@ -62,17 +63,25 @@ constructor(private val quranDisplayData: QuranDisplayData,
}
val audioRequest = AudioRequest(
- actualStart, actualEnd, qari, verseRepeat, rangeRepeat, enforceRange, stream, audioPath)
+ actualStart, actualEnd, qari, verseRepeat, rangeRepeat, enforceRange, playbackSpeed, stream, audioPath)
play(audioRequest)
}
}
- fun play(audioRequest: AudioRequest) {
+ private fun play(audioRequest: AudioRequest) {
lastAudioRequest = audioRequest
+ proceedWithAudioRequest(audioRequest)
+ }
+
+ private fun proceedWithAudioRequest(audioRequest: AudioRequest, bypassChecks: Boolean = false) {
pagerActivity?.let {
val downloadIntent = getDownloadIntent(it, audioRequest)
if (downloadIntent != null) {
- it.handleRequiredDownload(downloadIntent)
+ if (bypassChecks) {
+ it.proceedWithDownload(downloadIntent)
+ } else {
+ it.handleRequiredDownload(downloadIntent)
+ }
} else {
// play the audio
it.handlePlayback(audioRequest)
@@ -84,6 +93,12 @@ constructor(private val quranDisplayData: QuranDisplayData,
lastAudioRequest?.let { play(it) }
}
+ fun onPostNotificationsPermissionResponse(granted: Boolean) {
+ lastAudioRequest?.let { audioRequest ->
+ proceedWithAudioRequest(audioRequest, true)
+ }
+ }
+
fun onDownloadSuccess() {
lastAudioRequest?.let { play(it) }
}
diff --git a/app/src/main/java/com/quran/labs/androidquran/presenter/audio/service/AudioQueue.kt b/app/src/main/java/com/quran/labs/androidquran/presenter/audio/service/AudioQueue.kt
index 24a252e2c0..5feface706 100644
--- a/app/src/main/java/com/quran/labs/androidquran/presenter/audio/service/AudioQueue.kt
+++ b/app/src/main/java/com/quran/labs/androidquran/presenter/audio/service/AudioQueue.kt
@@ -2,7 +2,7 @@ package com.quran.labs.androidquran.presenter.audio.service
import com.quran.data.core.QuranInfo
import com.quran.labs.androidquran.dao.audio.AudioPlaybackInfo
-import com.quran.labs.androidquran.dao.audio.AudioRequest
+import com.quran.labs.androidquran.common.audio.model.playback.AudioRequest
import com.quran.data.model.SuraAyah
import com.quran.labs.androidquran.extension.requiresBasmallah
import java.util.Locale
@@ -55,6 +55,7 @@ class AudioQueue(private val quranInfo: QuranInfo,
fun getCurrentSura() = playbackInfo.currentAyah.sura
fun getCurrentAyah() = playbackInfo.currentAyah.ayah
+ fun getCurrentPlaybackAyah() = playbackInfo.currentAyah
fun playNextAyah(skipAyahRepeat: Boolean = false): Boolean {
if (playbackInfo.shouldPlayBasmallah) {
diff --git a/app/src/main/java/com/quran/labs/androidquran/presenter/bookmark/BookmarkPresenter.java b/app/src/main/java/com/quran/labs/androidquran/presenter/bookmark/BookmarkPresenter.java
index 31a6188f78..847623b12f 100644
--- a/app/src/main/java/com/quran/labs/androidquran/presenter/bookmark/BookmarkPresenter.java
+++ b/app/src/main/java/com/quran/labs/androidquran/presenter/bookmark/BookmarkPresenter.java
@@ -13,7 +13,6 @@
import com.quran.data.model.bookmark.RecentPage;
import com.quran.data.model.bookmark.Tag;
import com.quran.labs.androidquran.dao.bookmark.BookmarkResult;
-import com.quran.labs.androidquran.data.Constants;
import com.quran.labs.androidquran.model.bookmark.BookmarkModel;
import com.quran.labs.androidquran.model.translation.ArabicDatabaseUtils;
import com.quran.labs.androidquran.presenter.Presenter;
@@ -22,6 +21,7 @@
import com.quran.labs.androidquran.ui.helpers.QuranRowFactory;
import com.quran.labs.androidquran.util.QuranSettings;
import com.quran.labs.androidquran.util.QuranUtils;
+import com.quran.mobile.di.qualifier.ApplicationContext;
import java.util.ArrayList;
import java.util.HashMap;
@@ -48,6 +48,7 @@ public class BookmarkPresenter implements Presenter {
private final BookmarkModel bookmarkModel;
private final QuranSettings quranSettings;
private final QuranRowFactory quranRowFactory;
+ private final QuranInfo quranInfo;
private int sortOrder;
private boolean groupByTags;
@@ -61,10 +62,9 @@ public class BookmarkPresenter implements Presenter {
private DisposableSingleObserver pendingRemoval;
private List itemsToRemove;
- private final int totalPages;
@Inject
- BookmarkPresenter(Context appContext,
+ BookmarkPresenter(@ApplicationContext Context appContext,
BookmarkModel bookmarkModel,
QuranSettings quranSettings,
ArabicDatabaseUtils arabicDatabaseUtils,
@@ -75,12 +75,12 @@ public class BookmarkPresenter implements Presenter {
this.bookmarkModel = bookmarkModel;
this.arabicDatabaseUtils = arabicDatabaseUtils;
this.quranRowFactory = quranRowFactory;
+ this.quranInfo = quranInfo;
sortOrder = quranSettings.getBookmarksSortOrder();
groupByTags = quranSettings.getBookmarksGroupedByTags();
showRecents = quranSettings.getShowRecents();
showDate = quranSettings.getShowDate();
- totalPages = quranInfo.getNumberOfPages();
subscribeToChanges();
}
@@ -323,7 +323,7 @@ private List getBookmarkRows(BookmarkData data, boolean groupByTags) {
rows.add(0, quranRowFactory.fromRecentPageHeader(appContext, size));
for (int i = 0; i < size; i++) {
int page = recentPages.get(i).getPage();
- if (page < Constants.PAGES_FIRST || page > totalPages) {
+ if (!quranInfo.isValidPage(page)) {
page = 1;
}
rows.add(i + 1, quranRowFactory.fromCurrentPage(appContext, page, recentPages.get(i).getTimestamp()));
diff --git a/app/src/main/java/com/quran/labs/androidquran/presenter/data/QuranDataPresenter.kt b/app/src/main/java/com/quran/labs/androidquran/presenter/data/QuranDataPresenter.kt
index 3904cb0338..3e4588807d 100644
--- a/app/src/main/java/com/quran/labs/androidquran/presenter/data/QuranDataPresenter.kt
+++ b/app/src/main/java/com/quran/labs/androidquran/presenter/data/QuranDataPresenter.kt
@@ -11,11 +11,11 @@ import androidx.work.OneTimeWorkRequestBuilder
import androidx.work.PeriodicWorkRequestBuilder
import androidx.work.WorkManager
import androidx.work.workDataOf
+import com.quran.common.upgrade.LocalDataUpgrade
import com.quran.data.core.QuranInfo
import com.quran.data.model.QuranDataStatus
-import com.quran.data.source.PageProvider
-import com.quran.common.upgrade.LocalDataUpgrade
import com.quran.data.source.PageContentType
+import com.quran.data.source.PageProvider
import com.quran.labs.androidquran.QuranDataActivity
import com.quran.labs.androidquran.data.Constants
import com.quran.labs.androidquran.presenter.Presenter
@@ -26,9 +26,10 @@ import com.quran.labs.androidquran.worker.AudioUpdateWorker
import com.quran.labs.androidquran.worker.MissingPageDownloadWorker
import com.quran.labs.androidquran.worker.PartialPageCheckingWorker
import com.quran.labs.androidquran.worker.WorkerConstants
+import com.quran.mobile.di.qualifier.ApplicationContext
+import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
import io.reactivex.rxjava3.core.Completable
import io.reactivex.rxjava3.core.Single
-import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
import io.reactivex.rxjava3.disposables.Disposable
import io.reactivex.rxjava3.functions.Consumer
import io.reactivex.rxjava3.schedulers.Schedulers
@@ -38,12 +39,12 @@ import java.util.concurrent.TimeUnit.DAYS
import javax.inject.Inject
class QuranDataPresenter @Inject internal constructor(
- val appContext: Context,
- val quranInfo: QuranInfo,
- val quranScreenInfo: QuranScreenInfo,
- private val quranPageProvider: PageProvider,
- val quranFileUtils: QuranFileUtils,
- private val localDataUpgrade: LocalDataUpgrade
+ @ApplicationContext val appContext: Context,
+ val quranInfo: QuranInfo,
+ val quranScreenInfo: QuranScreenInfo,
+ private val quranPageProvider: PageProvider,
+ val quranFileUtils: QuranFileUtils,
+ private val localDataUpgrade: LocalDataUpgrade
) : Presenter {
private var activity: QuranDataActivity? = null
@@ -115,7 +116,7 @@ class QuranDataPresenter @Inject internal constructor(
fun imagesVersion() = quranPageProvider.getImageVersion()
- fun canProceedWithoutDownload() = quranPageProvider.getPageContentType() == PageContentType.IMAGE
+ fun canProceedWithoutDownload() = quranPageProvider.getPageContentType() == PageContentType.Image
fun fallbackToImageType() {
val fallbackType = quranPageProvider.getFallbackPageType()
diff --git a/app/src/main/java/com/quran/labs/androidquran/presenter/quran/QuranPagePresenter.kt b/app/src/main/java/com/quran/labs/androidquran/presenter/quran/QuranPagePresenter.kt
index 1ef01d7531..938785b773 100644
--- a/app/src/main/java/com/quran/labs/androidquran/presenter/quran/QuranPagePresenter.kt
+++ b/app/src/main/java/com/quran/labs/androidquran/presenter/quran/QuranPagePresenter.kt
@@ -90,7 +90,7 @@ class QuranPagePresenter @Inject constructor(
// drop empty pages - this happens in Shemerly, for example, where there are an odd number of
// pages. in dual page mode, we have an empty page at the end, so we don't want to try to load
// the empty page.
- val actualPages = pages.filter { it <= quranInfo.numberOfPages }
+ val actualPages = pages.filter { quranInfo.isValidPage(it) }
compositeDisposable.add(
quranPageLoader.loadPages(actualPages.toTypedArray())
.observeOn(AndroidSchedulers.mainThread())
diff --git a/app/src/main/java/com/quran/labs/androidquran/presenter/quran/QuranPageScreen.kt b/app/src/main/java/com/quran/labs/androidquran/presenter/quran/QuranPageScreen.kt
index 8e5587e7e2..8743956c2f 100644
--- a/app/src/main/java/com/quran/labs/androidquran/presenter/quran/QuranPageScreen.kt
+++ b/app/src/main/java/com/quran/labs/androidquran/presenter/quran/QuranPageScreen.kt
@@ -6,10 +6,10 @@ import com.quran.page.common.data.AyahCoordinates
import com.quran.page.common.data.PageCoordinates
interface QuranPageScreen {
- fun setPageCoordinates(pageCoordinates: PageCoordinates?)
+ fun setPageCoordinates(pageCoordinates: PageCoordinates)
fun setAyahCoordinatesError()
fun setPageBitmap(page: Int, pageBitmap: Bitmap)
fun hidePageDownloadError()
fun setPageDownloadError(@StringRes errorMessage: Int)
- fun setAyahCoordinatesData(coordinates: AyahCoordinates?)
+ fun setAyahCoordinatesData(coordinates: AyahCoordinates)
}
diff --git a/app/src/main/java/com/quran/labs/androidquran/presenter/quran/ayahtracker/AyahImageTrackerItem.kt b/app/src/main/java/com/quran/labs/androidquran/presenter/quran/ayahtracker/AyahImageTrackerItem.kt
index 4d4c7fdf87..153feb83e3 100644
--- a/app/src/main/java/com/quran/labs/androidquran/presenter/quran/ayahtracker/AyahImageTrackerItem.kt
+++ b/app/src/main/java/com/quran/labs/androidquran/presenter/quran/ayahtracker/AyahImageTrackerItem.kt
@@ -40,7 +40,8 @@ open class AyahImageTrackerItem @JvmOverloads constructor(
val juzText = quranDisplayData.getJuzDisplayStringForPage(context, page)
val pageText = QuranUtils.getLocalizedNumber(context, page)
val rub3Text = QuranDisplayHelper.displayRub3(context, quranInfo, page)
- ayahView.setOverlayText(context, suraText, juzText, pageText, rub3Text)
+ val manzilText = quranDisplayData.getManzilForPage(context, page)
+ ayahView.setOverlayText(suraText, juzText, pageText, rub3Text, manzilText)
}
ayahView.setPageData(pageCoordinates, imageDrawHelpers)
}
diff --git a/app/src/main/java/com/quran/labs/androidquran/presenter/quran/ayahtracker/AyahTrackerItem.kt b/app/src/main/java/com/quran/labs/androidquran/presenter/quran/ayahtracker/AyahTrackerItem.kt
index 8f88d2643c..8ddaa83442 100644
--- a/app/src/main/java/com/quran/labs/androidquran/presenter/quran/ayahtracker/AyahTrackerItem.kt
+++ b/app/src/main/java/com/quran/labs/androidquran/presenter/quran/ayahtracker/AyahTrackerItem.kt
@@ -7,8 +7,8 @@ import com.quran.data.model.SuraAyah
import com.quran.data.model.highlight.HighlightInfo
import com.quran.data.model.highlight.HighlightType
import com.quran.data.model.selection.SelectionIndicator
-import com.quran.labs.androidquran.common.LocalTranslation
import com.quran.labs.androidquran.common.QuranAyahInfo
+import com.quran.mobile.translation.model.LocalTranslation
import com.quran.page.common.data.AyahCoordinates
import com.quran.page.common.data.PageCoordinates
diff --git a/app/src/main/java/com/quran/labs/androidquran/presenter/quran/ayahtracker/AyahTrackerPresenter.kt b/app/src/main/java/com/quran/labs/androidquran/presenter/quran/ayahtracker/AyahTrackerPresenter.kt
index 38763f56fb..ede00ac03f 100644
--- a/app/src/main/java/com/quran/labs/androidquran/presenter/quran/ayahtracker/AyahTrackerPresenter.kt
+++ b/app/src/main/java/com/quran/labs/androidquran/presenter/quran/ayahtracker/AyahTrackerPresenter.kt
@@ -16,8 +16,9 @@ import com.quran.data.model.highlight.HighlightType
import com.quran.data.model.selection.AyahSelection
import com.quran.data.model.selection.SelectionIndicator
import com.quran.data.model.selection.startSuraAyah
-import com.quran.labs.androidquran.common.LocalTranslation
import com.quran.labs.androidquran.common.QuranAyahInfo
+import com.quran.labs.androidquran.common.audio.model.playback.currentPlaybackAyah
+import com.quran.labs.androidquran.common.audio.repository.AudioStatusRepository
import com.quran.labs.androidquran.data.QuranDisplayData
import com.quran.labs.androidquran.data.SuraAyahIterator
import com.quran.labs.androidquran.presenter.Presenter
@@ -32,9 +33,9 @@ import com.quran.labs.androidquran.ui.helpers.HighlightTypes
import com.quran.labs.androidquran.util.QuranFileUtils
import com.quran.labs.androidquran.util.QuranSettings
import com.quran.mobile.bookmark.model.BookmarkModel
+import com.quran.mobile.translation.model.LocalTranslation
import com.quran.page.common.data.AyahCoordinates
import com.quran.page.common.data.PageCoordinates
-import com.quran.reading.common.AudioEventPresenter
import com.quran.reading.common.ReadingEventPresenter
import com.quran.recitation.events.RecitationEventPresenter
import com.quran.recitation.presenter.RecitationHighlightsPresenter
@@ -58,8 +59,8 @@ class AyahTrackerPresenter @Inject constructor(
private val quranSettings: QuranSettings,
private val readingEventPresenter: ReadingEventPresenter,
private val bookmarkModel: BookmarkModel,
- private val audioEventPresenter: AudioEventPresenter,
- private val recitationPresenter: RecitationPresenter,
+ private val audioStatusRepository: AudioStatusRepository,
+ recitationPresenter: RecitationPresenter,
private val recitationEventPresenter: RecitationEventPresenter,
private val recitationPopupPresenter: RecitationPopupPresenter,
private val recitationHighlightsPresenter: RecitationHighlightsPresenter,
@@ -81,8 +82,8 @@ class AyahTrackerPresenter @Inject constructor(
.onEach { onAyahSelectionChanged(it) }
.launchIn(scope)
- audioEventPresenter.audioPlaybackAyahFlow
- .onEach { onAudioSelectionChanged(it) }
+ audioStatusRepository.audioPlaybackFlow
+ .onEach { onAudioSelectionChanged(it.currentPlaybackAyah()) }
.launchIn(scope)
items.forEach { trackerItem ->
@@ -371,7 +372,7 @@ class AyahTrackerPresenter @Inject constructor(
}
override fun bind(what: AyahInteractionHandler) {
- items = what.ayahTrackerItems
+ items = what.getAyahTrackerItems()
scope = MainScope()
if (isRecitationEnabled) {
recitationPopupPresenter.bind(this)
@@ -390,7 +391,7 @@ class AyahTrackerPresenter @Inject constructor(
}
interface AyahInteractionHandler {
- val ayahTrackerItems: Array
+ fun getAyahTrackerItems(): Array
}
// PopupContainer <--> AyahTrackerItem adapter
diff --git a/app/src/main/java/com/quran/labs/androidquran/presenter/quran/ayahtracker/AyahTranslationTrackerItem.kt b/app/src/main/java/com/quran/labs/androidquran/presenter/quran/ayahtracker/AyahTranslationTrackerItem.kt
index 170d05447d..f18e67f09b 100644
--- a/app/src/main/java/com/quran/labs/androidquran/presenter/quran/ayahtracker/AyahTranslationTrackerItem.kt
+++ b/app/src/main/java/com/quran/labs/androidquran/presenter/quran/ayahtracker/AyahTranslationTrackerItem.kt
@@ -4,7 +4,7 @@ import com.quran.data.core.QuranInfo
import com.quran.data.model.SuraAyah
import com.quran.data.model.highlight.HighlightType
import com.quran.data.model.selection.SelectionIndicator
-import com.quran.labs.androidquran.common.LocalTranslation
+import com.quran.mobile.translation.model.LocalTranslation
import com.quran.labs.androidquran.common.QuranAyahInfo
import com.quran.labs.androidquran.ui.translation.TranslationView
diff --git a/app/src/main/java/com/quran/labs/androidquran/presenter/translation/BaseTranslationPresenter.kt b/app/src/main/java/com/quran/labs/androidquran/presenter/translation/BaseTranslationPresenter.kt
index 0fd2229669..12995febd4 100644
--- a/app/src/main/java/com/quran/labs/androidquran/presenter/translation/BaseTranslationPresenter.kt
+++ b/app/src/main/java/com/quran/labs/androidquran/presenter/translation/BaseTranslationPresenter.kt
@@ -5,8 +5,6 @@ import com.quran.data.model.QuranText
import com.quran.data.model.SuraAyah
import com.quran.data.model.SuraAyahIterator
import com.quran.data.model.VerseRange
-import com.quran.labs.androidquran.common.LocalTranslation
-import com.quran.labs.androidquran.common.LocalTranslationDisplaySort
import com.quran.labs.androidquran.common.QuranAyahInfo
import com.quran.labs.androidquran.common.TranslationMetadata
import com.quran.labs.androidquran.database.TranslationsDBAdapter
@@ -14,63 +12,74 @@ import com.quran.labs.androidquran.model.translation.TranslationModel
import com.quran.labs.androidquran.presenter.Presenter
import com.quran.labs.androidquran.util.QuranSettings
import com.quran.labs.androidquran.util.TranslationUtil
-import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
-import io.reactivex.rxjava3.core.Observable
-import io.reactivex.rxjava3.core.Single
-import io.reactivex.rxjava3.disposables.Disposable
-import io.reactivex.rxjava3.schedulers.Schedulers
-import java.util.Collections
-
-internal open class BaseTranslationPresenter internal constructor(
+import com.quran.mobile.translation.model.LocalTranslation
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.SupervisorJob
+import kotlinx.coroutines.async
+import kotlinx.coroutines.flow.first
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.withContext
+
+open class BaseTranslationPresenter internal constructor(
private val translationModel: TranslationModel,
private val translationsAdapter: TranslationsDBAdapter,
private val translationUtil: TranslationUtil,
private val quranInfo: QuranInfo
) : Presenter {
- private var lastCacheTime: Long = 0
private val translationMap: MutableMap = HashMap()
var translationScreen: T? = null
- var disposable: Disposable? = null
-
- fun getVerses(getArabic: Boolean,
- translationsFileNames: List,
- verseRange: VerseRange
- ): Single {
-
- val translations = translationsAdapter.getTranslations()
-
- val sortedTranslations: List = ArrayList(translations)
- Collections.sort(sortedTranslations, LocalTranslationDisplaySort())
-
- val orderedTranslationsFileNames = sortedTranslations
- .filter { translationsFileNames.contains(it.filename) }
- .map { it.filename }
-
- // get all the translations for these verses, using a source of the list of ordered active translations
- val source = Observable.fromIterable(orderedTranslationsFileNames)
-
- val translationsObservable =
- source.concatMapEager { db ->
- translationModel.getTranslationFromDatabase(verseRange, db)
- .map { texts -> ensureProperTranslations(verseRange, texts) }
- .onErrorReturnItem(ArrayList())
- .toObservable()
- }
- .toList()
- val arabicObservable = if (!getArabic)
- Single.just(ArrayList())
- else
- translationModel.getArabicFromDatabase(verseRange).onErrorReturnItem(ArrayList())
- return Single.zip(arabicObservable, translationsObservable, getTranslationMapSingle(),
- { arabic: List,
- texts: List>,
- map: Map ->
- val translationInfos = getTranslations(orderedTranslationsFileNames, map)
- val ayahInfo = combineAyahData(verseRange, arabic, texts, translationInfos)
- ResultHolder(translationInfos, ayahInfo)
- })
- .subscribeOn(Schedulers.io())
+
+ suspend fun getVerses(
+ getArabic: Boolean,
+ translationsFileNames: List,
+ verseRange: VerseRange
+ ): ResultHolder {
+ return withContext(Dispatchers.IO) {
+ val translations = translationsAdapter.getTranslations().first()
+ val sortedTranslations: List = translations.sortedBy { it.displayOrder }
+
+ val orderedTranslationsFileNames = sortedTranslations
+ .filter { translationsFileNames.contains(it.filename) }
+ .map { it.filename }
+
+ val job = SupervisorJob()
+ // get all the translations for these verses, using a source of the list of ordered active translations
+ val translationData = orderedTranslationsFileNames.map {
+ async(job) {
+ val initialTexts = translationModel.getTranslationFromDatabase(verseRange, it)
+ ensureProperTranslations(verseRange, initialTexts)
+ }
+ }
+
+ val arabic = async(job) {
+ if (getArabic) {
+ translationModel.getArabicFromDatabase(verseRange)
+ } else {
+ emptyList()
+ }
+ }
+
+ val arabicText =
+ try {
+ arabic.await()
+ } catch (e: Exception) {
+ emptyList()
+ }
+
+ val translationTexts = translationData.map { deferred ->
+ try {
+ deferred.await()
+ } catch (e: Exception) {
+ emptyList()
+ }
+ }
+ val translationMap = getTranslationMap()
+
+ val translationInfos = getTranslations(orderedTranslationsFileNames, translationMap)
+ val ayahInfo = combineAyahData(verseRange, arabicText, translationTexts, translationInfos)
+ ResultHolder(translationInfos, ayahInfo)
+ }
}
fun getTranslations(quranSettings: QuranSettings): List {
@@ -115,9 +124,9 @@ internal open class BaseTranslationPresenter internal constructor(
translationMinVersion >= TranslationUtil.MINIMUM_PROCESSING_VERSION
val text = quranText ?: QuranText(element.sura, element.ayah, "")
if (shouldProcess) {
- translationUtil.parseTranslationText(text, translationId)
+ translationUtil.parseTranslationText(text, translationId.toInt())
} else {
- TranslationMetadata(element.sura, element.ayah, text.text, translationId)
+ TranslationMetadata(element.sura, element.ayah, text.text, translationId.toInt())
}
}
@@ -175,25 +184,24 @@ internal open class BaseTranslationPresenter internal constructor(
return texts
}
- private fun getTranslationMapSingle(): Single