Last active
April 22, 2024 09:45
-
-
Save hanihashemi/a6d3ff640ebdd28b7abaa39ec74a2296 to your computer and use it in GitHub Desktop.
youtube link:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import androidx.compose.animation.core.LinearOutSlowInEasing | |
import androidx.compose.animation.core.animateDpAsState | |
import androidx.compose.animation.core.animateFloatAsState | |
import androidx.compose.animation.core.tween | |
import androidx.compose.foundation.background | |
import androidx.compose.foundation.layout.Box | |
import androidx.compose.foundation.layout.Column | |
import androidx.compose.foundation.layout.Spacer | |
import androidx.compose.foundation.layout.fillMaxWidth | |
import androidx.compose.foundation.layout.offset | |
import androidx.compose.foundation.layout.padding | |
import androidx.compose.foundation.layout.widthIn | |
import androidx.compose.material3.MaterialTheme | |
import androidx.compose.material3.Text | |
import androidx.compose.runtime.Composable | |
import androidx.compose.runtime.getValue | |
import androidx.compose.ui.Alignment | |
import androidx.compose.ui.Modifier | |
import androidx.compose.ui.draw.alpha | |
import androidx.compose.ui.draw.clip | |
import androidx.compose.ui.draw.scale | |
import androidx.compose.ui.graphics.Color | |
import androidx.compose.ui.platform.LocalConfiguration | |
import androidx.compose.ui.platform.LocalContext | |
import androidx.compose.ui.text.style.TextAlign | |
import androidx.compose.ui.tooling.preview.Preview | |
import androidx.compose.ui.unit.dp | |
import io.github.hanihashemi.eggmaster.R | |
import io.github.hanihashemi.eggmaster.components.Button | |
import io.github.hanihashemi.eggmaster.ui.theme.Dimens | |
import io.github.hanihashemi.eggmaster.ui.theme.Shapes | |
private val infoText = listOf( | |
R.string.intro_info_text_1, | |
R.string.intro_info_text_2, | |
R.string.intro_info_text_3 | |
) | |
private val infoButtonText = listOf( | |
R.string.intro_info_button_1, | |
R.string.intro_info_button_2, | |
R.string.intro_info_button_3 | |
) | |
@Composable | |
fun InformationCards(tutorialCurrentStep: Int, onNextPressed: () -> Unit) { | |
val screenWith = LocalConfiguration.current.screenWidthDp.dp | |
Box(modifier = Modifier.fillMaxWidth(), contentAlignment = Alignment.Center) { | |
for (index in 0 until 3) { | |
val offset by animateDpAsState( | |
targetValue = when { | |
index < tutorialCurrentStep -> -screenWith | |
index > tutorialCurrentStep -> screenWith | |
else -> 0.dp | |
}, | |
animationSpec = tween(durationMillis = 500, easing = LinearOutSlowInEasing), | |
label = "offset animation" | |
) | |
val alpha by animateFloatAsState( | |
targetValue = if (index == tutorialCurrentStep) 1f else 0f, | |
animationSpec = tween(durationMillis = 500, easing = LinearOutSlowInEasing), | |
label = "alpha animation", | |
) | |
val scale by animateFloatAsState( | |
targetValue = if (index == tutorialCurrentStep) 1f else 0.8f, | |
animationSpec = tween(durationMillis = 500, easing = LinearOutSlowInEasing), | |
label = "scale animation", | |
) | |
Box( | |
modifier = Modifier | |
.offset(x = offset) | |
.alpha(alpha) | |
.scale(scale) | |
.widthIn(max = 350.dp) | |
.padding(Dimens.PaddingNormal) | |
.clip(Shapes.large) | |
.fillMaxWidth() | |
.background(color = Color.White) | |
.padding(Dimens.PaddingLarge), | |
contentAlignment = Alignment.Center, | |
) { | |
Column(horizontalAlignment = Alignment.CenterHorizontally) { | |
Text( | |
text = LocalContext.current.getString(infoText[index]), | |
textAlign = TextAlign.Center, | |
color = Color(0xFF202143), | |
) | |
Spacer(modifier = Modifier.padding(Dimens.PaddingNormal)) | |
Button(text = LocalContext.current.getString(infoButtonText[index])) { | |
onNextPressed() | |
} | |
} | |
} | |
} | |
} | |
} | |
// VIEW MODEL | |
package io.github.hanihashemi.eggmaster | |
import androidx.lifecycle.ViewModel | |
import androidx.lifecycle.viewModelScope | |
import dagger.hilt.android.lifecycle.HiltViewModel | |
import kotlinx.coroutines.channels.Channel | |
import kotlinx.coroutines.flow.MutableStateFlow | |
import kotlinx.coroutines.flow.SharingStarted | |
import kotlinx.coroutines.flow.StateFlow | |
import kotlinx.coroutines.flow.map | |
import kotlinx.coroutines.flow.receiveAsFlow | |
import kotlinx.coroutines.flow.stateIn | |
import javax.inject.Inject | |
@HiltViewModel | |
class MainViewModel @Inject constructor() : ViewModel() { | |
private val _viewEvent: Channel<ViewEvent> = Channel() | |
val viewEvent = _viewEvent.receiveAsFlow() | |
private val internalState: MutableStateFlow<InternalState> = MutableStateFlow(InternalState()) | |
val viewState: StateFlow<UiState> = internalState | |
.map { internalState -> generateUiState(internalState) } | |
.stateIn( | |
viewModelScope, | |
SharingStarted.WhileSubscribed(), | |
UiState() | |
) | |
private fun generateUiState(internalState: InternalState): UiState { | |
return UiState( | |
tutorialCurrentStep = internalState.tutorialCurrentStep, | |
) | |
} | |
fun dispatch(action: ViewAction) { | |
when (action) { | |
is ViewAction.TutorialNextPressed -> onTutorialNextPressed() | |
is ViewAction.TutorialPreviousPressed -> onTutorialPreviousPressed() | |
} | |
} | |
private fun onTutorialNextPressed() { | |
val currentStep = internalState.value.tutorialCurrentStep | |
if (currentStep == 2) { | |
_viewEvent.trySend(ViewEvent.OpenNextPage) | |
} else { | |
internalState.value = internalState.value.copy(tutorialCurrentStep = currentStep + 1) | |
} | |
} | |
private fun onTutorialPreviousPressed() { | |
val currentStep = internalState.value.tutorialCurrentStep | |
if (currentStep == 0) { | |
_viewEvent.trySend(ViewEvent.NavigateBack) | |
} else { | |
internalState.value = internalState.value.copy(tutorialCurrentStep = currentStep - 1) | |
} | |
} | |
data class UiState( | |
val tutorialCurrentStep: Int = 0, | |
val dropEgg: Boolean = false, | |
) | |
data class InternalState( | |
val tutorialCurrentStep: Int = 0, | |
) | |
sealed class ViewAction { | |
data object TutorialNextPressed : ViewAction() | |
data object TutorialPreviousPressed : ViewAction() | |
} | |
sealed class ViewEvent { | |
data object NavigateBack : ViewEvent() | |
data object OpenNextPage : ViewEvent() | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment