mirror of
https://github.com/msfjarvis/compose-lobsters
synced 2025-08-18 03:17:03 +05:30
Switch to Modifier.swipeable
Signed-off-by: Harsh Shandilya <me@msfjarvis.dev>
This commit is contained in:
parent
8c162c75c5
commit
a52c75601c
5 changed files with 36 additions and 85 deletions
|
@ -53,6 +53,7 @@ tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).configureEach {
|
||||||
"-Xskip-prerelease-check",
|
"-Xskip-prerelease-check",
|
||||||
"-Xopt-in=kotlin.RequiresOptIn",
|
"-Xopt-in=kotlin.RequiresOptIn",
|
||||||
"-Xopt-in=kotlinx.coroutines.ExperimentalCoroutinesApi",
|
"-Xopt-in=kotlinx.coroutines.ExperimentalCoroutinesApi",
|
||||||
|
"-Xopt-in=androidx.compose.material.ExperimentalMaterialApi",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,6 @@ import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import dev.msfjarvis.lobsters.model.LobstersPost
|
import dev.msfjarvis.lobsters.model.LobstersPost
|
||||||
import dev.msfjarvis.lobsters.ui.urllauncher.UrlLauncherAmbient
|
import dev.msfjarvis.lobsters.ui.urllauncher.UrlLauncherAmbient
|
||||||
import dev.msfjarvis.lobsters.util.AnimatedSwipeDismiss
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun HottestPosts(
|
fun HottestPosts(
|
||||||
|
@ -31,17 +30,11 @@ fun HottestPosts(
|
||||||
if (posts.lastIndex == index) {
|
if (posts.lastIndex == index) {
|
||||||
overscrollAction.invoke()
|
overscrollAction.invoke()
|
||||||
}
|
}
|
||||||
AnimatedSwipeDismiss(
|
LobstersItem(
|
||||||
item = item,
|
post = item,
|
||||||
background = {},
|
linkOpenAction = { post -> urlLauncher.launch(post.url.ifEmpty { post.commentsUrl }) },
|
||||||
content = {
|
commentOpenAction = { post -> urlLauncher.launch(post.commentsUrl) },
|
||||||
LobstersItem(
|
saveAction = saveAction,
|
||||||
post = item,
|
|
||||||
linkOpenAction = { post -> urlLauncher.launch(post.url.ifEmpty { post.commentsUrl }) },
|
|
||||||
commentOpenAction = { post -> urlLauncher.launch(post.commentsUrl) },
|
|
||||||
)
|
|
||||||
},
|
|
||||||
onDismiss = saveAction,
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,16 +6,23 @@ import androidx.compose.foundation.clickable
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
|
import androidx.compose.foundation.layout.offsetPx
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.width
|
import androidx.compose.foundation.layout.width
|
||||||
import androidx.compose.foundation.layout.wrapContentHeight
|
import androidx.compose.foundation.layout.wrapContentHeight
|
||||||
import androidx.compose.foundation.lazy.LazyColumnFor
|
import androidx.compose.foundation.lazy.LazyColumnFor
|
||||||
import androidx.compose.foundation.lazy.LazyItemScope
|
import androidx.compose.foundation.lazy.LazyItemScope
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
|
import androidx.compose.material.FractionalThreshold
|
||||||
|
import androidx.compose.material.rememberSwipeableState
|
||||||
|
import androidx.compose.material.swipeable
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.gesture.scrollorientationlocking.Orientation
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.platform.ConfigurationAmbient
|
||||||
|
import androidx.compose.ui.platform.DensityAmbient
|
||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.ui.tooling.preview.Preview
|
import androidx.ui.tooling.preview.Preview
|
||||||
|
@ -34,12 +41,29 @@ fun LazyItemScope.LobstersItem(
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
linkOpenAction: (LobstersPost) -> Unit,
|
linkOpenAction: (LobstersPost) -> Unit,
|
||||||
commentOpenAction: (LobstersPost) -> Unit,
|
commentOpenAction: (LobstersPost) -> Unit,
|
||||||
|
saveAction: (LobstersPost) -> Unit,
|
||||||
) {
|
) {
|
||||||
val titleColor = if (post.isLiked) savedTitleColor else titleColor
|
val titleColor = if (post.isLiked) savedTitleColor else titleColor
|
||||||
|
val width = with(DensityAmbient.current) {
|
||||||
|
ConfigurationAmbient.current.screenWidthDp.toDp().toPx()
|
||||||
|
}
|
||||||
|
val swipeableState = rememberSwipeableState("Not Swiped")
|
||||||
|
val anchors = mapOf(0f to "Not Swiped", width to "Fully Swiped")
|
||||||
|
if (swipeableState.offset.value >= (width / 2)) {
|
||||||
|
saveAction.invoke(post)
|
||||||
|
swipeableState.animateTo("Not Swiped")
|
||||||
|
}
|
||||||
|
|
||||||
Column(
|
Column(
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
.fillParentMaxWidth()
|
.fillParentMaxWidth()
|
||||||
|
.swipeable(
|
||||||
|
state = swipeableState,
|
||||||
|
anchors = anchors,
|
||||||
|
thresholds = { _, _ -> FractionalThreshold(0.5f) },
|
||||||
|
orientation = Orientation.Horizontal
|
||||||
|
)
|
||||||
|
.offsetPx(swipeableState.offset)
|
||||||
.clickable(
|
.clickable(
|
||||||
onClick = { linkOpenAction.invoke(post) },
|
onClick = { linkOpenAction.invoke(post) },
|
||||||
onLongClick = { commentOpenAction.invoke(post) },
|
onLongClick = { commentOpenAction.invoke(post) },
|
||||||
|
@ -119,6 +143,7 @@ fun PreviewLobstersItem() {
|
||||||
post = item,
|
post = item,
|
||||||
linkOpenAction = {},
|
linkOpenAction = {},
|
||||||
commentOpenAction = {},
|
commentOpenAction = {},
|
||||||
|
saveAction = {},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,6 @@ import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import dev.msfjarvis.lobsters.model.LobstersPost
|
import dev.msfjarvis.lobsters.model.LobstersPost
|
||||||
import dev.msfjarvis.lobsters.ui.urllauncher.UrlLauncherAmbient
|
import dev.msfjarvis.lobsters.ui.urllauncher.UrlLauncherAmbient
|
||||||
import dev.msfjarvis.lobsters.util.AnimatedSwipeDismiss
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun SavedPosts(
|
fun SavedPosts(
|
||||||
|
@ -27,17 +26,11 @@ fun SavedPosts(
|
||||||
state = listState,
|
state = listState,
|
||||||
modifier = Modifier.padding(horizontal = 8.dp).then(modifier)
|
modifier = Modifier.padding(horizontal = 8.dp).then(modifier)
|
||||||
) { item ->
|
) { item ->
|
||||||
AnimatedSwipeDismiss(
|
LobstersItem(
|
||||||
item = item,
|
post = item,
|
||||||
background = {},
|
linkOpenAction = { post -> urlLauncher.launch(post.url.ifEmpty { post.commentsUrl }) },
|
||||||
content = {
|
commentOpenAction = { post -> urlLauncher.launch(post.commentsUrl) },
|
||||||
LobstersItem(
|
saveAction = saveAction,
|
||||||
post = item,
|
|
||||||
linkOpenAction = { post -> urlLauncher.launch(post.url.ifEmpty { post.commentsUrl }) },
|
|
||||||
commentOpenAction = { post -> urlLauncher.launch(post.commentsUrl) },
|
|
||||||
)
|
|
||||||
},
|
|
||||||
onDismiss = saveAction,
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,61 +0,0 @@
|
||||||
package dev.msfjarvis.lobsters.util
|
|
||||||
|
|
||||||
import androidx.compose.animation.AnimatedVisibility
|
|
||||||
import androidx.compose.animation.EnterTransition
|
|
||||||
import androidx.compose.animation.ExitTransition
|
|
||||||
import androidx.compose.animation.ExperimentalAnimationApi
|
|
||||||
import androidx.compose.animation.core.tween
|
|
||||||
import androidx.compose.animation.expandVertically
|
|
||||||
import androidx.compose.animation.shrinkVertically
|
|
||||||
import androidx.compose.material.DismissDirection
|
|
||||||
import androidx.compose.material.DismissValue
|
|
||||||
import androidx.compose.material.ExperimentalMaterialApi
|
|
||||||
import androidx.compose.material.SwipeToDismiss
|
|
||||||
import androidx.compose.material.rememberDismissState
|
|
||||||
import androidx.compose.runtime.Composable
|
|
||||||
import androidx.compose.runtime.onCommit
|
|
||||||
import androidx.compose.ui.Modifier
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Imported from Brandon McAnsh's [Gist](https://gist.github.com/bmc08gt/fca95db3bf9fcf255d76f03ec10ea3f9).
|
|
||||||
*/
|
|
||||||
@OptIn(ExperimentalAnimationApi::class, ExperimentalMaterialApi::class)
|
|
||||||
@Composable
|
|
||||||
fun <T> AnimatedSwipeDismiss(
|
|
||||||
modifier: Modifier = Modifier,
|
|
||||||
item: T,
|
|
||||||
background: @Composable (isDismissed: Boolean) -> Unit,
|
|
||||||
content: @Composable (isDismissed: Boolean) -> Unit,
|
|
||||||
directions: Set<DismissDirection> = setOf(DismissDirection.StartToEnd, DismissDirection.EndToStart),
|
|
||||||
enter: EnterTransition = expandVertically(),
|
|
||||||
exit: ExitTransition = shrinkVertically(
|
|
||||||
animSpec = tween(
|
|
||||||
durationMillis = 500,
|
|
||||||
)
|
|
||||||
),
|
|
||||||
onDismiss: (T) -> Unit
|
|
||||||
) {
|
|
||||||
val dismissState = rememberDismissState()
|
|
||||||
val isDismissed = dismissState.isDismissed(DismissDirection.EndToStart)
|
|
||||||
|
|
||||||
onCommit(dismissState.value) {
|
|
||||||
if (dismissState.value == DismissValue.DismissedToStart) {
|
|
||||||
onDismiss(item)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
AnimatedVisibility(
|
|
||||||
modifier = modifier,
|
|
||||||
visible = !isDismissed,
|
|
||||||
enter = enter,
|
|
||||||
exit = exit
|
|
||||||
) {
|
|
||||||
SwipeToDismiss(
|
|
||||||
modifier = modifier,
|
|
||||||
state = dismissState,
|
|
||||||
directions = directions,
|
|
||||||
background = { background(isDismissed) },
|
|
||||||
dismissContent = { content(isDismissed) }
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Add table
Add a link
Reference in a new issue