fix: unnecessary reload of drawer menu

This commit is contained in:
Diego Beraldin 2023-10-19 22:05:18 +02:00
parent d006dc8266
commit 3ad5bb2ee6
4 changed files with 124 additions and 136 deletions

View File

@ -97,7 +97,6 @@ object ModalDrawerContent : Tab {
val languageRepository = remember { getLanguageRepository() }
val themeRepository = remember { getThemeRepository() }
val lang by languageRepository.currentLanguage.collectAsState()
val uiFontSize = themeRepository.uiFontScale.collectAsState()
LaunchedEffect(model) {
model.effects.onEach { evt ->
@ -415,7 +414,7 @@ private fun ChangeInstanceDialog(
supportingText = {
if (instanceNameError != null) {
Text(
text = instanceNameError?.localized().orEmpty(),
text = instanceNameError.localized(),
color = MaterialTheme.colorScheme.error,
)
}

View File

@ -13,7 +13,6 @@ import com.github.diegoberaldin.raccoonforlemmy.resources.MR
import dev.icerock.moko.resources.desc.desc
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.IO
import kotlinx.coroutines.flow.drop
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
@ -43,17 +42,12 @@ class ModalDrawerViewModel(
mvi.updateState {
it.copy(user = user)
}
}.launchIn(this)
identityRepository.authToken.drop(1).onEach { _ ->
refresh()
}.launchIn(this)
settingsRepository.currentSettings.onEach { settings ->
mvi.updateState { it.copy(autoLoadImages = settings.autoLoadImages) }
}.launchIn(this)
}
if (uiState.value.communities.isEmpty()) {
refresh()
}
}
override fun reduce(intent: ModalDrawerMviModel.Intent) {

View File

@ -10,7 +10,11 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.ExperimentalMaterialApi
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.DrawerValue
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.ModalDrawerSheet
import androidx.compose.material3.ModalNavigationDrawer
import androidx.compose.material3.rememberDrawerState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.LaunchedEffect
@ -32,6 +36,7 @@ import cafe.adriel.voyager.navigator.CurrentScreen
import cafe.adriel.voyager.navigator.LocalNavigator
import cafe.adriel.voyager.navigator.Navigator
import cafe.adriel.voyager.navigator.bottomSheet.BottomSheetNavigator
import cafe.adriel.voyager.navigator.tab.TabNavigator
import com.github.diegoberaldin.raccoonforlemmy.core.appearance.data.UiTheme
import com.github.diegoberaldin.raccoonforlemmy.core.appearance.data.toInt
import com.github.diegoberaldin.raccoonforlemmy.core.appearance.data.toPostLayout
@ -45,12 +50,18 @@ import com.github.diegoberaldin.raccoonforlemmy.core.commonui.communitydetail.Co
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.getCommmunityFromUrl
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.getPostFromUrl
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.getUserFromUrl
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.di.getDrawerCoordinator
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.di.getNavigationCoordinator
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.drawer.DrawerEvent
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.drawer.ModalDrawerContent
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.postdetail.PostDetailScreen
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.saveditems.SavedItemsScreen
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.userdetail.UserDetailScreen
import com.github.diegoberaldin.raccoonforlemmy.core.persistence.di.getAccountRepository
import com.github.diegoberaldin.raccoonforlemmy.core.persistence.di.getSettingsRepository
import com.github.diegoberaldin.raccoonforlemmy.domain.identity.di.getApiConfigurationRepository
import com.github.diegoberaldin.raccoonforlemmy.feature.search.managesubscriptions.ManageSubscriptionsScreen
import com.github.diegoberaldin.raccoonforlemmy.feature.search.multicommunity.detail.MultiCommunityScreen
import com.github.diegoberaldin.raccoonforlemmy.resources.MR
import com.github.diegoberaldin.raccoonforlemmy.resources.di.getLanguageRepository
import dev.icerock.moko.resources.compose.painterResource
@ -168,35 +179,74 @@ fun App() {
}
}
}
Navigator(
screens = screens,
onBackPressed = {
val callback = navigationCoordinator.getCanGoBackCallback()
callback?.let { it() } ?: true
val drawerState = rememberDrawerState(initialValue = DrawerValue.Closed)
val drawerCoordinator = remember { getDrawerCoordinator() }
LaunchedEffect(drawerCoordinator) {
drawerCoordinator.toggleEvents.onEach { evt ->
val navigator = navigationCoordinator.getRootNavigator()
when (evt) {
DrawerEvent.Toggled -> {
drawerState.apply {
if (isClosed) open() else close()
}
}
is DrawerEvent.OpenCommunity -> {
navigator?.push(CommunityDetailScreen(evt.community))
}
is DrawerEvent.OpenMultiCommunity -> {
navigator?.push(MultiCommunityScreen(evt.community))
}
DrawerEvent.ManageSubscriptions -> {
navigator?.push(ManageSubscriptionsScreen())
}
DrawerEvent.OpenBookmarks -> {
navigator?.push(SavedItemsScreen())
}
}
}.launchIn(this)
}
ModalNavigationDrawer(
drawerState = drawerState,
drawerContent = {
ModalDrawerSheet {
TabNavigator(ModalDrawerContent)
}
}
) {
val navigator = LocalNavigator.current
navigationCoordinator.setRootNavigator(navigator)
if (hasBeenInitialized) {
CurrentScreen()
} else {
// loading screen
Box(
modifier = Modifier.fillMaxSize(),
contentAlignment = Alignment.Center,
) {
Column(
modifier = Modifier.padding(top = 24.dp),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.spacedBy(Spacing.s),
Navigator(
screens = screens,
onBackPressed = {
val callback = navigationCoordinator.getCanGoBackCallback()
callback?.let { it() } ?: true
}
) {
val navigator = LocalNavigator.current
navigationCoordinator.setRootNavigator(navigator)
if (hasBeenInitialized) {
CurrentScreen()
} else {
// loading screen
Box(
modifier = Modifier.fillMaxSize(),
contentAlignment = Alignment.Center,
) {
Image(
painter = painterResource(MR.images.icon),
contentDescription = null,
)
CircularProgressIndicator(
color = MaterialTheme.colorScheme.onPrimary,
)
Column(
modifier = Modifier.padding(top = 24.dp),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.spacedBy(Spacing.s),
) {
Image(
painter = painterResource(MR.images.icon),
contentDescription = null,
)
CircularProgressIndicator(
color = MaterialTheme.colorScheme.onPrimary,
)
}
}
}
}

View File

@ -3,12 +3,8 @@ package com.github.diegoberaldin.raccoonforlemmy
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.offset
import androidx.compose.material.BottomAppBar
import androidx.compose.material3.DrawerValue
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.ModalDrawerSheet
import androidx.compose.material3.ModalNavigationDrawer
import androidx.compose.material3.Scaffold
import androidx.compose.material3.rememberDrawerState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.LaunchedEffect
@ -23,7 +19,6 @@ import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
import androidx.compose.ui.input.nestedscroll.NestedScrollSource
import androidx.compose.ui.layout.onGloballyPositioned
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.platform.LocalUriHandler
import androidx.compose.ui.unit.Density
import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.dp
@ -34,19 +29,11 @@ import cafe.adriel.voyager.navigator.tab.CurrentTab
import cafe.adriel.voyager.navigator.tab.TabNavigator
import com.github.diegoberaldin.raccoonforlemmy.core.appearance.di.getThemeRepository
import com.github.diegoberaldin.raccoonforlemmy.core.architecture.bindToLifecycle
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.communitydetail.CommunityDetailScreen
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.di.getDrawerCoordinator
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.di.getNavigationCoordinator
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.drawer.DrawerEvent
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.drawer.ModalDrawerContent
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.saveditems.SavedItemsScreen
import com.github.diegoberaldin.raccoonforlemmy.core.persistence.di.getSettingsRepository
import com.github.diegoberaldin.raccoonforlemmy.di.getMainViewModel
import com.github.diegoberaldin.raccoonforlemmy.feature.home.ui.HomeTab
import com.github.diegoberaldin.raccoonforlemmy.feature.inbox.ui.InboxTab
import com.github.diegoberaldin.raccoonforlemmy.feature.profile.ui.ProfileTab
import com.github.diegoberaldin.raccoonforlemmy.feature.search.managesubscriptions.ManageSubscriptionsScreen
import com.github.diegoberaldin.raccoonforlemmy.feature.search.multicommunity.detail.MultiCommunityScreen
import com.github.diegoberaldin.raccoonforlemmy.feature.search.ui.ExploreTab
import com.github.diegoberaldin.raccoonforlemmy.feature.settings.ui.SettingsTab
import com.github.diegoberaldin.raccoonforlemmy.ui.navigation.TabNavigationItem
@ -63,15 +50,10 @@ internal class MainScreen : Screen {
val themeRepository = remember { getThemeRepository() }
var bottomBarHeightPx by remember { mutableStateOf(0f) }
val navigationCoordinator = remember { getNavigationCoordinator() }
val drawerCoordinator = remember { getDrawerCoordinator() }
val navigator = remember { navigationCoordinator.getRootNavigator() }
val model = rememberScreenModel { getMainViewModel() }
model.bindToLifecycle(key)
val uiState by model.uiState.collectAsState()
val uiFontScale by themeRepository.uiFontScale.collectAsState()
val uriHandler = LocalUriHandler.current
val settingsRepository = remember { getSettingsRepository() }
val settings by settingsRepository.currentSettings.collectAsState()
LaunchedEffect(model) {
model.effects.onEach {
@ -102,94 +84,57 @@ internal class MainScreen : Screen {
}
}
val drawerState = rememberDrawerState(initialValue = DrawerValue.Closed)
LaunchedEffect(drawerCoordinator) {
drawerCoordinator.toggleEvents.onEach { evt ->
when (evt) {
DrawerEvent.Toggled -> {
drawerState.apply {
if (isClosed) open() else close()
}
}
is DrawerEvent.OpenCommunity -> {
navigator?.push(CommunityDetailScreen(evt.community))
}
is DrawerEvent.OpenMultiCommunity -> {
navigator?.push(MultiCommunityScreen(evt.community))
}
DrawerEvent.ManageSubscriptions -> {
navigator?.push(ManageSubscriptionsScreen())
}
DrawerEvent.OpenBookmarks -> {
navigator?.push(SavedItemsScreen())
}
}
}.launchIn(this)
}
ModalNavigationDrawer(
drawerState = drawerState,
drawerContent = {
ModalDrawerSheet {
TabNavigator(ModalDrawerContent)
}
TabNavigator(HomeTab) {
LaunchedEffect(it.current) {
// when the current tab chanes, reset the bottom bar offset to the default value
model.reduce(MainScreenMviModel.Intent.SetBottomBarOffsetHeightPx(0f))
}
) {
TabNavigator(HomeTab) {
LaunchedEffect(it.current) {
// when the current tab chanes, reset the bottom bar offset to the default value
model.reduce(MainScreenMviModel.Intent.SetBottomBarOffsetHeightPx(0f))
}
Scaffold(
content = {
CurrentTab()
},
bottomBar = {
CompositionLocalProvider(
LocalDensity provides Density(
density = LocalDensity.current.density,
fontScale = uiFontScale,
),
) {
val titleVisible by themeRepository.navItemTitles.collectAsState()
var uiFontSizeWorkaround by remember { mutableStateOf(true) }
LaunchedEffect(themeRepository) {
themeRepository.uiFontScale.drop(1).onEach {
uiFontSizeWorkaround = false
delay(50)
uiFontSizeWorkaround = true
}.launchIn(this)
}
if (uiFontSizeWorkaround) {
BottomAppBar(
modifier = Modifier
.onGloballyPositioned {
bottomBarHeightPx = it.size.toSize().height
}
.offset {
IntOffset(
x = 0,
y = -uiState.bottomBarOffsetHeightPx.roundToInt()
)
},
contentPadding = PaddingValues(0.dp),
backgroundColor = MaterialTheme.colorScheme.background,
) {
TabNavigationItem(HomeTab, withText = titleVisible)
TabNavigationItem(ExploreTab, withText = titleVisible)
TabNavigationItem(ProfileTab, withText = titleVisible)
TabNavigationItem(InboxTab, withText = titleVisible)
TabNavigationItem(SettingsTab, withText = titleVisible)
}
Scaffold(
content = {
CurrentTab()
},
bottomBar = {
CompositionLocalProvider(
LocalDensity provides Density(
density = LocalDensity.current.density,
fontScale = uiFontScale,
),
) {
val titleVisible by themeRepository.navItemTitles.collectAsState()
var uiFontSizeWorkaround by remember { mutableStateOf(true) }
LaunchedEffect(themeRepository) {
themeRepository.uiFontScale.drop(1).onEach {
uiFontSizeWorkaround = false
delay(50)
uiFontSizeWorkaround = true
}.launchIn(this)
}
if (uiFontSizeWorkaround) {
BottomAppBar(
modifier = Modifier
.onGloballyPositioned {
bottomBarHeightPx = it.size.toSize().height
}
.offset {
IntOffset(
x = 0,
y = -uiState.bottomBarOffsetHeightPx.roundToInt()
)
},
contentPadding = PaddingValues(0.dp),
backgroundColor = MaterialTheme.colorScheme.background,
) {
TabNavigationItem(HomeTab, withText = titleVisible)
TabNavigationItem(ExploreTab, withText = titleVisible)
TabNavigationItem(ProfileTab, withText = titleVisible)
TabNavigationItem(InboxTab, withText = titleVisible)
TabNavigationItem(SettingsTab, withText = titleVisible)
}
}
},
)
}
}
},
)
}
}
}