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/EmptyList.kt b/app/src/main/java/dev/msfjarvis/lobsters/ui/posts/EmptyList.kt index a88d86af..4173c68c 100644 --- a/app/src/main/java/dev/msfjarvis/lobsters/ui/posts/EmptyList.kt +++ b/app/src/main/java/dev/msfjarvis/lobsters/ui/posts/EmptyList.kt @@ -8,11 +8,11 @@ import androidx.compose.foundation.layout.padding import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import dev.msfjarvis.lobsters.R import dev.msfjarvis.lobsters.util.IconResource -import dev.msfjarvis.lobsters.ui.theme.savedTitleColor @Composable fun EmptyList(saved: Boolean) { @@ -24,7 +24,7 @@ fun EmptyList(saved: Boolean) { if (saved) { IconResource( R.drawable.ic_favorite_border_24px, - tint = savedTitleColor, + tint = Color(0xFFD97373), modifier = Modifier.padding(16.dp) ) Text(stringResource(R.string.no_saved_posts)) 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 ec994581..b43c71c2 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,18 +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.runtime.mutableStateOf -import androidx.compose.runtime.remember 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 @@ -27,9 +32,13 @@ import dev.msfjarvis.lobsters.injection.ApiModule import dev.msfjarvis.lobsters.model.LobstersPost import dev.msfjarvis.lobsters.model.Submitter import dev.msfjarvis.lobsters.ui.theme.LobstersTheme -import dev.msfjarvis.lobsters.ui.theme.savedTitleColor import dev.msfjarvis.lobsters.ui.theme.titleColor +private enum class SwipeState { + NotSwiped, + FullySwiped, +} + @Composable fun LazyItemScope.LobstersItem( post: LobstersPost, @@ -38,20 +47,29 @@ fun LazyItemScope.LobstersItem( commentOpenAction: (LobstersPost) -> Unit, saveAction: (LobstersPost) -> Unit, ) { - val liked = remember { mutableStateOf(false) } - val titleColor = if (post.isLiked || liked.value) savedTitleColor else titleColor + val width = with(DensityAmbient.current) { + ConfigurationAmbient.current.screenWidthDp.toDp().toPx() + } + val swipeableState = rememberSwipeableState(SwipeState.NotSwiped) + val anchors = mapOf(0f to SwipeState.NotSwiped, width to SwipeState.FullySwiped) + if (swipeableState.offset.value >= (width / 2)) { + saveAction.invoke(post) + swipeableState.animateTo(SwipeState.NotSwiped) + } 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) }, - onDoubleClick = { - post.isLiked = true - liked.value = true - saveAction.invoke(post) - }, ), ) { Text( @@ -128,7 +146,8 @@ fun PreviewLobstersItem() { post = item, linkOpenAction = {}, commentOpenAction = {}, - saveAction = {}) + saveAction = {}, + ) } } } diff --git a/app/src/main/java/dev/msfjarvis/lobsters/ui/theme/Theme.kt b/app/src/main/java/dev/msfjarvis/lobsters/ui/theme/Theme.kt index 1bc934d9..d80e8b95 100644 --- a/app/src/main/java/dev/msfjarvis/lobsters/ui/theme/Theme.kt +++ b/app/src/main/java/dev/msfjarvis/lobsters/ui/theme/Theme.kt @@ -6,7 +6,6 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.graphics.Color val titleColor = Color(0xFF7395D9) -val savedTitleColor = Color(0xFFD97373) val darkColors = darkColors( primary = Color.White, diff --git a/app/src/main/java/dev/msfjarvis/lobsters/ui/viewmodel/LobstersViewModel.kt b/app/src/main/java/dev/msfjarvis/lobsters/ui/viewmodel/LobstersViewModel.kt index cb29bd7b..76c59379 100644 --- a/app/src/main/java/dev/msfjarvis/lobsters/ui/viewmodel/LobstersViewModel.kt +++ b/app/src/main/java/dev/msfjarvis/lobsters/ui/viewmodel/LobstersViewModel.kt @@ -54,15 +54,9 @@ class LobstersViewModel @ViewModelInject constructor( getMorePostsInternal(false) } - fun refreshPosts() { - apiPage = 1 - getMorePostsInternal(true) - } - private fun getMorePostsInternal(firstLoad: Boolean) { viewModelScope.launch(coroutineExceptionHandler) { val newPosts = lobstersApi.getHottestPosts(apiPage) - .transformLikedFlag() .toList() if (firstLoad) { _posts.value = newPosts @@ -79,7 +73,6 @@ class LobstersViewModel @ViewModelInject constructor( viewModelScope.launch { savedPostsDao.insertPosts(post) getSavedPosts() - _posts.value = _posts.value.transformLikedFlag().toList() } } @@ -87,11 +80,6 @@ class LobstersViewModel @ViewModelInject constructor( viewModelScope.launch { savedPostsDao.deletePostById(post.shortId) getSavedPosts() - _posts.value = _posts.value.transformLikedFlag().toList() } } - - private suspend fun List.transformLikedFlag() = map { - it.apply { isLiked = savedPostsDao.isLiked(shortId) } - } } diff --git a/model/src/main/java/dev/msfjarvis/lobsters/model/LobstersPost.kt b/model/src/main/java/dev/msfjarvis/lobsters/model/LobstersPost.kt index 5feb2f92..c379b440 100644 --- a/model/src/main/java/dev/msfjarvis/lobsters/model/LobstersPost.kt +++ b/model/src/main/java/dev/msfjarvis/lobsters/model/LobstersPost.kt @@ -23,5 +23,6 @@ class LobstersPost( @Json(name = "submitter_user") val submitterUser: Submitter, val tags: List, - var isLiked: Boolean = false, + @Deprecated("Retained for database compatibility as I am too lazy to write migrations") + val isLiked: Boolean = false, )