Skip to content

Commit

Permalink
prepare medium edit
Browse files Browse the repository at this point in the history
  • Loading branch information
DatL4g committed May 12, 2024
1 parent 1bf4cae commit b8c3f1e
Show file tree
Hide file tree
Showing 22 changed files with 717 additions and 114 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package dev.datlag.aniflow.anilist

import com.apollographql.apollo3.ApolloCall
import com.apollographql.apollo3.ApolloClient
import com.apollographql.apollo3.api.Optional
import dev.datlag.aniflow.anilist.model.Medium
Expand Down Expand Up @@ -54,6 +55,15 @@ class MediumRepository(

fun load(id: Int) = this.id.update { id }

fun updateRatingCall(value: Int): ApolloCall<RatingMutation.Data> {
val mutation = RatingMutation(
mediaId = Optional.present(id.value),
rating = Optional.present(value)
)

return client.mutation(mutation)
}

private data class Query(
val id: Int,
) {
Expand All @@ -65,6 +75,7 @@ class MediumRepository(
}

sealed interface State {
data object None : State
data class Success(val medium: Medium) : State
data object Error : State

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package dev.datlag.aniflow.ui.custom.speeddial

import androidx.compose.animation.*
import androidx.compose.animation.core.animateFloat
import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.animation.core.tween
import androidx.compose.foundation.layout.Row
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.alpha
import androidx.compose.ui.draw.scale

@Composable
fun AnimatedSmallFABWithLabel(
state: SpeedDialFABState,
showLabel: Boolean,
modifier: Modifier = Modifier,
labelContent: @Composable () -> Unit = { },
fabContent: @Composable () -> Unit,
) {
val alpha = state.transition?.animateFloat(
transitionSpec = {
tween(durationMillis = 50)
},
targetValueByState = {
if (it == SpeedDialState.Expanded) 1F else 0F
}
)
val scale = state.transition?.animateFloat(
targetValueByState = {
if (it == SpeedDialState.Expanded) 1F else 0F
}
)

Row(
modifier = modifier
.alpha(animateFloatAsState((alpha?.value ?: 0F)).value)
.scale(animateFloatAsState(scale?.value ?: 0F).value),
verticalAlignment = Alignment.CenterVertically,
) {
AnimatedVisibility(
visible = showLabel,
enter = slideInHorizontally { it / 2 } + fadeIn(),
exit = slideOutHorizontally { it / 2 } + fadeOut()
) {
labelContent.invoke()
}
fabContent.invoke()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package dev.datlag.aniflow.ui.custom.speeddial

import androidx.compose.foundation.layout.size
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.painter.Painter
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.unit.dp

open class FABItem(
val icon: ImageVector? = null,
val painter: Painter? = null,
val tint: Boolean = false,
val modifier: Modifier = if (painter == null) Modifier else Modifier.size(24.dp),
val label: String,
val onClick: () -> Unit,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package dev.datlag.aniflow.ui.custom.speeddial

import androidx.compose.animation.core.Spring
import androidx.compose.animation.core.animateFloat
import androidx.compose.animation.core.spring
import androidx.compose.foundation.layout.Box
import androidx.compose.material3.ExtendedFloatingActionButton
import androidx.compose.material3.FloatingActionButtonDefaults
import androidx.compose.material3.FloatingActionButtonElevation
import androidx.compose.material3.contentColorFor
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.rotate
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Shape

@Composable
fun SpeedDialFAB(
modifier: Modifier = Modifier,
state: SpeedDialFABState,
onClick: (SpeedDialFABState) -> Unit = { it.changeState() },
iconRotation: Float = 45F,
expanded: Boolean = false,
shape: Shape = FloatingActionButtonDefaults.extendedFabShape,
containerColor: Color = FloatingActionButtonDefaults.containerColor,
contentColor: Color = contentColorFor(containerColor),
elevation: FloatingActionButtonElevation = FloatingActionButtonDefaults.elevation(),
text: @Composable () -> Unit = { },
icon: @Composable () -> Unit,
) {
val rotation = if (iconRotation > 0F) {
state.transition?.animateFloat(
transitionSpec = {
if (targetState == SpeedDialState.Expanded) {
spring(stiffness = Spring.StiffnessLow)
} else {
spring(stiffness = Spring.StiffnessMedium)
}
},
label = "",
targetValueByState = {
if (it == SpeedDialState.Expanded) iconRotation else 0F
}
)
} else {
null
}

ExtendedFloatingActionButton(
modifier = modifier,
onClick = {
onClick(state)
},
expanded = expanded,
shape = shape,
containerColor = containerColor,
contentColor = contentColor,
elevation = elevation,
icon = {
Box(
modifier = Modifier.rotate(rotation?.value ?: 0F),
contentAlignment = Alignment.Center
) {
icon()
}
},
text = {
text()
}
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package dev.datlag.aniflow.ui.custom.speeddial

import androidx.compose.animation.core.Transition
import androidx.compose.animation.core.updateTransition
import androidx.compose.runtime.*

@Composable
fun rememberSpeedDialState(): SpeedDialFABState {
val state = remember { SpeedDialFABState() }

state.transition = updateTransition(targetState = state.currentState)

return state
}

class SpeedDialFABState {

var currentState by mutableStateOf<SpeedDialState>(SpeedDialState.Collapsed)
var transition: Transition<SpeedDialState>? = null

fun changeState() {
currentState = if (transition?.currentState == SpeedDialState.Expanded
|| (transition?.isRunning == true && transition?.targetState == SpeedDialState.Expanded)) {
SpeedDialState.Collapsed
} else {
SpeedDialState.Expanded
}
}

fun collapse() {
currentState = SpeedDialState.Collapsed
}

fun expand() {
currentState = SpeedDialState.Expanded
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package dev.datlag.aniflow.ui.custom.speeddial

import kotlinx.serialization.Serializable

@Serializable
sealed interface SpeedDialState {
@Serializable
data object Collapsed : SpeedDialState

@Serializable
data object Expanded : SpeedDialState
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package dev.datlag.aniflow.ui.custom.speeddial

import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.*
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.unit.dp

@Composable
fun <T: FABItem> SubSpeedDialFABs(
state: SpeedDialFABState,
items: List<T>,
showLabels: Boolean = true,
verticalArrangement: Arrangement.Vertical = Arrangement.Top,
labelContent: @Composable (T) -> Unit = {
val backgroundColor = FloatingActionButtonDefaults.containerColor

Surface(
color = backgroundColor,
shape = MaterialTheme.shapes.small,
shadowElevation = 2.dp,
onClick = { it.onClick() }
) {
Text(
text = it.label,
color = contentColorFor(backgroundColor),
modifier = Modifier.padding(horizontal = 6.dp, vertical = 4.dp)
)
}
},
fabContent: @Composable (T) -> Unit = {
SmallFloatingActionButton(
modifier = Modifier.padding(4.dp),
onClick = { it.onClick() },
elevation = FloatingActionButtonDefaults.elevation(
defaultElevation = 4.dp,
hoveredElevation = 4.dp
)
) {
if (it.icon != null) {
Icon(
modifier = it.modifier,
imageVector = it.icon,
contentDescription = it.label
)
} else if (it.painter != null) {
Image(
modifier = it.modifier,
painter = it.painter,
contentDescription = it.label,
colorFilter = if (it.tint) ColorFilter.tint(LocalContentColor.current) else null
)
}
}
}
) {
Column(
horizontalAlignment = Alignment.End,
verticalArrangement = verticalArrangement,
) {
items.forEach { item ->
AnimatedSmallFABWithLabel(
state = state,
showLabel = showLabels,
labelContent = { labelContent(item) },
fabContent = { fabContent(item) }
)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,11 @@ fun CollapsingToolbar(
) {
val user by userFlow.collectAsStateWithLifecycle(null)
val tintColor = LocalContentColor.current
var colorFilter by remember(user) { mutableStateOf<ColorFilter?>(null) }
var colorFilter by remember(user, tintColor) {
mutableStateOf<ColorFilter?>(
if (user == null) ColorFilter.tint(tintColor) else null
)
}

AsyncImage(
model = user?.avatar?.large,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ fun SettingsScreen(component: SettingsComponent) {
contentDescription = null,
colorFilter = ColorFilter.tint(LocalContentColor.current)
)
Text(text = "GitHub Repository")
Text(text = stringResource(SharedRes.strings.github_repository))
}
}
item {
Expand All @@ -176,7 +176,7 @@ fun SettingsScreen(component: SettingsComponent) {
imageVector = Icons.Rounded.Code,
contentDescription = null,
)
Text(text = "Developed by DatLag")
Text(text = stringResource(SharedRes.strings.developed_by_datlag))
}
}
item {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import com.maxkeppeler.sheets.option.models.DisplayMode
import com.maxkeppeler.sheets.option.models.Option
import com.maxkeppeler.sheets.option.models.OptionConfig
import com.maxkeppeler.sheets.option.models.OptionSelection
import dev.datlag.aniflow.SharedRes
import dev.datlag.aniflow.common.toComposeColor
import dev.datlag.aniflow.common.toComposeString
import dev.datlag.aniflow.other.StateSaver
Expand Down Expand Up @@ -91,7 +92,7 @@ fun ColorSection(
contentDescription = null,
)
Text(
text = "Profile Color"
text = stringResource(SharedRes.strings.profile_color)
)
Spacer(modifier = Modifier.weight(1F))
IconButton(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ fun UserSection(
)
Markdown(
modifier = Modifier.padding(bottom = 16.dp),
content = user?.description ?: "Login with [AniList](${loginUri})"
content = user?.description ?: stringResource(SharedRes.strings.login_markdown, loginUri)
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -61,11 +61,13 @@ interface MediumComponent : ContentHolderComponent {

val dialog: Value<ChildSlot<DialogConfig, DialogComponent>>

val bsAvailable: Boolean
val bsOptions: Flow<Collection<Series>>

fun back()
override fun dismissContent() {
back()
}
fun rate(onLoggedIn: () -> Unit)
fun rate(value: Int)
fun descriptionTranslation(text: String?)
fun showCharacter(character: Character)
Expand Down
Loading

0 comments on commit b8c3f1e

Please sign in to comment.