mirror of
https://github.com/kiwix/kiwix-android.git
synced 2025-09-08 14:52:13 -04:00
#4159 migrated Help Fragment to jetpack Compose
This commit is contained in:
parent
102162fde3
commit
6873bd53c2
@ -22,6 +22,9 @@ import org.kiwix.kiwixmobile.core.R
|
|||||||
import org.kiwix.kiwixmobile.core.help.HelpFragment
|
import org.kiwix.kiwixmobile.core.help.HelpFragment
|
||||||
|
|
||||||
class KiwixHelpFragment : HelpFragment() {
|
class KiwixHelpFragment : HelpFragment() {
|
||||||
|
override val navHostFragmentId: Int
|
||||||
|
get() = org.kiwix.kiwixmobile.R.id.nav_host_fragment
|
||||||
|
|
||||||
override fun rawTitleDescriptionMap() =
|
override fun rawTitleDescriptionMap() =
|
||||||
if (sharedPreferenceUtil.isPlayStoreBuildWithAndroid11OrAbove()) {
|
if (sharedPreferenceUtil.isPlayStoreBuildWithAndroid11OrAbove()) {
|
||||||
listOf(
|
listOf(
|
||||||
|
@ -366,4 +366,44 @@ object Libs {
|
|||||||
*/
|
*/
|
||||||
const val fetch: String = "com.github.tonyofrancis.Fetch:fetch2:" + Versions.fetch
|
const val fetch: String = "com.github.tonyofrancis.Fetch:fetch2:" + Versions.fetch
|
||||||
const val fetchOkhttp: String = "com.github.tonyofrancis.Fetch:fetch2okhttp:" + Versions.fetch
|
const val fetchOkhttp: String = "com.github.tonyofrancis.Fetch:fetch2okhttp:" + Versions.fetch
|
||||||
|
|
||||||
|
/**
|
||||||
|
* https://developer.android.com/reference/kotlin/androidx/compose/material3
|
||||||
|
*/
|
||||||
|
const val androidx_compose_material3: String =
|
||||||
|
"androidx.compose.material3:material3-android:" + Versions.androidx_compose_material3_version
|
||||||
|
|
||||||
|
/**
|
||||||
|
* https://developer.android.com/reference/kotlin/androidx/activity/compose
|
||||||
|
*/
|
||||||
|
const val androidx_activity_compose: String =
|
||||||
|
"androidx.activity:activity-compose:" + Versions.androidx_activity_compose_version
|
||||||
|
|
||||||
|
/**
|
||||||
|
* https://developer.android.com/develop/ui/compose/documentation
|
||||||
|
*/
|
||||||
|
const val androidx_compose_ui: String =
|
||||||
|
"androidx.compose.ui:ui:" + Versions.androidx_compose_ui_version
|
||||||
|
|
||||||
|
const val androidx_compose_bom: String =
|
||||||
|
"androidx.compose:compose-bom:" + Versions.androidx_compose_bom_version
|
||||||
|
|
||||||
|
const val androidx_compose_tooling_preview: String =
|
||||||
|
"androidx.compose.ui:ui-tooling-preview"
|
||||||
|
|
||||||
|
const val androidx_compose_runtime_livedata: String =
|
||||||
|
"androidx.compose.runtime:runtime-livedata"
|
||||||
|
|
||||||
|
const val androidx_compose_runtime_rxjava2: String =
|
||||||
|
"androidx.compose.runtime:runtime-rxjava2"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* testing libraries for compose
|
||||||
|
*/
|
||||||
|
const val androidx_compose_ui_test_junit4: String =
|
||||||
|
"androidx.compose.ui:ui-test-junit4"
|
||||||
|
|
||||||
|
const val androidx_compose_ui_tooling: String =
|
||||||
|
"androidx.compose.ui:ui-tooling"
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -115,6 +115,18 @@ object Versions {
|
|||||||
const val keeper = "0.16.1"
|
const val keeper = "0.16.1"
|
||||||
|
|
||||||
const val fetch: String = "3.4.1"
|
const val fetch: String = "3.4.1"
|
||||||
|
|
||||||
|
const val org_jetbrains_kotlin_plugin_compose = "2.1.10"
|
||||||
|
|
||||||
|
const val kotlin_compiler_extension_version = "1.5.15"
|
||||||
|
|
||||||
|
const val androidx_compose_material3_version = "1.3.1"
|
||||||
|
|
||||||
|
const val androidx_activity_compose_version = "1.10.0"
|
||||||
|
|
||||||
|
const val androidx_compose_ui_version = "1.7.7"
|
||||||
|
|
||||||
|
const val androidx_compose_bom_version = "2025.01.01"
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -13,6 +13,8 @@ buildscript {
|
|||||||
}
|
}
|
||||||
plugins {
|
plugins {
|
||||||
`android-library`
|
`android-library`
|
||||||
|
id("org.jetbrains.kotlin.android")
|
||||||
|
id("org.jetbrains.kotlin.plugin.compose") version Versions.org_jetbrains_kotlin_plugin_compose
|
||||||
}
|
}
|
||||||
plugins.apply(KiwixConfigurationPlugin::class)
|
plugins.apply(KiwixConfigurationPlugin::class)
|
||||||
apply(plugin = "io.objectbox")
|
apply(plugin = "io.objectbox")
|
||||||
@ -26,6 +28,12 @@ android {
|
|||||||
isMinifyEnabled = false
|
isMinifyEnabled = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
buildFeatures {
|
||||||
|
compose = true
|
||||||
|
}
|
||||||
|
composeOptions {
|
||||||
|
kotlinCompilerExtensionVersion = Versions.kotlin_compiler_extension_version
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun shouldUseLocalVersion() = File(projectDir, "libs").exists()
|
fun shouldUseLocalVersion() = File(projectDir, "libs").exists()
|
||||||
@ -63,4 +71,17 @@ dependencies {
|
|||||||
implementation(Libs.kotlinx_coroutines_android)
|
implementation(Libs.kotlinx_coroutines_android)
|
||||||
implementation(Libs.kotlinx_coroutines_rx3)
|
implementation(Libs.kotlinx_coroutines_rx3)
|
||||||
implementation(Libs.zxing)
|
implementation(Libs.zxing)
|
||||||
|
|
||||||
|
implementation(Libs.androidx_compose_material3)
|
||||||
|
implementation(Libs.androidx_activity_compose)
|
||||||
|
|
||||||
|
implementation(Libs.androidx_compose_ui)
|
||||||
|
implementation(platform(Libs.androidx_compose_bom))
|
||||||
|
implementation(Libs.androidx_compose_ui_tooling)
|
||||||
|
implementation(Libs.androidx_compose_runtime_livedata)
|
||||||
|
implementation(Libs.androidx_compose_runtime_rxjava2)
|
||||||
|
|
||||||
|
// For Compose UI Testing
|
||||||
|
androidTestImplementation(Libs.androidx_compose_ui_test_junit4)
|
||||||
|
debugImplementation(Libs.androidx_compose_ui_tooling)
|
||||||
}
|
}
|
||||||
|
@ -17,83 +17,91 @@
|
|||||||
*/
|
*/
|
||||||
package org.kiwix.kiwixmobile.core.help
|
package org.kiwix.kiwixmobile.core.help
|
||||||
|
|
||||||
|
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.appcompat.app.AppCompatActivity
|
|
||||||
import androidx.appcompat.widget.Toolbar
|
import androidx.appcompat.widget.Toolbar
|
||||||
import androidx.recyclerview.widget.DividerItemDecoration
|
import androidx.compose.ui.platform.ComposeView
|
||||||
|
import androidx.navigation.Navigation
|
||||||
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.base.BaseFragment
|
import org.kiwix.kiwixmobile.core.base.BaseFragment
|
||||||
import org.kiwix.kiwixmobile.core.databinding.FragmentHelpBinding
|
|
||||||
import org.kiwix.kiwixmobile.core.error.DiagnosticReportActivity
|
|
||||||
import org.kiwix.kiwixmobile.core.extensions.ActivityExtensions.start
|
|
||||||
import org.kiwix.kiwixmobile.core.main.CoreMainActivity
|
import org.kiwix.kiwixmobile.core.main.CoreMainActivity
|
||||||
import org.kiwix.kiwixmobile.core.utils.SharedPreferenceUtil
|
import org.kiwix.kiwixmobile.core.utils.SharedPreferenceUtil
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@Suppress("UnnecessaryAbstractClass")
|
@Suppress("UnnecessaryAbstractClass")
|
||||||
abstract class HelpFragment : BaseFragment() {
|
abstract class HelpFragment : BaseFragment() {
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var sharedPreferenceUtil: SharedPreferenceUtil
|
lateinit var sharedPreferenceUtil: SharedPreferenceUtil
|
||||||
private var fragmentHelpBinding: FragmentHelpBinding? = null
|
|
||||||
protected open fun rawTitleDescriptionMap(): List<Pair<Int, Any>> = emptyList()
|
|
||||||
override val fragmentToolbar: Toolbar? by lazy {
|
|
||||||
fragmentHelpBinding?.root?.findViewById(R.id.toolbar)
|
|
||||||
}
|
|
||||||
override val fragmentTitle: String? by lazy { getString(R.string.menu_help) }
|
|
||||||
|
|
||||||
private val titleDescriptionMap by lazy {
|
protected abstract val navHostFragmentId: Int
|
||||||
rawTitleDescriptionMap().associate { (title, description) ->
|
|
||||||
val descriptionValue = when (description) {
|
// Instead of keeping the XML binding, we now directly return a ComposeView.
|
||||||
is String -> description
|
protected open fun createFragmentView(
|
||||||
is Int -> resources.getStringArray(description).joinToString(separator = "\n")
|
inflater: LayoutInflater,
|
||||||
else -> {
|
container: ViewGroup?
|
||||||
throw IllegalArgumentException("Invalid description resource type for title: $title")
|
): View {
|
||||||
}
|
return ComposeView(requireContext()).apply {
|
||||||
|
setContent {
|
||||||
|
// Create the helpScreen data using your rawTitleDescriptionMap.
|
||||||
|
val helpScreenData = transformToHelpScreenData(
|
||||||
|
requireContext(),
|
||||||
|
rawTitleDescriptionMap()
|
||||||
|
)
|
||||||
|
// Retrieve the NavController if your composable needs it.
|
||||||
|
val navController = Navigation.findNavController(requireActivity(), navHostFragmentId)
|
||||||
|
// Call your HelpScreen composable.
|
||||||
|
HelpScreen(data = helpScreenData, navController = navController)
|
||||||
}
|
}
|
||||||
|
|
||||||
getString(title) to descriptionValue
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Each subclass is responsible for providing its own raw data.
|
||||||
|
protected open fun rawTitleDescriptionMap(): List<Pair<Int, Any>> = emptyList()
|
||||||
|
|
||||||
|
// The following properties are now optional – if no longer use an XML toolbar or title,
|
||||||
|
// we can remove or update these accordingly.
|
||||||
|
override val fragmentToolbar: Toolbar? by lazy {
|
||||||
|
// Already Applied ad TopAppBAr in scaffold in composable
|
||||||
|
null
|
||||||
|
}
|
||||||
|
override val fragmentTitle: String? by lazy { getString(R.string.menu_help) }
|
||||||
|
|
||||||
override fun inject(baseActivity: BaseActivity) {
|
override fun inject(baseActivity: BaseActivity) {
|
||||||
(baseActivity as CoreMainActivity).cachedComponent.inject(this)
|
(baseActivity as CoreMainActivity).cachedComponent.inject(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Remove or adjust onViewCreated if you no longer need to manipulate XML-based views.
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
val activity = requireActivity() as AppCompatActivity
|
// Any additional logic that is independent of the XML layout can be kept here.
|
||||||
fragmentHelpBinding?.activityHelpDiagnosticImageView?.setOnClickListener {
|
|
||||||
sendDiagnosticReport()
|
|
||||||
}
|
|
||||||
fragmentHelpBinding?.activityHelpDiagnosticTextView?.setOnClickListener {
|
|
||||||
sendDiagnosticReport()
|
|
||||||
}
|
|
||||||
fragmentHelpBinding?.activityHelpRecyclerView?.addItemDecoration(
|
|
||||||
DividerItemDecoration(activity, DividerItemDecoration.VERTICAL)
|
|
||||||
)
|
|
||||||
fragmentHelpBinding?.activityHelpRecyclerView?.adapter = HelpAdapter(titleDescriptionMap)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateView(
|
override fun onCreateView(
|
||||||
inflater: LayoutInflater,
|
inflater: LayoutInflater,
|
||||||
container: ViewGroup?,
|
container: ViewGroup?,
|
||||||
savedInstanceState: Bundle?
|
savedInstanceState: Bundle?
|
||||||
): View? {
|
): View? = createFragmentView(inflater, container)
|
||||||
fragmentHelpBinding =
|
}
|
||||||
FragmentHelpBinding.inflate(inflater, container, false)
|
|
||||||
return fragmentHelpBinding?.root
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun sendDiagnosticReport() {
|
// Util function to modify the data accordingly
|
||||||
requireActivity().start<DiagnosticReportActivity>()
|
fun transformToHelpScreenData(
|
||||||
}
|
context: Context,
|
||||||
|
rawTitleDescriptionMap: List<Pair<Int, Any>>
|
||||||
override fun onDestroyView() {
|
): List<HelpScreenItemDataClass> {
|
||||||
super.onDestroyView()
|
return rawTitleDescriptionMap.map { (titleResId, description) ->
|
||||||
fragmentHelpBinding = null
|
val title = context.getString(titleResId)
|
||||||
|
val descriptionValue = when (description) {
|
||||||
|
is String -> description
|
||||||
|
is Int -> context.resources.getStringArray(description).joinToString(separator = "\n")
|
||||||
|
else -> {
|
||||||
|
throw IllegalArgumentException("Invalid description resource type for title: $titleResId")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
HelpScreenItemDataClass(title, descriptionValue)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
152
core/src/main/java/org/kiwix/kiwixmobile/core/help/HelpScreen.kt
Normal file
152
core/src/main/java/org/kiwix/kiwixmobile/core/help/HelpScreen.kt
Normal file
@ -0,0 +1,152 @@
|
|||||||
|
/*
|
||||||
|
* 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.core.help
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
|
import androidx.compose.foundation.Image
|
||||||
|
import androidx.compose.foundation.clickable
|
||||||
|
import androidx.compose.foundation.isSystemInDarkTheme
|
||||||
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.Row
|
||||||
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
|
import androidx.compose.foundation.lazy.itemsIndexed
|
||||||
|
|
||||||
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.filled.ArrowBack
|
||||||
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
|
import androidx.compose.material3.HorizontalDivider
|
||||||
|
import androidx.compose.material3.Icon
|
||||||
|
import androidx.compose.material3.IconButton
|
||||||
|
import androidx.compose.material3.Scaffold
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.material3.TopAppBar
|
||||||
|
import androidx.compose.material3.TopAppBarDefaults
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
import androidx.compose.ui.res.colorResource
|
||||||
|
import androidx.compose.ui.res.painterResource
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.unit.sp
|
||||||
|
|
||||||
|
import androidx.navigation.NavController
|
||||||
|
import org.kiwix.kiwixmobile.core.R
|
||||||
|
import org.kiwix.kiwixmobile.core.error.DiagnosticReportActivity
|
||||||
|
import org.kiwix.kiwixmobile.core.extensions.ActivityExtensions.start
|
||||||
|
|
||||||
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
|
@Composable
|
||||||
|
fun HelpScreen(
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
|
data: List<HelpScreenItemDataClass>,
|
||||||
|
navController: NavController
|
||||||
|
) {
|
||||||
|
val context = LocalContext.current
|
||||||
|
|
||||||
|
val isDarkTheme = isSystemInDarkTheme()
|
||||||
|
|
||||||
|
val backgroundColor =
|
||||||
|
if (isDarkTheme) colorResource(id = R.color.mine_shaft_gray900) else Color.White
|
||||||
|
val dividerColor =
|
||||||
|
if (isDarkTheme) colorResource(id = R.color.mine_shaft_gray600) else colorResource(
|
||||||
|
id = R.color.mine_shaft_gray350
|
||||||
|
)
|
||||||
|
|
||||||
|
Scaffold(
|
||||||
|
modifier = Modifier.fillMaxSize(),
|
||||||
|
topBar = {
|
||||||
|
TopAppBar(
|
||||||
|
title = {
|
||||||
|
Text(
|
||||||
|
modifier = modifier.padding(start = 16.dp),
|
||||||
|
text = stringResource(id = R.string.menu_help),
|
||||||
|
color = Color.White // Set title text color to white
|
||||||
|
)
|
||||||
|
},
|
||||||
|
navigationIcon = {
|
||||||
|
IconButton(onClick = navController::popBackStack) {
|
||||||
|
Icon(
|
||||||
|
imageVector = Icons.Filled.ArrowBack,
|
||||||
|
contentDescription = "Back",
|
||||||
|
tint = Color.White // Set navigation icon color to white
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
colors = TopAppBarDefaults.topAppBarColors(
|
||||||
|
containerColor = Color.Black // Set top app bar background color to black
|
||||||
|
)
|
||||||
|
)
|
||||||
|
},
|
||||||
|
containerColor = backgroundColor
|
||||||
|
) {
|
||||||
|
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(it)
|
||||||
|
) {
|
||||||
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.clickable {
|
||||||
|
(context as? Activity)?.start<DiagnosticReportActivity>()
|
||||||
|
},
|
||||||
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
|
horizontalArrangement = Arrangement.Start
|
||||||
|
) {
|
||||||
|
Image(
|
||||||
|
painter = painterResource(R.drawable.ic_feedback_orange_24dp),
|
||||||
|
contentDescription = "Feedback",
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(16.dp)
|
||||||
|
)
|
||||||
|
|
||||||
|
Text(
|
||||||
|
text = stringResource(R.string.send_report),
|
||||||
|
color = if (isDarkTheme) Color.LightGray else Color.DarkGray,
|
||||||
|
fontSize = 18.sp
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
LazyColumn(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
) {
|
||||||
|
itemsIndexed(data, key = { _, item -> item.title }) { index, item ->
|
||||||
|
HorizontalDivider(
|
||||||
|
color = dividerColor
|
||||||
|
)
|
||||||
|
HelpScreenItem(data = item)
|
||||||
|
}
|
||||||
|
item {
|
||||||
|
HorizontalDivider(
|
||||||
|
color = dividerColor
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,125 @@
|
|||||||
|
/*
|
||||||
|
* 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.core.help
|
||||||
|
|
||||||
|
import androidx.compose.animation.AnimatedVisibility
|
||||||
|
import androidx.compose.animation.core.animateFloatAsState
|
||||||
|
import androidx.compose.animation.core.tween
|
||||||
|
import androidx.compose.foundation.clickable
|
||||||
|
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||||
|
import androidx.compose.foundation.isSystemInDarkTheme
|
||||||
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
|
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.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.height
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.layout.size
|
||||||
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.filled.KeyboardArrowDown
|
||||||
|
import androidx.compose.material3.Icon
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.graphics.graphicsLayer
|
||||||
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.unit.sp
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun HelpScreenItem(
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
|
data: HelpScreenItemDataClass,
|
||||||
|
initiallyOpened: Boolean = false
|
||||||
|
) {
|
||||||
|
var isOpen by remember { mutableStateOf(initiallyOpened) }
|
||||||
|
val isDarkTheme = isSystemInDarkTheme()
|
||||||
|
val itemColor = if (isDarkTheme) Color.White else Color.Black
|
||||||
|
val arrowRotation by animateFloatAsState(
|
||||||
|
targetValue = if (isOpen) 180f else 0f,
|
||||||
|
animationSpec = tween(300),
|
||||||
|
label = "arrowRotation"
|
||||||
|
)
|
||||||
|
|
||||||
|
val interactionSource = remember(::MutableInteractionSource)
|
||||||
|
|
||||||
|
Column(
|
||||||
|
modifier = modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(top = 12.dp),
|
||||||
|
verticalArrangement = Arrangement.Center,
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally
|
||||||
|
) {
|
||||||
|
Row(
|
||||||
|
horizontalArrangement = Arrangement.SpaceBetween,
|
||||||
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.clickable(interactionSource = interactionSource, indication = null, onClick = {
|
||||||
|
isOpen = !isOpen
|
||||||
|
})
|
||||||
|
.padding(horizontal = 16.dp)
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = data.title,
|
||||||
|
fontSize = 18.sp,
|
||||||
|
color = itemColor,
|
||||||
|
fontWeight = FontWeight.SemiBold
|
||||||
|
)
|
||||||
|
Icon(
|
||||||
|
imageVector = Icons.Default.KeyboardArrowDown,
|
||||||
|
contentDescription = "Open or Close DropDown",
|
||||||
|
modifier = Modifier
|
||||||
|
.graphicsLayer {
|
||||||
|
rotationZ = arrowRotation
|
||||||
|
}
|
||||||
|
.size(46.dp),
|
||||||
|
tint = itemColor
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.height(12.dp))
|
||||||
|
|
||||||
|
AnimatedVisibility(visible = isOpen) {
|
||||||
|
Box(
|
||||||
|
contentAlignment = Alignment.Center,
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(start = 16.dp, end = 16.dp)
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = data.description,
|
||||||
|
fontSize = 16.sp,
|
||||||
|
textAlign = TextAlign.Left,
|
||||||
|
color = itemColor,
|
||||||
|
modifier = Modifier.padding(bottom = 8.dp)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,22 @@
|
|||||||
|
/*
|
||||||
|
* 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.core.help
|
||||||
|
|
||||||
|
//same as HelpItem data class in HelpAdapter.kt
|
||||||
|
data class HelpScreenItemDataClass(val title: String, val description: String)
|
Loading…
x
Reference in New Issue
Block a user