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:
MohitMaliFtechiz 2024-09-17 15:00:02 +05:30
parent 90f711b244
commit c5d0d8aeea
6 changed files with 128 additions and 53 deletions

View File

@ -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

View File

@ -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"
)
)
}
}

View File

@ -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)

View File

@ -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() }
}
}

View File

@ -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>

View File

@ -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
}
}