Coverage Summary for Class: ActiveScreen (com.vsevolodganin.clicktrack.ui)
Class |
Class, %
|
Method, %
|
Branch, %
|
Line, %
|
Instruction, %
|
ActiveScreen |
0%
(0/1)
|
0%
(0/1)
|
|
0%
(0/4)
|
0%
(0/17)
|
package com.vsevolodganin.clicktrack.ui
import androidx.compose.animation.AnimatedContent
import androidx.compose.animation.AnimatedContentTransitionScope
import androidx.compose.animation.core.VisibilityThreshold
import androidx.compose.animation.core.spring
import androidx.compose.animation.core.updateTransition
import androidx.compose.animation.togetherWith
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material.DrawerValue
import androidx.compose.material.Scaffold
import androidx.compose.material.rememberDrawerState
import androidx.compose.material.rememberScaffoldState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.IntOffset
import com.arkivanov.decompose.extensions.compose.subscribeAsState
import com.vsevolodganin.clicktrack.RootViewModel
import com.vsevolodganin.clicktrack.ScreenConfiguration
import com.vsevolodganin.clicktrack.ScreenViewModel
import com.vsevolodganin.clicktrack.drawer.DrawerViewModel
import com.vsevolodganin.clicktrack.ui.screen.AboutScreenView
import com.vsevolodganin.clicktrack.ui.screen.ClickTrackListScreenView
import com.vsevolodganin.clicktrack.ui.screen.EditClickTrackScreenView
import com.vsevolodganin.clicktrack.ui.screen.MetronomeScreenView
import com.vsevolodganin.clicktrack.ui.screen.PlayClickTrackScreenView
import com.vsevolodganin.clicktrack.ui.screen.PolyrhythmsScreenView
import com.vsevolodganin.clicktrack.ui.screen.SettingsScreenView
import com.vsevolodganin.clicktrack.ui.screen.SoundLibraryScreenView
import com.vsevolodganin.clicktrack.ui.screen.TrainingScreenView
import com.vsevolodganin.clicktrack.ui.theme.ClickTrackTheme
import com.vsevolodganin.clicktrack.utils.compose.ForcedHapticFeedback
import androidx.compose.material.DrawerState as ComposeDrawerState
@Composable
fun RootView(viewModel: RootViewModel) {
ClickTrackTheme {
ForcedHapticFeedback {
Scaffold(
scaffoldState = rememberScaffoldState(drawerState = drawerState(viewModel.drawer)),
drawerContent = { DrawerView(viewModel.drawer) },
) {
RootView(viewModel, Modifier.padding(it))
}
}
}
}
@Composable
private fun RootView(viewModel: RootViewModel, modifier: Modifier) {
val screens by viewModel.screens.subscribeAsState()
val activeScreen by remember {
derivedStateOf {
ActiveScreen(screens.active.configuration, screens.active.instance, screens.backStack.size)
}
}
updateTransition(targetState = activeScreen, label = "ContentView").AnimatedContent(
modifier = modifier,
transitionSpec = {
val animationSpec = spring(visibilityThreshold = IntOffset.VisibilityThreshold)
val isPush = targetState.position >= initialState.position
if (isPush) {
slideIntoContainer(
towards = AnimatedContentTransitionScope.SlideDirection.Left,
animationSpec = animationSpec,
) togetherWith slideOutOfContainer(
towards = AnimatedContentTransitionScope.SlideDirection.Left,
animationSpec = animationSpec,
)
} else {
slideIntoContainer(
towards = AnimatedContentTransitionScope.SlideDirection.Right,
animationSpec = animationSpec,
) togetherWith slideOutOfContainer(
towards = AnimatedContentTransitionScope.SlideDirection.Right,
animationSpec = animationSpec,
)
}
},
contentKey = ActiveScreen::config,
) { screen ->
RootView(screen.viewModel)
}
}
private data class ActiveScreen(
val config: ScreenConfiguration,
val viewModel: ScreenViewModel,
val position: Int,
)
@Composable
private fun RootView(viewModel: ScreenViewModel) {
val modifier = Modifier.fillMaxSize()
when (viewModel) {
is ScreenViewModel.ClickTrackList -> ClickTrackListScreenView(viewModel.value, modifier)
is ScreenViewModel.PlayClickTrack -> PlayClickTrackScreenView(viewModel.value, modifier)
is ScreenViewModel.EditClickTrack -> EditClickTrackScreenView(viewModel.value, modifier)
is ScreenViewModel.Metronome -> MetronomeScreenView(viewModel.value, modifier)
is ScreenViewModel.Settings -> SettingsScreenView(viewModel.value, modifier)
is ScreenViewModel.SoundLibrary -> SoundLibraryScreenView(viewModel.value, modifier)
is ScreenViewModel.Training -> TrainingScreenView(viewModel.value, modifier)
is ScreenViewModel.About -> AboutScreenView(viewModel.value, modifier)
is ScreenViewModel.Polyrhythms -> PolyrhythmsScreenView(viewModel.value, modifier)
}
}
@Composable
private fun drawerState(drawerViewModel: DrawerViewModel): ComposeDrawerState {
val drawerState by drawerViewModel.state.collectAsState()
val drawerValue by remember {
derivedStateOf { if (drawerState.isOpened) DrawerValue.Open else DrawerValue.Closed }
}
return rememberDrawerState(
initialValue = drawerValue,
confirmStateChange = remember {
{ newDrawerValue ->
when (newDrawerValue) {
DrawerValue.Closed -> drawerViewModel.closeDrawer()
DrawerValue.Open -> drawerViewModel.openDrawer()
}
true
}
},
).apply {
LaunchedEffect(drawerValue) {
when (drawerValue) {
DrawerValue.Closed -> close()
DrawerValue.Open -> open()
}
}
}
}