Fixed: The Text Zoom slider did not correctly display the previously set position after restarting the application.

* Removed the BaseDelegateAdapter and its subclasses, as RecyclerView is no longer used in the codebase.
* Fixed: CustomApps was crashing when opening the settings screen.
* Fixed: StorageList was not appearing on the settings screen.
* Fixed: Dark Mode and Language dialogs to match the theme design.
* Created KiwixBasicDialogFrame, a reusable Compose UI component to standardize the design of alert dialogs.
* Removed unused code from the project.
This commit is contained in:
MohitMaliFtechiz 2025-05-30 17:55:02 +05:30
parent 164e38b113
commit ba476058fe
23 changed files with 149 additions and 960 deletions

View File

@ -24,7 +24,6 @@ import dagger.Module
import dagger.multibindings.IntoMap import dagger.multibindings.IntoMap
import org.kiwix.kiwixmobile.core.di.ViewModelKey import org.kiwix.kiwixmobile.core.di.ViewModelKey
import org.kiwix.kiwixmobile.core.di.modules.CoreViewModelModule import org.kiwix.kiwixmobile.core.di.modules.CoreViewModelModule
import org.kiwix.kiwixmobile.core.settings.viewmodel.SettingsViewModel
import org.kiwix.kiwixmobile.language.viewmodel.LanguageViewModel import org.kiwix.kiwixmobile.language.viewmodel.LanguageViewModel
import org.kiwix.kiwixmobile.zimManager.ZimManageViewModel import org.kiwix.kiwixmobile.zimManager.ZimManageViewModel
@ -39,9 +38,4 @@ abstract class KiwixViewModelModule {
@IntoMap @IntoMap
@ViewModelKey(LanguageViewModel::class) @ViewModelKey(LanguageViewModel::class)
abstract fun bindLanguageViewModel(languageViewModel: LanguageViewModel): ViewModel abstract fun bindLanguageViewModel(languageViewModel: LanguageViewModel): ViewModel
@Binds
@IntoMap
@ViewModelKey(SettingsViewModel::class)
abstract fun bindSettingsViewModel(settingsViewModel: SettingsViewModel): ViewModel
} }

View File

@ -22,9 +22,7 @@ import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.os.Environment import android.os.Environment
import android.view.View import android.view.View
import androidx.lifecycle.lifecycleScope
import eu.mhutti1.utils.storage.StorageDevice import eu.mhutti1.utils.storage.StorageDevice
import kotlinx.coroutines.launch
import org.kiwix.kiwixmobile.core.R 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.extensions.update import org.kiwix.kiwixmobile.core.extensions.update
@ -55,16 +53,17 @@ class KiwixSettingsFragment : CoreSettingsFragment() {
return@setStorage return@setStorage
} }
showHideProgressBarWhileFetchingStorageInfo(true) showHideProgressBarWhileFetchingStorageInfo(true)
lifecycleScope.launch { storageDeviceList = (requireActivity() as KiwixMainActivity).getStorageDeviceList()
storageDeviceList = (requireActivity() as KiwixMainActivity).getStorageDeviceList() showHideProgressBarWhileFetchingStorageInfo(false)
showHideProgressBarWhileFetchingStorageInfo(false) setUpStoragePreference()
setUpStoragePreference()
}
} }
} }
private fun setUpStoragePreference() { private fun setUpStoragePreference() {
settingsScreenState.value.update { copy(storageDeviceList = storageDeviceList) } settingsScreenState.value.value =
settingsScreenState.value.value.copy(storageDeviceList = emptyList())
settingsScreenState.value.value =
settingsScreenState.value.value.copy(storageDeviceList = storageDeviceList)
} }
/** /**

View File

@ -1,41 +0,0 @@
/*
* 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.zimManager
import androidx.viewpager.widget.ViewPager.OnPageChangeListener
class SimplePageChangeListener constructor(
private val onPageSelectedAction: (Int) -> Unit,
private val onPageScrollStateChanged: ((Int) -> Unit)? = null
) : OnPageChangeListener {
override fun onPageScrolled(
position: Int,
positionOffset: Float,
positionOffsetPixels: Int
) {
}
override fun onPageSelected(position: Int) {
onPageSelectedAction.invoke(position)
}
override fun onPageScrollStateChanged(state: Int) {
onPageScrollStateChanged?.invoke(state)
}
}

View File

@ -1,42 +0,0 @@
/*
* 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.base.adapter
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
interface AbsDelegateAdapter<
INSTANCE : SUPERTYPE,
SUPERTYPE : Any,
out VIEWHOLDER : BaseViewHolder<INSTANCE>
> : AdapterDelegate<SUPERTYPE> {
val itemClass: Class<INSTANCE>
@Suppress("UNCHECKED_CAST")
override fun bind(
viewHolder: RecyclerView.ViewHolder,
itemToBind: SUPERTYPE
) {
(viewHolder as VIEWHOLDER).bind(itemToBind as INSTANCE)
}
override fun isFor(item: SUPERTYPE) = itemClass.isInstance(item)
override fun createViewHolder(parent: ViewGroup): VIEWHOLDER
}

View File

@ -1,30 +0,0 @@
/*
* 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.base.adapter
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView.ViewHolder
interface AdapterDelegate<in T> {
fun createViewHolder(parent: ViewGroup): ViewHolder
fun bind(viewHolder: ViewHolder, itemToBind: T)
fun isFor(item: T): Boolean
}

View File

@ -1,56 +0,0 @@
/*
* 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.base.adapter
import android.view.ViewGroup
import androidx.collection.SparseArrayCompat
import androidx.recyclerview.widget.RecyclerView
class AdapterDelegateManager<T> {
fun addDelegate(delegate: AdapterDelegate<T>) {
delegates.put(delegates.size(), delegate)
}
@Suppress("UnsafeCallOnNullableType")
fun createViewHolder(
parent: ViewGroup,
viewType: Int
) = delegates[viewType]!!.createViewHolder(parent)
fun onBindViewHolder(
libraryListItem: T,
holder: RecyclerView.ViewHolder
) {
delegates[holder.itemViewType]?.bind(holder, libraryListItem)
}
fun getViewTypeFor(item: T) = delegates.keyAt(getDelegateIndexFor(item))
private fun getDelegateIndexFor(item: T): Int {
for (index in 0..delegates.size()) {
val valueAt = delegates.valueAt(index)
if (valueAt.isFor(item) == true) {
return index
}
}
throw RuntimeException("No delegate registered for $item")
}
private var delegates: SparseArrayCompat<AdapterDelegate<T>> = SparseArrayCompat()
}

View File

@ -1,66 +0,0 @@
/*
* 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.base.adapter
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView.Adapter
import androidx.recyclerview.widget.RecyclerView.ViewHolder
abstract class BaseDelegateAdapter<ITEM>(
vararg delegates: AdapterDelegate<ITEM>,
private val delegateManager: AdapterDelegateManager<ITEM> = AdapterDelegateManager()
) : Adapter<ViewHolder>() {
init {
delegates.forEach(delegateManager::addDelegate)
@Suppress("LeakingThis")
setHasStableIds(true)
}
var items: List<ITEM> = mutableListOf()
set(value) {
field = value
notifyDataSetChanged()
}
// Function to add new data to the adapter
fun addData(newData: List<ITEM>) {
val startPosition = items.size
items = items.toMutableList().apply { addAll(newData) }
notifyItemRangeInserted(startPosition, newData.size)
}
override fun onCreateViewHolder(
parent: ViewGroup,
viewType: Int
) = delegateManager.createViewHolder(parent, viewType)
override fun getItemCount() = items.size
override fun onBindViewHolder(
holder: ViewHolder,
position: Int
) {
delegateManager.onBindViewHolder(items[position], holder)
}
override fun getItemViewType(position: Int) =
delegateManager.getViewTypeFor(items[position])
override fun getItemId(position: Int): Long = getIdFor(items[position])
abstract fun getIdFor(item: ITEM): Long
}

View File

@ -29,6 +29,7 @@ import org.kiwix.kiwixmobile.core.page.bookmark.viewmodel.BookmarkViewModel
import org.kiwix.kiwixmobile.core.page.history.viewmodel.HistoryViewModel import org.kiwix.kiwixmobile.core.page.history.viewmodel.HistoryViewModel
import org.kiwix.kiwixmobile.core.page.notes.viewmodel.NotesViewModel import org.kiwix.kiwixmobile.core.page.notes.viewmodel.NotesViewModel
import org.kiwix.kiwixmobile.core.search.viewmodel.SearchViewModel import org.kiwix.kiwixmobile.core.search.viewmodel.SearchViewModel
import org.kiwix.kiwixmobile.core.settings.viewmodel.SettingsViewModel
@Module @Module
abstract class CoreViewModelModule { abstract class CoreViewModelModule {
@ -54,4 +55,9 @@ abstract class CoreViewModelModule {
@IntoMap @IntoMap
@ViewModelKey(BookmarkViewModel::class) @ViewModelKey(BookmarkViewModel::class)
abstract fun bindBookmarksViewModel(bookmarksViewModel: BookmarkViewModel): ViewModel abstract fun bindBookmarksViewModel(bookmarksViewModel: BookmarkViewModel): ViewModel
@Binds
@IntoMap
@ViewModelKey(SettingsViewModel::class)
abstract fun bindSettingsViewModel(settingsViewModel: SettingsViewModel): ViewModel
} }

View File

@ -1,25 +0,0 @@
/*
* Kiwix Android
* Copyright (c) 2022 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.di.qualifiers
import javax.inject.Qualifier
@Qualifier
@kotlin.annotation.Retention
annotation class Computation

View File

@ -1,24 +0,0 @@
/*
* 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.di.qualifiers
import javax.inject.Qualifier
@Qualifier
@kotlin.annotation.Retention
annotation class IO

View File

@ -1,24 +0,0 @@
/*
* 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.di.qualifiers
import javax.inject.Qualifier
@Qualifier
@kotlin.annotation.Retention
annotation class MainThread

View File

@ -31,6 +31,8 @@ import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import org.kiwix.kiwixmobile.core.BuildConfig import org.kiwix.kiwixmobile.core.BuildConfig
@ -145,11 +147,9 @@ open class KiwixWebView @SuppressLint("SetJavaScriptEnabled") constructor(
super.onAttachedToWindow() super.onAttachedToWindow()
// cancel any previous running job. // cancel any previous running job.
textZoomJob?.cancel() textZoomJob?.cancel()
textZoomJob = CoroutineScope(SupervisorJob() + Dispatchers.Main).launch { textZoomJob = sharedPreferenceUtil.textZooms
sharedPreferenceUtil.textZooms.collect { .onEach { settings.textZoom = it }
settings.textZoom = it .launchIn(CoroutineScope(SupervisorJob() + Dispatchers.Main))
}
}
} }
override fun onDetachedFromWindow() { override fun onDetachedFromWindow() {

View File

@ -1,21 +0,0 @@
/*
* 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.search
data class SearchSuggestion(val title: String, val url: String)

View File

@ -144,9 +144,6 @@ abstract class CoreSettingsFragment : SettingsContract.View, BaseFragment() {
DialogHost(alertDialogShower as AlertDialogShower) DialogHost(alertDialogShower as AlertDialogShower)
} }
} }
lifecycleScope.launch {
setStorage()
}
settingsScreenState.value.update { settingsScreenState.value.update {
copy(versionInformation = "$versionName Build: $versionCode") copy(versionInformation = "$versionName Build: $versionCode")
} }
@ -173,6 +170,9 @@ abstract class CoreSettingsFragment : SettingsContract.View, BaseFragment() {
Action.OpenCredits -> openCredits() Action.OpenCredits -> openCredits()
} }
}.launchIn(lifecycleScope) }.launchIn(lifecycleScope)
lifecycleScope.launch {
setStorage()
}
} }
override fun onCreateView( override fun onCreateView(

View File

@ -34,8 +34,9 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.size
import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.LazyListScope import androidx.compose.foundation.lazy.LazyListScope
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.selection.selectable import androidx.compose.foundation.selection.selectable
import androidx.compose.material3.AlertDialog import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
@ -44,7 +45,6 @@ import androidx.compose.material3.Scaffold
import androidx.compose.material3.Slider import androidx.compose.material3.Slider
import androidx.compose.material3.Switch import androidx.compose.material3.Switch
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
@ -69,11 +69,14 @@ import org.kiwix.kiwixmobile.core.settings.viewmodel.Action.ImportBookmarks
import org.kiwix.kiwixmobile.core.settings.viewmodel.Action.OnStorageItemClick import org.kiwix.kiwixmobile.core.settings.viewmodel.Action.OnStorageItemClick
import org.kiwix.kiwixmobile.core.settings.viewmodel.Action.OpenCredits import org.kiwix.kiwixmobile.core.settings.viewmodel.Action.OpenCredits
import org.kiwix.kiwixmobile.core.settings.viewmodel.SettingsViewModel import org.kiwix.kiwixmobile.core.settings.viewmodel.SettingsViewModel
import org.kiwix.kiwixmobile.core.settings.viewmodel.ZOOM_OFFSET
import org.kiwix.kiwixmobile.core.settings.viewmodel.ZOOM_SCALE
import org.kiwix.kiwixmobile.core.ui.components.ContentLoadingProgressBar import org.kiwix.kiwixmobile.core.ui.components.ContentLoadingProgressBar
import org.kiwix.kiwixmobile.core.ui.components.KiwixAppBar import org.kiwix.kiwixmobile.core.ui.components.KiwixAppBar
import org.kiwix.kiwixmobile.core.ui.components.StorageDeviceItem import org.kiwix.kiwixmobile.core.ui.components.StorageDeviceItem
import org.kiwix.kiwixmobile.core.ui.theme.KiwixTheme import org.kiwix.kiwixmobile.core.ui.theme.KiwixTheme
import org.kiwix.kiwixmobile.core.utils.ComposeDimens.CATEGORY_TITLE_TEXT_SIZE import org.kiwix.kiwixmobile.core.utils.ComposeDimens.CATEGORY_TITLE_TEXT_SIZE
import org.kiwix.kiwixmobile.core.utils.ComposeDimens.DIALOG_DEFAULT_PADDING_FOR_CONTENT
import org.kiwix.kiwixmobile.core.utils.ComposeDimens.EIGHT_DP import org.kiwix.kiwixmobile.core.utils.ComposeDimens.EIGHT_DP
import org.kiwix.kiwixmobile.core.utils.ComposeDimens.FIVE_DP import org.kiwix.kiwixmobile.core.utils.ComposeDimens.FIVE_DP
import org.kiwix.kiwixmobile.core.utils.ComposeDimens.ONE_DP import org.kiwix.kiwixmobile.core.utils.ComposeDimens.ONE_DP
@ -83,6 +86,9 @@ import org.kiwix.kiwixmobile.core.utils.ComposeDimens.STORAGE_LOADING_PROGRESS_B
import org.kiwix.kiwixmobile.core.utils.ComposeDimens.TWELVE_DP import org.kiwix.kiwixmobile.core.utils.ComposeDimens.TWELVE_DP
import org.kiwix.kiwixmobile.core.utils.LanguageUtils import org.kiwix.kiwixmobile.core.utils.LanguageUtils
import org.kiwix.kiwixmobile.core.utils.LanguageUtils.Companion.handleLocaleChange import org.kiwix.kiwixmobile.core.utils.LanguageUtils.Companion.handleLocaleChange
import org.kiwix.kiwixmobile.core.utils.dialog.DialogConfirmButton
import org.kiwix.kiwixmobile.core.utils.dialog.DialogTitle
import org.kiwix.kiwixmobile.core.utils.dialog.KiwixBasicDialogFrame
import java.util.Locale import java.util.Locale
import kotlin.math.roundToInt import kotlin.math.roundToInt
@ -201,7 +207,7 @@ private fun LanguageCategory(settingScreenState: SettingScreenState) {
val selectedIndex = languageCodes.indexOf(selectedCode) val selectedIndex = languageCodes.indexOf(selectedCode)
SettingsCategory(stringResource(R.string.pref_language_title)) { SettingsCategory(stringResource(R.string.pref_language_title)) {
ListPreference( ListPreference(
title = stringResource(R.string.pref_language_title), titleId = R.string.pref_language_title,
summary = languageDisplayNames.getOrNull(selectedIndex) ?: selectedCode, summary = languageDisplayNames.getOrNull(selectedIndex) ?: selectedCode,
options = languageDisplayNames, options = languageDisplayNames,
selectedOption = languageDisplayNames[selectedIndex] selectedOption = languageDisplayNames[selectedIndex]
@ -319,7 +325,7 @@ private fun DisplayCategory(settingsViewModel: SettingsViewModel) {
val darkModeLabel by settingsViewModel.darkModeLabel.collectAsState() val darkModeLabel by settingsViewModel.darkModeLabel.collectAsState()
val backToTopEnabled by settingsViewModel.backToTopEnabled val backToTopEnabled by settingsViewModel.backToTopEnabled
val textZoom by settingsViewModel.textZoom.collectAsState() val textZoom by settingsViewModel.textZoom.collectAsState()
val textZoomPosition by settingsViewModel.textZoomPosition.collectAsState() val textZoomPosition = (textZoom / ZOOM_SCALE) - ZOOM_OFFSET
SettingsCategory(stringResource(R.string.pref_display_title)) { SettingsCategory(stringResource(R.string.pref_display_title)) {
DarkModePreference(darkModeLabel = darkModeLabel, settingsViewModel = settingsViewModel) DarkModePreference(darkModeLabel = darkModeLabel, settingsViewModel = settingsViewModel)
SwitchPreference( SwitchPreference(
@ -352,7 +358,7 @@ fun DarkModePreference(
} }
ListPreference( ListPreference(
title = stringResource(id = R.string.pref_dark_mode), titleId = R.string.pref_dark_mode,
summary = stringResource(id = R.string.pref_dark_mode_summary), summary = stringResource(id = R.string.pref_dark_mode_summary),
options = entries, options = entries,
selectedOption = darkModeLabel, selectedOption = darkModeLabel,
@ -443,9 +449,10 @@ private fun SeekBarPreference(
} }
} }
@OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
fun ListPreference( fun ListPreference(
title: String, titleId: Int,
summary: String, summary: String,
options: List<String>, options: List<String>,
selectedOption: String, selectedOption: String,
@ -459,53 +466,68 @@ fun ListPreference(
.fillMaxWidth() .fillMaxWidth()
.clickable { showDialog = true } .clickable { showDialog = true }
) { ) {
PreferenceItem(title, summary) { showDialog = true } PreferenceItem(stringResource(titleId), summary) { showDialog = true }
} }
if (showDialog) { if (showDialog) {
AlertDialog( KiwixBasicDialogFrame(
onDismissRequest = { showDialog = false }, onDismissRequest = { showDialog = false }
title = { ) {
Text(text = title) DialogTitle(titleId)
}, ListOptions(
text = { modifier = Modifier
Column { .fillMaxWidth()
options.forEach { option -> .weight(1f, fill = false)
Row( .verticalScroll(rememberScrollState()),
verticalAlignment = Alignment.CenterVertically, options = options,
modifier = Modifier selected = selected,
.fillMaxWidth() onOptionSelected = {
.selectable( selected = it
selected = option == selected, onOptionSelected(it)
onClick = {
selected = option
onOptionSelected(option)
showDialog = false
}
)
.padding(vertical = EIGHT_DP)
) {
RadioButton(
selected = option == selected,
onClick = {
selected = option
onOptionSelected(option)
showDialog = false
}
)
Text(text = option, style = MaterialTheme.typography.bodyLarge)
}
}
}
},
confirmButton = {
TextButton(onClick = {
showDialog = false showDialog = false
}) {
Text(stringResource(R.string.cancel))
} }
)
Spacer(modifier = Modifier.height(DIALOG_DEFAULT_PADDING_FOR_CONTENT))
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.End
) {
DialogConfirmButton(
confirmButtonText = stringResource(R.string.cancel),
dialogConfirmButtonClick = { showDialog = false },
null
)
} }
) }
}
}
@Composable
private fun ListOptions(
modifier: Modifier,
options: List<String>,
selected: String,
onOptionSelected: (String) -> Unit
) {
Column(modifier = modifier) {
options.forEach { option ->
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier
.fillMaxWidth()
.selectable(
selected = option == selected,
onClick = { onOptionSelected(option) }
)
.padding(vertical = EIGHT_DP)
) {
RadioButton(
selected = option == selected,
onClick = { onOptionSelected(option) }
)
Text(text = option, style = MaterialTheme.typography.bodyLarge)
}
}
} }
} }

View File

@ -1,121 +0,0 @@
/*
* 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,
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
}
}
}

View File

@ -1,92 +0,0 @@
/*
* 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.core.settings
import android.content.Context
import android.util.AttributeSet
import android.widget.ProgressBar
import android.widget.RadioButton
import android.widget.TextView
import androidx.preference.CheckBoxPreference
import androidx.preference.PreferenceViewHolder
import org.kiwix.kiwixmobile.core.R
import org.kiwix.kiwixmobile.core.utils.SharedPreferenceUtil.Companion.PREF_EXTERNAL_STORAGE
import org.kiwix.kiwixmobile.core.utils.SharedPreferenceUtil.Companion.PREF_INTERNAL_STORAGE
class StorageRadioButtonPreference @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : CheckBoxPreference(context, attrs, defStyleAttr) {
init {
widgetLayoutResource = R.layout.item_storage_preference
}
private var radioButton: RadioButton? = null
private var progressBar: ProgressBar? = null
private var usedSpaceTextView: TextView? = null
private var freeSpaceTextView: TextView? = null
private var pathAndTitleTextView: TextView? = null
private var usedSpace: String? = null
private var freeSpace: String? = null
private var pathAndTitle: String? = null
private var progress: Int = 0
override fun onBindViewHolder(holder: PreferenceViewHolder) {
super.onBindViewHolder(holder)
radioButton = holder.findViewById(R.id.radioButton) as RadioButton
progressBar = holder.findViewById(R.id.storageProgressBar) as ProgressBar
usedSpaceTextView = holder.findViewById(R.id.usedSpace) as TextView
freeSpaceTextView = holder.findViewById(R.id.freeSpace) as TextView
pathAndTitleTextView = holder.findViewById(R.id.storagePathAndTitle) as TextView
radioButton?.isChecked = isChecked
usedSpaceTextView?.let { it.text = usedSpace }
freeSpaceTextView?.let { it.text = freeSpace }
pathAndTitleTextView?.let { it.text = pathAndTitle }
progressBar?.let { it.progress = progress }
}
override fun onClick() {
if (isChecked) return
preferenceManager.findPreference<CheckBoxPreference>(PREF_INTERNAL_STORAGE)?.isChecked = false
preferenceManager.findPreference<CheckBoxPreference>(PREF_EXTERNAL_STORAGE)?.isChecked = false
super.onClick()
}
fun setProgress(usedPercentage: Int) {
progress = usedPercentage
progressBar?.progress = usedPercentage
}
fun setUsedSpace(usedSpace: String) {
this.usedSpace = usedSpace
usedSpaceTextView?.text = usedSpace
}
fun setFreeSpace(freeSpace: String) {
this.freeSpace = freeSpace
freeSpaceTextView?.text = freeSpace
}
fun setPathAndTitleForStorage(storageTitleAndPath: String) {
pathAndTitle = storageTitleAndPath
pathAndTitleTextView?.text = storageTitleAndPath
}
}

View File

@ -23,7 +23,6 @@ import androidx.compose.runtime.mutableStateOf
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharedFlow import kotlinx.coroutines.flow.SharedFlow
import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.StateFlow
@ -32,7 +31,6 @@ import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import org.kiwix.kiwixmobile.core.DarkModeConfig import org.kiwix.kiwixmobile.core.DarkModeConfig
import org.kiwix.kiwixmobile.core.R import org.kiwix.kiwixmobile.core.R
import org.kiwix.kiwixmobile.core.ui.components.TWO
import org.kiwix.kiwixmobile.core.utils.SharedPreferenceUtil import org.kiwix.kiwixmobile.core.utils.SharedPreferenceUtil
import javax.inject.Inject import javax.inject.Inject
@ -73,9 +71,6 @@ class SettingsViewModel @Inject constructor(
initialValue = sharedPreferenceUtil.textZoom initialValue = sharedPreferenceUtil.textZoom
) )
private val _textZoomPosition = MutableStateFlow(TWO)
val textZoomPosition: StateFlow<Int> = _textZoomPosition
var newTabInBackground = mutableStateOf(sharedPreferenceUtil.prefNewTabBackground) var newTabInBackground = mutableStateOf(sharedPreferenceUtil.prefNewTabBackground)
val wifiOnly: StateFlow<Boolean> = sharedPreferenceUtil.prefWifiOnlys val wifiOnly: StateFlow<Boolean> = sharedPreferenceUtil.prefWifiOnlys
@ -108,7 +103,6 @@ class SettingsViewModel @Inject constructor(
} }
fun setTextZoom(position: Int) { fun setTextZoom(position: Int) {
_textZoomPosition.value = position
sharedPreferenceUtil.textZoom = (position + ZOOM_OFFSET) * ZOOM_SCALE sharedPreferenceUtil.textZoom = (position + ZOOM_OFFSET) * ZOOM_SCALE
} }

View File

@ -50,9 +50,8 @@ class SharedPreferenceUtil @Inject constructor(val context: Context) {
private val _prefStorages = MutableStateFlow("") private val _prefStorages = MutableStateFlow("")
val prefStorages val prefStorages
get() = _prefStorages.asStateFlow().onStart { emit(prefStorage) } get() = _prefStorages.asStateFlow().onStart { emit(prefStorage) }
private val _textZooms = MutableStateFlow(DEFAULT_ZOOM) private val _textZooms = MutableStateFlow(textZoom)
val textZooms val textZooms get() = _textZooms.asStateFlow()
get() = _textZooms.asStateFlow().onStart { emit(textZoom) }
private val darkModes = MutableStateFlow(DarkModeConfig.Mode.SYSTEM) private val darkModes = MutableStateFlow(DarkModeConfig.Mode.SYSTEM)
private val _prefWifiOnlys = MutableStateFlow(true) private val _prefWifiOnlys = MutableStateFlow(true)
val prefWifiOnlys val prefWifiOnlys

View File

@ -26,6 +26,7 @@ import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.combinedClickable import androidx.compose.foundation.combinedClickable
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.ColumnScope
import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.Spacer
@ -104,41 +105,53 @@ fun DialogHost(alertDialogShower: AlertDialogShower) {
val dialogData = alertDialogShower.dialogState.value val dialogData = alertDialogShower.dialogState.value
dialogData?.let { (dialog, clickListeners, uri) -> dialogData?.let { (dialog, clickListeners, uri) ->
KiwixDialogTheme { KiwixBasicDialogFrame(
BasicAlertDialog( onDismissRequest = { alertDialogShower.dismiss() },
onDismissRequest = { cancelable = dialog.cancelable,
if (dialog.cancelable) { ) {
alertDialogShower.dismiss() Row(
} verticalAlignment = Alignment.CenterVertically
},
properties = DialogProperties(usePlatformDefaultWidth = false),
modifier = Modifier.padding(DIALOG_PADDING)
) { ) {
Surface( DialogIcon(dialog)
DialogTitle(dialog.title)
}
DialogMessage(dialog)
ShowUri(uri)
ShowCustomComposeView(dialog)
ShowDialogButtons(dialog, clickListeners, alertDialogShower)
}
}
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun KiwixBasicDialogFrame(
onDismissRequest: () -> Unit,
cancelable: Boolean = true,
content: @Composable ColumnScope.() -> Unit
) {
KiwixDialogTheme {
BasicAlertDialog(
onDismissRequest = {
if (cancelable) onDismissRequest()
},
properties = DialogProperties(usePlatformDefaultWidth = false),
modifier = Modifier.padding(DIALOG_PADDING)
) {
Surface(
modifier = Modifier
.wrapContentSize()
.wrapContentHeight(),
shape = MaterialTheme.shapes.extraSmall,
tonalElevation = AlertDialogDefaults.TonalElevation,
color = MaterialTheme.colorScheme.background
) {
Column(
modifier = Modifier modifier = Modifier
.wrapContentSize() .padding(horizontal = DIALOG_DEFAULT_PADDING_FOR_CONTENT)
.wrapContentHeight(), .padding(top = DIALOG_DEFAULT_PADDING_FOR_CONTENT),
shape = MaterialTheme.shapes.extraSmall, content = content
tonalElevation = AlertDialogDefaults.TonalElevation, )
color = MaterialTheme.colorScheme.background
) {
Column(
modifier = Modifier
.padding(horizontal = DIALOG_DEFAULT_PADDING_FOR_CONTENT)
.padding(top = DIALOG_DEFAULT_PADDING_FOR_CONTENT)
) {
Row(
verticalAlignment = Alignment.CenterVertically
) {
DialogIcon(dialog)
DialogTitle(dialog)
}
DialogMessage(dialog)
ShowUri(uri)
ShowCustomComposeView(dialog)
ShowDialogButtons(dialog, clickListeners, alertDialogShower)
}
}
} }
} }
} }
@ -175,16 +188,15 @@ fun DialogIcon(dialog: KiwixDialog) {
} }
@Composable @Composable
private fun DialogConfirmButton( fun DialogConfirmButton(
dialog: KiwixDialog, confirmButtonText: String,
dialogConfirmButtonClick: (() -> Unit)?, dialogConfirmButtonClick: (() -> Unit)?,
alertDialogShower: AlertDialogShower alertDialogShower: AlertDialogShower?
) { ) {
val confirmButtonText = stringResource(id = dialog.confirmButtonText)
if (confirmButtonText.isNotEmpty()) { if (confirmButtonText.isNotEmpty()) {
TextButton( TextButton(
onClick = { onClick = {
alertDialogShower.dismiss() alertDialogShower?.dismiss()
dialogConfirmButtonClick?.invoke() dialogConfirmButtonClick?.invoke()
}, },
modifier = Modifier.semantics { testTag = ALERT_DIALOG_CONFIRM_BUTTON_TESTING_TAG }, modifier = Modifier.semantics { testTag = ALERT_DIALOG_CONFIRM_BUTTON_TESTING_TAG },
@ -285,13 +297,17 @@ private fun ShowDialogButtons(
) )
Spacer(modifier = Modifier.weight(1f)) Spacer(modifier = Modifier.weight(1f))
DialogDismissButton(dialog, clickListeners.getOrNull(1), alertDialogShower) DialogDismissButton(dialog, clickListeners.getOrNull(1), alertDialogShower)
DialogConfirmButton(dialog, clickListeners.getOrNull(0), alertDialogShower) DialogConfirmButton(
stringResource(dialog.confirmButtonText),
clickListeners.getOrNull(0),
alertDialogShower
)
} }
} }
@Composable @Composable
private fun DialogTitle(dialog: KiwixDialog) { fun DialogTitle(title: Int?) {
dialog.title?.let { title?.let {
Text( Text(
text = stringResource(id = it), text = stringResource(id = it),
style = MaterialTheme.typography.titleSmall.copy( style = MaterialTheme.typography.titleSmall.copy(

View File

@ -1,45 +0,0 @@
<?xml version="1.0" encoding="utf-8"?><!--
~ Kiwix Android
~ Copyright (c) 2023 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/>.
~
-->
<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="wrap_content"
android:layout_height="wrap_content"
android:padding="@dimen/activity_horizontal_margin">
<ProgressBar
android:id="@+id/custom_progressbar"
style="?android:attr/progressBarStyleLarge"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_centerHorizontal="true"
android:indeterminate="true"
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>

View File

@ -1,76 +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="wrap_content"
android:padding="@dimen/activity_horizontal_margin">
<RadioButton
android:id="@+id/radioButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clickable="false"
android:focusable="false"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0" />
<TextView
android:id="@+id/storagePathAndTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceListItem"
android:textColor="?android:attr/textColorPrimary"
android:textAlignment="viewStart"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0"
app:layout_constraintStart_toEndOf="@id/radioButton"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/usedSpace"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:textAppearance="?android:attr/textAppearanceListItemSecondary"
android:textColor="?android:attr/textColorSecondary"
app:layout_constraintStart_toStartOf="@+id/storagePathAndTitle"
app:layout_constraintTop_toBottomOf="@+id/storageProgressBar" />
<TextView
android:id="@+id/freeSpace"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceListItemSecondary"
android:textColor="?android:attr/textColorSecondary"
app:layout_constraintBaseline_toBaselineOf="@id/usedSpace"
app:layout_constraintEnd_toEndOf="parent" />
<ProgressBar
android:id="@+id/storageProgressBar"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:indeterminate="false"
android:max="100"
android:progress="0"
android:progressDrawable="@drawable/progress_bar_state"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/radioButton"
app:layout_constraintTop_toBottomOf="@id/storagePathAndTitle" />
<View
android:id="@+id/clickOverlay"
android:layout_width="0dp"
android:layout_height="0dp"
android:visibility="gone"
android:background="?selectableItemBackground"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -1,178 +0,0 @@
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
app:iconSpaceReserved="false">
<PreferenceCategory
android:key="pref_display"
android:title="@string/pref_display_title"
app:iconSpaceReserved="false">
<ListPreference
android:defaultValue="-1"
android:entries="@array/pref_dark_modes_entries"
android:entryValues="@array/pref_dark_modes_values"
android:key="pref_dark_mode"
android:summary="@string/pref_dark_mode_summary"
android:title="@string/pref_dark_mode"
app:iconSpaceReserved="false" />
<SwitchPreferenceCompat
android:defaultValue="false"
android:key="pref_backtotop"
android:summary="@string/pref_back_to_top_summary"
android:title="@string/pref_back_to_top"
app:iconSpaceReserved="false" />
<SeekBarPreference
android:defaultValue="2"
android:max="6"
android:summary="@string/pref_text_zoom_summary"
app:iconSpaceReserved="false"
app:key="text_zoom"
app:title="@string/pref_text_zoom_title"
app:updatesContinuously="true" />
</PreferenceCategory>
<PreferenceCategory
android:key="pref_extras"
android:title="@string/pref_extras"
app:iconSpaceReserved="false">
<SwitchPreferenceCompat
android:defaultValue="false"
android:key="pref_newtab_background"
android:summary="@string/pref_newtab_background_summary"
android:title="@string/pref_newtab_background_title"
app:iconSpaceReserved="false" />
<SwitchPreferenceCompat
android:defaultValue="true"
android:key="pref_external_link_popup"
android:summary="@string/pref_external_link_popup_summary"
android:title="@string/pref_external_link_popup_title"
app:iconSpaceReserved="false" />
<SwitchPreferenceCompat
android:defaultValue="true"
android:key="pref_wifi_only"
android:summary="@string/pref_wifi_only"
android:title="@string/pref_wifi_only"
app:iconSpaceReserved="false" />
</PreferenceCategory>
<PreferenceCategory
android:key="pref_storage"
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:isPreferenceVisible="false" />
<org.kiwix.kiwixmobile.core.settings.StorageRadioButtonPreference
android:key="pref_external_storage"
android:layout="@layout/item_storage_preference"
app:iconSpaceReserved="false"
app:isPreferenceVisible="false" />
</PreferenceCategory>
<PreferenceCategory
android:key="pref_history"
android:title="@string/history"
app:iconSpaceReserved="false">
<Preference
android:key="pref_clear_all_history"
android:summary="@string/pref_clear_all_history_summary"
android:title="@string/pref_clear_all_history_title"
app:iconSpaceReserved="false" />
</PreferenceCategory>
<PreferenceCategory
android:key="pref_notes"
android:title="@string/pref_notes"
app:iconSpaceReserved="false">
<Preference
android:key="pref_clear_all_notes"
android:summary="@string/pref_clear_all_notes_summary"
android:title="@string/pref_clear_all_notes_title"
app:iconSpaceReserved="false" />
</PreferenceCategory>
<PreferenceCategory
android:key="pref_bookmark"
android:title="@string/bookmarks"
app:iconSpaceReserved="false">
<Preference
android:key="pref_import_bookmark"
android:summary="@string/pref_import_bookmark_summary"
android:title="@string/pref_import_bookmark_title"
app:iconSpaceReserved="false" />
<Preference
android:key="pref_export_bookmark"
android:summary="@string/pref_export_bookmark_summary"
android:title="@string/pref_export_bookmark_title"
app:iconSpaceReserved="false" />
</PreferenceCategory>
<PreferenceCategory
android:key="pref_permissions"
android:title="@string/pref_permission"
app:iconSpaceReserved="false"
app:isPreferenceVisible="false">
<Preference
android:key="pref_manage_external_storage"
android:title="@string/pref_allow_to_read_or_write_zim_files_on_sd_card"
app:iconSpaceReserved="false" />
</PreferenceCategory>
<PreferenceCategory
android:key="pref_language"
android:title="@string/pref_language_title"
app:iconSpaceReserved="false">
<ListPreference
android:key="pref_language_chooser"
android:summary="@string/pref_language_chooser"
android:title="@string/pref_language_title"
app:iconSpaceReserved="false" />
</PreferenceCategory>
<PreferenceCategory
android:key="pref_info"
android:title="@string/pref_info_title"
app:iconSpaceReserved="false">
<EditTextPreference
android:enabled="false"
android:key="pref_version"
android:persistent="false"
android:selectable="true"
android:shouldDisableView="false"
android:title="@string/pref_info_version"
app:iconSpaceReserved="false" />
<Preference
android:key="pref_credits"
android:summary="@string/pref_credits"
android:title="@string/pref_credits_title"
app:iconSpaceReserved="false" />
</PreferenceCategory>
</PreferenceScreen>