Refactored the NoteFragmentTest to test with compose UI.

* Added testing tags to our compose UI components which help us to test the compose UI.
This commit is contained in:
MohitMaliFtechiz 2025-03-10 18:32:19 +05:30 committed by MohitMaliFtechiz
parent 3162d38ff9
commit 4444a6f236
8 changed files with 133 additions and 116 deletions

View File

@ -19,6 +19,7 @@
package org.kiwix.kiwixmobile.note package org.kiwix.kiwixmobile.note
import android.os.Build import android.os.Build
import androidx.compose.ui.test.junit4.createComposeRule
import androidx.core.content.edit import androidx.core.content.edit
import androidx.core.net.toUri import androidx.core.net.toUri
import androidx.lifecycle.Lifecycle import androidx.lifecycle.Lifecycle
@ -33,6 +34,7 @@ import androidx.test.uiautomator.UiDevice
import com.google.android.apps.common.testing.accessibility.framework.AccessibilityCheckResultUtils.matchesCheck import com.google.android.apps.common.testing.accessibility.framework.AccessibilityCheckResultUtils.matchesCheck
import com.google.android.apps.common.testing.accessibility.framework.AccessibilityCheckResultUtils.matchesViews import com.google.android.apps.common.testing.accessibility.framework.AccessibilityCheckResultUtils.matchesViews
import com.google.android.apps.common.testing.accessibility.framework.checks.DuplicateClickableBoundsCheck import com.google.android.apps.common.testing.accessibility.framework.checks.DuplicateClickableBoundsCheck
import com.google.android.apps.common.testing.accessibility.framework.checks.SpeakableTextPresentCheck
import com.google.android.apps.common.testing.accessibility.framework.checks.TouchTargetSizeCheck import com.google.android.apps.common.testing.accessibility.framework.checks.TouchTargetSizeCheck
import leakcanary.LeakAssertions import leakcanary.LeakAssertions
import org.hamcrest.Matchers.allOf import org.hamcrest.Matchers.allOf
@ -64,6 +66,9 @@ class NoteFragmentTest : BaseActivityTest() {
private lateinit var kiwixMainActivity: KiwixMainActivity private lateinit var kiwixMainActivity: KiwixMainActivity
@get:Rule
val composeTestRule = createComposeRule()
@Before @Before
override fun waitForIdle() { override fun waitForIdle() {
UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()).apply { UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()).apply {
@ -107,7 +112,8 @@ class NoteFragmentTest : BaseActivityTest() {
allOf( allOf(
matchesCheck(TouchTargetSizeCheck::class.java), matchesCheck(TouchTargetSizeCheck::class.java),
matchesViews(withContentDescription("More options")) matchesViews(withContentDescription("More options"))
) ),
matchesCheck(SpeakableTextPresentCheck::class.java)
) )
) )
} }
@ -133,16 +139,16 @@ class NoteFragmentTest : BaseActivityTest() {
StandardActions.closeDrawer() // close the drawer if open before running the test cases. StandardActions.closeDrawer() // close the drawer if open before running the test cases.
note { note {
clickOnNoteMenuItem(context) clickOnNoteMenuItem(context)
assertNoteDialogDisplayed() assertNoteDialogDisplayed(composeTestRule)
writeDemoNote() writeDemoNote(composeTestRule)
saveNote() saveNote(composeTestRule)
pressBack() pressBack()
openNoteFragment() openNoteFragment()
assertToolbarExist() assertToolbarExist()
assertNoteRecyclerViewExist() assertNoteRecyclerViewExist()
clickOnSavedNote() clickOnSavedNote()
clickOnOpenNote() clickOnOpenNote()
assertNoteSaved() assertNoteSaved(composeTestRule)
// to close the note dialog. // to close the note dialog.
pressBack() pressBack()
// to close the notes fragment. // to close the notes fragment.
@ -166,7 +172,7 @@ class NoteFragmentTest : BaseActivityTest() {
assertNoteRecyclerViewExist() assertNoteRecyclerViewExist()
clickOnSavedNote() clickOnSavedNote()
clickOnOpenNote() clickOnOpenNote()
assertNoteSaved() assertNoteSaved(composeTestRule)
pressBack() pressBack()
} }
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.N_MR1) { if (Build.VERSION.SDK_INT > Build.VERSION_CODES.N_MR1) {
@ -182,16 +188,16 @@ class NoteFragmentTest : BaseActivityTest() {
note { note {
assertHomePageIsLoadedOfTestZimFile() assertHomePageIsLoadedOfTestZimFile()
clickOnNoteMenuItem(context) clickOnNoteMenuItem(context)
assertNoteDialogDisplayed() assertNoteDialogDisplayed(composeTestRule)
writeDemoNote() writeDemoNote(composeTestRule)
saveNote() saveNote(composeTestRule)
pressBack() pressBack()
openNoteFragment() openNoteFragment()
assertToolbarExist() assertToolbarExist()
assertNoteRecyclerViewExist() assertNoteRecyclerViewExist()
clickOnSavedNote() clickOnSavedNote()
clickOnOpenNote() clickOnOpenNote()
assertNoteSaved() assertNoteSaved(composeTestRule)
// to close the note dialog. // to close the note dialog.
pressBack() pressBack()
// to close the notes fragment. // to close the notes fragment.
@ -205,16 +211,16 @@ class NoteFragmentTest : BaseActivityTest() {
loadZimFileInReader("testzim.zim") loadZimFileInReader("testzim.zim")
note { note {
clickOnNoteMenuItem(context) clickOnNoteMenuItem(context)
assertNoteDialogDisplayed() assertNoteDialogDisplayed(composeTestRule)
writeDemoNote() writeDemoNote(composeTestRule)
saveNote() saveNote(composeTestRule)
pressBack() pressBack()
openNoteFragment() openNoteFragment()
assertToolbarExist() assertToolbarExist()
assertNoteRecyclerViewExist() assertNoteRecyclerViewExist()
clickOnSavedNote() clickOnSavedNote()
clickOnOpenNote() clickOnOpenNote()
assertNoteSaved() assertNoteSaved(composeTestRule)
clickOnDeleteIcon() clickOnDeleteIcon()
pressBack() pressBack()
assertNoNotesTextDisplayed() assertNoNotesTextDisplayed()
@ -228,9 +234,9 @@ class NoteFragmentTest : BaseActivityTest() {
// Save a note. // Save a note.
note { note {
clickOnNoteMenuItem(context) clickOnNoteMenuItem(context)
assertNoteDialogDisplayed() assertNoteDialogDisplayed(composeTestRule)
writeDemoNote() writeDemoNote(composeTestRule)
saveNote() saveNote(composeTestRule)
pressBack() pressBack()
} }
// Delete that note from "Note" screen. // Delete that note from "Note" screen.
@ -238,7 +244,7 @@ class NoteFragmentTest : BaseActivityTest() {
// Test the note file is deleted or not. // Test the note file is deleted or not.
note { note {
clickOnNoteMenuItem(context) clickOnNoteMenuItem(context)
assertNoteDialogDisplayed() assertNoteDialogDisplayed(composeTestRule)
assertNotDoesNotExist() assertNotDoesNotExist()
pressBack() pressBack()
} }

View File

@ -19,13 +19,16 @@
package org.kiwix.kiwixmobile.note package org.kiwix.kiwixmobile.note
import android.content.Context import android.content.Context
import androidx.compose.ui.test.assertTextEquals
import androidx.compose.ui.test.junit4.ComposeContentTestRule
import androidx.compose.ui.test.onNodeWithTag
import androidx.compose.ui.test.performClick
import androidx.compose.ui.test.performTextInput
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import androidx.test.espresso.Espresso.closeSoftKeyboard import androidx.test.espresso.Espresso.closeSoftKeyboard
import androidx.test.espresso.Espresso.onView import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.Espresso.openActionBarOverflowOrOptionsMenu import androidx.test.espresso.Espresso.openActionBarOverflowOrOptionsMenu
import androidx.test.espresso.action.ViewActions.clearText
import androidx.test.espresso.action.ViewActions.click import androidx.test.espresso.action.ViewActions.click
import androidx.test.espresso.action.ViewActions.typeText
import androidx.test.espresso.assertion.ViewAssertions.doesNotExist import androidx.test.espresso.assertion.ViewAssertions.doesNotExist
import androidx.test.espresso.contrib.RecyclerViewActions.actionOnItemAtPosition import androidx.test.espresso.contrib.RecyclerViewActions.actionOnItemAtPosition
import androidx.test.espresso.matcher.ViewMatchers import androidx.test.espresso.matcher.ViewMatchers
@ -41,6 +44,9 @@ import org.kiwix.kiwixmobile.Findable.StringId.TextId
import org.kiwix.kiwixmobile.Findable.Text import org.kiwix.kiwixmobile.Findable.Text
import org.kiwix.kiwixmobile.Findable.ViewId import org.kiwix.kiwixmobile.Findable.ViewId
import org.kiwix.kiwixmobile.core.R import org.kiwix.kiwixmobile.core.R
import org.kiwix.kiwixmobile.core.main.ADD_NOTE_TEXT_FILED_TESTING_TAG
import org.kiwix.kiwixmobile.core.main.SAVE_MENU_BUTTON_TESTING_TAG
import org.kiwix.kiwixmobile.core.ui.components.TOOLBAR_TITLE_TESTING_TAG
import org.kiwix.kiwixmobile.testutils.TestUtils import org.kiwix.kiwixmobile.testutils.TestUtils
import org.kiwix.kiwixmobile.testutils.TestUtils.testFlakyView import org.kiwix.kiwixmobile.testutils.TestUtils.testFlakyView
import org.kiwix.kiwixmobile.utils.StandardActions.openDrawer import org.kiwix.kiwixmobile.utils.StandardActions.openDrawer
@ -49,7 +55,6 @@ fun note(func: NoteRobot.() -> Unit) = NoteRobot().apply(func)
class NoteRobot : BaseRobot() { class NoteRobot : BaseRobot() {
private val noteText = "Test Note" private val noteText = "Test Note"
private val editTextId = R.id.add_note_edit_text
fun assertToolbarExist() { fun assertToolbarExist() {
isVisible(ViewId(R.id.toolbar)) isVisible(ViewId(R.id.toolbar))
@ -71,19 +76,34 @@ class NoteRobot : BaseRobot() {
clickOn(TextId(R.string.take_notes)) clickOn(TextId(R.string.take_notes))
} }
fun assertNoteDialogDisplayed() { fun assertNoteDialogDisplayed(composeTestRule: ComposeContentTestRule) {
pauseForBetterTestPerformance() pauseForBetterTestPerformance()
isVisible(TextId(R.string.note)) testFlakyView({
composeTestRule.onNodeWithTag(TOOLBAR_TITLE_TESTING_TAG)
.assertTextEquals(context.getString(R.string.note))
})
} }
fun writeDemoNote() { fun writeDemoNote(composeTestRule: ComposeContentTestRule) {
onView(withId(editTextId)).perform(clearText(), typeText(noteText)) pauseForBetterTestPerformance()
closeSoftKeyboard() testFlakyView({
// Click on the TextField to focus it
composeTestRule.onNodeWithTag(ADD_NOTE_TEXT_FILED_TESTING_TAG)
.assertExists("TextField not found in dialog")
.performClick()
.performTextInput(noteText)
// Close the keyboard after typing
closeSoftKeyboard()
})
} }
fun saveNote() { fun saveNote(composeTestRule: ComposeContentTestRule) {
pauseForBetterTestPerformance() pauseForBetterTestPerformance()
clickOn(ViewId(R.id.save_note)) testFlakyView({
composeTestRule.onNodeWithTag(SAVE_MENU_BUTTON_TESTING_TAG)
.performClick()
})
} }
fun openNoteFragment() { fun openNoteFragment() {
@ -106,10 +126,13 @@ class NoteRobot : BaseRobot() {
testFlakyView({ clickOn(Text("OPEN NOTE")) }) testFlakyView({ clickOn(Text("OPEN NOTE")) })
} }
fun assertNoteSaved() { fun assertNoteSaved(composeTestRule: ComposeContentTestRule) {
// This is flaky since it is shown in a dialog and sometimes // This is flaky since it is shown in a dialog and sometimes
// UIDevice does not found the view immediately due to rendering process. // UIDevice does not found the view immediately due to rendering process.
testFlakyView({ isVisible(Text(noteText)) }) testFlakyView({
composeTestRule.onNodeWithTag(ADD_NOTE_TEXT_FILED_TESTING_TAG)
.assertTextEquals(noteText)
})
} }
fun assertNotDoesNotExist() { fun assertNotDoesNotExist() {

View File

@ -18,41 +18,11 @@
package org.kiwix.kiwixmobile.core.extensions package org.kiwix.kiwixmobile.core.extensions
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Snackbar
import androidx.compose.material3.SnackbarDuration import androidx.compose.material3.SnackbarDuration
import androidx.compose.material3.SnackbarHost
import androidx.compose.material3.SnackbarHostState import androidx.compose.material3.SnackbarHostState
import androidx.compose.material3.SnackbarResult import androidx.compose.material3.SnackbarResult
import androidx.compose.runtime.Composable
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import org.kiwix.kiwixmobile.core.ui.theme.DenimBlue400
/**
* A custom SnackbarHost for displaying snackbars with theme-aware action button colors.
*
* This function ensures that the action button color follows the app's theme:
* - In **light mode**, the action button color is `DenimBlue400`.
* - In **dark mode**, the action button color is `surface`, similar to the XML-based styling.
*
* @param snackbarHostState The state that controls the Snackbar display.
*/
@Composable
fun KiwixSnackbarHost(snackbarHostState: SnackbarHostState) {
val actionColor = if (isSystemInDarkTheme()) {
MaterialTheme.colorScheme.surface
} else {
DenimBlue400
}
SnackbarHost(hostState = snackbarHostState) { snackbarData ->
Snackbar(
snackbarData = snackbarData,
actionColor = actionColor
)
}
}
fun SnackbarHostState.snack( fun SnackbarHostState.snack(
message: String, message: String,

View File

@ -209,19 +209,22 @@ class AddNoteDialog : DialogFragment() {
Vector(Icons.Default.Delete), Vector(Icons.Default.Delete),
R.string.delete, R.string.delete,
{ deleteNote() }, { deleteNote() },
isEnabled = false isEnabled = false,
testingTag = DELETE_MENU_BUTTON_TESTING_TAG
), ),
ActionMenuItem( ActionMenuItem(
Vector(Icons.Default.Share), Vector(Icons.Default.Share),
R.string.share, R.string.share,
{ shareNote() }, { shareNote() },
isEnabled = false isEnabled = false,
testingTag = SHARE_MENU_BUTTON_TESTING_TAG
), ),
ActionMenuItem( ActionMenuItem(
Drawable(R.drawable.ic_save), Drawable(R.drawable.ic_save),
R.string.save, R.string.save,
{ saveNote() }, { saveNote() },
isEnabled = false isEnabled = false,
testingTag = SAVE_MENU_BUTTON_TESTING_TAG
) )
) )

View File

@ -18,7 +18,6 @@
package org.kiwix.kiwixmobile.core.main package org.kiwix.kiwixmobile.core.main
import android.content.res.Configuration
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
@ -26,9 +25,6 @@ import androidx.compose.foundation.layout.heightIn
import androidx.compose.foundation.layout.imePadding import androidx.compose.foundation.layout.imePadding
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Delete
import androidx.compose.material.icons.filled.Share
import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold import androidx.compose.material3.Scaffold
@ -46,19 +42,15 @@ import androidx.compose.ui.focus.focusRequester
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.RectangleShape import androidx.compose.ui.graphics.RectangleShape
import androidx.compose.ui.platform.LocalFocusManager import androidx.compose.ui.platform.LocalFocusManager
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.input.KeyboardCapitalization import androidx.compose.ui.text.input.KeyboardCapitalization
import androidx.compose.ui.text.input.KeyboardType import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.text.input.TextFieldValue import androidx.compose.ui.text.input.TextFieldValue
import androidx.compose.ui.tooling.preview.Preview
import org.kiwix.kiwixmobile.core.R import org.kiwix.kiwixmobile.core.R
import org.kiwix.kiwixmobile.core.extensions.KiwixSnackbarHost
import org.kiwix.kiwixmobile.core.ui.components.KiwixAppBar import org.kiwix.kiwixmobile.core.ui.components.KiwixAppBar
import org.kiwix.kiwixmobile.core.ui.components.NavigationIcon import org.kiwix.kiwixmobile.core.ui.components.KiwixSnackbarHost
import org.kiwix.kiwixmobile.core.ui.models.ActionMenuItem import org.kiwix.kiwixmobile.core.ui.models.ActionMenuItem
import org.kiwix.kiwixmobile.core.ui.models.IconItem
import org.kiwix.kiwixmobile.core.ui.models.IconItem.Drawable
import org.kiwix.kiwixmobile.core.ui.models.IconItem.Vector
import org.kiwix.kiwixmobile.core.ui.theme.KiwixTheme import org.kiwix.kiwixmobile.core.ui.theme.KiwixTheme
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.FOUR_DP import org.kiwix.kiwixmobile.core.utils.ComposeDimens.FOUR_DP
@ -66,6 +58,11 @@ import org.kiwix.kiwixmobile.core.utils.ComposeDimens.MINIMUM_HEIGHT_OF_NOTE_TEX
import org.kiwix.kiwixmobile.core.utils.ComposeDimens.TEN_DP import org.kiwix.kiwixmobile.core.utils.ComposeDimens.TEN_DP
import org.kiwix.kiwixmobile.core.utils.ComposeDimens.TWENTY_DP import org.kiwix.kiwixmobile.core.utils.ComposeDimens.TWENTY_DP
const val ADD_NOTE_TEXT_FILED_TESTING_TAG = "addNoteTextFiledTestingTag"
const val SAVE_MENU_BUTTON_TESTING_TAG = "saveMenuButtonTestingTag"
const val SHARE_MENU_BUTTON_TESTING_TAG = "shareMenuButtonTestingTag"
const val DELETE_MENU_BUTTON_TESTING_TAG = "deleteMenuButtonTestingTag"
@Suppress("ComposableLambdaParameterNaming") @Suppress("ComposableLambdaParameterNaming")
@Composable @Composable
fun AddNoteDialogScreen( fun AddNoteDialogScreen(
@ -138,7 +135,8 @@ private fun NoteTextField(
.heightIn(min = MINIMUM_HEIGHT_OF_NOTE_TEXT_FILED) .heightIn(min = MINIMUM_HEIGHT_OF_NOTE_TEXT_FILED)
.padding(bottom = TEN_DP) .padding(bottom = TEN_DP)
.padding(horizontal = FOUR_DP) .padding(horizontal = FOUR_DP)
.focusRequester(focusRequester), .focusRequester(focusRequester)
.testTag(ADD_NOTE_TEXT_FILED_TESTING_TAG),
placeholder = { Text(text = stringResource(R.string.note)) }, placeholder = { Text(text = stringResource(R.string.note)) },
singleLine = false, singleLine = false,
shape = RectangleShape, shape = RectangleShape,
@ -158,42 +156,3 @@ private fun NoteTextField(
) )
) )
} }
@Preview
@Preview(name = "Night mode", uiMode = Configuration.UI_MODE_NIGHT_YES)
@Composable
fun PreviewAddNoteDialog() {
AddNoteDialogScreen(
"Demo note",
navigationIcon = {
NavigationIcon(
iconItem = IconItem.Drawable(R.drawable.ic_close_white_24dp),
onClick = {}
)
},
noteText = TextFieldValue(""),
actionMenuItems = listOf(
ActionMenuItem(
Vector(Icons.Default.Delete),
R.string.delete,
{ },
isEnabled = false
),
ActionMenuItem(
Vector(Icons.Default.Share),
R.string.share,
{ },
isEnabled = false
),
ActionMenuItem(
Drawable(R.drawable.ic_save),
R.string.save,
{ },
isEnabled = false
)
),
onTextChange = { text -> },
isNoteFileExist = true,
snackBarHostState = SnackbarHostState()
)
}

View File

@ -34,6 +34,7 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.vector.rememberVectorPainter import androidx.compose.ui.graphics.vector.rememberVectorPainter
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight.Companion.SemiBold import androidx.compose.ui.text.font.FontWeight.Companion.SemiBold
@ -44,6 +45,8 @@ import org.kiwix.kiwixmobile.core.ui.theme.White
import org.kiwix.kiwixmobile.core.utils.ComposeDimens.KIWIX_APP_BAR_HEIGHT import org.kiwix.kiwixmobile.core.utils.ComposeDimens.KIWIX_APP_BAR_HEIGHT
import org.kiwix.kiwixmobile.core.utils.ComposeDimens.SIXTEEN_DP import org.kiwix.kiwixmobile.core.utils.ComposeDimens.SIXTEEN_DP
const val TOOLBAR_TITLE_TESTING_TAG = "toolbarTitle"
@Composable @Composable
fun KiwixAppBar( fun KiwixAppBar(
@StringRes titleId: Int, @StringRes titleId: Int,
@ -80,7 +83,7 @@ private fun AppBarTitle(
text = stringResource(titleId), text = stringResource(titleId),
color = White, color = White,
style = MaterialTheme.typography.titleLarge.copy(fontWeight = SemiBold), style = MaterialTheme.typography.titleLarge.copy(fontWeight = SemiBold),
modifier = Modifier.padding(horizontal = SIXTEEN_DP) modifier = Modifier.padding(horizontal = SIXTEEN_DP).testTag(TOOLBAR_TITLE_TESTING_TAG)
) )
} }
@ -90,7 +93,8 @@ private fun ActionMenu(actionMenuItems: List<ActionMenuItem>) {
actionMenuItems.forEach { menuItem -> actionMenuItems.forEach { menuItem ->
IconButton( IconButton(
enabled = menuItem.isEnabled, enabled = menuItem.isEnabled,
onClick = menuItem.onClick onClick = menuItem.onClick,
modifier = Modifier.testTag(menuItem.testingTag)
) { ) {
Icon( Icon(
painter = when (val icon = menuItem.icon) { painter = when (val icon = menuItem.icon) {

View File

@ -0,0 +1,51 @@
/*
* 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.ui.components
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Snackbar
import androidx.compose.material3.SnackbarHost
import androidx.compose.material3.SnackbarHostState
import androidx.compose.runtime.Composable
import org.kiwix.kiwixmobile.core.ui.theme.DenimBlue400
/**
* A custom SnackbarHost for displaying snackbars with theme-aware action button colors.
*
* This function ensures that the action button color follows the app's theme:
* - In **light mode**, the action button color is `DenimBlue400`.
* - In **dark mode**, the action button color is `surface`, similar to the XML-based styling.
*
* @param snackbarHostState The state that controls the Snackbar display.
*/
@Composable
fun KiwixSnackbarHost(snackbarHostState: SnackbarHostState) {
val actionColor = if (isSystemInDarkTheme()) {
MaterialTheme.colorScheme.surface
} else {
DenimBlue400
}
SnackbarHost(hostState = snackbarHostState) { snackbarData ->
Snackbar(
snackbarData = snackbarData,
actionColor = actionColor
)
}
}

View File

@ -27,5 +27,6 @@ data class ActionMenuItem(
@StringRes val contentDescription: Int, @StringRes val contentDescription: Int,
val onClick: () -> Unit, val onClick: () -> Unit,
val iconTint: Color = White, val iconTint: Color = White,
val isEnabled: Boolean = true val isEnabled: Boolean = true,
val testingTag: String
) )