mirror of
https://github.com/kiwix/kiwix-android.git
synced 2025-09-25 14:02:36 -04:00
Merge pull request #4388 from kiwix/Fixes#4387
Fixed: When changing the app's language, a blank screen appeared instead of the settings screen.
This commit is contained in:
commit
6bb8512391
@ -205,9 +205,13 @@ class DownloadTest : BaseActivityTest() {
|
||||
clickLanguagePreference(composeTestRule)
|
||||
assertLanguagePrefDialogDisplayed(composeTestRule)
|
||||
selectDeviceDefaultLanguage(composeTestRule)
|
||||
// Advance the main clock to settle the frame of compose.
|
||||
composeTestRule.mainClock.advanceTimeByFrame()
|
||||
clickLanguagePreference(composeTestRule)
|
||||
assertLanguagePrefDialogDisplayed(composeTestRule)
|
||||
selectAlbanianLanguage(composeTestRule)
|
||||
// Advance the main clock to settle the frame of compose.
|
||||
composeTestRule.mainClock.advanceTimeByFrame()
|
||||
}
|
||||
}
|
||||
clickDownloadOnBottomNav(composeTestRule)
|
||||
@ -226,6 +230,8 @@ class DownloadTest : BaseActivityTest() {
|
||||
clickLanguagePreference(composeTestRule)
|
||||
assertLanguagePrefDialogDisplayed(composeTestRule)
|
||||
selectDeviceDefaultLanguage(composeTestRule)
|
||||
// Advance the main clock to settle the frame of compose.
|
||||
composeTestRule.mainClock.advanceTimeByFrame()
|
||||
// check if the device default language is selected or not.
|
||||
clickLanguagePreference(composeTestRule)
|
||||
// close the language dialog.
|
||||
|
@ -144,34 +144,36 @@ class LanguageViewModelTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `observeLanguages uses network when no cache and online`() = runTest {
|
||||
every { application.getString(any()) } returns ""
|
||||
val fetchedLanguages = listOf(language(languageCode = "eng"))
|
||||
LanguageSessionCache.hasFetched = false
|
||||
languages.value = emptyList()
|
||||
fun `observeLanguages uses network when no cache and online`() = flakyTest {
|
||||
runTest {
|
||||
every { application.getString(any()) } returns ""
|
||||
val fetchedLanguages = listOf(language(languageCode = "eng"))
|
||||
LanguageSessionCache.hasFetched = false
|
||||
languages.value = emptyList()
|
||||
|
||||
every { sharedPreferenceUtil.getCachedLanguageList() } returns null
|
||||
coEvery { kiwixService.getLanguages() } returns LanguageFeed().apply {
|
||||
entries = fetchedLanguages.map {
|
||||
LanguageEntry().apply {
|
||||
languageCode = it.languageCode
|
||||
count = 1
|
||||
title = "English"
|
||||
every { sharedPreferenceUtil.getCachedLanguageList() } returns null
|
||||
coEvery { kiwixService.getLanguages() } returns LanguageFeed().apply {
|
||||
entries = fetchedLanguages.map {
|
||||
LanguageEntry().apply {
|
||||
languageCode = it.languageCode
|
||||
count = 1
|
||||
title = "English"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
every { sharedPreferenceUtil.selectedOnlineContentLanguage } returns ""
|
||||
every { sharedPreferenceUtil.saveLanguageList(any()) } just Runs
|
||||
every { sharedPreferenceUtil.selectedOnlineContentLanguage } returns ""
|
||||
every { sharedPreferenceUtil.saveLanguageList(any()) } just Runs
|
||||
|
||||
testFlow(
|
||||
languageViewModel.actions,
|
||||
triggerAction = {},
|
||||
assert = {
|
||||
val result = awaitItem()
|
||||
assertThat(result).isInstanceOf(UpdateLanguages::class.java)
|
||||
verify { sharedPreferenceUtil.saveLanguageList(any()) }
|
||||
}
|
||||
)
|
||||
testFlow(
|
||||
languageViewModel.actions,
|
||||
triggerAction = {},
|
||||
assert = {
|
||||
val result = awaitItem()
|
||||
assertThat(result).isInstanceOf(UpdateLanguages::class.java)
|
||||
verify { sharedPreferenceUtil.saveLanguageList(any()) }
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
|
@ -314,7 +314,6 @@ class ZimManageViewModelTest {
|
||||
version = 100L
|
||||
)
|
||||
viewModel.onlineLibraryRequest.test {
|
||||
skipItems(1)
|
||||
viewModel.updateOnlineLibraryFilters(newRequest)
|
||||
assertThat(awaitItem()).isEqualTo(newRequest)
|
||||
}
|
||||
|
@ -35,6 +35,7 @@ import android.widget.Toast
|
||||
import androidx.activity.result.ActivityResultLauncher
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.withFrameNanos
|
||||
import androidx.compose.ui.platform.ComposeView
|
||||
import androidx.compose.ui.viewinterop.AndroidView
|
||||
import androidx.core.content.ContextCompat
|
||||
@ -183,12 +184,27 @@ abstract class CoreSettingsFragment : SettingsContract.View, BaseFragment() {
|
||||
composeView = it
|
||||
}
|
||||
|
||||
/**
|
||||
* Restarts the Settings screen by popping it from the back stack and reopening it.
|
||||
*
|
||||
* This is useful when we need to refresh the Settings UI (e.g., after a app's language
|
||||
* change) without fully recreating the activity.
|
||||
*
|
||||
* Steps:
|
||||
* 1. Get the CoreMainActivity reference to access the NavController.
|
||||
* 2. Pop the Settings fragment from the navigation back stack.
|
||||
* 3. Wait for one frame so the back stack can settle after the pop operation.
|
||||
* 4. Navigate back to the Settings fragment route.
|
||||
*/
|
||||
private fun restartActivity() {
|
||||
(activity as CoreMainActivity?)?.let {
|
||||
it.navController.apply {
|
||||
popBackStack()
|
||||
navigate(it.settingsFragmentRoute)
|
||||
}
|
||||
val coreMainActivity = activity as? CoreMainActivity ?: return
|
||||
val navController = coreMainActivity.navController
|
||||
navController.popBackStack()
|
||||
coreMainActivity.uiCoroutineScope.launch {
|
||||
// Wait for one frame to ensure the back stack has settled before navigation
|
||||
// Bug fix #4387
|
||||
withFrameNanos { }
|
||||
navController.navigate(coreMainActivity.settingsFragmentRoute)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -29,7 +29,6 @@ import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.only
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.statusBars
|
||||
import androidx.compose.foundation.lazy.LazyListState
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.MoreVert
|
||||
import androidx.compose.material3.DropdownMenu
|
||||
@ -44,21 +43,16 @@ import androidx.compose.material3.TopAppBar
|
||||
import androidx.compose.material3.TopAppBarDefaults
|
||||
import androidx.compose.material3.TopAppBarScrollBehavior
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableIntStateOf
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberUpdatedState
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.runtime.snapshotFlow
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.platform.testTag
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import org.kiwix.kiwixmobile.core.downloader.downloadManager.ZERO
|
||||
import org.kiwix.kiwixmobile.core.ui.models.ActionMenuItem
|
||||
import org.kiwix.kiwixmobile.core.ui.models.toPainter
|
||||
import org.kiwix.kiwixmobile.core.ui.theme.Black
|
||||
@ -234,23 +228,3 @@ private fun OverflowMenuItems(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun rememberBottomNavigationVisibility(lazyListState: LazyListState?): Boolean {
|
||||
var isToolbarVisible by remember { mutableStateOf(true) }
|
||||
var lastScrollIndex by remember { mutableIntStateOf(ZERO) }
|
||||
val updatedLazyListState = rememberUpdatedState(lazyListState)
|
||||
|
||||
LaunchedEffect(updatedLazyListState) {
|
||||
updatedLazyListState.value?.let { state ->
|
||||
snapshotFlow { state.firstVisibleItemIndex }
|
||||
.collect { newScrollIndex ->
|
||||
if (newScrollIndex != lastScrollIndex) {
|
||||
isToolbarVisible = newScrollIndex < lastScrollIndex
|
||||
lastScrollIndex = newScrollIndex
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return isToolbarVisible
|
||||
}
|
||||
|
@ -215,7 +215,6 @@ internal class CustomDownloadViewModelTest {
|
||||
triggerAction = { customDownloadViewModel.actions.tryEmit(action) },
|
||||
assert = {
|
||||
val items = (1..awaitItemCount).map { awaitItem() }
|
||||
print("items = $items")
|
||||
assertThat(items).contains(endState)
|
||||
}
|
||||
)
|
||||
|
Loading…
x
Reference in New Issue
Block a user