Skip to content

Commit

Permalink
Introduced Room database for managing the downloads. * Refactored the…
Browse files Browse the repository at this point in the history
… code to use the room database instead of objectbox database with fetch.

* Refactored the test cases.
  • Loading branch information
MohitMaliDeveloper authored and MohitMaliFtechiz committed Jul 23, 2024
1 parent 5b651f8 commit 1318a42
Show file tree
Hide file tree
Showing 30 changed files with 600 additions and 222 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@ import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.tonyodev.fetch2.Status
import eu.mhutti1.utils.storage.StorageDevice
import eu.mhutti1.utils.storage.StorageSelectDialog
import org.kiwix.kiwixmobile.R
Expand All @@ -59,6 +58,7 @@ import org.kiwix.kiwixmobile.core.base.BaseActivity
import org.kiwix.kiwixmobile.core.base.BaseFragment
import org.kiwix.kiwixmobile.core.base.FragmentActivityExtensions
import org.kiwix.kiwixmobile.core.downloader.Downloader
import org.kiwix.kiwixmobile.core.downloader.downloadManager.Status
import org.kiwix.kiwixmobile.core.entity.LibraryNetworkEntity
import org.kiwix.kiwixmobile.core.extensions.ActivityExtensions.hasNotificationPermission
import org.kiwix.kiwixmobile.core.extensions.ActivityExtensions.isManageExternalStoragePermissionGranted
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ import org.kiwix.kiwixmobile.core.R
import org.kiwix.kiwixmobile.core.StorageObserver
import org.kiwix.kiwixmobile.core.base.SideEffect
import org.kiwix.kiwixmobile.core.compat.CompatHelper.Companion.isWifi
import org.kiwix.kiwixmobile.core.dao.FetchDownloadDao
import org.kiwix.kiwixmobile.core.dao.DownloadRoomDao
import org.kiwix.kiwixmobile.core.dao.NewBookDao
import org.kiwix.kiwixmobile.core.dao.NewLanguagesDao
import org.kiwix.kiwixmobile.core.data.DataSource
Expand Down Expand Up @@ -81,8 +81,9 @@ import javax.inject.Inject

const val DEFAULT_PROGRESS = 0
const val MAX_PROGRESS = 100

class ZimManageViewModel @Inject constructor(
private val downloadDao: FetchDownloadDao,
private val downloadDao: DownloadRoomDao,
private val bookDao: NewBookDao,
private val languageDao: NewLanguagesDao,
private val storageObserver: StorageObserver,
Expand Down Expand Up @@ -321,10 +322,12 @@ class ZimManageViewModel @Inject constructor(
fromLocalesWithNetworkMatchesSetActiveBy(
networkLanguageCounts(booksFromNetwork), defaultLanguage()
)

booksFromNetwork.isNotEmpty() && allLanguages.isNotEmpty() ->
fromLocalesWithNetworkMatchesSetActiveBy(
networkLanguageCounts(booksFromNetwork), allLanguages
)

else -> throw RuntimeException("Impossible state")
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import eu.mhutti1.utils.storage.Kb
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers
import org.kiwix.kiwixmobile.core.dao.DownloadRoomDao
import org.kiwix.kiwixmobile.core.dao.FetchDownloadDao
import org.kiwix.kiwixmobile.core.downloader.model.DownloadModel
import org.kiwix.kiwixmobile.core.entity.LibraryNetworkEntity.Book
Expand All @@ -31,7 +32,7 @@ import org.kiwix.kiwixmobile.zimManager.libraryView.adapter.LibraryListItem
import javax.inject.Inject

class AvailableSpaceCalculator @Inject constructor(
private val downloadDao: FetchDownloadDao,
private val downloadRoomDao: DownloadRoomDao,
private val storageCalculator: StorageCalculator
) {
private var availableSpaceCalculatorDisposable: Disposable? = null
Expand All @@ -40,7 +41,7 @@ class AvailableSpaceCalculator @Inject constructor(
successAction: (LibraryListItem.BookItem) -> Unit,
failureAction: (String) -> Unit
) {
availableSpaceCalculatorDisposable = downloadDao.allDownloads()
availableSpaceCalculatorDisposable = downloadRoomDao.allDownloads()
.map { it.map(DownloadModel::bytesRemaining).sum() }
.map { bytesToBeDownloaded -> storageCalculator.availableBytes() - bytesToBeDownloaded }
.subscribeOn(Schedulers.io())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
package org.kiwix.kiwixmobile.zimManager.libraryView.adapter

import androidx.annotation.StringRes
import com.tonyodev.fetch2.Status
import org.kiwix.kiwixmobile.core.downloader.downloadManager.Status
import org.kiwix.kiwixmobile.core.downloader.model.Base64String
import org.kiwix.kiwixmobile.core.downloader.model.DownloadModel
import org.kiwix.kiwixmobile.core.downloader.model.DownloadState
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@
package org.kiwix.kiwixmobile.zimManager.libraryView.adapter

import android.view.View
import com.tonyodev.fetch2.Status
import org.kiwix.kiwixmobile.R
import org.kiwix.kiwixmobile.core.base.adapter.BaseViewHolder
import org.kiwix.kiwixmobile.core.downloader.downloadManager.Status
import org.kiwix.kiwixmobile.core.downloader.model.Base64String
import org.kiwix.kiwixmobile.core.extensions.setBitmap
import org.kiwix.kiwixmobile.core.extensions.setImageDrawableCompat
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import org.junit.jupiter.api.Test
import org.junit.jupiter.api.extension.ExtendWith
import org.kiwix.kiwixmobile.core.R
import org.kiwix.kiwixmobile.core.StorageObserver
import org.kiwix.kiwixmobile.core.dao.DownloadRoomDao
import org.kiwix.kiwixmobile.core.dao.FetchDownloadDao
import org.kiwix.kiwixmobile.core.dao.NewBookDao
import org.kiwix.kiwixmobile.core.dao.NewLanguagesDao
Expand Down Expand Up @@ -84,7 +85,7 @@ import java.util.concurrent.TimeUnit.MILLISECONDS
@ExtendWith(InstantExecutorExtension::class)
class ZimManageViewModelTest {

private val downloadDao: FetchDownloadDao = mockk()
private val downloadRoomDao: DownloadRoomDao = mockk()
private val newBookDao: NewBookDao = mockk()
private val newLanguagesDao: NewLanguagesDao = mockk()
private val storageObserver: StorageObserver = mockk()
Expand Down Expand Up @@ -127,7 +128,7 @@ class ZimManageViewModelTest {
fun init() {
clearAllMocks()
every { connectivityBroadcastReceiver.action } returns "test"
every { downloadDao.downloads() } returns downloads
every { downloadRoomDao.downloads() } returns downloads
every { newBookDao.books() } returns books
every {
storageObserver.getBooksOnFileSystem(
Expand All @@ -144,7 +145,7 @@ class ZimManageViewModelTest {
} returns networkCapabilities
every { networkCapabilities.hasTransport(TRANSPORT_WIFI) } returns true
viewModel = ZimManageViewModel(
downloadDao,
downloadRoomDao,
newBookDao,
newLanguagesDao,
storageObserver,
Expand Down
14 changes: 3 additions & 11 deletions core/objectbox-models/default.json
Original file line number Diff line number Diff line change
Expand Up @@ -339,16 +339,6 @@
"name": "totalSizeOfDownload",
"type": 6
},
{
"id": "19:3378789699620971394",
"name": "status",
"type": 5
},
{
"id": "20:6867355950440828062",
"name": "error",
"type": 5
},
{
"id": "21:5555873126720275555",
"name": "file",
Expand Down Expand Up @@ -478,7 +468,9 @@
8819082642546094709,
7233601933599801875,
4335394620556092321,
1899740026144478138
1899740026144478138,
3378789699620971394,
6867355950440828062
],
"retiredRelationUids": [],
"version": 1
Expand Down
7 changes: 6 additions & 1 deletion core/objectbox-models/default.json.bak
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@
},
{
"id": "7:7635075139296819361",
"lastPropertyId": "3:3320858395373055542",
"lastPropertyId": "4:6431198268026321201",
"name": "RecentSearchEntity",
"properties": [
{
Expand All @@ -239,6 +239,11 @@
"id": "3:3320858395373055542",
"name": "zimId",
"type": 9
},
{
"id": "4:6431198268026321201",
"name": "url",
"type": 9
}
],
"relations": []
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import io.reactivex.Flowable
import io.reactivex.functions.BiFunction
import io.reactivex.schedulers.Schedulers
import kotlinx.coroutines.runBlocking
import org.kiwix.kiwixmobile.core.dao.DownloadRoomDao
import org.kiwix.kiwixmobile.core.dao.FetchDownloadDao
import org.kiwix.kiwixmobile.core.dao.LibkiwixBookmarks
import org.kiwix.kiwixmobile.core.downloader.model.DownloadModel
Expand All @@ -33,7 +34,7 @@ import java.io.File
import javax.inject.Inject

class StorageObserver @Inject constructor(
private val downloadDao: FetchDownloadDao,
private val downloadRoomDao: DownloadRoomDao,
private val fileSearch: FileSearch,
private val zimReaderFactory: ZimFileReader.Factory,
private val libkiwixBookmarks: LibkiwixBookmarks
Expand All @@ -43,7 +44,7 @@ class StorageObserver @Inject constructor(
scanningProgressListener: ScanningProgressListener
): Flowable<List<BookOnDisk>> {
return scanFiles(scanningProgressListener)
.withLatestFrom(downloadDao.downloads(), BiFunction(::toFilesThatAreNotDownloading))
.withLatestFrom(downloadRoomDao.downloads(), BiFunction(::toFilesThatAreNotDownloading))
.map { it.mapNotNull(::convertToBookOnDisk) }
}

Expand Down
104 changes: 96 additions & 8 deletions core/src/main/java/org/kiwix/kiwixmobile/core/dao/DownloadRoomDao.kt
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,100 @@
package org.kiwix.kiwixmobile.core.dao

import androidx.room.Dao
import androidx.room.Delete
import androidx.room.Insert
import androidx.room.Query
import androidx.room.Update
import io.reactivex.Flowable
import io.reactivex.Single
import org.kiwix.kiwixmobile.core.dao.entities.DownloadRoomEntity
import org.kiwix.kiwixmobile.core.downloader.DownloadRequester
import org.kiwix.kiwixmobile.core.downloader.downloadManager.Status
import org.kiwix.kiwixmobile.core.downloader.model.DownloadModel
import org.kiwix.kiwixmobile.core.downloader.model.DownloadRequest
import org.kiwix.kiwixmobile.core.entity.LibraryNetworkEntity
import org.kiwix.kiwixmobile.core.extensions.deleteFile
import org.kiwix.kiwixmobile.core.utils.SharedPreferenceUtil
import javax.inject.Inject

// @Dao
// abstract class DownloadRoomDao @Inject constructor(
// private val newBookDao: NewBookDao,
// private val sharedPreferenceUtil: SharedPreferenceUtil
// ) {
// }
import java.io.File

@Dao
abstract class DownloadRoomDao {

@Query("SELECT * FROM DownloadRoomEntity")
abstract fun downloadRoomEntity(): Flowable<List<DownloadRoomEntity>>

@Query("SELECT * FROM DownloadRoomEntity")
abstract fun getAllDownloads(): Single<List<DownloadRoomEntity>>

fun downloads(): Flowable<List<DownloadModel>> =
downloadRoomEntity()
.distinctUntilChanged()
.doOnNext(::moveCompletedToBooksOnDiskDao)
.map { it.map(::DownloadModel) }

fun allDownloads() = getAllDownloads().map { it.map(::DownloadModel) }

private fun moveCompletedToBooksOnDiskDao(downloadEntities: List<DownloadRoomEntity>) {
downloadEntities.filter { it.status == Status.COMPLETED }
.takeIf(List<DownloadRoomEntity>::isNotEmpty)
?.let {
deleteDownloadsList(it)
// newBookDao.insert(it.map(BooksOnDiskListItem::BookOnDisk))
}
}

fun update(downloadModel: DownloadModel) {
getEntityForDownloadId(downloadModel.downloadId)?.let { downloadRoomEntity ->
downloadRoomEntity.updateWith(downloadModel)
.takeIf { updatedEntity -> updatedEntity != downloadRoomEntity }
?.let(::updateDownloadItem)
}
}

@Update
abstract fun updateDownloadItem(downloadRoomEntity: DownloadRoomEntity)

@Delete
abstract fun deleteDownloadsList(downloadRoomEntityList: List<DownloadRoomEntity>)

@Query("DELETE FROM DownloadRoomEntity WHERE downloadId=:downloadId")
abstract fun deleteDownloadByDownloadId(downloadId: Long)

@Query("SELECT * FROM DownloadRoomEntity WHERE downloadId=:downloadId")
abstract fun getEntityForDownloadId(downloadId: Long): DownloadRoomEntity?

@Query("SELECT COUNT() FROM DownloadRoomEntity WHERE bookId = :bookId")
abstract fun count(bookId: String): Int

@Insert
abstract fun saveDownload(downloadRoomEntity: DownloadRoomEntity)

fun delete(downloadId: Long) {
// remove the previous file from storage since we have cancelled the download.
getEntityForDownloadId(downloadId)?.file?.let {
File(it).deleteFile()
}
deleteDownloadByDownloadId(downloadId)
}

fun addIfDoesNotExist(
url: String,
book: LibraryNetworkEntity.Book,
downloadRequester: DownloadRequester,
sharedPreferenceUtil: SharedPreferenceUtil
) {
if (doesNotAlreadyExist(book)) {
val downloadRequest = DownloadRequest(url, book.title)
saveDownload(
DownloadRoomEntity(
downloadRequester.enqueue(downloadRequest),
book = book,
file = downloadRequest.getDestinationFile(sharedPreferenceUtil).path
)
)
}
}

private fun doesNotAlreadyExist(book: LibraryNetworkEntity.Book) =
count(book.id) == 0
}
Loading

0 comments on commit 1318a42

Please sign in to comment.