mirror of
https://github.com/kiwix/kiwix-android.git
synced 2025-09-24 05:04:50 -04:00
Merge pull request #4372 from kiwix/Fixes#4371
Migrated the `CustomDownloadFragment` to Jetpack Compose.
This commit is contained in:
commit
e7d9f3c809
@ -1769,7 +1769,7 @@ abstract class CoreReaderFragment :
|
|||||||
}
|
}
|
||||||
|
|
||||||
// opens home screen when user closes all tabs
|
// opens home screen when user closes all tabs
|
||||||
protected fun showNoBookOpenViews() {
|
open fun showNoBookOpenViews() {
|
||||||
readerScreenState.update { copy(isNoBookOpenInReader = true) }
|
readerScreenState.update { copy(isNoBookOpenInReader = true) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -195,4 +195,8 @@ object ComposeDimens {
|
|||||||
|
|
||||||
// MainActivity dimens
|
// MainActivity dimens
|
||||||
val NAVIGATION_DRAWER_WIDTH = 280.dp
|
val NAVIGATION_DRAWER_WIDTH = 280.dp
|
||||||
|
|
||||||
|
// Custom download screen dimens
|
||||||
|
val CUSTOM_DOWNLOAD_LAYOUT_TOP_MARGIN = 100.dp
|
||||||
|
val CUSTOM_DOWNLOAD_PROGRESS_BAR_WIDTH = 200.dp
|
||||||
}
|
}
|
||||||
|
@ -1,8 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<androidx.recyclerview.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:id="@+id/right_drawer_list"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:clickable="true"
|
|
||||||
android:clipToPadding="false"
|
|
||||||
android:focusable="true" />
|
|
@ -1,29 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?><!--
|
|
||||||
~ Kiwix Android
|
|
||||||
~ Copyright (c) 2020 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/>.
|
|
||||||
~
|
|
||||||
-->
|
|
||||||
|
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools">
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
tools:ignore="ContentDescription"
|
|
||||||
android:src="@drawable/ic_home_kiwix_banner" />
|
|
||||||
</LinearLayout>
|
|
@ -1,30 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="@dimen/section_list_height"
|
|
||||||
android:background="?android:attr/selectableItemBackground"
|
|
||||||
android:clickable="false"
|
|
||||||
android:focusable="false"
|
|
||||||
android:gravity="center_vertical"
|
|
||||||
android:orientation="horizontal"
|
|
||||||
tools:ignore="Overdraw">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/titleText"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_centerVertical="true"
|
|
||||||
android:layout_marginStart="@dimen/title_text_margin"
|
|
||||||
android:layout_marginEnd="@dimen/title_text_margin"
|
|
||||||
android:ellipsize="end"
|
|
||||||
android:fontFamily="sans-serif-light"
|
|
||||||
android:gravity="center_vertical"
|
|
||||||
android:maxLines="1"
|
|
||||||
android:minHeight="?listPreferredItemHeightSmall"
|
|
||||||
android:paddingStart="@dimen/title_text_padding"
|
|
||||||
android:paddingEnd="0dp"
|
|
||||||
android:textAppearance="?textAppearanceBody1"
|
|
||||||
tools:text="Some text" />
|
|
||||||
|
|
||||||
</RelativeLayout>
|
|
@ -19,39 +19,33 @@
|
|||||||
package org.kiwix.kiwixmobile.custom.download
|
package org.kiwix.kiwixmobile.custom.download
|
||||||
|
|
||||||
import android.Manifest.permission.POST_NOTIFICATIONS
|
import android.Manifest.permission.POST_NOTIFICATIONS
|
||||||
import android.content.Context
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.ui.platform.ComposeView
|
||||||
import androidx.core.app.ActivityCompat
|
import androidx.core.app.ActivityCompat
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import org.kiwix.kiwixmobile.core.R
|
|
||||||
import org.kiwix.kiwixmobile.core.base.BaseActivity
|
import org.kiwix.kiwixmobile.core.base.BaseActivity
|
||||||
import org.kiwix.kiwixmobile.core.base.BaseFragment
|
import org.kiwix.kiwixmobile.core.base.BaseFragment
|
||||||
import org.kiwix.kiwixmobile.core.base.FragmentActivityExtensions
|
import org.kiwix.kiwixmobile.core.base.FragmentActivityExtensions
|
||||||
import org.kiwix.kiwixmobile.core.data.remote.isAuthenticationUrl
|
|
||||||
import org.kiwix.kiwixmobile.core.downloader.model.DownloadItem
|
|
||||||
import org.kiwix.kiwixmobile.core.downloader.model.DownloadState
|
|
||||||
import org.kiwix.kiwixmobile.core.extensions.ActivityExtensions.hasNotificationPermission
|
import org.kiwix.kiwixmobile.core.extensions.ActivityExtensions.hasNotificationPermission
|
||||||
import org.kiwix.kiwixmobile.core.extensions.ActivityExtensions.requestNotificationPermission
|
import org.kiwix.kiwixmobile.core.extensions.ActivityExtensions.requestNotificationPermission
|
||||||
import org.kiwix.kiwixmobile.core.extensions.setDistinctDisplayedChild
|
import org.kiwix.kiwixmobile.core.extensions.update
|
||||||
import org.kiwix.kiwixmobile.core.extensions.viewModel
|
import org.kiwix.kiwixmobile.core.extensions.viewModel
|
||||||
import org.kiwix.kiwixmobile.core.main.CoreMainActivity
|
import org.kiwix.kiwixmobile.core.main.CoreMainActivity
|
||||||
import org.kiwix.kiwixmobile.core.navigateToAppSettings
|
import org.kiwix.kiwixmobile.core.navigateToAppSettings
|
||||||
import org.kiwix.kiwixmobile.core.utils.SharedPreferenceUtil
|
import org.kiwix.kiwixmobile.core.utils.SharedPreferenceUtil
|
||||||
|
import org.kiwix.kiwixmobile.core.utils.dialog.AlertDialogShower
|
||||||
|
import org.kiwix.kiwixmobile.core.utils.dialog.DialogHost
|
||||||
import org.kiwix.kiwixmobile.core.utils.dialog.DialogShower
|
import org.kiwix.kiwixmobile.core.utils.dialog.DialogShower
|
||||||
import org.kiwix.kiwixmobile.core.utils.dialog.KiwixDialog
|
import org.kiwix.kiwixmobile.core.utils.dialog.KiwixDialog
|
||||||
import org.kiwix.kiwixmobile.custom.customActivityComponent
|
import org.kiwix.kiwixmobile.custom.customActivityComponent
|
||||||
import org.kiwix.kiwixmobile.custom.databinding.FragmentCustomDownloadBinding
|
|
||||||
import org.kiwix.kiwixmobile.custom.download.Action.ClickedDownload
|
import org.kiwix.kiwixmobile.custom.download.Action.ClickedDownload
|
||||||
import org.kiwix.kiwixmobile.custom.download.Action.ClickedRetry
|
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
|
import javax.inject.Inject
|
||||||
|
|
||||||
class CustomDownloadFragment : BaseFragment(), FragmentActivityExtensions {
|
class CustomDownloadFragment : BaseFragment(), FragmentActivityExtensions {
|
||||||
@ -68,8 +62,8 @@ class CustomDownloadFragment : BaseFragment(), FragmentActivityExtensions {
|
|||||||
var sharedPreferenceUtil: SharedPreferenceUtil? = null
|
var sharedPreferenceUtil: SharedPreferenceUtil? = null
|
||||||
|
|
||||||
@Inject lateinit var viewModelFactory: ViewModelProvider.Factory
|
@Inject lateinit var viewModelFactory: ViewModelProvider.Factory
|
||||||
|
private var composeView: ComposeView? = null
|
||||||
private var fragmentCustomDownloadBinding: FragmentCustomDownloadBinding? = null
|
private var downloadState = mutableStateOf<State>(State.DownloadRequired)
|
||||||
override fun inject(baseActivity: BaseActivity) {
|
override fun inject(baseActivity: BaseActivity) {
|
||||||
baseActivity.customActivityComponent.inject(this)
|
baseActivity.customActivityComponent.inject(this)
|
||||||
}
|
}
|
||||||
@ -80,12 +74,20 @@ class CustomDownloadFragment : BaseFragment(), FragmentActivityExtensions {
|
|||||||
savedInstanceState: Bundle?
|
savedInstanceState: Bundle?
|
||||||
): View? {
|
): View? {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
fragmentCustomDownloadBinding =
|
composeView = ComposeView(requireContext()).apply {
|
||||||
FragmentCustomDownloadBinding.inflate(inflater, container, false)
|
setContent {
|
||||||
|
CustomDownloadScreen(
|
||||||
|
state = downloadState.value,
|
||||||
|
onDownloadClick = { downloadButtonClick() },
|
||||||
|
onRetryClick = { retryButtonClick() }
|
||||||
|
)
|
||||||
|
DialogHost(alertDialogShower as AlertDialogShower)
|
||||||
|
}
|
||||||
|
}
|
||||||
val activity = requireActivity() as CoreMainActivity
|
val activity = requireActivity() as CoreMainActivity
|
||||||
viewLifecycleOwner.lifecycleScope.launch {
|
viewLifecycleOwner.lifecycleScope.launch {
|
||||||
downloadViewModel.state.collect { state ->
|
downloadViewModel.state.collect { state ->
|
||||||
render(state)
|
downloadState.update { state }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -95,28 +97,24 @@ class CustomDownloadFragment : BaseFragment(), FragmentActivityExtensions {
|
|||||||
effect.invokeWith(activity)
|
effect.invokeWith(activity)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return fragmentCustomDownloadBinding?.root
|
return composeView
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
private fun downloadButtonClick() {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
|
||||||
fragmentCustomDownloadBinding?.apply {
|
|
||||||
customDownloadRequired.cdDownloadButton.setOnClickListener {
|
|
||||||
if (requireActivity().hasNotificationPermission(sharedPreferenceUtil)) {
|
if (requireActivity().hasNotificationPermission(sharedPreferenceUtil)) {
|
||||||
performAction(ClickedDownload)
|
performAction(ClickedDownload)
|
||||||
} else {
|
} else {
|
||||||
requestNotificationPermission()
|
requestNotificationPermission()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
customDownloadError.cdRetryButton.setOnClickListener {
|
|
||||||
|
private fun retryButtonClick() {
|
||||||
if (requireActivity().hasNotificationPermission(sharedPreferenceUtil)) {
|
if (requireActivity().hasNotificationPermission(sharedPreferenceUtil)) {
|
||||||
performAction(ClickedRetry)
|
performAction(ClickedRetry)
|
||||||
} else {
|
} else {
|
||||||
requestNotificationPermission()
|
requestNotificationPermission()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun performAction(action: Action) {
|
private fun performAction(action: Action) {
|
||||||
viewLifecycleOwner.lifecycleScope.launch {
|
viewLifecycleOwner.lifecycleScope.launch {
|
||||||
@ -144,63 +142,9 @@ class CustomDownloadFragment : BaseFragment(), FragmentActivityExtensions {
|
|||||||
activity?.finish()
|
activity?.finish()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun render(state: State): Unit? {
|
|
||||||
return when (state) {
|
|
||||||
DownloadRequired ->
|
|
||||||
fragmentCustomDownloadBinding?.cdViewAnimator?.setDistinctDisplayedChild(0)
|
|
||||||
|
|
||||||
is DownloadInProgress -> {
|
|
||||||
fragmentCustomDownloadBinding?.cdViewAnimator?.setDistinctDisplayedChild(1)
|
|
||||||
showDownloadingProgress(state.downloads[0])
|
|
||||||
}
|
|
||||||
|
|
||||||
is DownloadFailed -> {
|
|
||||||
fragmentCustomDownloadBinding?.cdViewAnimator?.setDistinctDisplayedChild(2)
|
|
||||||
val errorMessage = context?.let { context ->
|
|
||||||
if (state.downloadState.zimUrl?.isAuthenticationUrl == false) {
|
|
||||||
return@let getErrorMessageFromDownloadState(state.downloadState, context)
|
|
||||||
}
|
|
||||||
|
|
||||||
val defaultErrorMessage = getErrorMessageFromDownloadState(state.downloadState, context)
|
|
||||||
// Check if `REQUEST_NOT_SUCCESSFUL` indicates an unsuccessful response from the server.
|
|
||||||
// If the server does not respond to the URL, we will display a custom message to the user.
|
|
||||||
if (defaultErrorMessage == context.getString(
|
|
||||||
R.string.failed_state,
|
|
||||||
"REQUEST_NOT_SUCCESSFUL"
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
context.getString(
|
|
||||||
R.string.failed_state,
|
|
||||||
context.getString(R.string.custom_download_error_message_for_authentication_failed)
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
defaultErrorMessage
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fragmentCustomDownloadBinding?.customDownloadError?.cdErrorText?.text = errorMessage
|
|
||||||
}
|
|
||||||
|
|
||||||
DownloadComplete ->
|
|
||||||
fragmentCustomDownloadBinding?.cdViewAnimator?.setDistinctDisplayedChild(3)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getErrorMessageFromDownloadState(
|
|
||||||
downloadState: DownloadState,
|
|
||||||
context: Context
|
|
||||||
): String = "${downloadState.toReadableState(context)}"
|
|
||||||
|
|
||||||
private fun showDownloadingProgress(downloadItem: DownloadItem) {
|
|
||||||
fragmentCustomDownloadBinding?.customDownloadInProgress?.apply {
|
|
||||||
cdDownloadState.text = downloadItem.readableEta
|
|
||||||
cdEta.text = context?.let(downloadItem.downloadState::toReadableState)
|
|
||||||
cdProgress.progress = downloadItem.progress
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onDestroyView() {
|
override fun onDestroyView() {
|
||||||
super.onDestroyView()
|
super.onDestroyView()
|
||||||
fragmentCustomDownloadBinding?.root?.removeAllViews()
|
composeView?.disposeComposition()
|
||||||
fragmentCustomDownloadBinding = null
|
composeView = null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,203 @@
|
|||||||
|
/*
|
||||||
|
* Kiwix Android
|
||||||
|
* Copyright (c) 2025 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.content.Context
|
||||||
|
import androidx.compose.animation.Crossfade
|
||||||
|
import androidx.compose.animation.animateContentSize
|
||||||
|
import androidx.compose.foundation.Image
|
||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.Row
|
||||||
|
import androidx.compose.foundation.layout.Spacer
|
||||||
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.height
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.layout.width
|
||||||
|
import androidx.compose.foundation.layout.wrapContentSize
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
import androidx.compose.ui.res.painterResource
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
|
import org.kiwix.kiwixmobile.core.R.string
|
||||||
|
import org.kiwix.kiwixmobile.core.data.remote.isAuthenticationUrl
|
||||||
|
import org.kiwix.kiwixmobile.core.downloader.model.DownloadItem
|
||||||
|
import org.kiwix.kiwixmobile.core.downloader.model.DownloadState
|
||||||
|
import org.kiwix.kiwixmobile.core.ui.components.ContentLoadingProgressBar
|
||||||
|
import org.kiwix.kiwixmobile.core.ui.components.KiwixButton
|
||||||
|
import org.kiwix.kiwixmobile.core.ui.components.ProgressBarStyle
|
||||||
|
import org.kiwix.kiwixmobile.core.utils.ComposeDimens.CUSTOM_DOWNLOAD_LAYOUT_TOP_MARGIN
|
||||||
|
import org.kiwix.kiwixmobile.core.utils.ComposeDimens.CUSTOM_DOWNLOAD_PROGRESS_BAR_WIDTH
|
||||||
|
import org.kiwix.kiwixmobile.core.utils.ComposeDimens.FIVE_DP
|
||||||
|
import org.kiwix.kiwixmobile.core.utils.ComposeDimens.SIX_DP
|
||||||
|
import org.kiwix.kiwixmobile.core.utils.ComposeDimens.TWENTY_DP
|
||||||
|
import org.kiwix.kiwixmobile.custom.R
|
||||||
|
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
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun CustomDownloadScreen(
|
||||||
|
state: State,
|
||||||
|
onDownloadClick: () -> Unit,
|
||||||
|
onRetryClick: () -> Unit
|
||||||
|
) {
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.animateContentSize()
|
||||||
|
) {
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.padding(top = CUSTOM_DOWNLOAD_LAYOUT_TOP_MARGIN),
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally
|
||||||
|
) {
|
||||||
|
Image(
|
||||||
|
painter = painterResource(id = R.mipmap.ic_launcher_foreground),
|
||||||
|
contentDescription = stringResource(id = R.string.app_name),
|
||||||
|
modifier = Modifier
|
||||||
|
.wrapContentSize()
|
||||||
|
.align(Alignment.CenterHorizontally)
|
||||||
|
)
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.weight(1f)
|
||||||
|
.fillMaxWidth(),
|
||||||
|
contentAlignment = Alignment.Center
|
||||||
|
) {
|
||||||
|
Crossfade(targetState = state, label = "download-state") { currentState ->
|
||||||
|
when (currentState) {
|
||||||
|
is DownloadRequired -> DownloadRequiredView(onDownloadClick)
|
||||||
|
is DownloadInProgress -> DownloadInProgressView(currentState.downloads[0])
|
||||||
|
is DownloadFailed -> DownloadErrorView(onRetryClick, currentState)
|
||||||
|
is DownloadComplete -> DownloadCompleteView()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun DownloadRequiredView(onDownloadClick: () -> Unit) {
|
||||||
|
Column(
|
||||||
|
modifier = Modifier.wrapContentSize(Alignment.Center),
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = stringResource(id = R.string.invalid_installation),
|
||||||
|
textAlign = TextAlign.Center
|
||||||
|
)
|
||||||
|
Spacer(modifier = Modifier.height(TWENTY_DP))
|
||||||
|
KiwixButton(
|
||||||
|
clickListener = onDownloadClick,
|
||||||
|
buttonText = stringResource(id = string.download)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun DownloadInProgressView(downloadItem: DownloadItem) {
|
||||||
|
Column(
|
||||||
|
modifier = Modifier.wrapContentSize(Alignment.Center),
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally
|
||||||
|
) {
|
||||||
|
Text(text = downloadItem.readableEta.toString())
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.height(TWENTY_DP))
|
||||||
|
|
||||||
|
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||||
|
ContentLoadingProgressBar(
|
||||||
|
progress = downloadItem.progress,
|
||||||
|
modifier = Modifier
|
||||||
|
.width(CUSTOM_DOWNLOAD_PROGRESS_BAR_WIDTH)
|
||||||
|
.height(SIX_DP),
|
||||||
|
progressBarStyle = ProgressBarStyle.HORIZONTAL
|
||||||
|
)
|
||||||
|
Spacer(modifier = Modifier.width(FIVE_DP))
|
||||||
|
Text(text = downloadItem.downloadState.toReadableState(LocalContext.current).toString())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun DownloadErrorView(onRetryClick: () -> Unit, downloadFailed: DownloadFailed) {
|
||||||
|
val context = LocalContext.current
|
||||||
|
Column(
|
||||||
|
modifier = Modifier.wrapContentSize(Alignment.Center),
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = getActualErrorMessage(downloadFailed, context),
|
||||||
|
textAlign = TextAlign.Center
|
||||||
|
)
|
||||||
|
Spacer(modifier = Modifier.height(TWENTY_DP))
|
||||||
|
KiwixButton(
|
||||||
|
clickListener = onRetryClick,
|
||||||
|
buttonText = stringResource(id = R.string.retry)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getActualErrorMessage(downloadFailed: DownloadFailed, context: Context): String {
|
||||||
|
if (downloadFailed.downloadState.zimUrl?.isAuthenticationUrl == false) {
|
||||||
|
return getErrorMessageFromDownloadState(downloadFailed.downloadState, context)
|
||||||
|
}
|
||||||
|
|
||||||
|
val defaultErrorMessage = getErrorMessageFromDownloadState(downloadFailed.downloadState, context)
|
||||||
|
// Check if `REQUEST_NOT_SUCCESSFUL` indicates an unsuccessful response from the server.
|
||||||
|
// If the server does not respond to the URL, we will display a custom message to the user.
|
||||||
|
return if (defaultErrorMessage == context.getString(
|
||||||
|
string.failed_state,
|
||||||
|
"REQUEST_NOT_SUCCESSFUL"
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
context.getString(
|
||||||
|
string.failed_state,
|
||||||
|
context.getString(string.custom_download_error_message_for_authentication_failed)
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
defaultErrorMessage
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getErrorMessageFromDownloadState(
|
||||||
|
downloadState: DownloadState,
|
||||||
|
context: Context
|
||||||
|
): String = "${downloadState.toReadableState(context)}"
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun DownloadCompleteView() {
|
||||||
|
Box(
|
||||||
|
modifier = Modifier.wrapContentSize(Alignment.Center),
|
||||||
|
contentAlignment = Alignment.TopCenter
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = stringResource(id = string.complete),
|
||||||
|
textAlign = TextAlign.Center
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
@ -20,6 +20,8 @@ package org.kiwix.kiwixmobile.custom.main
|
|||||||
|
|
||||||
import android.app.Dialog
|
import android.app.Dialog
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import android.os.Handler
|
||||||
|
import android.os.Looper
|
||||||
import android.view.Menu
|
import android.view.Menu
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
@ -53,6 +55,8 @@ import java.io.File
|
|||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
const val OPENING_DOWNLOAD_SCREEN_DELAY = 300L
|
||||||
|
|
||||||
class CustomReaderFragment : CoreReaderFragment() {
|
class CustomReaderFragment : CoreReaderFragment() {
|
||||||
override fun inject(baseActivity: BaseActivity) {
|
override fun inject(baseActivity: BaseActivity) {
|
||||||
baseActivity.customActivityComponent.inject(this)
|
baseActivity.customActivityComponent.inject(this)
|
||||||
@ -288,6 +292,7 @@ class CustomReaderFragment : CoreReaderFragment() {
|
|||||||
},
|
},
|
||||||
onNoFilesFound = {
|
onNoFilesFound = {
|
||||||
if (sharedPreferenceUtil?.prefIsTest == false) {
|
if (sharedPreferenceUtil?.prefIsTest == false) {
|
||||||
|
Handler(Looper.getMainLooper()).postDelayed({
|
||||||
val navOptions = NavOptions.Builder()
|
val navOptions = NavOptions.Builder()
|
||||||
.setPopUpTo(CustomDestination.Reader.route, true)
|
.setPopUpTo(CustomDestination.Reader.route, true)
|
||||||
.build()
|
.build()
|
||||||
@ -295,6 +300,7 @@ class CustomReaderFragment : CoreReaderFragment() {
|
|||||||
CustomDestination.Downloads.route,
|
CustomDestination.Downloads.route,
|
||||||
navOptions
|
navOptions
|
||||||
)
|
)
|
||||||
|
}, OPENING_DOWNLOAD_SCREEN_DELAY)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@ -389,6 +395,10 @@ class CustomReaderFragment : CoreReaderFragment() {
|
|||||||
newMainPageTab()
|
newMainPageTab()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun showNoBookOpenViews() {
|
||||||
|
readerScreenState.update { copy(isNoBookOpenInReader = false) }
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Overrides the method to show the donation popup. When the "Support url" is disabled
|
* Overrides the method to show the donation popup. When the "Support url" is disabled
|
||||||
* in a custom app, this function stop to show the donationPopup.
|
* in a custom app, this function stop to show the donationPopup.
|
||||||
|
@ -1,47 +0,0 @@
|
|||||||
<?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="100dp"
|
|
||||||
android:contentDescription="@string/app_name"
|
|
||||||
android:src="@mipmap/ic_launcher_foreground"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
|
||||||
|
|
||||||
<ViewAnimator
|
|
||||||
android:id="@+id/cd_view_animator"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="0dp"
|
|
||||||
android:inAnimation="@android:anim/fade_in"
|
|
||||||
android:outAnimation="@android:anim/fade_out"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toBottomOf="@+id/cd_icon">
|
|
||||||
|
|
||||||
<include
|
|
||||||
android:id="@+id/custom_download_required"
|
|
||||||
layout="@layout/layout_custom_download_required" />
|
|
||||||
|
|
||||||
<include
|
|
||||||
android:id="@+id/custom_download_in_progress"
|
|
||||||
layout="@layout/layout_custom_download_in_progress" />
|
|
||||||
|
|
||||||
<include
|
|
||||||
android:id="@+id/custom_download_error"
|
|
||||||
layout="@layout/layout_custom_download_error" />
|
|
||||||
|
|
||||||
<include
|
|
||||||
android:id="@+id/custom_download_complete"
|
|
||||||
layout="@layout/layout_custom_download_complete" />
|
|
||||||
</ViewAnimator>
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -1,20 +0,0 @@
|
|||||||
<?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/fragment_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_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
|
||||||
app:layout_constraintVertical_bias=".3" />
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -1,30 +0,0 @@
|
|||||||
<?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/fragment_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_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintEnd_toEndOf="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_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintTop_toBottomOf="@+id/cd_error_text" />
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -1,36 +0,0 @@
|
|||||||
<?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_constraintStart_toStartOf="@+id/cd_progress"
|
|
||||||
app:layout_constraintEnd_toEndOf="@+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_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintEnd_toEndOf="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"
|
|
||||||
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>
|
|
@ -1,31 +0,0 @@
|
|||||||
<?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/fragment_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_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintEnd_toEndOf="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_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintTop_toBottomOf="@+id/cd_text" />
|
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
Loading…
x
Reference in New Issue
Block a user