mirror of
https://github.com/kiwix/kiwix-android.git
synced 2025-09-28 07:31: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)
|
clickLanguagePreference(composeTestRule)
|
||||||
assertLanguagePrefDialogDisplayed(composeTestRule)
|
assertLanguagePrefDialogDisplayed(composeTestRule)
|
||||||
selectDeviceDefaultLanguage(composeTestRule)
|
selectDeviceDefaultLanguage(composeTestRule)
|
||||||
|
// Advance the main clock to settle the frame of compose.
|
||||||
|
composeTestRule.mainClock.advanceTimeByFrame()
|
||||||
clickLanguagePreference(composeTestRule)
|
clickLanguagePreference(composeTestRule)
|
||||||
assertLanguagePrefDialogDisplayed(composeTestRule)
|
assertLanguagePrefDialogDisplayed(composeTestRule)
|
||||||
selectAlbanianLanguage(composeTestRule)
|
selectAlbanianLanguage(composeTestRule)
|
||||||
|
// Advance the main clock to settle the frame of compose.
|
||||||
|
composeTestRule.mainClock.advanceTimeByFrame()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
clickDownloadOnBottomNav(composeTestRule)
|
clickDownloadOnBottomNav(composeTestRule)
|
||||||
@ -226,6 +230,8 @@ class DownloadTest : BaseActivityTest() {
|
|||||||
clickLanguagePreference(composeTestRule)
|
clickLanguagePreference(composeTestRule)
|
||||||
assertLanguagePrefDialogDisplayed(composeTestRule)
|
assertLanguagePrefDialogDisplayed(composeTestRule)
|
||||||
selectDeviceDefaultLanguage(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.
|
// check if the device default language is selected or not.
|
||||||
clickLanguagePreference(composeTestRule)
|
clickLanguagePreference(composeTestRule)
|
||||||
// close the language dialog.
|
// close the language dialog.
|
||||||
|
@ -144,7 +144,8 @@ class LanguageViewModelTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `observeLanguages uses network when no cache and online`() = runTest {
|
fun `observeLanguages uses network when no cache and online`() = flakyTest {
|
||||||
|
runTest {
|
||||||
every { application.getString(any()) } returns ""
|
every { application.getString(any()) } returns ""
|
||||||
val fetchedLanguages = listOf(language(languageCode = "eng"))
|
val fetchedLanguages = listOf(language(languageCode = "eng"))
|
||||||
LanguageSessionCache.hasFetched = false
|
LanguageSessionCache.hasFetched = false
|
||||||
@ -173,6 +174,7 @@ class LanguageViewModelTest {
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@OptIn(ExperimentalCoroutinesApi::class)
|
@OptIn(ExperimentalCoroutinesApi::class)
|
||||||
@Test
|
@Test
|
||||||
|
@ -314,7 +314,6 @@ class ZimManageViewModelTest {
|
|||||||
version = 100L
|
version = 100L
|
||||||
)
|
)
|
||||||
viewModel.onlineLibraryRequest.test {
|
viewModel.onlineLibraryRequest.test {
|
||||||
skipItems(1)
|
|
||||||
viewModel.updateOnlineLibraryFilters(newRequest)
|
viewModel.updateOnlineLibraryFilters(newRequest)
|
||||||
assertThat(awaitItem()).isEqualTo(newRequest)
|
assertThat(awaitItem()).isEqualTo(newRequest)
|
||||||
}
|
}
|
||||||
|
@ -35,6 +35,7 @@ import android.widget.Toast
|
|||||||
import androidx.activity.result.ActivityResultLauncher
|
import androidx.activity.result.ActivityResultLauncher
|
||||||
import androidx.activity.result.contract.ActivityResultContracts
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.withFrameNanos
|
||||||
import androidx.compose.ui.platform.ComposeView
|
import androidx.compose.ui.platform.ComposeView
|
||||||
import androidx.compose.ui.viewinterop.AndroidView
|
import androidx.compose.ui.viewinterop.AndroidView
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
@ -183,12 +184,27 @@ abstract class CoreSettingsFragment : SettingsContract.View, BaseFragment() {
|
|||||||
composeView = it
|
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() {
|
private fun restartActivity() {
|
||||||
(activity as CoreMainActivity?)?.let {
|
val coreMainActivity = activity as? CoreMainActivity ?: return
|
||||||
it.navController.apply {
|
val navController = coreMainActivity.navController
|
||||||
popBackStack()
|
navController.popBackStack()
|
||||||
navigate(it.settingsFragmentRoute)
|
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.only
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.statusBars
|
import androidx.compose.foundation.layout.statusBars
|
||||||
import androidx.compose.foundation.lazy.LazyListState
|
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.filled.MoreVert
|
import androidx.compose.material.icons.filled.MoreVert
|
||||||
import androidx.compose.material3.DropdownMenu
|
import androidx.compose.material3.DropdownMenu
|
||||||
@ -44,21 +43,16 @@ import androidx.compose.material3.TopAppBar
|
|||||||
import androidx.compose.material3.TopAppBarDefaults
|
import androidx.compose.material3.TopAppBarDefaults
|
||||||
import androidx.compose.material3.TopAppBarScrollBehavior
|
import androidx.compose.material3.TopAppBarScrollBehavior
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableIntStateOf
|
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.rememberUpdatedState
|
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.runtime.snapshotFlow
|
|
||||||
import androidx.compose.ui.Alignment
|
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.platform.testTag
|
import androidx.compose.ui.platform.testTag
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.text.style.TextOverflow
|
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.ActionMenuItem
|
||||||
import org.kiwix.kiwixmobile.core.ui.models.toPainter
|
import org.kiwix.kiwixmobile.core.ui.models.toPainter
|
||||||
import org.kiwix.kiwixmobile.core.ui.theme.Black
|
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) },
|
triggerAction = { customDownloadViewModel.actions.tryEmit(action) },
|
||||||
assert = {
|
assert = {
|
||||||
val items = (1..awaitItemCount).map { awaitItem() }
|
val items = (1..awaitItemCount).map { awaitItem() }
|
||||||
print("items = $items")
|
|
||||||
assertThat(items).contains(endState)
|
assertThat(items).contains(endState)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user