mirror of
https://github.com/kiwix/kiwix-android.git
synced 2025-09-21 19:41:38 -04:00
Downloads now fully support states from a Query. Language handling improved. Guava & apache commons removed
This commit is contained in:
parent
f318da929c
commit
287d816304
@ -51,7 +51,7 @@ dependencies {
|
||||
implementation "com.android.support:cardview-v7:$supportLibraryVersion"
|
||||
implementation 'com.android.support:multidex:1.0.2'
|
||||
|
||||
compile 'com.android.support.constraint:constraint-layout:1.0.2'
|
||||
implementation 'com.android.support.constraint:constraint-layout:1.0.2'
|
||||
|
||||
androidTestImplementation 'com.android.support.test.uiautomator:uiautomator-v18:2.1.3'
|
||||
|
||||
@ -77,9 +77,6 @@ dependencies {
|
||||
androidTestImplementation 'com.android.support.test:runner:1.0.1'
|
||||
androidTestImplementation 'com.android.support.test:rules:1.0.1'
|
||||
|
||||
// Guava
|
||||
implementation group: 'com.google.guava', name: 'guava', version: '21.0'
|
||||
|
||||
// Dagger
|
||||
compileOnly "javax.annotation:javax.annotation-api:$javaxAnnotationVersion"
|
||||
androidTestCompileOnly "javax.annotation:javax.annotation-api:$javaxAnnotationVersion"
|
||||
@ -94,9 +91,6 @@ dependencies {
|
||||
implementation 'com.yahoo.squidb:squidb-annotations:2.0.0'
|
||||
annotationProcessor 'com.yahoo.squidb:squidb-processor:2.0.0'
|
||||
|
||||
// Apache
|
||||
implementation 'commons-io:commons-io:2.5'
|
||||
|
||||
// Square
|
||||
implementation "com.squareup.okhttp3:okhttp:$okHttpVersion"
|
||||
implementation "com.squareup.okhttp3:logging-interceptor:$okHttpVersion"
|
||||
|
@ -75,6 +75,11 @@ public class KiwixApplication extends MultiDexApplication implements HasActivity
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
if (LeakCanary.isInAnalyzerProcess(this)) {
|
||||
// This process is dedicated to LeakCanary for heap analysis.
|
||||
// You should not init your app in this process.
|
||||
return;
|
||||
}
|
||||
if (isExternalStorageWritable()) {
|
||||
File appDirectory = new File(Environment.getExternalStorageDirectory() + "/Kiwix");
|
||||
logFile = new File(appDirectory, "logcat.txt");
|
||||
@ -105,13 +110,7 @@ public class KiwixApplication extends MultiDexApplication implements HasActivity
|
||||
}
|
||||
|
||||
Log.d("KIWIX", "Started KiwixApplication");
|
||||
|
||||
applicationComponent.inject(this);
|
||||
if (LeakCanary.isInAnalyzerProcess(this)) {
|
||||
// This process is dedicated to LeakCanary for heap analysis.
|
||||
// You should not init your app in this process.
|
||||
return;
|
||||
}
|
||||
LeakCanary.install(this);
|
||||
}
|
||||
|
||||
|
@ -21,7 +21,6 @@ package org.kiwix.kiwixmobile.database;
|
||||
|
||||
import com.yahoo.squidb.data.SquidCursor;
|
||||
import com.yahoo.squidb.sql.Query;
|
||||
import com.yahoo.squidb.sql.Table;
|
||||
import io.reactivex.Flowable;
|
||||
import io.reactivex.processors.BehaviorProcessor;
|
||||
import java.util.ArrayList;
|
||||
@ -34,8 +33,6 @@ import org.kiwix.kiwixmobile.zim_manager.library_view.adapter.Language;
|
||||
|
||||
public class NetworkLanguageDao extends BaseDao {
|
||||
|
||||
private final BehaviorProcessor<List<Language>> activeLanguageProcessor =
|
||||
BehaviorProcessor.create();
|
||||
private final BehaviorProcessor<List<Language>> allLanguageProcessor = BehaviorProcessor.create();
|
||||
|
||||
@Inject
|
||||
@ -45,14 +42,9 @@ public class NetworkLanguageDao extends BaseDao {
|
||||
|
||||
@Override
|
||||
protected void onUpdateToTable() {
|
||||
activeLanguageProcessor.onNext(fetchActiveLanguages());
|
||||
allLanguageProcessor.onNext(fetchAllLanguages());
|
||||
}
|
||||
|
||||
public Flowable<List<Language>> activeLanguages() {
|
||||
return activeLanguageProcessor;
|
||||
}
|
||||
|
||||
public Flowable<List<Language>> allLanguages() {
|
||||
return allLanguageProcessor;
|
||||
}
|
||||
@ -61,10 +53,6 @@ public class NetworkLanguageDao extends BaseDao {
|
||||
return fetchWith(Query.select());
|
||||
}
|
||||
|
||||
public List<Language> fetchActiveLanguages() {
|
||||
return fetchWith(Query.select().where(NetworkLanguageDatabaseEntity.ENABLED.eq(true)));
|
||||
}
|
||||
|
||||
@NotNull private List<Language> fetchWith(Query query) {
|
||||
ArrayList<Language> result = new ArrayList<>();
|
||||
final NetworkLanguageDatabaseEntity databaseEntity =
|
||||
|
@ -17,15 +17,24 @@
|
||||
*/
|
||||
package org.kiwix.kiwixmobile.downloader
|
||||
|
||||
import android.content.Context
|
||||
import android.support.v7.widget.RecyclerView
|
||||
import android.view.View
|
||||
import kotlinx.android.extensions.LayoutContainer
|
||||
import kotlinx.android.synthetic.main.download_item.description
|
||||
import kotlinx.android.synthetic.main.download_item.downloadProgress
|
||||
import kotlinx.android.synthetic.main.download_item.downloadState
|
||||
import kotlinx.android.synthetic.main.download_item.favicon
|
||||
import kotlinx.android.synthetic.main.download_item.stop
|
||||
import kotlinx.android.synthetic.main.download_item.title
|
||||
import org.kiwix.kiwixmobile.downloader.model.DownloadItem
|
||||
import org.kiwix.kiwixmobile.downloader.model.DownloadState
|
||||
import org.kiwix.kiwixmobile.downloader.model.DownloadState.Failed
|
||||
import org.kiwix.kiwixmobile.downloader.model.DownloadState.Paused
|
||||
import org.kiwix.kiwixmobile.downloader.model.DownloadState.Pending
|
||||
import org.kiwix.kiwixmobile.downloader.model.DownloadState.Running
|
||||
import org.kiwix.kiwixmobile.downloader.model.DownloadState.Successful
|
||||
import org.kiwix.kiwixmobile.downloader.model.FailureReason.Rfc2616HttpCode
|
||||
import org.kiwix.kiwixmobile.extensions.setBitmap
|
||||
|
||||
class DownloadViewHolder(override val containerView: View) : RecyclerView.ViewHolder(containerView),
|
||||
@ -41,5 +50,36 @@ class DownloadViewHolder(override val containerView: View) : RecyclerView.ViewHo
|
||||
stop.setOnClickListener {
|
||||
itemClickListener.invoke(downloadItem)
|
||||
}
|
||||
downloadState.text = toReadableState(
|
||||
downloadItem.downloadState, containerView.context
|
||||
)
|
||||
}
|
||||
|
||||
private fun toReadableState(
|
||||
downloadState: DownloadState,
|
||||
context: Context
|
||||
) = when (downloadState) {
|
||||
is Paused -> context.getString(
|
||||
downloadState.stringId,
|
||||
context.getString(downloadState.reason.stringId)
|
||||
)
|
||||
is Failed -> context.getString(
|
||||
downloadState.stringId,
|
||||
getTemplateString(downloadState, context)
|
||||
)
|
||||
Pending,
|
||||
Running,
|
||||
Successful -> context.getString(downloadState.stringId)
|
||||
}
|
||||
|
||||
private fun getTemplateString(
|
||||
downloadState: Failed,
|
||||
context: Context
|
||||
) = when (downloadState.reason) {
|
||||
is Rfc2616HttpCode -> context.getString(
|
||||
downloadState.reason.stringId,
|
||||
downloadState.reason.code
|
||||
)
|
||||
else -> context.getString(downloadState.reason.stringId)
|
||||
}
|
||||
}
|
@ -24,8 +24,7 @@ data class DownloadItem(
|
||||
val description: String,
|
||||
val bytesDownloaded: Long,
|
||||
val totalSizeBytes: Long,
|
||||
val downloadState: DownloadState,
|
||||
val reason: String
|
||||
val downloadState: DownloadState
|
||||
) {
|
||||
val progress get() = ((bytesDownloaded.toFloat() / totalSizeBytes) * 100).toInt()
|
||||
|
||||
@ -36,7 +35,6 @@ data class DownloadItem(
|
||||
downloadStatus.description,
|
||||
downloadStatus.bytesDownloadedSoFar,
|
||||
downloadStatus.totalSizeBytes,
|
||||
downloadStatus.state,
|
||||
downloadStatus.reason
|
||||
downloadStatus.state
|
||||
)
|
||||
}
|
@ -29,6 +29,19 @@ import android.app.DownloadManager.COLUMN_STATUS
|
||||
import android.app.DownloadManager.COLUMN_TITLE
|
||||
import android.app.DownloadManager.COLUMN_TOTAL_SIZE_BYTES
|
||||
import android.app.DownloadManager.COLUMN_URI
|
||||
import android.app.DownloadManager.ERROR_CANNOT_RESUME
|
||||
import android.app.DownloadManager.ERROR_DEVICE_NOT_FOUND
|
||||
import android.app.DownloadManager.ERROR_FILE_ALREADY_EXISTS
|
||||
import android.app.DownloadManager.ERROR_FILE_ERROR
|
||||
import android.app.DownloadManager.ERROR_HTTP_DATA_ERROR
|
||||
import android.app.DownloadManager.ERROR_INSUFFICIENT_SPACE
|
||||
import android.app.DownloadManager.ERROR_TOO_MANY_REDIRECTS
|
||||
import android.app.DownloadManager.ERROR_UNHANDLED_HTTP_CODE
|
||||
import android.app.DownloadManager.ERROR_UNKNOWN
|
||||
import android.app.DownloadManager.PAUSED_QUEUED_FOR_WIFI
|
||||
import android.app.DownloadManager.PAUSED_UNKNOWN
|
||||
import android.app.DownloadManager.PAUSED_WAITING_FOR_NETWORK
|
||||
import android.app.DownloadManager.PAUSED_WAITING_TO_RETRY
|
||||
import android.app.DownloadManager.STATUS_FAILED
|
||||
import android.app.DownloadManager.STATUS_PAUSED
|
||||
import android.app.DownloadManager.STATUS_PENDING
|
||||
@ -36,6 +49,7 @@ import android.app.DownloadManager.STATUS_RUNNING
|
||||
import android.app.DownloadManager.STATUS_SUCCESSFUL
|
||||
import android.database.Cursor
|
||||
import android.net.Uri
|
||||
import org.kiwix.kiwixmobile.R
|
||||
import org.kiwix.kiwixmobile.extensions.get
|
||||
import org.kiwix.kiwixmobile.library.entity.LibraryNetworkEntity.Book
|
||||
import java.io.File
|
||||
@ -45,7 +59,6 @@ class DownloadStatus(
|
||||
val title: String,
|
||||
val description: String,
|
||||
val state: DownloadState,
|
||||
val reason: String,
|
||||
val bytesDownloadedSoFar: Long,
|
||||
val totalSizeBytes: Long,
|
||||
val lastModified: String,
|
||||
@ -66,8 +79,7 @@ class DownloadStatus(
|
||||
cursor[COLUMN_ID],
|
||||
cursor[COLUMN_TITLE],
|
||||
cursor[COLUMN_DESCRIPTION],
|
||||
DownloadState.from(cursor[COLUMN_STATUS]),
|
||||
cursor[COLUMN_REASON],
|
||||
DownloadState.from(cursor[COLUMN_STATUS], cursor[COLUMN_REASON]),
|
||||
cursor[COLUMN_BYTES_DOWNLOADED_SO_FAR],
|
||||
cursor[COLUMN_TOTAL_SIZE_BYTES],
|
||||
cursor[COLUMN_LAST_MODIFIED_TIMESTAMP],
|
||||
@ -79,11 +91,14 @@ class DownloadStatus(
|
||||
)
|
||||
}
|
||||
|
||||
sealed class DownloadState {
|
||||
sealed class DownloadState(val stringId: Int) {
|
||||
companion object {
|
||||
fun from(status: Int) = when (status) {
|
||||
STATUS_FAILED -> Failed
|
||||
STATUS_PAUSED -> Paused
|
||||
fun from(
|
||||
status: Int,
|
||||
reason: Int
|
||||
) = when (status) {
|
||||
STATUS_PAUSED -> Paused(PausedReason.from(reason))
|
||||
STATUS_FAILED -> Failed(FailureReason.from(reason))
|
||||
STATUS_PENDING -> Pending
|
||||
STATUS_RUNNING -> Running
|
||||
STATUS_SUCCESSFUL -> Successful
|
||||
@ -91,13 +106,59 @@ sealed class DownloadState {
|
||||
}
|
||||
}
|
||||
|
||||
object Paused : DownloadState()
|
||||
object Failed : DownloadState()
|
||||
object Pending : DownloadState()
|
||||
object Running : DownloadState()
|
||||
object Successful : DownloadState()
|
||||
data class Paused(val reason: PausedReason) : DownloadState(R.string.paused_state)
|
||||
data class Failed(val reason: FailureReason) : DownloadState(R.string.failed_state)
|
||||
object Pending : DownloadState(R.string.pending_state)
|
||||
object Running : DownloadState(R.string.running_state)
|
||||
object Successful : DownloadState(R.string.successful_state)
|
||||
|
||||
override fun toString(): String {
|
||||
return javaClass.simpleName
|
||||
}
|
||||
}
|
||||
|
||||
sealed class FailureReason(val stringId: Int) {
|
||||
companion object {
|
||||
fun from(reason: Int) = when (reason) {
|
||||
in 100..505 -> Rfc2616HttpCode(reason)
|
||||
ERROR_CANNOT_RESUME -> CannotResume
|
||||
ERROR_DEVICE_NOT_FOUND -> StorageNotFound
|
||||
ERROR_FILE_ALREADY_EXISTS -> FileAlreadyExists
|
||||
ERROR_FILE_ERROR -> UnknownFileError
|
||||
ERROR_HTTP_DATA_ERROR -> HttpError
|
||||
ERROR_INSUFFICIENT_SPACE -> InsufficientSpace
|
||||
ERROR_TOO_MANY_REDIRECTS -> TooManyRedirects
|
||||
ERROR_UNHANDLED_HTTP_CODE -> UnhandledHttpCode
|
||||
ERROR_UNKNOWN -> Unknown
|
||||
else -> Unknown
|
||||
}
|
||||
}
|
||||
|
||||
object CannotResume : FailureReason(R.string.failed_cannot_resume)
|
||||
object StorageNotFound : FailureReason(R.string.failed_storage_not_found)
|
||||
object FileAlreadyExists : FailureReason(R.string.failed_file_already_exists)
|
||||
object UnknownFileError : FailureReason(R.string.failed_unknown_file_error)
|
||||
object HttpError : FailureReason(R.string.failed_http_error)
|
||||
object InsufficientSpace : FailureReason(R.string.failed_insufficient_space)
|
||||
object TooManyRedirects : FailureReason(R.string.failed_too_many_redirects)
|
||||
object UnhandledHttpCode : FailureReason(R.string.failed_unhandled_http_code)
|
||||
object Unknown : FailureReason(R.string.failed_unknown)
|
||||
data class Rfc2616HttpCode(val code: Int) : FailureReason(R.string.failed_http_code)
|
||||
}
|
||||
|
||||
sealed class PausedReason(val stringId: Int) {
|
||||
companion object {
|
||||
fun from(reason: Int) = when (reason) {
|
||||
PAUSED_QUEUED_FOR_WIFI -> WaitingForWifi
|
||||
PAUSED_WAITING_FOR_NETWORK -> WaitingForConnectivity
|
||||
PAUSED_WAITING_TO_RETRY -> WaitingForRetry
|
||||
PAUSED_UNKNOWN -> Unknown
|
||||
else -> Unknown
|
||||
}
|
||||
}
|
||||
|
||||
object WaitingForWifi : PausedReason(R.string.paused_wifi)
|
||||
object WaitingForConnectivity : PausedReason(R.string.paused_connectivity)
|
||||
object WaitingForRetry : PausedReason(R.string.paused_retry)
|
||||
object Unknown : PausedReason(R.string.paused_unknown)
|
||||
}
|
@ -29,7 +29,6 @@ import io.reactivex.functions.Function5
|
||||
import io.reactivex.processors.BehaviorProcessor
|
||||
import io.reactivex.processors.PublishProcessor
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import org.kiwix.kiwixmobile.KiwixApplication
|
||||
import org.kiwix.kiwixmobile.R
|
||||
import org.kiwix.kiwixmobile.database.BookDao
|
||||
import org.kiwix.kiwixmobile.database.DownloadDao
|
||||
@ -45,7 +44,6 @@ import org.kiwix.kiwixmobile.library.entity.LibraryNetworkEntity
|
||||
import org.kiwix.kiwixmobile.library.entity.LibraryNetworkEntity.Book
|
||||
import org.kiwix.kiwixmobile.network.KiwixService
|
||||
import org.kiwix.kiwixmobile.utils.BookUtils
|
||||
import org.kiwix.kiwixmobile.utils.NetworkUtils
|
||||
import org.kiwix.kiwixmobile.zim_manager.fileselect_view.StorageObserver
|
||||
import org.kiwix.kiwixmobile.zim_manager.library_view.adapter.Language
|
||||
import org.kiwix.kiwixmobile.zim_manager.library_view.adapter.LibraryListItem
|
||||
@ -53,6 +51,7 @@ import org.kiwix.kiwixmobile.zim_manager.library_view.adapter.LibraryListItem.Bo
|
||||
import org.kiwix.kiwixmobile.zim_manager.library_view.adapter.LibraryListItem.DividerItem
|
||||
import java.util.LinkedList
|
||||
import java.util.Locale
|
||||
import java.util.concurrent.TimeUnit.MILLISECONDS
|
||||
import java.util.concurrent.TimeUnit.SECONDS
|
||||
import javax.inject.Inject
|
||||
|
||||
@ -105,7 +104,7 @@ class ZimManageViewModel @Inject constructor(
|
||||
updateBookItems(booksFromDao),
|
||||
checkFileSystemForBooksOnRequest(booksFromDao),
|
||||
updateLibraryItems(booksFromDao, downloads, library),
|
||||
updateActiveLanguages(library),
|
||||
updateLanguagesInDao(library),
|
||||
updateNetworkStates(),
|
||||
updateLanguageItemsForDialog()
|
||||
)
|
||||
@ -127,14 +126,16 @@ class ZimManageViewModel @Inject constructor(
|
||||
private fun libraryFromNetwork() =
|
||||
Flowable.combineLatest(
|
||||
requestDownloadLibrary,
|
||||
connectivityBroadcastReceiver.networkStates.distinctUntilChanged().filter(NetworkState.CONNECTED::equals),
|
||||
connectivityBroadcastReceiver.networkStates.distinctUntilChanged().filter(
|
||||
NetworkState.CONNECTED::equals
|
||||
),
|
||||
BiFunction<Unit, NetworkState, Unit> { _, _ -> Unit }
|
||||
)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.doOnNext { libraryListIsRefreshing.postValue(true) }
|
||||
.switchMap { kiwixService.library }
|
||||
.onErrorResumeNext(Flowable.just(LibraryNetworkEntity().apply { book = LinkedList() }))
|
||||
.doOnError(Throwable::printStackTrace)
|
||||
.onErrorResumeNext(Flowable.just(LibraryNetworkEntity().apply { book = LinkedList() }))
|
||||
|
||||
private fun updateLibraryItems(
|
||||
booksFromDao: Flowable<List<Book>>,
|
||||
@ -143,7 +144,9 @@ class ZimManageViewModel @Inject constructor(
|
||||
) = Flowable.combineLatest(
|
||||
booksFromDao,
|
||||
downloads,
|
||||
languageDao.activeLanguages().filter { it.isNotEmpty() },
|
||||
languageDao.allLanguages()
|
||||
.debounce(100, MILLISECONDS)
|
||||
.filter { it.isNotEmpty() },
|
||||
library,
|
||||
requestFiltering
|
||||
.doOnNext { libraryListIsRefreshing.postValue(true) }
|
||||
@ -158,11 +161,13 @@ class ZimManageViewModel @Inject constructor(
|
||||
Throwable::printStackTrace
|
||||
)
|
||||
|
||||
private fun updateActiveLanguages(library: Flowable<LibraryNetworkEntity>) = library
|
||||
private fun updateLanguagesInDao(
|
||||
library: Flowable<LibraryNetworkEntity>
|
||||
) = library
|
||||
.subscribeOn(Schedulers.io())
|
||||
.map { it.books }
|
||||
.withLatestFrom(
|
||||
languageDao.activeLanguages(),
|
||||
languageDao.allLanguages(),
|
||||
BiFunction(this::combineToLanguageList)
|
||||
)
|
||||
.subscribe(
|
||||
@ -172,47 +177,68 @@ class ZimManageViewModel @Inject constructor(
|
||||
|
||||
private fun combineToLanguageList(
|
||||
booksFromNetwork: List<Book>,
|
||||
activeLanguages: List<Language>
|
||||
allLanguages: List<Language>
|
||||
): List<Language> {
|
||||
val languageCounts = booksFromNetwork.mapNotNull { it.language }
|
||||
val networkLanguageCounts = booksFromNetwork.mapNotNull { it.language }
|
||||
.fold(
|
||||
mutableMapOf<String, Int>(),
|
||||
{ acc, language ->
|
||||
acc[language] = acc.getOrElse(language, { 0 }) + 1
|
||||
acc
|
||||
}
|
||||
{ acc, language -> acc.increment(language) }
|
||||
)
|
||||
return when {
|
||||
booksFromNetwork.isEmpty() && allLanguages.isEmpty() -> defaultLanguage()
|
||||
booksFromNetwork.isEmpty() && allLanguages.isNotEmpty() -> allLanguages
|
||||
booksFromNetwork.isNotEmpty() && allLanguages.isEmpty() ->
|
||||
fromLocalesWithNetworkMatchesSetActiveBy(networkLanguageCounts, defaultLanguage())
|
||||
booksFromNetwork.isNotEmpty() && allLanguages.isNotEmpty() ->
|
||||
fromLocalesWithNetworkMatchesSetActiveBy(networkLanguageCounts, allLanguages)
|
||||
else -> throw RuntimeException("Impossible state")
|
||||
}
|
||||
}
|
||||
|
||||
private fun <K> MutableMap<K, Int>.increment(key: K) =
|
||||
apply { set(key, getOrElse(key, { 0 }) + 1) }
|
||||
|
||||
private fun fromLocalesWithNetworkMatchesSetActiveBy(
|
||||
networkLanguageCounts: MutableMap<String, Int>,
|
||||
listToActivateBy: List<Language>
|
||||
): List<Language> {
|
||||
return Locale.getISOLanguages()
|
||||
.map { Locale(it) }
|
||||
.filter { languageCounts.containsKey(it.isO3Language) }
|
||||
.filter { networkLanguageCounts.containsKey(it.isO3Language) }
|
||||
.map { locale ->
|
||||
Language(
|
||||
locale.isO3Language,
|
||||
languageWasPreviouslyActiveOrIsPrimaryLanguage(activeLanguages, locale),
|
||||
languageCounts.getOrElse(locale.isO3Language, { 0 })
|
||||
languageIsActive(listToActivateBy, locale),
|
||||
networkLanguageCounts.getOrElse(locale.isO3Language, { 0 })
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun languageWasPreviouslyActiveOrIsPrimaryLanguage(
|
||||
activeLanguages: List<Language>,
|
||||
locale: Locale
|
||||
) = activeLanguages.firstOrNull { it.languageCode == locale.isO3Language }?.let { true }
|
||||
?: isPrimaryLocale(locale)
|
||||
private fun defaultLanguage() =
|
||||
listOf(
|
||||
Language(
|
||||
context.resources.configuration.locale.isO3Language,
|
||||
true,
|
||||
1
|
||||
)
|
||||
)
|
||||
|
||||
private fun isPrimaryLocale(locale: Locale) =
|
||||
context.resources.configuration.locale.isO3Language == locale.isO3Language
|
||||
private fun languageIsActive(
|
||||
allLanguages: List<Language>,
|
||||
locale: Locale
|
||||
) = allLanguages.firstOrNull { it.languageCode == locale.isO3Language }?.active == true
|
||||
|
||||
private fun combineLibrarySources(
|
||||
booksOnFileSystem: List<Book>,
|
||||
activeDownloads: List<DownloadModel>,
|
||||
activeLanguages: List<Language>,
|
||||
allLanguages: List<Language>,
|
||||
libraryNetworkEntity: LibraryNetworkEntity,
|
||||
filter: String
|
||||
): List<LibraryListItem> {
|
||||
val downloadedBooksIds = booksOnFileSystem.map { it.id }
|
||||
val downloadingBookIds = activeDownloads.map { it.book.id }
|
||||
val activeLanguageCodes = activeLanguages.map { it.languageCode }
|
||||
val activeLanguageCodes = allLanguages.filter(Language::active)
|
||||
.map { it.languageCode }
|
||||
val booksUnfilteredByLanguage =
|
||||
applyUserFilter(
|
||||
libraryNetworkEntity.books
|
||||
@ -340,4 +366,6 @@ class ZimManageViewModel @Inject constructor(
|
||||
.map(downloader::queryStatus)
|
||||
.distinctUntilChanged()
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -58,12 +58,12 @@
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/time_remaining"
|
||||
android:id="@+id/downloadState"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="end"
|
||||
android:layout_gravity="start"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
tools:text="3hrs 45 mins"
|
||||
tools:text="In Progress"
|
||||
/>
|
||||
</LinearLayout>
|
||||
|
||||
|
@ -181,4 +181,23 @@
|
||||
<string name="crash_checkbox_device">Device Details</string>
|
||||
<string name="crash_button_confirm">SEND DETAILS</string>
|
||||
<string name="crash_button_decline">NO THANKS</string>
|
||||
<string name="pending_state">Pending</string>
|
||||
<string name="running_state">In Progress</string>
|
||||
<string name="successful_state">Complete</string>
|
||||
<string name="paused_state">Paused: %s</string>
|
||||
<string name="failed_state">Failed: %s</string>
|
||||
<string name="paused_wifi">Waiting for Wifi</string>
|
||||
<string name="paused_connectivity">Waiting to connect to a network</string>
|
||||
<string name="paused_retry">Waiting to retry</string>
|
||||
<string name="paused_unknown">Unknown</string>
|
||||
<string name="failed_cannot_resume">Cannot resume due to unknown reason</string>
|
||||
<string name="failed_storage_not_found">Could not find storage</string>
|
||||
<string name="failed_file_already_exists">File already exists</string>
|
||||
<string name="failed_unknown_file_error">Unknown file system error</string>
|
||||
<string name="failed_http_error">HTTP data error</string>
|
||||
<string name="failed_insufficient_space">Not enough space on storage</string>
|
||||
<string name="failed_too_many_redirects">Too many redirects</string>
|
||||
<string name="failed_unhandled_http_code">Unknown HTTP code received</string>
|
||||
<string name="failed_unknown">Unknown</string>
|
||||
<string name="failed_http_code">HTTP code %s</string>
|
||||
</resources>
|
||||
|
Loading…
x
Reference in New Issue
Block a user