mirror of
https://github.com/kiwix/kiwix-android.git
synced 2025-08-03 10:46:53 -04:00
Improved the design of showing the downloading progress of online library.
* Also, disabled the refresh layout so avoid unnecessary calls when a request is already in progress.
This commit is contained in:
parent
90f711b244
commit
c5d0d8aeea
@ -41,6 +41,7 @@ import androidx.core.app.ActivityCompat
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.view.MenuHost
|
||||
import androidx.core.view.MenuProvider
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import androidx.lifecycle.Observer
|
||||
@ -86,6 +87,7 @@ import org.kiwix.kiwixmobile.core.utils.dialog.KiwixDialog
|
||||
import org.kiwix.kiwixmobile.core.utils.dialog.KiwixDialog.YesNoDialog.WifiOnly
|
||||
import org.kiwix.kiwixmobile.databinding.FragmentDestinationDownloadBinding
|
||||
import org.kiwix.kiwixmobile.zimManager.NetworkState
|
||||
import org.kiwix.kiwixmobile.zimManager.OnlineLibraryStatus
|
||||
import org.kiwix.kiwixmobile.zimManager.ZimManageViewModel
|
||||
import org.kiwix.kiwixmobile.zimManager.libraryView.AvailableSpaceCalculator
|
||||
import org.kiwix.kiwixmobile.zimManager.libraryView.adapter.LibraryAdapter
|
||||
@ -192,16 +194,11 @@ class OnlineLibraryFragment : BaseFragment(), FragmentActivityExtensions {
|
||||
viewLifecycleOwner
|
||||
) {
|
||||
if (it && !NetworkUtils.isWiFi(requireContext())) {
|
||||
hideProgressBarOfFetchingOnlineLibrary()
|
||||
showInternetAccessViaMobileNetworkDialog()
|
||||
}
|
||||
}
|
||||
zimManageViewModel.downloadProgress.observe(viewLifecycleOwner) { progress ->
|
||||
fragmentDestinationDownloadBinding?.onlineLibraryProgressBar?.progress = progress
|
||||
}
|
||||
|
||||
zimManageViewModel.downloadStatus.observe(viewLifecycleOwner) { status ->
|
||||
fragmentDestinationDownloadBinding?.libraryErrorText?.text = status
|
||||
}
|
||||
zimManageViewModel.downloadProgress.observe(viewLifecycleOwner, ::onLibraryStatusChanged)
|
||||
setupMenu()
|
||||
|
||||
// hides keyboard when scrolled
|
||||
@ -254,13 +251,11 @@ class OnlineLibraryFragment : BaseFragment(), FragmentActivityExtensions {
|
||||
dialogShower.show(
|
||||
WifiOnly,
|
||||
{
|
||||
onRefreshStateChange(true)
|
||||
showRecyclerviewAndHideSwipeDownForLibraryErrorText()
|
||||
sharedPreferenceUtil.putPrefWifiOnly(false)
|
||||
zimManageViewModel.shouldShowWifiOnlyDialog.value = false
|
||||
},
|
||||
{
|
||||
onRefreshStateChange(false)
|
||||
context.toast(
|
||||
resources.getString(string.denied_internet_permission_message),
|
||||
Toast.LENGTH_SHORT
|
||||
@ -285,17 +280,32 @@ class OnlineLibraryFragment : BaseFragment(), FragmentActivityExtensions {
|
||||
)
|
||||
libraryErrorText.visibility = View.VISIBLE
|
||||
libraryList.visibility = View.GONE
|
||||
onlineLibraryProgressBar.visibility = View.GONE
|
||||
}
|
||||
hideProgressBarOfFetchingOnlineLibrary()
|
||||
}
|
||||
|
||||
private fun showProgressBarOfFetchingOnlineLibrary() {
|
||||
onRefreshStateChange(false)
|
||||
fragmentDestinationDownloadBinding?.apply {
|
||||
onlineLibraryProgressBar.visibility = View.VISIBLE
|
||||
libraryErrorText.apply {
|
||||
visibility = View.VISIBLE
|
||||
setText(string.reaching_remote_library)
|
||||
}
|
||||
librarySwipeRefresh.isEnabled = false
|
||||
onlineLibraryProgressLayout.visibility = View.VISIBLE
|
||||
onlineLibraryProgressStatusText.setText(string.reaching_remote_library)
|
||||
}
|
||||
}
|
||||
|
||||
private fun hideProgressBarOfFetchingOnlineLibrary() {
|
||||
onRefreshStateChange(false)
|
||||
fragmentDestinationDownloadBinding?.apply {
|
||||
librarySwipeRefresh.isEnabled = true
|
||||
onlineLibraryProgressLayout.visibility = View.GONE
|
||||
onlineLibraryProgressStatusText.setText(string.reaching_remote_library)
|
||||
}
|
||||
}
|
||||
|
||||
private fun onLibraryStatusChanged(onlineLibraryStatus: OnlineLibraryStatus) {
|
||||
fragmentDestinationDownloadBinding?.apply {
|
||||
onlineLibraryProgressBar.progress = onlineLibraryStatus.progress
|
||||
onlineLibraryProgressStatusText.text = onlineLibraryStatus.status
|
||||
}
|
||||
}
|
||||
|
||||
@ -312,17 +322,20 @@ class OnlineLibraryFragment : BaseFragment(), FragmentActivityExtensions {
|
||||
}
|
||||
|
||||
private fun onRefreshStateChange(isRefreshing: Boolean?) {
|
||||
fragmentDestinationDownloadBinding?.librarySwipeRefresh?.isRefreshing = isRefreshing == true
|
||||
var refreshing = isRefreshing == true
|
||||
// do not show the refreshing when the online library is downloading
|
||||
if (fragmentDestinationDownloadBinding?.onlineLibraryProgressLayout?.isVisible == true) {
|
||||
refreshing = false
|
||||
}
|
||||
fragmentDestinationDownloadBinding?.librarySwipeRefresh?.isRefreshing = refreshing
|
||||
}
|
||||
|
||||
private fun onNetworkStateChange(networkState: NetworkState?) {
|
||||
when (networkState) {
|
||||
NetworkState.CONNECTED -> {
|
||||
if (NetworkUtils.isWiFi(requireContext())) {
|
||||
onRefreshStateChange(true)
|
||||
refreshFragment()
|
||||
} else if (noWifiWithWifiOnlyPreferenceSet) {
|
||||
onRefreshStateChange(false)
|
||||
hideRecyclerviewAndShowSwipeDownForLibraryErrorText()
|
||||
}
|
||||
}
|
||||
@ -344,7 +357,7 @@ class OnlineLibraryFragment : BaseFragment(), FragmentActivityExtensions {
|
||||
)
|
||||
fragmentDestinationDownloadBinding?.libraryErrorText?.visibility = View.VISIBLE
|
||||
}
|
||||
fragmentDestinationDownloadBinding?.librarySwipeRefresh?.isRefreshing = false
|
||||
hideProgressBarOfFetchingOnlineLibrary()
|
||||
}
|
||||
|
||||
private fun noInternetSnackbar() {
|
||||
@ -364,7 +377,7 @@ class OnlineLibraryFragment : BaseFragment(), FragmentActivityExtensions {
|
||||
if (it != null) {
|
||||
libraryAdapter.items = it
|
||||
}
|
||||
fragmentDestinationDownloadBinding?.onlineLibraryProgressBar?.visibility = View.GONE
|
||||
hideProgressBarOfFetchingOnlineLibrary()
|
||||
if (it?.isEmpty() == true) {
|
||||
fragmentDestinationDownloadBinding?.libraryErrorText?.setText(
|
||||
if (isNotConnected) string.no_network_connection
|
||||
|
@ -26,6 +26,11 @@ class AppProgressListenerProvider(
|
||||
@Suppress("MagicNumber")
|
||||
override fun onProgress(bytesRead: Long, contentLength: Long, done: Boolean) {
|
||||
val progress = if (contentLength == -1L) 0 else (bytesRead * 100 / contentLength).toInt()
|
||||
zimManageViewModel.downloadProgress.postValue(progress)
|
||||
zimManageViewModel.downloadProgress.postValue(
|
||||
OnlineLibraryStatus(
|
||||
progress,
|
||||
"Downloading online content"
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Kiwix Android
|
||||
* Copyright (c) 2024 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.zimManager
|
||||
|
||||
data class OnlineLibraryStatus(val progress: Int, val status: String)
|
@ -140,8 +140,7 @@ class ZimManageViewModel @Inject constructor(
|
||||
val requestFiltering = BehaviorProcessor.createDefault("")
|
||||
|
||||
private var compositeDisposable: CompositeDisposable? = CompositeDisposable()
|
||||
val downloadProgress = MutableLiveData<Int>()
|
||||
val downloadStatus = MutableLiveData<String>()
|
||||
val downloadProgress = MutableLiveData<OnlineLibraryStatus>()
|
||||
|
||||
init {
|
||||
// add listener to retrofit to get updates of downloading online library
|
||||
@ -299,14 +298,6 @@ class ZimManageViewModel @Inject constructor(
|
||||
.map { }
|
||||
}
|
||||
}
|
||||
.doOnEach {
|
||||
downloadStatus.postValue("Reaching remote library")
|
||||
}
|
||||
.switchMap {
|
||||
Flowable.fromCallable {
|
||||
downloadStatus.postValue("Starting download of the online library")
|
||||
}
|
||||
}
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(Schedulers.io())
|
||||
.flatMap {
|
||||
@ -314,18 +305,32 @@ class ZimManageViewModel @Inject constructor(
|
||||
.toFlowable()
|
||||
.retry(5)
|
||||
.doOnSubscribe {
|
||||
downloadStatus.postValue("Downloading library 0%")
|
||||
downloadProgress.postValue(OnlineLibraryStatus(0, "Downloading library 0%"))
|
||||
}
|
||||
.map { response ->
|
||||
downloadStatus.postValue("Downloading library... parsing response")
|
||||
downloadProgress.postValue(
|
||||
OnlineLibraryStatus(
|
||||
0,
|
||||
"Downloading library... parsing response"
|
||||
)
|
||||
)
|
||||
response
|
||||
}
|
||||
.doFinally {
|
||||
downloadStatus.postValue("Remote library downloaded, parsing data")
|
||||
downloadProgress.postValue(
|
||||
OnlineLibraryStatus(
|
||||
0,
|
||||
"Remote library downloaded, parsing data"
|
||||
)
|
||||
)
|
||||
}
|
||||
.onErrorReturn {
|
||||
it.printStackTrace()
|
||||
downloadStatus.postValue("Failed to download the library")
|
||||
downloadProgress.postValue(
|
||||
OnlineLibraryStatus(
|
||||
0, "Failed to download the library"
|
||||
)
|
||||
)
|
||||
LibraryNetworkEntity().apply { book = LinkedList() }
|
||||
}
|
||||
}
|
||||
|
@ -47,8 +47,8 @@
|
||||
android:id="@+id/libraryList"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:scrollbars="vertical"
|
||||
android:contentDescription="@string/library"
|
||||
android:scrollbars="vertical"
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior"
|
||||
tools:listitem="@layout/item_download" />
|
||||
|
||||
@ -66,13 +66,44 @@
|
||||
app:layout_constraintVertical_bias="0.45"
|
||||
tools:ignore="RequiredSize" />
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/onlineLibraryProgressBar"
|
||||
<androidx.cardview.widget.CardView
|
||||
android:id="@+id/progressCardView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
android:layout_margin="16dp"
|
||||
android:visibility="visible"
|
||||
app:cardCornerRadius="4dp"
|
||||
app:cardElevation="4dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toTopOf="@+id/libraryErrorText" />
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/onlineLibraryProgressLayout"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
android:padding="@dimen/activity_horizontal_margin"
|
||||
android:visibility="gone">
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/onlineLibraryProgressBar"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/activity_horizontal_margin" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/onlineLibraryProgressStatusText"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginBottom="@dimen/activity_horizontal_margin"
|
||||
android:gravity="center"
|
||||
android:text="@string/reaching_remote_library"
|
||||
android:textColor="@color/mine_shaft_gray900"
|
||||
android:textSize="12sp" />
|
||||
</LinearLayout>
|
||||
</androidx.cardview.widget.CardView>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
@ -32,18 +32,17 @@ class ProgressResponseBody(
|
||||
private val progressListener: OnlineLibraryProgressListener
|
||||
) : ResponseBody() {
|
||||
|
||||
private var bufferedSource: BufferedSource? = null
|
||||
private lateinit var bufferedSource: BufferedSource
|
||||
|
||||
override fun contentType(): MediaType? = responseBody.contentType()
|
||||
|
||||
override fun contentLength(): Long = responseBody.contentLength()
|
||||
|
||||
@Suppress("UnsafeCallOnNullableType")
|
||||
override fun source(): BufferedSource {
|
||||
if (bufferedSource == null) {
|
||||
if (!::bufferedSource.isInitialized) {
|
||||
bufferedSource = source(responseBody.source()).buffer()
|
||||
}
|
||||
return bufferedSource!!
|
||||
return bufferedSource
|
||||
}
|
||||
|
||||
private fun source(source: Source): Source {
|
||||
@ -57,14 +56,15 @@ class ProgressResponseBody(
|
||||
totalBytesRead,
|
||||
responseBody.contentLength(),
|
||||
isDone
|
||||
).also {
|
||||
Log.e(
|
||||
"PROGRESS",
|
||||
"onProgress: ${contentLength()} and byteRead = $totalBytesRead\n" +
|
||||
" sink ${bytesRead == -1L} \n byteRead = $bytesRead " +
|
||||
"\n bufferedSource = ${bufferedSource?.isOpen}"
|
||||
)
|
||||
}
|
||||
)
|
||||
.also {
|
||||
Log.e(
|
||||
"PROGRESS",
|
||||
"onProgress: ${contentLength()} and byteRead = $totalBytesRead\n" +
|
||||
" sink ${bytesRead == -1L} \n byteRead = $bytesRead " +
|
||||
"\n bufferedSource = ${bufferedSource.isOpen}"
|
||||
)
|
||||
}
|
||||
return bytesRead
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user