diff --git a/app/src/main/java/org/kiwix/kiwixmobile/KiwixViewModelFactory.java b/app/src/main/java/org/kiwix/kiwixmobile/KiwixViewModelFactory.java index 6f7871ca8..5a3bca9f1 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/KiwixViewModelFactory.java +++ b/app/src/main/java/org/kiwix/kiwixmobile/KiwixViewModelFactory.java @@ -19,40 +19,17 @@ package org.kiwix.kiwixmobile; import androidx.lifecycle.ViewModel; -import androidx.lifecycle.ViewModelProvider; import java.util.Map; import javax.inject.Inject; import javax.inject.Provider; +import org.kiwix.kiwixmobile.core.ViewModelFactory; import org.kiwix.kiwixmobile.di.KiwixScope; @KiwixScope -public class KiwixViewModelFactory implements ViewModelProvider.Factory { - private final Map, Provider> creators; +public class KiwixViewModelFactory extends ViewModelFactory { @Inject public KiwixViewModelFactory(Map, Provider> creators) { - this.creators = creators; - } - - @SuppressWarnings("unchecked") - @Override - public T create(Class modelClass) { - Provider creator = creators.get(modelClass); - if (creator == null) { - for (Map.Entry, Provider> entry : creators.entrySet()) { - if (modelClass.isAssignableFrom(entry.getKey())) { - creator = entry.getValue(); - break; - } - } - } - if (creator == null) { - throw new IllegalArgumentException("unknown model class " + modelClass); - } - try { - return (T) creator.get(); - } catch (Exception e) { - throw new RuntimeException(e); - } + super(creators); } } diff --git a/app/src/main/java/org/kiwix/kiwixmobile/language/viewmodel/LanguageViewModel.kt b/app/src/main/java/org/kiwix/kiwixmobile/language/viewmodel/LanguageViewModel.kt index 1f6b7ef7e..5e03c93fc 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/language/viewmodel/LanguageViewModel.kt +++ b/app/src/main/java/org/kiwix/kiwixmobile/language/viewmodel/LanguageViewModel.kt @@ -22,6 +22,7 @@ import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import io.reactivex.disposables.CompositeDisposable import io.reactivex.processors.PublishProcessor +import org.kiwix.kiwixmobile.core.base.SideEffect import org.kiwix.kiwixmobile.core.dao.NewLanguagesDao import org.kiwix.kiwixmobile.language.adapter.LanguageListItem.LanguageItem import org.kiwix.kiwixmobile.language.viewmodel.Action.Filter @@ -31,7 +32,6 @@ import org.kiwix.kiwixmobile.language.viewmodel.Action.UpdateLanguages import org.kiwix.kiwixmobile.language.viewmodel.State.Content import org.kiwix.kiwixmobile.language.viewmodel.State.Loading import org.kiwix.kiwixmobile.language.viewmodel.State.Saving -import org.kiwix.kiwixmobile.zim_manager.fileselect_view.effects.SideEffect import javax.inject.Inject class LanguageViewModel @Inject constructor( diff --git a/app/src/main/java/org/kiwix/kiwixmobile/language/viewmodel/SaveLanguagesAndFinish.kt b/app/src/main/java/org/kiwix/kiwixmobile/language/viewmodel/SaveLanguagesAndFinish.kt index 83f50778d..6e308ad24 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/language/viewmodel/SaveLanguagesAndFinish.kt +++ b/app/src/main/java/org/kiwix/kiwixmobile/language/viewmodel/SaveLanguagesAndFinish.kt @@ -22,7 +22,7 @@ import io.reactivex.Flowable import io.reactivex.schedulers.Schedulers import org.kiwix.kiwixmobile.core.dao.NewLanguagesDao import org.kiwix.kiwixmobile.core.zim_manager.Language -import org.kiwix.kiwixmobile.zim_manager.fileselect_view.effects.SideEffect +import org.kiwix.kiwixmobile.core.base.SideEffect data class SaveLanguagesAndFinish( val languages: List, diff --git a/app/src/main/java/org/kiwix/kiwixmobile/zim_manager/ZimManageViewModel.kt b/app/src/main/java/org/kiwix/kiwixmobile/zim_manager/ZimManageViewModel.kt index 667f4ee10..a65470a50 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/zim_manager/ZimManageViewModel.kt +++ b/app/src/main/java/org/kiwix/kiwixmobile/zim_manager/ZimManageViewModel.kt @@ -66,7 +66,7 @@ import org.kiwix.kiwixmobile.zim_manager.fileselect_view.effects.DeleteFiles import org.kiwix.kiwixmobile.zim_manager.fileselect_view.effects.None import org.kiwix.kiwixmobile.zim_manager.fileselect_view.effects.OpenFile import org.kiwix.kiwixmobile.zim_manager.fileselect_view.effects.ShareFiles -import org.kiwix.kiwixmobile.zim_manager.fileselect_view.effects.SideEffect +import org.kiwix.kiwixmobile.core.base.SideEffect import org.kiwix.kiwixmobile.zim_manager.fileselect_view.effects.StartMultiSelection import org.kiwix.kiwixmobile.zim_manager.library_view.adapter.LibraryListItem import org.kiwix.kiwixmobile.zim_manager.library_view.adapter.LibraryListItem.BookItem diff --git a/app/src/main/java/org/kiwix/kiwixmobile/zim_manager/download_view/DownloadViewHolder.kt b/app/src/main/java/org/kiwix/kiwixmobile/zim_manager/download_view/DownloadViewHolder.kt index f765aeefe..6235838c5 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/zim_manager/download_view/DownloadViewHolder.kt +++ b/app/src/main/java/org/kiwix/kiwixmobile/zim_manager/download_view/DownloadViewHolder.kt @@ -17,7 +17,6 @@ */ package org.kiwix.kiwixmobile.zim_manager.download_view -import android.content.Context import android.view.View import androidx.recyclerview.widget.RecyclerView import kotlinx.android.extensions.LayoutContainer @@ -29,12 +28,6 @@ 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.core.downloader.model.DownloadItem -import org.kiwix.kiwixmobile.core.downloader.model.DownloadState -import org.kiwix.kiwixmobile.core.downloader.model.DownloadState.Failed -import org.kiwix.kiwixmobile.core.downloader.model.DownloadState.Paused -import org.kiwix.kiwixmobile.core.downloader.model.DownloadState.Pending -import org.kiwix.kiwixmobile.core.downloader.model.DownloadState.Running -import org.kiwix.kiwixmobile.core.downloader.model.DownloadState.Successful import org.kiwix.kiwixmobile.core.extensions.setBitmap class DownloadViewHolder(override val containerView: View) : RecyclerView.ViewHolder(containerView), @@ -50,21 +43,7 @@ class DownloadViewHolder(override val containerView: View) : RecyclerView.ViewHo stop.setOnClickListener { itemClickListener.invoke(downloadItem) } - downloadState.text = toReadableState(downloadItem.downloadState, containerView.context) - eta.text = downloadItem.eta.takeIf { it.seconds > 0L }?.toHumanReadableTime() ?: "" - } - - private fun toReadableState( - downloadState: DownloadState, - context: Context - ) = when (downloadState) { - is Failed -> context.getString( - downloadState.stringId, - downloadState.reason.name - ) - Pending, - Running, - Paused, - Successful -> context.getString(downloadState.stringId) + downloadState.text = downloadItem.downloadState.toReadableState(containerView.context) + eta.text = downloadItem.readableEta } } diff --git a/app/src/main/java/org/kiwix/kiwixmobile/zim_manager/fileselect_view/effects/DeleteFiles.kt b/app/src/main/java/org/kiwix/kiwixmobile/zim_manager/fileselect_view/effects/DeleteFiles.kt index 0ac58f9dc..fcb8c7b65 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/zim_manager/fileselect_view/effects/DeleteFiles.kt +++ b/app/src/main/java/org/kiwix/kiwixmobile/zim_manager/fileselect_view/effects/DeleteFiles.kt @@ -20,6 +20,7 @@ package org.kiwix.kiwixmobile.zim_manager.fileselect_view.effects import android.app.Activity import org.kiwix.kiwixmobile.R +import org.kiwix.kiwixmobile.core.base.SideEffect import org.kiwix.kiwixmobile.core.dao.NewBookDao import org.kiwix.kiwixmobile.core.extensions.toast import org.kiwix.kiwixmobile.core.reader.ZimReaderContainer diff --git a/app/src/main/java/org/kiwix/kiwixmobile/zim_manager/fileselect_view/effects/None.kt b/app/src/main/java/org/kiwix/kiwixmobile/zim_manager/fileselect_view/effects/None.kt index 81b3e34af..db25051ae 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/zim_manager/fileselect_view/effects/None.kt +++ b/app/src/main/java/org/kiwix/kiwixmobile/zim_manager/fileselect_view/effects/None.kt @@ -19,6 +19,7 @@ package org.kiwix.kiwixmobile.zim_manager.fileselect_view.effects import android.app.Activity +import org.kiwix.kiwixmobile.core.base.SideEffect object None : SideEffect { override fun invokeWith(activity: Activity) { diff --git a/app/src/main/java/org/kiwix/kiwixmobile/zim_manager/fileselect_view/effects/OpenFile.kt b/app/src/main/java/org/kiwix/kiwixmobile/zim_manager/fileselect_view/effects/OpenFile.kt index b977bb9c4..6c2f8dcb0 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/zim_manager/fileselect_view/effects/OpenFile.kt +++ b/app/src/main/java/org/kiwix/kiwixmobile/zim_manager/fileselect_view/effects/OpenFile.kt @@ -20,12 +20,14 @@ package org.kiwix.kiwixmobile.zim_manager.fileselect_view.effects import android.app.Activity import androidx.core.net.toUri import org.kiwix.kiwixmobile.core.R +import org.kiwix.kiwixmobile.core.base.SideEffect import org.kiwix.kiwixmobile.core.extensions.start import org.kiwix.kiwixmobile.core.extensions.toast import org.kiwix.kiwixmobile.core.zim_manager.fileselect_view.adapter.BooksOnDiskListItem.BookOnDisk import org.kiwix.kiwixmobile.main.KiwixMainActivity -class OpenFile(private val bookOnDisk: BookOnDisk) : SideEffect { +class OpenFile(private val bookOnDisk: BookOnDisk) : + SideEffect { override fun invokeWith(activity: Activity) { val file = bookOnDisk.file diff --git a/app/src/main/java/org/kiwix/kiwixmobile/zim_manager/fileselect_view/effects/ShareFiles.kt b/app/src/main/java/org/kiwix/kiwixmobile/zim_manager/fileselect_view/effects/ShareFiles.kt index 1d98e2911..9a5163ad9 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/zim_manager/fileselect_view/effects/ShareFiles.kt +++ b/app/src/main/java/org/kiwix/kiwixmobile/zim_manager/fileselect_view/effects/ShareFiles.kt @@ -24,9 +24,11 @@ import android.net.Uri import android.os.Build import androidx.core.content.FileProvider import org.kiwix.kiwixmobile.core.R +import org.kiwix.kiwixmobile.core.base.SideEffect import org.kiwix.kiwixmobile.core.zim_manager.fileselect_view.adapter.BooksOnDiskListItem.BookOnDisk -class ShareFiles(private val selectedBooks: List) : SideEffect { +class ShareFiles(private val selectedBooks: List) : + SideEffect { override fun invokeWith(activity: Activity) { val selectedFileShareIntent = Intent() selectedFileShareIntent.action = Intent.ACTION_SEND_MULTIPLE diff --git a/app/src/main/java/org/kiwix/kiwixmobile/zim_manager/fileselect_view/effects/StartMultiSelection.kt b/app/src/main/java/org/kiwix/kiwixmobile/zim_manager/fileselect_view/effects/StartMultiSelection.kt index e45e86c77..9891b0d31 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/zim_manager/fileselect_view/effects/StartMultiSelection.kt +++ b/app/src/main/java/org/kiwix/kiwixmobile/zim_manager/fileselect_view/effects/StartMultiSelection.kt @@ -22,6 +22,7 @@ import android.app.Activity import android.view.ActionMode import io.reactivex.processors.PublishProcessor import org.kiwix.kiwixmobile.core.R +import org.kiwix.kiwixmobile.core.base.SideEffect import org.kiwix.kiwixmobile.core.extensions.startActionMode import org.kiwix.kiwixmobile.core.zim_manager.fileselect_view.adapter.BooksOnDiskListItem import org.kiwix.kiwixmobile.zim_manager.ZimManageViewModel.FileSelectActions diff --git a/buildSrc/src/main/kotlin/plugin/AllProjectConfigurer.kt b/buildSrc/src/main/kotlin/plugin/AllProjectConfigurer.kt index 907639379..60fd04350 100644 --- a/buildSrc/src/main/kotlin/plugin/AllProjectConfigurer.kt +++ b/buildSrc/src/main/kotlin/plugin/AllProjectConfigurer.kt @@ -143,6 +143,7 @@ class AllProjectConfigurer { implementation(Libs.kotlin_stdlib_jdk7) implementation(Libs.appcompat) implementation(Libs.material) + implementation(Libs.constraintlayout) implementation(Libs.androidx_multidex_multidex) implementation(Libs.okhttp) implementation(Libs.logging_interceptor) diff --git a/core/build.gradle b/core/build.gradle index 5ad1c1501..3c4d34abb 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -46,8 +46,6 @@ dependencies { // Android Support implementation(Libs.cardview) - implementation(Libs.constraintlayout) - // Tab indicator implementation(Libs.ink_page_indicator) diff --git a/core/src/main/AndroidManifest.xml b/core/src/main/AndroidManifest.xml index d831889d5..238e0ae4f 100644 --- a/core/src/main/AndroidManifest.xml +++ b/core/src/main/AndroidManifest.xml @@ -21,10 +21,10 @@ android:hardwareAccelerated="true" android:icon="@mipmap/kiwix_icon" android:label="@string/app_name" - android:usesCleartextTraffic="true" android:roundIcon="@mipmap/kiwix_icon_round" android:supportsRtl="true" android:theme="@style/AppTheme" + android:usesCleartextTraffic="true" tools:targetApi="m"> + diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/ViewModelFactory.java b/core/src/main/java/org/kiwix/kiwixmobile/core/ViewModelFactory.java new file mode 100644 index 000000000..d0d1fb3ab --- /dev/null +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/ViewModelFactory.java @@ -0,0 +1,55 @@ +/* + * Kiwix Android + * Copyright (c) 2019 Kiwix + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package org.kiwix.kiwixmobile.core; + +import androidx.lifecycle.ViewModel; +import androidx.lifecycle.ViewModelProvider; +import java.util.Map; +import javax.inject.Provider; + +public class ViewModelFactory implements ViewModelProvider.Factory { + private final Map, Provider> creators; + + public ViewModelFactory( + Map, Provider> creators) { + this.creators = creators; + } + + @SuppressWarnings("unchecked") + @Override + public T create(Class modelClass) { + Provider creator = creators.get(modelClass); + if (creator == null) { + for (Map.Entry, Provider> entry : creators.entrySet()) { + if (modelClass.isAssignableFrom(entry.getKey())) { + creator = entry.getValue(); + break; + } + } + } + if (creator == null) { + throw new IllegalArgumentException("unknown model class " + modelClass); + } + try { + return (T) creator.get(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } +} diff --git a/app/src/main/java/org/kiwix/kiwixmobile/zim_manager/fileselect_view/effects/SideEffect.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/base/SideEffect.kt similarity index 92% rename from app/src/main/java/org/kiwix/kiwixmobile/zim_manager/fileselect_view/effects/SideEffect.kt rename to core/src/main/java/org/kiwix/kiwixmobile/core/base/SideEffect.kt index a0cc0fd8a..063dccd71 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/zim_manager/fileselect_view/effects/SideEffect.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/base/SideEffect.kt @@ -15,7 +15,7 @@ * along with this program. If not, see . * */ -package org.kiwix.kiwixmobile.zim_manager.fileselect_view.effects +package org.kiwix.kiwixmobile.core.base import android.app.Activity diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/downloader/model/DownloadItem.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/downloader/model/DownloadItem.kt index 38809e722..87c738923 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/downloader/model/DownloadItem.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/downloader/model/DownloadItem.kt @@ -17,6 +17,7 @@ */ package org.kiwix.kiwixmobile.core.downloader.model +import android.content.Context import com.tonyodev.fetch2.Error import com.tonyodev.fetch2.Status import com.tonyodev.fetch2.Status.ADDED @@ -43,6 +44,8 @@ data class DownloadItem( val downloadState: DownloadState ) { + val readableEta: CharSequence = eta.takeIf { it.seconds > 0L }?.toHumanReadableTime() ?: "" + constructor(downloadModel: DownloadModel) : this( downloadModel.downloadId, Base64String(downloadModel.book.favicon), @@ -84,4 +87,12 @@ sealed class DownloadState(val stringId: Int) { data class Failed(val reason: Error) : DownloadState(R.string.failed_state) override fun toString(): String = javaClass.simpleName + + fun toReadableState(context: Context): CharSequence = when (this) { + is Failed -> context.getString(stringId, reason.name) + Pending, + Running, + Paused, + Successful -> context.getString(stringId) + } } diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/extensions/ViewAnimatorExtensions.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/extensions/ViewAnimatorExtensions.kt new file mode 100644 index 000000000..b02b8f03f --- /dev/null +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/extensions/ViewAnimatorExtensions.kt @@ -0,0 +1,27 @@ +/* + * Kiwix Android + * Copyright (c) 2019 Kiwix + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package org.kiwix.kiwixmobile.core.extensions + +import android.widget.ViewAnimator + +fun ViewAnimator.setDistinctDisplayedChild(index: Int) { + if (displayedChild != index) { + displayedChild = index + } +} diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/main/CoreMainActivity.java b/core/src/main/java/org/kiwix/kiwixmobile/core/main/CoreMainActivity.java index 6a79f7277..cfd5eb405 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/main/CoreMainActivity.java +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/main/CoreMainActivity.java @@ -1091,8 +1091,7 @@ public abstract class CoreMainActivity extends BaseActivity implements WebViewCa @NonNull String[] permissions, @NonNull int[] grantResults) { switch (requestCode) { case REQUEST_STORAGE_PERMISSION: { - if (grantResults.length > 0 - && grantResults[0] == PERMISSION_GRANTED) { + if (hasPermission(Manifest.permission.READ_EXTERNAL_STORAGE)) { finish(); Intent newZimFile = Intents.internal(CoreMainActivity.class); newZimFile.setData(Uri.fromFile(file)); @@ -1222,7 +1221,6 @@ public abstract class CoreMainActivity extends BaseActivity implements WebViewCa }, 300); } - @OnClick(R2.id.bottom_toolbar_bookmark) public void toggleBookmark() { //Check maybe need refresh @@ -1605,7 +1603,7 @@ public abstract class CoreMainActivity extends BaseActivity implements WebViewCa return true; } - protected boolean urlIsInvalid(){ + protected boolean urlIsInvalid() { return getCurrentWebView().getUrl() == null; } @@ -1827,14 +1825,10 @@ public abstract class CoreMainActivity extends BaseActivity implements WebViewCa } private void searchFiles() { - if (Build.VERSION.SDK_INT >= VERSION_CODES.M && ContextCompat.checkSelfPermission(this, - Manifest.permission.READ_EXTERNAL_STORAGE) - != PERMISSION_GRANTED) { - ActivityCompat.requestPermissions(this, - new String[] { Manifest.permission.READ_EXTERNAL_STORAGE }, - REQUEST_READ_STORAGE_PERMISSION); - } else { + if (hasPermission(Manifest.permission.READ_EXTERNAL_STORAGE)) { scanStorageForZims(); + } else { + requestExternalStoragePermission(); } } diff --git a/app/src/main/java/org/kiwix/kiwixmobile/di/ViewModelKey.kt b/core/src/main/java/org/kiwix/kiwixmobile/di/ViewModelKey.kt similarity index 100% rename from app/src/main/java/org/kiwix/kiwixmobile/di/ViewModelKey.kt rename to core/src/main/java/org/kiwix/kiwixmobile/di/ViewModelKey.kt diff --git a/core/src/main/res/values/styles.xml b/core/src/main/res/values/styles.xml index 8e75f9fff..753389e2b 100644 --- a/core/src/main/res/values/styles.xml +++ b/core/src/main/res/values/styles.xml @@ -53,6 +53,7 @@ @color/textDarkSecondary @color/textDarkTertiary @color/accent + @style/KiwixButtonStyle + + diff --git a/custom/build.gradle b/custom/build.gradle index f6e89940c..cbc7680cd 100644 --- a/custom/build.gradle +++ b/custom/build.gradle @@ -109,6 +109,7 @@ android { buildConfigField "int", "CONTENT_VERSION_CODE", "$parsedJson.version_code" } buildConfigField "String", "ENFORCED_LANG", "\"$parsedJson.enforced_lang\"" + buildConfigField "String", "ZIM_URL", "\"$parsedJson.zim_url\"" resValue "string", "app_name", "$parsedJson.app_name" resValue "string", "app_search_string", "Search " + "$parsedJson.app_name" } diff --git a/custom/src/customexample/AndroidManifest.xml b/custom/src/customexample/AndroidManifest.xml deleted file mode 100644 index b84e59644..000000000 --- a/custom/src/customexample/AndroidManifest.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - diff --git a/custom/src/customexample/info.json b/custom/src/customexample/info.json index 6e34580fb..f655e6716 100644 --- a/custom/src/customexample/info.json +++ b/custom/src/customexample/info.json @@ -3,7 +3,8 @@ "package": "org.kiwix.kiwixcustomexample", "version_name": "2017-07", "version_code": "1", - "zim_file": "wikipedia_fr_test_2017-07.zim", + "zim_file": "kiwix.granbluefantasy_en_all_all.zim", + "zim_url": "http://download.kiwix.org/zim/other/granbluefantasy_en_all_nopic_2018-10.zim.meta4", "embed_zim": false, "ic_launcher": "icon.png", "enforced_lang": "en" diff --git a/custom/src/main/AndroidManifest.xml b/custom/src/main/AndroidManifest.xml index c420346cb..b984597e3 100644 --- a/custom/src/main/AndroidManifest.xml +++ b/custom/src/main/AndroidManifest.xml @@ -39,5 +39,6 @@ + diff --git a/custom/src/main/java/org/kiwix/kiwixmobile/custom/CustomViewModelFactory.java b/custom/src/main/java/org/kiwix/kiwixmobile/custom/CustomViewModelFactory.java new file mode 100644 index 000000000..8e0abbbed --- /dev/null +++ b/custom/src/main/java/org/kiwix/kiwixmobile/custom/CustomViewModelFactory.java @@ -0,0 +1,35 @@ +/* + * Kiwix Android + * Copyright (c) 2019 Kiwix + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package org.kiwix.kiwixmobile.custom; + +import androidx.lifecycle.ViewModel; +import java.util.Map; +import javax.inject.Inject; +import javax.inject.Provider; +import org.kiwix.kiwixmobile.core.ViewModelFactory; +import org.kiwix.kiwixmobile.custom.di.CustomScope; + +@CustomScope +public class CustomViewModelFactory extends ViewModelFactory { + + @Inject + public CustomViewModelFactory(Map, Provider> creators) { + super(creators); + } +} diff --git a/custom/src/main/java/org/kiwix/kiwixmobile/custom/di/CustomActivityComponent.kt b/custom/src/main/java/org/kiwix/kiwixmobile/custom/di/CustomActivityComponent.kt index a25c8d17e..c4632bfb7 100644 --- a/custom/src/main/java/org/kiwix/kiwixmobile/custom/di/CustomActivityComponent.kt +++ b/custom/src/main/java/org/kiwix/kiwixmobile/custom/di/CustomActivityComponent.kt @@ -22,6 +22,7 @@ import android.app.Activity import dagger.BindsInstance import dagger.Subcomponent import org.kiwix.kiwixmobile.core.di.ActivityScope +import org.kiwix.kiwixmobile.custom.download.CustomDownloadActivity import org.kiwix.kiwixmobile.custom.main.CustomMainActivity import org.kiwix.kiwixmobile.custom.settings.CustomSettingsActivity @@ -30,6 +31,7 @@ import org.kiwix.kiwixmobile.custom.settings.CustomSettingsActivity interface CustomActivityComponent { fun inject(customMainActivity: CustomMainActivity) fun inject(customSettingsActivity: CustomSettingsActivity) + fun inject(customDownloadActivity: CustomDownloadActivity) @Subcomponent.Builder interface Builder { diff --git a/custom/src/main/java/org/kiwix/kiwixmobile/custom/di/CustomComponent.kt b/custom/src/main/java/org/kiwix/kiwixmobile/custom/di/CustomComponent.kt index 53f1a72bd..44b1b1a30 100644 --- a/custom/src/main/java/org/kiwix/kiwixmobile/custom/di/CustomComponent.kt +++ b/custom/src/main/java/org/kiwix/kiwixmobile/custom/di/CustomComponent.kt @@ -21,7 +21,7 @@ package org.kiwix.kiwixmobile.custom.di import dagger.Component import org.kiwix.kiwixmobile.core.di.components.CoreComponent -@Component(dependencies = [CoreComponent::class]) +@Component(dependencies = [CoreComponent::class], modules = [CustomViewModelModule::class]) @CustomScope interface CustomComponent { fun activityComponentBuilder(): CustomActivityComponent.Builder diff --git a/custom/src/main/java/org/kiwix/kiwixmobile/custom/di/CustomViewModelModule.kt b/custom/src/main/java/org/kiwix/kiwixmobile/custom/di/CustomViewModelModule.kt new file mode 100644 index 000000000..f26a6b67a --- /dev/null +++ b/custom/src/main/java/org/kiwix/kiwixmobile/custom/di/CustomViewModelModule.kt @@ -0,0 +1,40 @@ +/* + * Kiwix Android + * Copyright (c) 2019 Kiwix + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package org.kiwix.kiwixmobile.custom.di + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.ViewModelProvider +import dagger.Binds +import dagger.Module +import dagger.multibindings.IntoMap +import org.kiwix.kiwixmobile.custom.CustomViewModelFactory +import org.kiwix.kiwixmobile.custom.download.CustomDownloadViewModel +import org.kiwix.kiwixmobile.di.ViewModelKey + +@Module +abstract class CustomViewModelModule { + @Binds + @IntoMap + @ViewModelKey(CustomDownloadViewModel::class) + abstract fun bindCustomDownloadViewModel(zimManageViewModel: CustomDownloadViewModel): ViewModel + + @Binds + abstract fun bindViewModelFactory(factory: CustomViewModelFactory): + ViewModelProvider.Factory +} diff --git a/custom/src/main/java/org/kiwix/kiwixmobile/custom/download/Action.kt b/custom/src/main/java/org/kiwix/kiwixmobile/custom/download/Action.kt new file mode 100644 index 000000000..48b6a82b1 --- /dev/null +++ b/custom/src/main/java/org/kiwix/kiwixmobile/custom/download/Action.kt @@ -0,0 +1,27 @@ +/* + * Kiwix Android + * Copyright (c) 2019 Kiwix + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package org.kiwix.kiwixmobile.custom.download + +import org.kiwix.kiwixmobile.core.downloader.model.DownloadItem + +sealed class Action { + data class DatabaseEmission(val downloads: List) : Action() + object ClickedDownload : Action() + object ClickedRetry : Action() +} diff --git a/custom/src/main/java/org/kiwix/kiwixmobile/custom/download/CustomDownloadActivity.kt b/custom/src/main/java/org/kiwix/kiwixmobile/custom/download/CustomDownloadActivity.kt new file mode 100644 index 000000000..6784b9af8 --- /dev/null +++ b/custom/src/main/java/org/kiwix/kiwixmobile/custom/download/CustomDownloadActivity.kt @@ -0,0 +1,99 @@ +/* + * Kiwix Android + * Copyright (c) 2019 Kiwix + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package org.kiwix.kiwixmobile.custom.download + +import android.os.Bundle +import androidx.lifecycle.Observer +import androidx.lifecycle.ViewModelProvider +import io.reactivex.disposables.CompositeDisposable +import kotlinx.android.synthetic.main.activity_custom_download.cd_view_animator +import kotlinx.android.synthetic.main.layout_custom_download_error.cd_error_text +import kotlinx.android.synthetic.main.layout_custom_download_error.cd_retry_button +import kotlinx.android.synthetic.main.layout_custom_download_in_progress.cd_download_state +import kotlinx.android.synthetic.main.layout_custom_download_in_progress.cd_eta +import kotlinx.android.synthetic.main.layout_custom_download_in_progress.cd_progress +import kotlinx.android.synthetic.main.layout_custom_download_required.cd_download_button +import org.kiwix.kiwixmobile.core.base.BaseActivity +import org.kiwix.kiwixmobile.core.downloader.model.DownloadItem +import org.kiwix.kiwixmobile.core.extensions.setDistinctDisplayedChild +import org.kiwix.kiwixmobile.core.extensions.viewModel +import org.kiwix.kiwixmobile.custom.R +import org.kiwix.kiwixmobile.custom.customActivityComponent +import org.kiwix.kiwixmobile.custom.download.Action.ClickedDownload +import org.kiwix.kiwixmobile.custom.download.Action.ClickedRetry +import org.kiwix.kiwixmobile.custom.download.State.DownloadComplete +import org.kiwix.kiwixmobile.custom.download.State.DownloadFailed +import org.kiwix.kiwixmobile.custom.download.State.DownloadInProgress +import org.kiwix.kiwixmobile.custom.download.State.DownloadRequired +import javax.inject.Inject + +class CustomDownloadActivity : BaseActivity() { + + private val downloadViewModel by lazy { + viewModel(viewModelFactory) + } + + @Inject lateinit var viewModelFactory: ViewModelProvider.Factory + + private val compositeDisposable = CompositeDisposable() + + override fun injection() { + customActivityComponent.inject(this) + } + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_custom_download) + downloadViewModel.state.observe(this, Observer(::render)) + compositeDisposable.add( + downloadViewModel.effects.subscribe( + { it.invokeWith(this) }, + Throwable::printStackTrace + ) + ) + cd_download_button.setOnClickListener { downloadViewModel.actions.offer(ClickedDownload) } + cd_retry_button.setOnClickListener { downloadViewModel.actions.offer(ClickedRetry) } + } + + override fun onDestroy() { + super.onDestroy() + compositeDisposable.clear() + } + + private fun render(state: State) { + return when (state) { + DownloadRequired -> cd_view_animator.setDistinctDisplayedChild(0) + is DownloadInProgress -> { + cd_view_animator.setDistinctDisplayedChild(1) + render(state.downloads[0]) + } + is DownloadFailed -> { + cd_view_animator.setDistinctDisplayedChild(2) + cd_error_text.text = state.downloadState.toReadableState(this) + } + DownloadComplete -> cd_view_animator.setDistinctDisplayedChild(3) + } + } + + private fun render(downloadItem: DownloadItem) { + cd_progress.progress = downloadItem.progress + cd_eta.text = downloadItem.readableEta + cd_download_state.text = downloadItem.downloadState.toReadableState(this) + } +} diff --git a/custom/src/main/java/org/kiwix/kiwixmobile/custom/download/CustomDownloadViewModel.kt b/custom/src/main/java/org/kiwix/kiwixmobile/custom/download/CustomDownloadViewModel.kt new file mode 100644 index 000000000..1e5c88ec0 --- /dev/null +++ b/custom/src/main/java/org/kiwix/kiwixmobile/custom/download/CustomDownloadViewModel.kt @@ -0,0 +1,96 @@ +/* + * Kiwix Android + * Copyright (c) 2019 Kiwix + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package org.kiwix.kiwixmobile.custom.download + +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import io.reactivex.disposables.CompositeDisposable +import io.reactivex.processors.PublishProcessor +import org.kiwix.kiwixmobile.core.base.SideEffect +import org.kiwix.kiwixmobile.core.dao.FetchDownloadDao +import org.kiwix.kiwixmobile.core.downloader.model.DownloadItem +import org.kiwix.kiwixmobile.core.downloader.model.DownloadState.Failed +import org.kiwix.kiwixmobile.custom.download.Action.ClickedDownload +import org.kiwix.kiwixmobile.custom.download.Action.ClickedRetry +import org.kiwix.kiwixmobile.custom.download.Action.DatabaseEmission +import org.kiwix.kiwixmobile.custom.download.State.DownloadComplete +import org.kiwix.kiwixmobile.custom.download.State.DownloadFailed +import org.kiwix.kiwixmobile.custom.download.State.DownloadInProgress +import org.kiwix.kiwixmobile.custom.download.State.DownloadRequired +import org.kiwix.kiwixmobile.custom.download.effects.DownloadCustom +import org.kiwix.kiwixmobile.custom.download.effects.FinishAndStartMain +import org.kiwix.kiwixmobile.custom.download.effects.SetPreferredStorageWithMostSpace +import javax.inject.Inject + +class CustomDownloadViewModel @Inject constructor( + downloadDao: FetchDownloadDao, + setPreferredStorageWithMostSpace: SetPreferredStorageWithMostSpace, + private val downloadCustom: DownloadCustom +) : ViewModel() { + + val state = MutableLiveData().apply { value = DownloadRequired } + val actions = PublishProcessor.create() + private val _effects = PublishProcessor.create>() + val effects = _effects.startWith(setPreferredStorageWithMostSpace) + + private val compositeDisposable = CompositeDisposable() + + init { + compositeDisposable.addAll( + reducer(), + downloadsAsActions(downloadDao) + ) + } + + private fun reducer() = actions.map { reduce(it, state.value!!) } + .distinctUntilChanged() + .subscribe(state::postValue, Throwable::printStackTrace) + + private fun downloadsAsActions(downloadDao: FetchDownloadDao) = + downloadDao.downloads() + .map { it.map(::DownloadItem) } + .subscribe( + { actions.offer(DatabaseEmission(it)) }, + Throwable::printStackTrace + ) + + private fun reduce(action: Action, state: State): State { + return when (action) { + is DatabaseEmission -> reduceDatabaseEmission(state, action) + ClickedRetry, + ClickedDownload -> state.also { _effects.offer(downloadCustom) } + } + } + + private fun reduceDatabaseEmission(state: State, action: DatabaseEmission) = when (state) { + is DownloadFailed, + DownloadRequired -> + if (action.downloads.isNotEmpty()) DownloadInProgress(action.downloads) + else state + is DownloadInProgress -> + if (action.downloads.isNotEmpty()) + if (action.downloads[0].downloadState is Failed) + DownloadFailed(action.downloads[0].downloadState) + else + DownloadInProgress(action.downloads) + else + DownloadComplete.also { _effects.offer(FinishAndStartMain()) } + DownloadComplete -> state + } +} diff --git a/custom/src/main/java/org/kiwix/kiwixmobile/custom/download/State.kt b/custom/src/main/java/org/kiwix/kiwixmobile/custom/download/State.kt new file mode 100644 index 000000000..fb24923b3 --- /dev/null +++ b/custom/src/main/java/org/kiwix/kiwixmobile/custom/download/State.kt @@ -0,0 +1,29 @@ +/* + * Kiwix Android + * Copyright (c) 2019 Kiwix + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package org.kiwix.kiwixmobile.custom.download + +import org.kiwix.kiwixmobile.core.downloader.model.DownloadItem +import org.kiwix.kiwixmobile.core.downloader.model.DownloadState + +sealed class State { + object DownloadRequired : State() + data class DownloadInProgress(val downloads: List) : State() + data class DownloadFailed(val downloadState: DownloadState) : State() + object DownloadComplete : State() +} diff --git a/custom/src/main/java/org/kiwix/kiwixmobile/custom/download/effects/DownloadCustom.kt b/custom/src/main/java/org/kiwix/kiwixmobile/custom/download/effects/DownloadCustom.kt new file mode 100644 index 000000000..2ac6b60ea --- /dev/null +++ b/custom/src/main/java/org/kiwix/kiwixmobile/custom/download/effects/DownloadCustom.kt @@ -0,0 +1,63 @@ +/* + * Kiwix Android + * Copyright (c) 2019 Kiwix + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package org.kiwix.kiwixmobile.custom.download.effects + +import android.app.Activity +import org.kiwix.kiwixmobile.core.base.SideEffect +import org.kiwix.kiwixmobile.core.downloader.Downloader +import org.kiwix.kiwixmobile.core.entity.LibraryNetworkEntity.Book +import org.kiwix.kiwixmobile.custom.BuildConfig +import javax.inject.Inject + +data class DownloadCustom @Inject constructor(val downloader: Downloader) : SideEffect { + override fun invokeWith(activity: Activity) { + downloader.download(emptyBook(id = "custom", url = BuildConfig.ZIM_URL)) + } + + private fun emptyBook( + id: String = "", + title: String = "", + description: String = "", + language: String = "", + creator: String = "", + publisher: String = "", + date: String = "", + url: String = "", + articleCount: String = "", + mediaCount: String = "", + size: String = "", + name: String = "", + favIcon: String = "" + ) = + Book().apply { + this.id = id + this.title = title + this.description = description + this.language = language + this.creator = creator + this.publisher = publisher + this.date = date + this.url = url + this.articleCount = articleCount + this.mediaCount = mediaCount + this.size = size + bookName = name + favicon = favIcon + } +} diff --git a/custom/src/main/java/org/kiwix/kiwixmobile/custom/download/effects/FinishAndStartMain.kt b/custom/src/main/java/org/kiwix/kiwixmobile/custom/download/effects/FinishAndStartMain.kt new file mode 100644 index 000000000..c3508dc25 --- /dev/null +++ b/custom/src/main/java/org/kiwix/kiwixmobile/custom/download/effects/FinishAndStartMain.kt @@ -0,0 +1,31 @@ +/* + * Kiwix Android + * Copyright (c) 2019 Kiwix + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package org.kiwix.kiwixmobile.custom.download.effects + +import android.app.Activity +import org.kiwix.kiwixmobile.core.base.SideEffect +import org.kiwix.kiwixmobile.core.extensions.start +import org.kiwix.kiwixmobile.custom.main.CustomMainActivity + +class FinishAndStartMain() : SideEffect { + override fun invokeWith(activity: Activity) { + activity.finish() + activity.start() + } +} diff --git a/custom/src/main/java/org/kiwix/kiwixmobile/custom/download/effects/SetPreferredStorageWithMostSpace.kt b/custom/src/main/java/org/kiwix/kiwixmobile/custom/download/effects/SetPreferredStorageWithMostSpace.kt new file mode 100644 index 000000000..d294d967e --- /dev/null +++ b/custom/src/main/java/org/kiwix/kiwixmobile/custom/download/effects/SetPreferredStorageWithMostSpace.kt @@ -0,0 +1,38 @@ +/* + * Kiwix Android + * Copyright (c) 2019 Kiwix + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package org.kiwix.kiwixmobile.custom.download.effects + +import android.app.Activity +import androidx.core.content.ContextCompat +import org.kiwix.kiwixmobile.core.base.SideEffect +import org.kiwix.kiwixmobile.core.settings.StorageCalculator +import org.kiwix.kiwixmobile.core.utils.SharedPreferenceUtil +import javax.inject.Inject + +class SetPreferredStorageWithMostSpace @Inject constructor( + private val storageCalculator: StorageCalculator, + private val sharedPreferenceUtil: SharedPreferenceUtil +) : SideEffect { + override fun invokeWith(activity: Activity) { + ContextCompat.getExternalFilesDirs(activity, null) + .filterNotNull() + .maxBy(storageCalculator::availableBytes) + ?.let { sharedPreferenceUtil.putPrefStorage(it.path) } + } +} diff --git a/custom/src/main/java/org/kiwix/kiwixmobile/custom/main/CustomFileValidator.kt b/custom/src/main/java/org/kiwix/kiwixmobile/custom/main/CustomFileValidator.kt new file mode 100644 index 000000000..daf24bac0 --- /dev/null +++ b/custom/src/main/java/org/kiwix/kiwixmobile/custom/main/CustomFileValidator.kt @@ -0,0 +1,65 @@ +/* + * Kiwix Android + * Copyright (c) 2019 Kiwix + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package org.kiwix.kiwixmobile.custom.main + +import android.content.Context +import androidx.core.content.ContextCompat +import org.kiwix.kiwixmobile.custom.main.ValidationState.HasBothFiles +import org.kiwix.kiwixmobile.custom.main.ValidationState.HasFile +import org.kiwix.kiwixmobile.custom.main.ValidationState.HasNothing +import java.io.File +import javax.inject.Inject + +class CustomFileValidator @Inject constructor(private val context: Context) { + + fun validate(onFilesFound: (ValidationState) -> Unit, onNoFilesFound: () -> Unit) = + when (val installationState = detectInstallationState()) { + is HasBothFiles, + is HasFile -> onFilesFound(installationState) + HasNothing -> onNoFilesFound() + } + + private fun detectInstallationState( + obbFiles: List = obbFiles(), + zimFiles: List = zimFiles() + ): ValidationState { + return when { + obbFiles.isNotEmpty() && zimFiles().isNotEmpty() -> HasBothFiles(obbFiles[0], zimFiles[0]) + obbFiles.isNotEmpty() -> HasFile(obbFiles[0]) + zimFiles.isNotEmpty() -> HasFile(zimFiles[0]) + else -> HasNothing + } + } + + private fun obbFiles() = scanDirs(ContextCompat.getObbDirs(context), "obb") + + private fun zimFiles() = + scanDirs(ContextCompat.getExternalFilesDirs(context, null), "zim") + + private fun scanDirs(dirs: Array, extensionToMatch: String): List = + dirs.fold(listOf()) { acc, dir -> + acc + dir.walk().filter { it.extension.startsWith(extensionToMatch) }.toList() + } +} + +sealed class ValidationState { + data class HasBothFiles(val obbFile: File, val zimFile: File) : ValidationState() + data class HasFile(val file: File) : ValidationState() + object HasNothing : ValidationState() +} diff --git a/custom/src/main/java/org/kiwix/kiwixmobile/custom/main/CustomMainActivity.kt b/custom/src/main/java/org/kiwix/kiwixmobile/custom/main/CustomMainActivity.kt index 333435c2c..ef03f64c2 100644 --- a/custom/src/main/java/org/kiwix/kiwixmobile/custom/main/CustomMainActivity.kt +++ b/custom/src/main/java/org/kiwix/kiwixmobile/custom/main/CustomMainActivity.kt @@ -22,23 +22,24 @@ import android.content.Intent import android.os.Bundle import android.util.Log import android.view.Menu -import androidx.appcompat.app.AlertDialog -import androidx.core.net.toUri import org.kiwix.kiwixmobile.core.CoreApp import org.kiwix.kiwixmobile.core.R +import org.kiwix.kiwixmobile.core.extensions.start import org.kiwix.kiwixmobile.core.main.CoreMainActivity import org.kiwix.kiwixmobile.core.main.WebViewCallback import org.kiwix.kiwixmobile.core.reader.ZimReaderContainer -import org.kiwix.kiwixmobile.core.utils.Constants.TAG_KIWIX import org.kiwix.kiwixmobile.core.utils.LanguageUtils -import org.kiwix.kiwixmobile.core.utils.StyleUtils.dialogStyle -import org.kiwix.kiwixmobile.core.utils.files.FileUtils import org.kiwix.kiwixmobile.custom.BuildConfig import org.kiwix.kiwixmobile.custom.customActivityComponent +import org.kiwix.kiwixmobile.custom.download.CustomDownloadActivity +import org.kiwix.kiwixmobile.custom.main.ValidationState.HasBothFiles +import org.kiwix.kiwixmobile.custom.main.ValidationState.HasFile import java.io.File import java.util.Locale +import javax.inject.Inject class CustomMainActivity : CoreMainActivity() { + @Inject lateinit var customFileValidator: CustomFileValidator override fun showHomePage() { Log.e("CustomMain", "tried to show home page") @@ -54,17 +55,22 @@ class CustomMainActivity : CoreMainActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - Log.d(TAG_KIWIX, "This is a custom app:$packageName") - if (loadCustomAppContent()) { - Log.d(TAG_KIWIX, "Found custom content, continuing...") - // Continue - } else { - Log.e(TAG_KIWIX, "Problem finding the content, no more OnCreate() code") - // What should we do here? exit? I'll investigate empirically. - // It seems unpredictable behaviour if the code returns at this point as yesterday - // it didn't crash yet today the app crashes because it tries to load books - // in onResume(); - } + requireEnforcedLanguage() + customFileValidator.validate( + { + when (it) { + is HasFile -> openZimFile(it.file) + is HasBothFiles -> { + it.zimFile.delete() + openZimFile(it.obbFile) + } + } + }, + { + finish() + start() + } + ) } override fun onCreateOptionsMenu(menu: Menu?): Boolean { @@ -79,74 +85,15 @@ class CustomMainActivity : CoreMainActivity() { zimReaderContainer: ZimReaderContainer ) = CustomWebViewClient(webViewCallback, zimReaderContainer) - /** - * loadCustomAppContent Return true if all's well, else false. - */ - private fun loadCustomAppContent(): Boolean { - Log.d( - TAG_KIWIX, - "Kiwix Custom App starting for the first time. Checking Companion ZIM: " + - BuildConfig.ZIM_FILE_NAME - ) - + private fun requireEnforcedLanguage(): Boolean { val currentLocaleCode = Locale.getDefault().toString() - // Custom App recommends to start off a specific language - if (BuildConfig.ENFORCED_LANG.length > 0 && BuildConfig.ENFORCED_LANG != currentLocaleCode) { - - // change the locale machinery + if (BuildConfig.ENFORCED_LANG.isNotEmpty() && BuildConfig.ENFORCED_LANG != currentLocaleCode) { LanguageUtils.handleLocaleChange(this, BuildConfig.ENFORCED_LANG) - - // save new locale into preferences for next startup sharedPreferenceUtil.putPrefLanguage(BuildConfig.ENFORCED_LANG) - - // restart activity for new locale to take effect - this.setResult(1236) - this.finish() - this.startActivity(Intent(this, this.javaClass)) - return false - } - - var filePath = "" - if (BuildConfig.HAS_EMBEDDED_ZIM) { - val appPath = packageResourcePath - val libDir = File(appPath.substring(0, appPath.lastIndexOf("/")) + "/lib/") - if (libDir.exists() && libDir.listFiles().size > 0) { - filePath = libDir.listFiles()[0].path + "/" + BuildConfig.ZIM_FILE_NAME - } - if (filePath.isEmpty() || !File(filePath).exists()) { - filePath = String.format( - "/data/data/%s/lib/%s", packageName, - BuildConfig.ZIM_FILE_NAME - ) - } - } else { - filePath = generateExpansionFilePath() - } - - Log.d(TAG_KIWIX, "BuildConfig.ZIM_FILE_SIZE = " + BuildConfig.ZIM_FILE_SIZE) - if (!FileUtils.doesFileExist(filePath, BuildConfig.ZIM_FILE_SIZE, false)) { - - val zimFileMissingBuilder = AlertDialog.Builder(this, dialogStyle()) - zimFileMissingBuilder.setTitle(R.string.app_name) - zimFileMissingBuilder.setMessage(R.string.custom_app_missing_content) - zimFileMissingBuilder.setIcon(R.mipmap.kiwix_icon) - val activity = this - zimFileMissingBuilder.setPositiveButton( - getString(R.string.go_to_play_store) - ) { dialog, which -> - startActivity(Intent(Intent.ACTION_VIEW).apply { - data = "market://details?id=$packageName".toUri() - }) - activity.finish() - } - zimFileMissingBuilder.setCancelable(false) - val zimFileMissingDialog = zimFileMissingBuilder.create() - zimFileMissingDialog.show() - return false - } else { - openZimFile(File(filePath)) + startActivity(Intent(this, this.javaClass)) return true } + return false } override fun manageZimFiles(tab: Int) { diff --git a/custom/src/main/res/layout/activity_custom_download.xml b/custom/src/main/res/layout/activity_custom_download.xml new file mode 100644 index 000000000..99119938f --- /dev/null +++ b/custom/src/main/res/layout/activity_custom_download.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + diff --git a/custom/src/main/res/layout/layout_custom_download_complete.xml b/custom/src/main/res/layout/layout_custom_download_complete.xml new file mode 100644 index 000000000..bcdb979d3 --- /dev/null +++ b/custom/src/main/res/layout/layout_custom_download_complete.xml @@ -0,0 +1,20 @@ + + + + + + diff --git a/custom/src/main/res/layout/layout_custom_download_error.xml b/custom/src/main/res/layout/layout_custom_download_error.xml new file mode 100644 index 000000000..f1f5b99d7 --- /dev/null +++ b/custom/src/main/res/layout/layout_custom_download_error.xml @@ -0,0 +1,30 @@ + + + + + + +