Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improved the scanning of ZIM files in the Play Store variant. #4149

Merged
merged 2 commits into from
Dec 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,15 @@ import androidx.core.os.ConfigurationCompat
import androidx.core.os.bundleOf
import androidx.core.view.isVisible
import androidx.drawerlayout.widget.DrawerLayout
import androidx.lifecycle.lifecycleScope
import androidx.navigation.NavController
import androidx.navigation.NavDestination
import androidx.navigation.fragment.NavHostFragment
import androidx.navigation.ui.NavigationUI
import androidx.navigation.ui.setupWithNavController
import com.google.android.material.navigation.NavigationView
import eu.mhutti1.utils.storage.StorageDeviceUtils
import kotlinx.coroutines.launch
import org.kiwix.kiwixmobile.BuildConfig
import org.kiwix.kiwixmobile.R
import org.kiwix.kiwixmobile.core.R.id
Expand Down Expand Up @@ -126,13 +128,15 @@ class KiwixMainActivity : CoreMainActivity() {
onNavigationItemSelected(item)
}
activityKiwixMainBinding.bottomNavView.setupWithNavController(navController)
migrateInternalToPublicAppDirectory()
lifecycleScope.launch {
migrateInternalToPublicAppDirectory()
}
handleZimFileIntent(intent)
handleNotificationIntent(intent)
handleGetContentIntent(intent)
}

private fun migrateInternalToPublicAppDirectory() {
private suspend fun migrateInternalToPublicAppDirectory() {
if (!sharedPreferenceUtil.prefIsAppDirectoryMigrated) {
val storagePath = StorageDeviceUtils.getWritableStorage(this)
.getOrNull(sharedPreferenceUtil.storagePosition)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -501,7 +501,7 @@
@SuppressLint("InflateParams") fun showPreparingCopyMoveDialog() {
if (copyMovePreparingDialog == null) {
val dialogView: View =
activity.layoutInflater.inflate(layout.item_custom_spinner, null)
activity.layoutInflater.inflate(R.layout.item_custom_spinner, null)

Check warning on line 504 in app/src/main/java/org/kiwix/kiwixmobile/nav/destination/library/CopyMoveFileHandler.kt

View check run for this annotation

Codecov / codecov/patch

app/src/main/java/org/kiwix/kiwixmobile/nav/destination/library/CopyMoveFileHandler.kt#L504

Added line #L504 was not covered by tests
copyMovePreparingDialog =
alertDialogShower.create(KiwixDialog.PreparingCopyingFilesDialog { dialogView })
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,14 @@ import org.kiwix.kiwixmobile.core.extensions.storagePathAndTitle
import org.kiwix.kiwixmobile.core.extensions.usedPercentage
import org.kiwix.kiwixmobile.core.navigateToSettings
import org.kiwix.kiwixmobile.core.settings.CorePrefsFragment
import org.kiwix.kiwixmobile.core.settings.StorageLoadingPreference
import org.kiwix.kiwixmobile.core.settings.StorageRadioButtonPreference
import org.kiwix.kiwixmobile.core.utils.SharedPreferenceUtil
import org.kiwix.kiwixmobile.core.utils.SharedPreferenceUtil.Companion.PREF_EXTERNAL_STORAGE
import org.kiwix.kiwixmobile.core.utils.SharedPreferenceUtil.Companion.PREF_INTERNAL_STORAGE

const val PREF_STORAGE_PROGRESSBAR = "storage_progressbar"

class KiwixPrefsFragment : CorePrefsFragment() {
private var storageDisposable: Disposable? = null
private var storageDeviceList: List<StorageDevice> = listOf()
Expand All @@ -56,17 +59,21 @@ class KiwixPrefsFragment : CorePrefsFragment() {

override suspend fun setStorage() {
sharedPreferenceUtil?.let {
if (storageDisposable?.isDisposed == false) {
if (storageDeviceList.isNotEmpty()) {
// update the storage when user switch to other storage.
setUpStoragePreference(it)
return@setStorage
}
showHideProgressBarWhileFetchingStorageInfo(true)
storageDisposable =
Flowable.fromCallable { StorageDeviceUtils.getWritableStorage(requireActivity()) }
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
{ storageList ->
storageDeviceList = storageList
showHideProgressBarWhileFetchingStorageInfo(false)
showInternalStoragePreferece()
showExternalPreferenceIfAvailable()
setUpStoragePreference(it)
},
Expand All @@ -75,6 +82,20 @@ class KiwixPrefsFragment : CorePrefsFragment() {
}
}

/**
* Shows or hides the progress bar while the application is fetching
* storage information in the background. The progress bar is displayed
* with a title indicating that the storage information is being retrieved.
*
* @param show If true, the progress bar will be displayed; otherwise, it will be hidden.
*/
private fun showHideProgressBarWhileFetchingStorageInfo(show: Boolean) {
findPreference<StorageLoadingPreference>(PREF_STORAGE_PROGRESSBAR)?.apply {
isVisible = show
setTitle(getString(R.string.fetching_storage_info))
}
}

private fun setUpStoragePreference(sharedPreferenceUtil: SharedPreferenceUtil) {
lifecycleScope.launch {
storageDeviceList.forEachIndexed { index, storageDevice ->
Expand All @@ -100,6 +121,10 @@ class KiwixPrefsFragment : CorePrefsFragment() {
}
}

private fun showInternalStoragePreferece() {
findPreference<StorageRadioButtonPreference>(PREF_INTERNAL_STORAGE)?.isVisible = true
}

private fun showExternalPreferenceIfAvailable() {
findPreference<StorageRadioButtonPreference>(PREF_EXTERNAL_STORAGE)?.isVisible =
storageDeviceList.size > 1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,7 @@ class ZimHostFragment : BaseFragment(), ZimHostCallbacks, ZimHostContract.View {
private fun startKiwixHotspot() {
if (dialog == null) {
val dialogView: View =
layoutInflater.inflate(layout.item_custom_spinner, null)
layoutInflater.inflate(R.layout.item_custom_spinner, null)
dialog = alertDialogShower.create(StartServer { dialogView })
}
dialog?.show()
Expand Down
13 changes: 11 additions & 2 deletions core/src/main/java/eu/mhutti1/utils/storage/StorageDeviceUtils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import android.content.Context
import android.content.ContextWrapper
import android.os.Environment
import androidx.core.content.ContextCompat
import org.kiwix.kiwixmobile.core.utils.SharedPreferenceUtil
import java.io.File
import java.io.FileFilter
import java.io.RandomAccessFile
Expand All @@ -34,10 +35,9 @@ object StorageDeviceUtils {

@JvmStatic
fun getReadableStorage(context: Context): List<StorageDevice> {
var sharedPreferenceUtil: SharedPreferenceUtil? = SharedPreferenceUtil(context)
val storageDevices = ArrayList<StorageDevice>().apply {
add(environmentDevices(context))
addAll(externalMountPointDevices())
addAll(externalFilesDirsDevices(context, false))
addAll(externalMediaFilesDirsDevices(context))
// Scan the app-specific directory as well because we have limitations in scanning
// all directories on Android 11 and above in the Play Store variant.
Expand All @@ -47,6 +47,15 @@ object StorageDeviceUtils {
// Therefore, we need to explicitly include the app-specific directory for scanning.
// See https://github.com/kiwix/kiwix-android/issues/3579
addAll(externalFilesDirsDevices(context, true))
// Do not scan storage directories in the Play Store build on Android 11 and above.
// In the Play Store variant, we can only access app-specific directories,
// so scanning other directories is unnecessary, wastes resources,
// and increases the scanning time.
if (sharedPreferenceUtil?.isNotPlayStoreBuildWithAndroid11OrAbove() == true) {
addAll(externalMountPointDevices())
addAll(externalFilesDirsDevices(context, false))
}
sharedPreferenceUtil = null
}
return validate(storageDevices, false)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
/*
* Kiwix Android
* Copyright (c) 2O24 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.settings

import android.content.Context
import android.util.AttributeSet
import android.view.View.VISIBLE
import android.widget.ProgressBar
import android.widget.TextView
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.constraintlayout.widget.ConstraintSet
import androidx.preference.Preference
import androidx.preference.PreferenceViewHolder
import org.kiwix.kiwixmobile.core.R
import org.kiwix.kiwixmobile.core.downloader.downloadManager.ZERO

const val MARGIN_TOP = 8

class StorageLoadingPreference @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,

Check warning on line 37 in core/src/main/java/org/kiwix/kiwixmobile/core/settings/StorageLoadingPreference.kt

View check run for this annotation

Codecov / codecov/patch

core/src/main/java/org/kiwix/kiwixmobile/core/settings/StorageLoadingPreference.kt#L37

Added line #L37 was not covered by tests
defStyleAttr: Int = ZERO
) : Preference(context, attrs, defStyleAttr) {

private var customProgressTitle: TextView? = null
private var progressBarTitleText: String? = null

init {
widgetLayoutResource = R.layout.item_custom_spinner
}

override fun onBindViewHolder(holder: PreferenceViewHolder) {
super.onBindViewHolder(holder)
val progressBar = holder.findViewById(R.id.custom_progressbar) as? ProgressBar
customProgressTitle = holder.findViewById(R.id.custom_progress_title) as TextView
progressBarTitleText?.let(::setProgressBarTitle)

val constraintLayout = holder.itemView as ConstraintLayout
val constraintSet = ConstraintSet()
constraintSet.clone(constraintLayout)

constraintSet.connect(
progressBar?.id ?: ZERO,
ConstraintSet.START,
ConstraintSet.PARENT_ID,
ConstraintSet.START,
ZERO
)
constraintSet.connect(
progressBar?.id ?: ZERO,
ConstraintSet.END,
ConstraintSet.PARENT_ID,
ConstraintSet.END,
ZERO
)
constraintSet.connect(
progressBar?.id ?: ZERO,
ConstraintSet.TOP,
ConstraintSet.PARENT_ID,
ConstraintSet.TOP,
ZERO
)

constraintSet.connect(
customProgressTitle?.id ?: ZERO,
ConstraintSet.START,
ConstraintSet.PARENT_ID,
ConstraintSet.START,
ZERO
)
constraintSet.connect(
customProgressTitle?.id ?: ZERO,
ConstraintSet.END,
ConstraintSet.PARENT_ID,
ConstraintSet.END,
ZERO
)
constraintSet.connect(
customProgressTitle?.id ?: ZERO,
ConstraintSet.TOP,
progressBar?.id ?: ZERO,
ConstraintSet.BOTTOM,
MARGIN_TOP
)
constraintSet.connect(
customProgressTitle?.id ?: ZERO,
ConstraintSet.BOTTOM,
ConstraintSet.PARENT_ID,
ConstraintSet.BOTTOM,
ZERO
)
constraintSet.applyTo(constraintLayout)
}

fun setTitle(title: String) {
progressBarTitleText = title
setProgressBarTitle(title)
}

private fun setProgressBarTitle(title: String) {
customProgressTitle?.apply {
text = title
visibility = VISIBLE
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,10 @@
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="16dp">
android:padding="@dimen/activity_horizontal_margin">

<ProgressBar
android:id="@+id/custom_progressbar"
style="?android:attr/progressBarStyleLarge"
android:layout_width="50dp"
android:layout_height="50dp"
Expand All @@ -31,4 +32,14 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<TextView
android:id="@+id/custom_progress_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/card_margin"
android:layout_marginBottom="@dimen/activity_horizontal_margin"
android:gravity="center"
android:visibility="gone"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/custom_progressbar" />
</androidx.constraintlayout.widget.ConstraintLayout>
1 change: 1 addition & 0 deletions core/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@
<string name="help_9">• Other contents like Wikileaks or Wikisource are also available</string>
<string name="help_10">You can either download your chosen ZIM files in-app or carefully select the one(s) you want and download from a Desktop computer before transferring the ZIM files to your SD card.</string>
<string name="help_11">ZIM files download in-app are located in the external storage directory in a folder entitled Kiwix.</string>
<string name="fetching_storage_info">Fetching storage details…</string>
<string name="pref_storage">Storage</string>
<string name="pref_current_folder">Current Folder</string>
<string name="pref_storage_used">%s used</string>
Expand Down
12 changes: 10 additions & 2 deletions core/src/main/res/xml/preferences.xml
Original file line number Diff line number Diff line change
Expand Up @@ -65,15 +65,23 @@
app:iconSpaceReserved="false"
app:title="@string/pref_storage">

<org.kiwix.kiwixmobile.core.settings.StorageLoadingPreference
android:key="storage_progressbar"
android:layout="@layout/item_custom_spinner"
app:iconSpaceReserved="false"
app:isPreferenceVisible="false" />

<org.kiwix.kiwixmobile.core.settings.StorageRadioButtonPreference
android:key="pref_internal_storage"
android:layout="@layout/item_storage_preference"
app:iconSpaceReserved="false" />
app:iconSpaceReserved="false"
app:isPreferenceVisible="false" />

<org.kiwix.kiwixmobile.core.settings.StorageRadioButtonPreference
android:key="pref_external_storage"
android:layout="@layout/item_storage_preference"
app:iconSpaceReserved="false" />
app:iconSpaceReserved="false"
app:isPreferenceVisible="false" />

</PreferenceCategory>

Expand Down
Loading