diff --git a/app/build.gradle b/app/build.gradle index 76a5d65b..98cdc236 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -53,6 +53,7 @@ tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).configureEach { "-Xskip-prerelease-check", "-Xopt-in=kotlin.RequiresOptIn", "-Xopt-in=kotlinx.coroutines.ExperimentalCoroutinesApi", + "-Xopt-in=androidx.compose.material.ExperimentalMaterialApi", ] } } diff --git a/app/src/main/java/dev/msfjarvis/lobsters/ui/posts/HottestPosts.kt b/app/src/main/java/dev/msfjarvis/lobsters/ui/posts/HottestPosts.kt index 91ac21ca..6b040842 100644 --- a/app/src/main/java/dev/msfjarvis/lobsters/ui/posts/HottestPosts.kt +++ b/app/src/main/java/dev/msfjarvis/lobsters/ui/posts/HottestPosts.kt @@ -8,7 +8,6 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import dev.msfjarvis.lobsters.model.LobstersPost import dev.msfjarvis.lobsters.ui.urllauncher.UrlLauncherAmbient -import dev.msfjarvis.lobsters.util.AnimatedSwipeDismiss @Composable fun HottestPosts( @@ -31,17 +30,11 @@ fun HottestPosts( if (posts.lastIndex == index) { overscrollAction.invoke() } - AnimatedSwipeDismiss( - item = item, - background = {}, - content = { - LobstersItem( - post = item, - linkOpenAction = { post -> urlLauncher.launch(post.url.ifEmpty { post.commentsUrl }) }, - commentOpenAction = { post -> urlLauncher.launch(post.commentsUrl) }, - ) - }, - onDismiss = saveAction, + LobstersItem( + post = item, + linkOpenAction = { post -> urlLauncher.launch(post.url.ifEmpty { post.commentsUrl }) }, + commentOpenAction = { post -> urlLauncher.launch(post.commentsUrl) }, + saveAction = saveAction, ) } } diff --git a/app/src/main/java/dev/msfjarvis/lobsters/ui/posts/LobstersItem.kt b/app/src/main/java/dev/msfjarvis/lobsters/ui/posts/LobstersItem.kt index c84d8abd..277e15d5 100644 --- a/app/src/main/java/dev/msfjarvis/lobsters/ui/posts/LobstersItem.kt +++ b/app/src/main/java/dev/msfjarvis/lobsters/ui/posts/LobstersItem.kt @@ -6,16 +6,23 @@ import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.offsetPx import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.wrapContentHeight import androidx.compose.foundation.lazy.LazyColumnFor import androidx.compose.foundation.lazy.LazyItemScope 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.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.gesture.scrollorientationlocking.Orientation 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.unit.dp import androidx.ui.tooling.preview.Preview @@ -34,12 +41,29 @@ fun LazyItemScope.LobstersItem( modifier: Modifier = Modifier, linkOpenAction: (LobstersPost) -> Unit, commentOpenAction: (LobstersPost) -> Unit, + saveAction: (LobstersPost) -> Unit, ) { 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( modifier = modifier .fillParentMaxWidth() + .swipeable( + state = swipeableState, + anchors = anchors, + thresholds = { _, _ -> FractionalThreshold(0.5f) }, + orientation = Orientation.Horizontal + ) + .offsetPx(swipeableState.offset) .clickable( onClick = { linkOpenAction.invoke(post) }, onLongClick = { commentOpenAction.invoke(post) }, @@ -119,6 +143,7 @@ fun PreviewLobstersItem() { post = item, linkOpenAction = {}, commentOpenAction = {}, + saveAction = {}, ) } } diff --git a/app/src/main/java/dev/msfjarvis/lobsters/ui/posts/SavedPosts.kt b/app/src/main/java/dev/msfjarvis/lobsters/ui/posts/SavedPosts.kt index f15c8073..4765aed5 100644 --- a/app/src/main/java/dev/msfjarvis/lobsters/ui/posts/SavedPosts.kt +++ b/app/src/main/java/dev/msfjarvis/lobsters/ui/posts/SavedPosts.kt @@ -8,7 +8,6 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import dev.msfjarvis.lobsters.model.LobstersPost import dev.msfjarvis.lobsters.ui.urllauncher.UrlLauncherAmbient -import dev.msfjarvis.lobsters.util.AnimatedSwipeDismiss @Composable fun SavedPosts( @@ -27,17 +26,11 @@ fun SavedPosts( state = listState, modifier = Modifier.padding(horizontal = 8.dp).then(modifier) ) { item -> - AnimatedSwipeDismiss( - item = item, - background = {}, - content = { - LobstersItem( - post = item, - linkOpenAction = { post -> urlLauncher.launch(post.url.ifEmpty { post.commentsUrl }) }, - commentOpenAction = { post -> urlLauncher.launch(post.commentsUrl) }, - ) - }, - onDismiss = saveAction, + LobstersItem( + post = item, + linkOpenAction = { post -> urlLauncher.launch(post.url.ifEmpty { post.commentsUrl }) }, + commentOpenAction = { post -> urlLauncher.launch(post.commentsUrl) }, + saveAction = saveAction, ) } } diff --git a/app/src/main/java/dev/msfjarvis/lobsters/util/AnimatedSwipeDismiss.kt b/app/src/main/java/dev/msfjarvis/lobsters/util/AnimatedSwipeDismiss.kt deleted file mode 100644 index 963a8a0a..00000000 --- a/app/src/main/java/dev/msfjarvis/lobsters/util/AnimatedSwipeDismiss.kt +++ /dev/null @@ -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 AnimatedSwipeDismiss( - modifier: Modifier = Modifier, - item: T, - background: @Composable (isDismissed: Boolean) -> Unit, - content: @Composable (isDismissed: Boolean) -> Unit, - directions: Set = 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) } - ) - } -}