mirror of
https://github.com/kiwix/kiwix-android.git
synced 2025-09-08 06:42:21 -04:00
64 Custom apps should validate their expansion files and re-download if corrupt/missing - add Custom Download flow
This commit is contained in:
parent
fed540a390
commit
c05742d02a
@ -19,40 +19,17 @@
|
|||||||
package org.kiwix.kiwixmobile;
|
package org.kiwix.kiwixmobile;
|
||||||
|
|
||||||
import androidx.lifecycle.ViewModel;
|
import androidx.lifecycle.ViewModel;
|
||||||
import androidx.lifecycle.ViewModelProvider;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.inject.Provider;
|
import javax.inject.Provider;
|
||||||
|
import org.kiwix.kiwixmobile.core.ViewModelFactory;
|
||||||
import org.kiwix.kiwixmobile.di.KiwixScope;
|
import org.kiwix.kiwixmobile.di.KiwixScope;
|
||||||
|
|
||||||
@KiwixScope
|
@KiwixScope
|
||||||
public class KiwixViewModelFactory implements ViewModelProvider.Factory {
|
public class KiwixViewModelFactory extends ViewModelFactory {
|
||||||
private final Map<Class<? extends ViewModel>, Provider<ViewModel>> creators;
|
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public KiwixViewModelFactory(Map<Class<? extends ViewModel>, Provider<ViewModel>> creators) {
|
public KiwixViewModelFactory(Map<Class<? extends ViewModel>, Provider<ViewModel>> creators) {
|
||||||
this.creators = creators;
|
super(creators);
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
@Override
|
|
||||||
public <T extends ViewModel> T create(Class<T> modelClass) {
|
|
||||||
Provider<? extends ViewModel> creator = creators.get(modelClass);
|
|
||||||
if (creator == null) {
|
|
||||||
for (Map.Entry<Class<? extends ViewModel>, Provider<ViewModel>> 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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,7 @@ import androidx.lifecycle.MutableLiveData
|
|||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import io.reactivex.disposables.CompositeDisposable
|
import io.reactivex.disposables.CompositeDisposable
|
||||||
import io.reactivex.processors.PublishProcessor
|
import io.reactivex.processors.PublishProcessor
|
||||||
|
import org.kiwix.kiwixmobile.core.base.SideEffect
|
||||||
import org.kiwix.kiwixmobile.core.dao.NewLanguagesDao
|
import org.kiwix.kiwixmobile.core.dao.NewLanguagesDao
|
||||||
import org.kiwix.kiwixmobile.language.adapter.LanguageListItem.LanguageItem
|
import org.kiwix.kiwixmobile.language.adapter.LanguageListItem.LanguageItem
|
||||||
import org.kiwix.kiwixmobile.language.viewmodel.Action.Filter
|
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.Content
|
||||||
import org.kiwix.kiwixmobile.language.viewmodel.State.Loading
|
import org.kiwix.kiwixmobile.language.viewmodel.State.Loading
|
||||||
import org.kiwix.kiwixmobile.language.viewmodel.State.Saving
|
import org.kiwix.kiwixmobile.language.viewmodel.State.Saving
|
||||||
import org.kiwix.kiwixmobile.zim_manager.fileselect_view.effects.SideEffect
|
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
class LanguageViewModel @Inject constructor(
|
class LanguageViewModel @Inject constructor(
|
||||||
|
@ -22,7 +22,7 @@ import io.reactivex.Flowable
|
|||||||
import io.reactivex.schedulers.Schedulers
|
import io.reactivex.schedulers.Schedulers
|
||||||
import org.kiwix.kiwixmobile.core.dao.NewLanguagesDao
|
import org.kiwix.kiwixmobile.core.dao.NewLanguagesDao
|
||||||
import org.kiwix.kiwixmobile.core.zim_manager.Language
|
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(
|
data class SaveLanguagesAndFinish(
|
||||||
val languages: List<Language>,
|
val languages: List<Language>,
|
||||||
|
@ -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.None
|
||||||
import org.kiwix.kiwixmobile.zim_manager.fileselect_view.effects.OpenFile
|
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.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.fileselect_view.effects.StartMultiSelection
|
||||||
import org.kiwix.kiwixmobile.zim_manager.library_view.adapter.LibraryListItem
|
import org.kiwix.kiwixmobile.zim_manager.library_view.adapter.LibraryListItem
|
||||||
import org.kiwix.kiwixmobile.zim_manager.library_view.adapter.LibraryListItem.BookItem
|
import org.kiwix.kiwixmobile.zim_manager.library_view.adapter.LibraryListItem.BookItem
|
||||||
|
@ -17,7 +17,6 @@
|
|||||||
*/
|
*/
|
||||||
package org.kiwix.kiwixmobile.zim_manager.download_view
|
package org.kiwix.kiwixmobile.zim_manager.download_view
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import kotlinx.android.extensions.LayoutContainer
|
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.stop
|
||||||
import kotlinx.android.synthetic.main.download_item.title
|
import kotlinx.android.synthetic.main.download_item.title
|
||||||
import org.kiwix.kiwixmobile.core.downloader.model.DownloadItem
|
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
|
import org.kiwix.kiwixmobile.core.extensions.setBitmap
|
||||||
|
|
||||||
class DownloadViewHolder(override val containerView: View) : RecyclerView.ViewHolder(containerView),
|
class DownloadViewHolder(override val containerView: View) : RecyclerView.ViewHolder(containerView),
|
||||||
@ -50,21 +43,7 @@ class DownloadViewHolder(override val containerView: View) : RecyclerView.ViewHo
|
|||||||
stop.setOnClickListener {
|
stop.setOnClickListener {
|
||||||
itemClickListener.invoke(downloadItem)
|
itemClickListener.invoke(downloadItem)
|
||||||
}
|
}
|
||||||
downloadState.text = toReadableState(downloadItem.downloadState, containerView.context)
|
downloadState.text = downloadItem.downloadState.toReadableState(containerView.context)
|
||||||
eta.text = downloadItem.eta.takeIf { it.seconds > 0L }?.toHumanReadableTime() ?: ""
|
eta.text = downloadItem.readableEta
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,7 @@ package org.kiwix.kiwixmobile.zim_manager.fileselect_view.effects
|
|||||||
|
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import org.kiwix.kiwixmobile.R
|
import org.kiwix.kiwixmobile.R
|
||||||
|
import org.kiwix.kiwixmobile.core.base.SideEffect
|
||||||
import org.kiwix.kiwixmobile.core.dao.NewBookDao
|
import org.kiwix.kiwixmobile.core.dao.NewBookDao
|
||||||
import org.kiwix.kiwixmobile.core.extensions.toast
|
import org.kiwix.kiwixmobile.core.extensions.toast
|
||||||
import org.kiwix.kiwixmobile.core.reader.ZimReaderContainer
|
import org.kiwix.kiwixmobile.core.reader.ZimReaderContainer
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
package org.kiwix.kiwixmobile.zim_manager.fileselect_view.effects
|
package org.kiwix.kiwixmobile.zim_manager.fileselect_view.effects
|
||||||
|
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
|
import org.kiwix.kiwixmobile.core.base.SideEffect
|
||||||
|
|
||||||
object None : SideEffect<Unit> {
|
object None : SideEffect<Unit> {
|
||||||
override fun invokeWith(activity: Activity) {
|
override fun invokeWith(activity: Activity) {
|
||||||
|
@ -20,12 +20,14 @@ package org.kiwix.kiwixmobile.zim_manager.fileselect_view.effects
|
|||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import androidx.core.net.toUri
|
import androidx.core.net.toUri
|
||||||
import org.kiwix.kiwixmobile.core.R
|
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.start
|
||||||
import org.kiwix.kiwixmobile.core.extensions.toast
|
import org.kiwix.kiwixmobile.core.extensions.toast
|
||||||
import org.kiwix.kiwixmobile.core.zim_manager.fileselect_view.adapter.BooksOnDiskListItem.BookOnDisk
|
import org.kiwix.kiwixmobile.core.zim_manager.fileselect_view.adapter.BooksOnDiskListItem.BookOnDisk
|
||||||
import org.kiwix.kiwixmobile.main.KiwixMainActivity
|
import org.kiwix.kiwixmobile.main.KiwixMainActivity
|
||||||
|
|
||||||
class OpenFile(private val bookOnDisk: BookOnDisk) : SideEffect<Unit> {
|
class OpenFile(private val bookOnDisk: BookOnDisk) :
|
||||||
|
SideEffect<Unit> {
|
||||||
|
|
||||||
override fun invokeWith(activity: Activity) {
|
override fun invokeWith(activity: Activity) {
|
||||||
val file = bookOnDisk.file
|
val file = bookOnDisk.file
|
||||||
|
@ -24,9 +24,11 @@ import android.net.Uri
|
|||||||
import android.os.Build
|
import android.os.Build
|
||||||
import androidx.core.content.FileProvider
|
import androidx.core.content.FileProvider
|
||||||
import org.kiwix.kiwixmobile.core.R
|
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
|
import org.kiwix.kiwixmobile.core.zim_manager.fileselect_view.adapter.BooksOnDiskListItem.BookOnDisk
|
||||||
|
|
||||||
class ShareFiles(private val selectedBooks: List<BookOnDisk>) : SideEffect<Unit> {
|
class ShareFiles(private val selectedBooks: List<BookOnDisk>) :
|
||||||
|
SideEffect<Unit> {
|
||||||
override fun invokeWith(activity: Activity) {
|
override fun invokeWith(activity: Activity) {
|
||||||
val selectedFileShareIntent = Intent()
|
val selectedFileShareIntent = Intent()
|
||||||
selectedFileShareIntent.action = Intent.ACTION_SEND_MULTIPLE
|
selectedFileShareIntent.action = Intent.ACTION_SEND_MULTIPLE
|
||||||
|
@ -22,6 +22,7 @@ import android.app.Activity
|
|||||||
import android.view.ActionMode
|
import android.view.ActionMode
|
||||||
import io.reactivex.processors.PublishProcessor
|
import io.reactivex.processors.PublishProcessor
|
||||||
import org.kiwix.kiwixmobile.core.R
|
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.extensions.startActionMode
|
||||||
import org.kiwix.kiwixmobile.core.zim_manager.fileselect_view.adapter.BooksOnDiskListItem
|
import org.kiwix.kiwixmobile.core.zim_manager.fileselect_view.adapter.BooksOnDiskListItem
|
||||||
import org.kiwix.kiwixmobile.zim_manager.ZimManageViewModel.FileSelectActions
|
import org.kiwix.kiwixmobile.zim_manager.ZimManageViewModel.FileSelectActions
|
||||||
|
@ -143,6 +143,7 @@ class AllProjectConfigurer {
|
|||||||
implementation(Libs.kotlin_stdlib_jdk7)
|
implementation(Libs.kotlin_stdlib_jdk7)
|
||||||
implementation(Libs.appcompat)
|
implementation(Libs.appcompat)
|
||||||
implementation(Libs.material)
|
implementation(Libs.material)
|
||||||
|
implementation(Libs.constraintlayout)
|
||||||
implementation(Libs.androidx_multidex_multidex)
|
implementation(Libs.androidx_multidex_multidex)
|
||||||
implementation(Libs.okhttp)
|
implementation(Libs.okhttp)
|
||||||
implementation(Libs.logging_interceptor)
|
implementation(Libs.logging_interceptor)
|
||||||
|
@ -46,8 +46,6 @@ dependencies {
|
|||||||
|
|
||||||
// Android Support
|
// Android Support
|
||||||
implementation(Libs.cardview)
|
implementation(Libs.cardview)
|
||||||
implementation(Libs.constraintlayout)
|
|
||||||
|
|
||||||
|
|
||||||
// Tab indicator
|
// Tab indicator
|
||||||
implementation(Libs.ink_page_indicator)
|
implementation(Libs.ink_page_indicator)
|
||||||
|
@ -21,10 +21,10 @@
|
|||||||
android:hardwareAccelerated="true"
|
android:hardwareAccelerated="true"
|
||||||
android:icon="@mipmap/kiwix_icon"
|
android:icon="@mipmap/kiwix_icon"
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
android:usesCleartextTraffic="true"
|
|
||||||
android:roundIcon="@mipmap/kiwix_icon_round"
|
android:roundIcon="@mipmap/kiwix_icon_round"
|
||||||
android:supportsRtl="true"
|
android:supportsRtl="true"
|
||||||
android:theme="@style/AppTheme"
|
android:theme="@style/AppTheme"
|
||||||
|
android:usesCleartextTraffic="true"
|
||||||
tools:targetApi="m">
|
tools:targetApi="m">
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
@ -35,6 +35,7 @@
|
|||||||
<action android:name="android.intent.action.MAIN" />
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
|
||||||
<category android:name="android.intent.category.LAUNCHER" />
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
<category android:name="android.intent.category.MONKEY" />
|
<category android:name="android.intent.category.MONKEY" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
|
|
||||||
|
@ -0,0 +1,55 @@
|
|||||||
|
/*
|
||||||
|
* Kiwix Android
|
||||||
|
* Copyright (c) 2019 Kiwix <android.kiwix.org>
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
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<Class<? extends ViewModel>, Provider<ViewModel>> creators;
|
||||||
|
|
||||||
|
public ViewModelFactory(
|
||||||
|
Map<Class<? extends ViewModel>, Provider<ViewModel>> creators) {
|
||||||
|
this.creators = creators;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@Override
|
||||||
|
public <T extends ViewModel> T create(Class<T> modelClass) {
|
||||||
|
Provider<? extends ViewModel> creator = creators.get(modelClass);
|
||||||
|
if (creator == null) {
|
||||||
|
for (Map.Entry<Class<? extends ViewModel>, Provider<ViewModel>> 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -15,7 +15,7 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
package org.kiwix.kiwixmobile.zim_manager.fileselect_view.effects
|
package org.kiwix.kiwixmobile.core.base
|
||||||
|
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
|
|
@ -17,6 +17,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.kiwix.kiwixmobile.core.downloader.model
|
package org.kiwix.kiwixmobile.core.downloader.model
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
import com.tonyodev.fetch2.Error
|
import com.tonyodev.fetch2.Error
|
||||||
import com.tonyodev.fetch2.Status
|
import com.tonyodev.fetch2.Status
|
||||||
import com.tonyodev.fetch2.Status.ADDED
|
import com.tonyodev.fetch2.Status.ADDED
|
||||||
@ -43,6 +44,8 @@ data class DownloadItem(
|
|||||||
val downloadState: DownloadState
|
val downloadState: DownloadState
|
||||||
) {
|
) {
|
||||||
|
|
||||||
|
val readableEta: CharSequence = eta.takeIf { it.seconds > 0L }?.toHumanReadableTime() ?: ""
|
||||||
|
|
||||||
constructor(downloadModel: DownloadModel) : this(
|
constructor(downloadModel: DownloadModel) : this(
|
||||||
downloadModel.downloadId,
|
downloadModel.downloadId,
|
||||||
Base64String(downloadModel.book.favicon),
|
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)
|
data class Failed(val reason: Error) : DownloadState(R.string.failed_state)
|
||||||
|
|
||||||
override fun toString(): String = javaClass.simpleName
|
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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* Kiwix Android
|
||||||
|
* Copyright (c) 2019 Kiwix <android.kiwix.org>
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.kiwix.kiwixmobile.core.extensions
|
||||||
|
|
||||||
|
import android.widget.ViewAnimator
|
||||||
|
|
||||||
|
fun ViewAnimator.setDistinctDisplayedChild(index: Int) {
|
||||||
|
if (displayedChild != index) {
|
||||||
|
displayedChild = index
|
||||||
|
}
|
||||||
|
}
|
@ -1091,8 +1091,7 @@ public abstract class CoreMainActivity extends BaseActivity implements WebViewCa
|
|||||||
@NonNull String[] permissions, @NonNull int[] grantResults) {
|
@NonNull String[] permissions, @NonNull int[] grantResults) {
|
||||||
switch (requestCode) {
|
switch (requestCode) {
|
||||||
case REQUEST_STORAGE_PERMISSION: {
|
case REQUEST_STORAGE_PERMISSION: {
|
||||||
if (grantResults.length > 0
|
if (hasPermission(Manifest.permission.READ_EXTERNAL_STORAGE)) {
|
||||||
&& grantResults[0] == PERMISSION_GRANTED) {
|
|
||||||
finish();
|
finish();
|
||||||
Intent newZimFile = Intents.internal(CoreMainActivity.class);
|
Intent newZimFile = Intents.internal(CoreMainActivity.class);
|
||||||
newZimFile.setData(Uri.fromFile(file));
|
newZimFile.setData(Uri.fromFile(file));
|
||||||
@ -1222,7 +1221,6 @@ public abstract class CoreMainActivity extends BaseActivity implements WebViewCa
|
|||||||
}, 300);
|
}, 300);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@OnClick(R2.id.bottom_toolbar_bookmark)
|
@OnClick(R2.id.bottom_toolbar_bookmark)
|
||||||
public void toggleBookmark() {
|
public void toggleBookmark() {
|
||||||
//Check maybe need refresh
|
//Check maybe need refresh
|
||||||
@ -1605,7 +1603,7 @@ public abstract class CoreMainActivity extends BaseActivity implements WebViewCa
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean urlIsInvalid(){
|
protected boolean urlIsInvalid() {
|
||||||
return getCurrentWebView().getUrl() == null;
|
return getCurrentWebView().getUrl() == null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1827,14 +1825,10 @@ public abstract class CoreMainActivity extends BaseActivity implements WebViewCa
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void searchFiles() {
|
private void searchFiles() {
|
||||||
if (Build.VERSION.SDK_INT >= VERSION_CODES.M && ContextCompat.checkSelfPermission(this,
|
if (hasPermission(Manifest.permission.READ_EXTERNAL_STORAGE)) {
|
||||||
Manifest.permission.READ_EXTERNAL_STORAGE)
|
|
||||||
!= PERMISSION_GRANTED) {
|
|
||||||
ActivityCompat.requestPermissions(this,
|
|
||||||
new String[] { Manifest.permission.READ_EXTERNAL_STORAGE },
|
|
||||||
REQUEST_READ_STORAGE_PERMISSION);
|
|
||||||
} else {
|
|
||||||
scanStorageForZims();
|
scanStorageForZims();
|
||||||
|
} else {
|
||||||
|
requestExternalStoragePermission();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,6 +53,7 @@
|
|||||||
<item name="android:textColorSecondary">@color/textDarkSecondary</item>
|
<item name="android:textColorSecondary">@color/textDarkSecondary</item>
|
||||||
<item name="android:textColorTertiary">@color/textDarkTertiary</item>
|
<item name="android:textColorTertiary">@color/textDarkTertiary</item>
|
||||||
<item name="colorControlNormal">@color/accent</item>
|
<item name="colorControlNormal">@color/accent</item>
|
||||||
|
<item name="buttonStyle">@style/KiwixButtonStyle</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style name="AppTheme.Night" parent="AppTheme.Base">
|
<style name="AppTheme.Night" parent="AppTheme.Base">
|
||||||
@ -162,4 +163,8 @@
|
|||||||
<item name="layout_constraintBottom_toBottomOf">parent</item>
|
<item name="layout_constraintBottom_toBottomOf">parent</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
<style name="KiwixButtonStyle" parent="Widget.MaterialComponents.Button">
|
||||||
|
<item name="android:textAppearance">@style/TextAppearance.AppCompat.Medium</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -109,6 +109,7 @@ android {
|
|||||||
buildConfigField "int", "CONTENT_VERSION_CODE", "$parsedJson.version_code"
|
buildConfigField "int", "CONTENT_VERSION_CODE", "$parsedJson.version_code"
|
||||||
}
|
}
|
||||||
buildConfigField "String", "ENFORCED_LANG", "\"$parsedJson.enforced_lang\""
|
buildConfigField "String", "ENFORCED_LANG", "\"$parsedJson.enforced_lang\""
|
||||||
|
buildConfigField "String", "ZIM_URL", "\"$parsedJson.zim_url\""
|
||||||
resValue "string", "app_name", "$parsedJson.app_name"
|
resValue "string", "app_name", "$parsedJson.app_name"
|
||||||
resValue "string", "app_search_string", "Search " + "$parsedJson.app_name"
|
resValue "string", "app_search_string", "Search " + "$parsedJson.app_name"
|
||||||
}
|
}
|
||||||
|
@ -1,8 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools">
|
|
||||||
|
|
||||||
<uses-permission
|
|
||||||
android:name="android.permission.INTERNET"
|
|
||||||
tools:node="remove" />
|
|
||||||
</manifest>
|
|
@ -3,7 +3,8 @@
|
|||||||
"package": "org.kiwix.kiwixcustomexample",
|
"package": "org.kiwix.kiwixcustomexample",
|
||||||
"version_name": "2017-07",
|
"version_name": "2017-07",
|
||||||
"version_code": "1",
|
"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,
|
"embed_zim": false,
|
||||||
"ic_launcher": "icon.png",
|
"ic_launcher": "icon.png",
|
||||||
"enforced_lang": "en"
|
"enforced_lang": "en"
|
||||||
|
@ -39,5 +39,6 @@
|
|||||||
<category android:name="android.intent.category.DEFAULT" />
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
|
<activity android:name=".download.CustomDownloadActivity" />
|
||||||
</application>
|
</application>
|
||||||
</manifest>
|
</manifest>
|
||||||
|
@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* Kiwix Android
|
||||||
|
* Copyright (c) 2019 Kiwix <android.kiwix.org>
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
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<Class<? extends ViewModel>, Provider<ViewModel>> creators) {
|
||||||
|
super(creators);
|
||||||
|
}
|
||||||
|
}
|
@ -22,6 +22,7 @@ import android.app.Activity
|
|||||||
import dagger.BindsInstance
|
import dagger.BindsInstance
|
||||||
import dagger.Subcomponent
|
import dagger.Subcomponent
|
||||||
import org.kiwix.kiwixmobile.core.di.ActivityScope
|
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.main.CustomMainActivity
|
||||||
import org.kiwix.kiwixmobile.custom.settings.CustomSettingsActivity
|
import org.kiwix.kiwixmobile.custom.settings.CustomSettingsActivity
|
||||||
|
|
||||||
@ -30,6 +31,7 @@ import org.kiwix.kiwixmobile.custom.settings.CustomSettingsActivity
|
|||||||
interface CustomActivityComponent {
|
interface CustomActivityComponent {
|
||||||
fun inject(customMainActivity: CustomMainActivity)
|
fun inject(customMainActivity: CustomMainActivity)
|
||||||
fun inject(customSettingsActivity: CustomSettingsActivity)
|
fun inject(customSettingsActivity: CustomSettingsActivity)
|
||||||
|
fun inject(customDownloadActivity: CustomDownloadActivity)
|
||||||
|
|
||||||
@Subcomponent.Builder
|
@Subcomponent.Builder
|
||||||
interface Builder {
|
interface Builder {
|
||||||
|
@ -21,7 +21,7 @@ package org.kiwix.kiwixmobile.custom.di
|
|||||||
import dagger.Component
|
import dagger.Component
|
||||||
import org.kiwix.kiwixmobile.core.di.components.CoreComponent
|
import org.kiwix.kiwixmobile.core.di.components.CoreComponent
|
||||||
|
|
||||||
@Component(dependencies = [CoreComponent::class])
|
@Component(dependencies = [CoreComponent::class], modules = [CustomViewModelModule::class])
|
||||||
@CustomScope
|
@CustomScope
|
||||||
interface CustomComponent {
|
interface CustomComponent {
|
||||||
fun activityComponentBuilder(): CustomActivityComponent.Builder
|
fun activityComponentBuilder(): CustomActivityComponent.Builder
|
||||||
|
@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
* Kiwix Android
|
||||||
|
* Copyright (c) 2019 Kiwix <android.kiwix.org>
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* Kiwix Android
|
||||||
|
* Copyright (c) 2019 Kiwix <android.kiwix.org>
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.kiwix.kiwixmobile.custom.download
|
||||||
|
|
||||||
|
import org.kiwix.kiwixmobile.core.downloader.model.DownloadItem
|
||||||
|
|
||||||
|
sealed class Action {
|
||||||
|
data class DatabaseEmission(val downloads: List<DownloadItem>) : Action()
|
||||||
|
object ClickedDownload : Action()
|
||||||
|
object ClickedRetry : Action()
|
||||||
|
}
|
@ -0,0 +1,99 @@
|
|||||||
|
/*
|
||||||
|
* Kiwix Android
|
||||||
|
* Copyright (c) 2019 Kiwix <android.kiwix.org>
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
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<CustomDownloadViewModel>(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)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,96 @@
|
|||||||
|
/*
|
||||||
|
* Kiwix Android
|
||||||
|
* Copyright (c) 2019 Kiwix <android.kiwix.org>
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
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<State>().apply { value = DownloadRequired }
|
||||||
|
val actions = PublishProcessor.create<Action>()
|
||||||
|
private val _effects = PublishProcessor.create<SideEffect<*>>()
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,29 @@
|
|||||||
|
/*
|
||||||
|
* Kiwix Android
|
||||||
|
* Copyright (c) 2019 Kiwix <android.kiwix.org>
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
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<DownloadItem>) : State()
|
||||||
|
data class DownloadFailed(val downloadState: DownloadState) : State()
|
||||||
|
object DownloadComplete : State()
|
||||||
|
}
|
@ -0,0 +1,63 @@
|
|||||||
|
/*
|
||||||
|
* Kiwix Android
|
||||||
|
* Copyright (c) 2019 Kiwix <android.kiwix.org>
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
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<Unit> {
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
* Kiwix Android
|
||||||
|
* Copyright (c) 2019 Kiwix <android.kiwix.org>
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
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<Unit> {
|
||||||
|
override fun invokeWith(activity: Activity) {
|
||||||
|
activity.finish()
|
||||||
|
activity.start<CustomMainActivity>()
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
* Kiwix Android
|
||||||
|
* Copyright (c) 2019 Kiwix <android.kiwix.org>
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
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<Unit> {
|
||||||
|
override fun invokeWith(activity: Activity) {
|
||||||
|
ContextCompat.getExternalFilesDirs(activity, null)
|
||||||
|
.filterNotNull()
|
||||||
|
.maxBy(storageCalculator::availableBytes)
|
||||||
|
?.let { sharedPreferenceUtil.putPrefStorage(it.path) }
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,65 @@
|
|||||||
|
/*
|
||||||
|
* Kiwix Android
|
||||||
|
* Copyright (c) 2019 Kiwix <android.kiwix.org>
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
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<File> = obbFiles(),
|
||||||
|
zimFiles: List<File> = 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<out File>, extensionToMatch: String): List<File> =
|
||||||
|
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()
|
||||||
|
}
|
@ -22,23 +22,24 @@ import android.content.Intent
|
|||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.view.Menu
|
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.CoreApp
|
||||||
import org.kiwix.kiwixmobile.core.R
|
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.CoreMainActivity
|
||||||
import org.kiwix.kiwixmobile.core.main.WebViewCallback
|
import org.kiwix.kiwixmobile.core.main.WebViewCallback
|
||||||
import org.kiwix.kiwixmobile.core.reader.ZimReaderContainer
|
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.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.BuildConfig
|
||||||
import org.kiwix.kiwixmobile.custom.customActivityComponent
|
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.io.File
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
class CustomMainActivity : CoreMainActivity() {
|
class CustomMainActivity : CoreMainActivity() {
|
||||||
|
@Inject lateinit var customFileValidator: CustomFileValidator
|
||||||
|
|
||||||
override fun showHomePage() {
|
override fun showHomePage() {
|
||||||
Log.e("CustomMain", "tried to show home page")
|
Log.e("CustomMain", "tried to show home page")
|
||||||
@ -54,17 +55,22 @@ class CustomMainActivity : CoreMainActivity() {
|
|||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
Log.d(TAG_KIWIX, "This is a custom app:$packageName")
|
requireEnforcedLanguage()
|
||||||
if (loadCustomAppContent()) {
|
customFileValidator.validate(
|
||||||
Log.d(TAG_KIWIX, "Found custom content, continuing...")
|
{
|
||||||
// Continue
|
when (it) {
|
||||||
} else {
|
is HasFile -> openZimFile(it.file)
|
||||||
Log.e(TAG_KIWIX, "Problem finding the content, no more OnCreate() code")
|
is HasBothFiles -> {
|
||||||
// What should we do here? exit? I'll investigate empirically.
|
it.zimFile.delete()
|
||||||
// It seems unpredictable behaviour if the code returns at this point as yesterday
|
openZimFile(it.obbFile)
|
||||||
// it didn't crash yet today the app crashes because it tries to load books
|
}
|
||||||
// in onResume();
|
}
|
||||||
}
|
},
|
||||||
|
{
|
||||||
|
finish()
|
||||||
|
start<CustomDownloadActivity>()
|
||||||
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
|
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
|
||||||
@ -79,74 +85,15 @@ class CustomMainActivity : CoreMainActivity() {
|
|||||||
zimReaderContainer: ZimReaderContainer
|
zimReaderContainer: ZimReaderContainer
|
||||||
) = CustomWebViewClient(webViewCallback, zimReaderContainer)
|
) = CustomWebViewClient(webViewCallback, zimReaderContainer)
|
||||||
|
|
||||||
/**
|
private fun requireEnforcedLanguage(): Boolean {
|
||||||
* 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
|
|
||||||
)
|
|
||||||
|
|
||||||
val currentLocaleCode = Locale.getDefault().toString()
|
val currentLocaleCode = Locale.getDefault().toString()
|
||||||
// Custom App recommends to start off a specific language
|
if (BuildConfig.ENFORCED_LANG.isNotEmpty() && BuildConfig.ENFORCED_LANG != currentLocaleCode) {
|
||||||
if (BuildConfig.ENFORCED_LANG.length > 0 && BuildConfig.ENFORCED_LANG != currentLocaleCode) {
|
|
||||||
|
|
||||||
// change the locale machinery
|
|
||||||
LanguageUtils.handleLocaleChange(this, BuildConfig.ENFORCED_LANG)
|
LanguageUtils.handleLocaleChange(this, BuildConfig.ENFORCED_LANG)
|
||||||
|
|
||||||
// save new locale into preferences for next startup
|
|
||||||
sharedPreferenceUtil.putPrefLanguage(BuildConfig.ENFORCED_LANG)
|
sharedPreferenceUtil.putPrefLanguage(BuildConfig.ENFORCED_LANG)
|
||||||
|
startActivity(Intent(this, this.javaClass))
|
||||||
// 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))
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun manageZimFiles(tab: Int) {
|
override fun manageZimFiles(tab: Int) {
|
||||||
|
38
custom/src/main/res/layout/activity_custom_download.xml
Normal file
38
custom/src/main/res/layout/activity_custom_download.xml
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:animateLayoutChanges="true">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/cd_icon"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="@dimen/activity_vertical_margin"
|
||||||
|
android:src="@drawable/kiwix_icon_with_title"
|
||||||
|
app:layout_constraintLeft_toLeftOf="parent"
|
||||||
|
app:layout_constraintRight_toRightOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<ViewAnimator
|
||||||
|
android:id="@+id/cd_view_animator"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:inAnimation="@anim/fade_in"
|
||||||
|
android:outAnimation="@anim/fade_out"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintLeft_toLeftOf="parent"
|
||||||
|
app:layout_constraintRight_toRightOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/cd_icon">
|
||||||
|
|
||||||
|
<include layout="@layout/layout_custom_download_required" />
|
||||||
|
|
||||||
|
<include layout="@layout/layout_custom_download_in_progress" />
|
||||||
|
|
||||||
|
<include layout="@layout/layout_custom_download_error" />
|
||||||
|
|
||||||
|
<include layout="@layout/layout_custom_download_complete" />
|
||||||
|
</ViewAnimator>
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
@ -0,0 +1,20 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
tools:showIn="@layout/activity_custom_download">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
android:text="@string/complete"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintLeft_toLeftOf="parent"
|
||||||
|
app:layout_constraintRight_toRightOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintVertical_bias=".3" />
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
30
custom/src/main/res/layout/layout_custom_download_error.xml
Normal file
30
custom/src/main/res/layout/layout_custom_download_error.xml
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
tools:showIn="@layout/activity_custom_download">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/cd_error_text"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintLeft_toLeftOf="parent"
|
||||||
|
app:layout_constraintRight_toRightOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintVertical_bias=".3" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/cd_retry_button"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="20dp"
|
||||||
|
android:text="@string/retry"
|
||||||
|
app:layout_constraintLeft_toLeftOf="parent"
|
||||||
|
app:layout_constraintRight_toRightOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/cd_error_text" />
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
@ -0,0 +1,37 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/cd_download_state"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:layout_constraintBottom_toTopOf="@id/cd_progress"
|
||||||
|
app:layout_constraintLeft_toLeftOf="@+id/cd_progress"
|
||||||
|
app:layout_constraintRight_toRightOf="@+id/cd_progress" />
|
||||||
|
|
||||||
|
<ProgressBar
|
||||||
|
android:id="@+id/cd_progress"
|
||||||
|
style="?android:progressBarStyleHorizontal"
|
||||||
|
android:layout_width="200dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:max="100"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintLeft_toLeftOf="parent"
|
||||||
|
app:layout_constraintRight_toRightOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintVertical_bias=".3" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/cd_eta"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="5dp"
|
||||||
|
android:layout_marginLeft="5dp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="@id/cd_progress"
|
||||||
|
app:layout_constraintStart_toEndOf="@id/cd_progress"
|
||||||
|
app:layout_constraintTop_toTopOf="@id/cd_progress" />
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
@ -0,0 +1,31 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
tools:showIn="@layout/activity_custom_download">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/cd_text"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
android:text="@string/invalid_installation"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintLeft_toLeftOf="parent"
|
||||||
|
app:layout_constraintRight_toRightOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintVertical_bias=".3" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/cd_download_button"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="20dp"
|
||||||
|
android:text="@string/download"
|
||||||
|
app:layout_constraintLeft_toLeftOf="parent"
|
||||||
|
app:layout_constraintRight_toRightOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/cd_text" />
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
8
custom/src/main/res/values/strings.xml
Normal file
8
custom/src/main/res/values/strings.xml
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
|
<resources>
|
||||||
|
<string name="retry">Retry</string>
|
||||||
|
<string name="download">Download</string>
|
||||||
|
<string name="invalid_installation">Invalid Install. Please Download Zim.\n Ensure WiFi is on and you have enough storage</string>
|
||||||
|
<string name="complete">Complete</string>
|
||||||
|
</resources>
|
Loading…
x
Reference in New Issue
Block a user