Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,26 @@ package com.moscow.tudee.presentation.component.tudeeSwitch

import androidx.compose.animation.Crossfade
import androidx.compose.animation.ExperimentalAnimationApi
import androidx.compose.animation.core.Animatable
import androidx.compose.animation.core.EaseOut
import androidx.compose.animation.core.animateDp
import androidx.compose.animation.core.animateFloat
import androidx.compose.animation.core.tween
import androidx.compose.animation.core.updateTransition
import androidx.compose.foundation.background
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.BiasAlignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
Expand All @@ -31,114 +38,122 @@ fun TudeeSwitch(
) {
val themeState = Theme.state
val isLightTheme = !themeState.isDark
var isClickable by remember { mutableStateOf(true) }

val transition = updateTransition(
targetState = isLightTheme,
label = "switchButtonTransition"
)

val transitionFloatAnimationSpec = remember {
tween<Float>(800, easing = EaseOut)
tween<Float>(600, easing = EaseOut)
}

val transitionDpAnimationSpec = remember {
tween<Dp>(800, easing = EaseOut)
tween<Dp>(600, easing = EaseOut)
}


val movingCloudySize by transition.animateDp(
transitionSpec = {
transitionDpAnimationSpec
},
transitionSpec = { transitionDpAnimationSpec },
label = "movingCloudySize"
) {
if (it) 29.dp else 8.dp
}


val outerTopCloudSize by transition.animateDp(
transitionSpec = {
transitionDpAnimationSpec
},
transitionSpec = { transitionDpAnimationSpec },
label = "cloudyOutlierTopDp"
) {
if (it) 32.dp
else 0.dp
if (it) 32.dp else 0.dp
}

val cloudyOutlierBottomDp by transition.animateDp(
transitionSpec = {
transitionDpAnimationSpec
},
transitionSpec = { transitionDpAnimationSpec },
label = "cloudyOutlierBottomDp"
) {
if (it) 0.dp else -(8).dp
}

val movingCloudyPositionX by transition.animateDp(
transitionSpec = {
transitionDpAnimationSpec
},
transitionSpec = { transitionDpAnimationSpec },
label = "movingCloudyPositionX"
) {
if (it) 13.5.dp else (-17).dp
}

val movingCloudyPositionY by transition.animateDp(
transitionSpec = {
transitionDpAnimationSpec
},
transitionSpec = { transitionDpAnimationSpec },
label = "movingCloudyPositionY"
) {
if (it) 0.dp else 4.dp
}


val movingSmallCloudySize by transition.animateDp(
transitionSpec = {
transitionDpAnimationSpec
},
transitionSpec = { transitionDpAnimationSpec },
label = "movingSmallCloudySize"
) {
if (it) 16.dp else 0.dp
}

val circleHorizontalBias by transition.animateFloat(
transitionSpec = {
transitionFloatAnimationSpec
},
transitionSpec = { transitionFloatAnimationSpec },
label = "horizontalBias"
) {
if (it) 1f
else -1f
if (it) 1f else -1f
}

val circleAlignment by remember {
derivedStateOf {
BiasAlignment(circleHorizontalBias, 1f)
}
}

//400
val circlePositionX by transition.animateDp(
transitionSpec = {
transitionDpAnimationSpec
},
label = "circleSize"
transitionSpec = { transitionDpAnimationSpec },
label = "circleSizeX"
) {
if (it) -(14.5).dp else -14.5.dp
if (it) -(14.5).dp else -(14.5).dp
}

val circlePositionY by transition.animateDp(
transitionSpec = {
transitionDpAnimationSpec
},
label = "circleSize"
transitionSpec = { transitionDpAnimationSpec },
label = "circleSizeY"
) {
if (it) 4.dp else 26.dp
}

val sunBiasAlignment = remember {
Animatable(if (isLightTheme) -1f else 1f)
}

val moonBiasAlignment = remember {
Animatable(if (isLightTheme) 1f else -1f)
}

//dark

LaunchedEffect(isLightTheme) {
val startSunBiasAlignment = -1f
val startMoonBiasAlignment = 1f
isClickable = false

if (!isLightTheme) {
moonBiasAlignment.snapTo(startMoonBiasAlignment)
sunBiasAlignment.animateTo(
targetValue = -startSunBiasAlignment,
animationSpec = transitionFloatAnimationSpec
)
} else {
sunBiasAlignment.snapTo(startSunBiasAlignment)
moonBiasAlignment.animateTo(
targetValue = -startMoonBiasAlignment,
animationSpec = transitionFloatAnimationSpec
)
}
isClickable = true
}



Expand All @@ -149,11 +164,8 @@ fun TudeeSwitch(
) {
if (it) {
TudeeSwitchLightTheme(
transitionFloatAnimationSpec = transitionFloatAnimationSpec,
isClickable = isLightTheme,
onToggleState = {
themeState.onThemeChanged(isLightTheme)
},
isClickable = isClickable,
onToggleState = { themeState.onThemeChanged(isLightTheme) },
movingCloudySize = movingCloudySize,
outerTopCloudSize = outerTopCloudSize,
cloudyOutlierBottomDp = cloudyOutlierBottomDp,
Expand All @@ -162,17 +174,15 @@ fun TudeeSwitch(
movingSmallCloudySize = movingSmallCloudySize,
circleAlignment = circleAlignment,
circlePositionX = circlePositionX,
circlePositionY = circlePositionY
circlePositionY = circlePositionY,
sunAlignment = BiasAlignment(sunBiasAlignment.value, 0f)
)
} else {
TudeeSwitchDarkTheme(
isClickable = !isLightTheme,
onToggleState = {
themeState.onThemeChanged(isLightTheme)
},
movingCloudySize = movingCloudySize,
transitionFloatAnimationSpec = transitionFloatAnimationSpec

moonAlignment = BiasAlignment(moonBiasAlignment.value, 0f),
isClickable = isClickable,
onToggleState = { themeState.onThemeChanged(isLightTheme) },
movingCloudySize = movingCloudySize
)
}
}
Expand All @@ -195,11 +205,14 @@ private fun TudeeSwitchPreview() {
}

TudeeTheme(themeState) {
val localState = Theme.state

Column(modifier = Modifier) {
TudeeSwitch(
)
Column(
modifier = Modifier
.fillMaxSize()
.background(Theme.colors.surface),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
TudeeSwitch()
}
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
package com.moscow.tudee.presentation.component.tudeeSwitch

import androidx.compose.animation.animateContentSize
import androidx.compose.animation.core.Animatable
import androidx.compose.animation.core.TweenSpec
import androidx.compose.animation.core.tween
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
Expand All @@ -18,10 +16,6 @@ import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.runtime.Composable
import androidx.compose.runtime.Stable
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.BiasAlignment
import androidx.compose.ui.Modifier
Expand All @@ -37,28 +31,15 @@ import androidx.compose.ui.unit.dp
import com.moscow.tudee.R
import com.moscow.tudee.presentation.designSystem.shadow.innerShadow
import com.moscow.tudee.presentation.designSystem.theme.Theme
import kotlinx.coroutines.launch

@Stable
@Composable
fun TudeeSwitchDarkTheme(
onToggleState: () -> Unit,
isClickable: Boolean,
transitionFloatAnimationSpec: TweenSpec<Float>,
movingCloudySize: Dp
movingCloudySize: Dp,
moonAlignment: BiasAlignment,
) {
val coroutineScope = rememberCoroutineScope()
val moonBiasAlignment = remember {
Animatable(1f)
}


val moonAlignment by remember {
derivedStateOf {
BiasAlignment(moonBiasAlignment.value, 0f)
}
}

Box(
modifier = Modifier
.requiredSize(width = 64.dp, height = 36.dp)
Expand Down Expand Up @@ -105,15 +86,10 @@ fun TudeeSwitchDarkTheme(
.padding(end = 2.dp)
.size(32.dp)
.clip(CircleShape)
.clickable(isClickable) {
coroutineScope.launch {
moonBiasAlignment.animateTo(
targetValue = -1f,
animationSpec = transitionFloatAnimationSpec
)
}
onToggleState()
}
.clickable(
enabled = isClickable,
onClick = onToggleState
)
.align(moonAlignment)
) {
Box(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
package com.moscow.tudee.presentation.component.tudeeSwitch

import androidx.compose.animation.animateContentSize
import androidx.compose.animation.core.Animatable
import androidx.compose.animation.core.TweenSpec
import androidx.compose.animation.core.tween
import androidx.compose.foundation.background
import androidx.compose.foundation.border
Expand All @@ -15,10 +13,6 @@ import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.runtime.Composable
import androidx.compose.runtime.Stable
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.BiasAlignment
import androidx.compose.ui.Modifier
Expand All @@ -32,15 +26,13 @@ import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.dp
import com.moscow.tudee.presentation.designSystem.theme.Theme
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch

@Stable
@Composable
fun TudeeSwitchLightTheme(
onToggleState: () -> Unit,
isClickable: Boolean,
transitionFloatAnimationSpec: TweenSpec<Float>,
sunAlignment: BiasAlignment,
movingCloudySize: Dp,
outerTopCloudSize: Dp,
cloudyOutlierBottomDp: Dp,
Expand All @@ -52,19 +44,6 @@ fun TudeeSwitchLightTheme(
circlePositionY: Dp,
surfaceLow: Color = Color(0xFFF0F0F0)
) {

val coroutineScope = rememberCoroutineScope()

val sunBiasAlignment = remember {
Animatable(-1f)
}

val sunAlignment by remember {
derivedStateOf {
BiasAlignment(sunBiasAlignment.value, 0f)
}
}

Box(
modifier = Modifier
.requiredSize(width = 64.dp, height = 36.dp)
Expand Down Expand Up @@ -151,15 +130,10 @@ fun TudeeSwitchLightTheme(
edgeTreatment = BlurredEdgeTreatment(CircleShape)
)
.clip(CircleShape)
.clickable(isClickable) {
coroutineScope.launch(Dispatchers.Main.immediate) {
sunBiasAlignment.animateTo(
targetValue = 1f,
animationSpec = transitionFloatAnimationSpec
)
}
onToggleState()
}
.clickable(
enabled = isClickable,
onClick = onToggleState
)
.align(sunAlignment)
)

Expand Down
Loading