From 0fbacfd6683237a4fc435a2e323315cba2974fc6 Mon Sep 17 00:00:00 2001 From: Zac Sweers Date: Mon, 28 Aug 2023 10:18:13 -0400 Subject: [PATCH 1/7] Tmp enable snapshots --- gradle.properties | 2 ++ 1 file changed, 2 insertions(+) diff --git a/gradle.properties b/gradle.properties index 07c871244..a312038aa 100755 --- a/gradle.properties +++ b/gradle.properties @@ -17,6 +17,8 @@ org.gradle.parallel=true org.gradle.caching=true org.gradle.configureondemand=true +catchup.config.enableSnapshots=true +slack.gradle.config.enableSnapshots=true org.gradle.jvmargs=-Xmx3g -Dfile.encoding=UTF-8 From 63884b42b7e65eb62e0737983d6c77e60c0160f9 Mon Sep 17 00:00:00 2001 From: Zac Sweers Date: Mon, 28 Aug 2023 10:20:37 -0400 Subject: [PATCH 2/7] Add support for background color to imageviewerscreen --- .../kotlin/dev/zacsweers/catchup/service/ServiceScreen.kt | 8 +++++--- .../dev/zacsweers/catchup/service/VisualServiceUi.kt | 4 +++- .../io/sweers/catchup/ui/activity/ImageViewerScreen.kt | 3 +++ 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/app/src/main/kotlin/dev/zacsweers/catchup/service/ServiceScreen.kt b/app/src/main/kotlin/dev/zacsweers/catchup/service/ServiceScreen.kt index 20ae39997..8c835de17 100644 --- a/app/src/main/kotlin/dev/zacsweers/catchup/service/ServiceScreen.kt +++ b/app/src/main/kotlin/dev/zacsweers/catchup/service/ServiceScreen.kt @@ -104,7 +104,7 @@ data class ServiceScreen(val serviceKey: String) : Screen { } sealed interface Event : CircuitUiEvent { - data class ItemClicked(val item: CatchUpItem) : Event + data class ItemClicked(val item: CatchUpItem, val colorHint: Color = Color.Unspecified) : Event data class ItemActionClicked(val item: CatchUpItem, val action: Action) : Event { enum class Action { @@ -182,7 +182,8 @@ constructor( info.detailUrl, isBitmap = !info.animatable, info.cacheKey, - info.sourceUrl + info.sourceUrl, + event.colorHint.toArgb(), ) ) } else { @@ -201,7 +202,8 @@ constructor( url = url, isBitmap = bestGuessIsBitmap, alias = null, - sourceUrl = url + sourceUrl = url, + backgroundColor = event.colorHint.toArgb(), ) ) } else { diff --git a/app/src/main/kotlin/dev/zacsweers/catchup/service/VisualServiceUi.kt b/app/src/main/kotlin/dev/zacsweers/catchup/service/VisualServiceUi.kt index 193699b93..631a60edf 100644 --- a/app/src/main/kotlin/dev/zacsweers/catchup/service/VisualServiceUi.kt +++ b/app/src/main/kotlin/dev/zacsweers/catchup/service/VisualServiceUi.kt @@ -100,7 +100,9 @@ fun VisualServiceUi( ?: Color.Unspecified, ) ClickableItem( - onClick = { eventSink(ServiceScreen.Event.ItemClicked(item)) }, + onClick = { + eventSink(ServiceScreen.Event.ItemClicked(item, clickableItemState.contentColor)) + }, state = clickableItemState, ) { VisualItem( diff --git a/app/src/main/kotlin/io/sweers/catchup/ui/activity/ImageViewerScreen.kt b/app/src/main/kotlin/io/sweers/catchup/ui/activity/ImageViewerScreen.kt index 7de33b3de..9886b2636 100644 --- a/app/src/main/kotlin/io/sweers/catchup/ui/activity/ImageViewerScreen.kt +++ b/app/src/main/kotlin/io/sweers/catchup/ui/activity/ImageViewerScreen.kt @@ -72,6 +72,7 @@ data class ImageViewerScreen( val isBitmap: Boolean, val alias: String?, val sourceUrl: String, + @ColorInt val backgroundColor: Int = Color.Unspecified.toArgb() ) : Screen { data class State( val id: String, @@ -79,6 +80,7 @@ data class ImageViewerScreen( val alias: String?, val sourceUrl: String, val isBitmap: Boolean, + val backgroundColor: Color, val eventSink: (Event) -> Unit, ) : CircuitUiState @@ -124,6 +126,7 @@ constructor( alias = screen.alias, isBitmap = screen.isBitmap, sourceUrl = screen.sourceUrl, + backgroundColor = Color(screen.backgroundColor), ) { event -> // TODO finish implementing these. Also why is copying an image on android so terrible in // 2023. From f7d67f80bbf5df1d937094aecdb3a2dbeecd5d88 Mon Sep 17 00:00:00 2001 From: Zac Sweers Date: Mon, 28 Aug 2023 10:21:16 -0400 Subject: [PATCH 3/7] Fix system bar icon colors --- .../kotlin/io/sweers/catchup/ui/activity/ImageViewerScreen.kt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/src/main/kotlin/io/sweers/catchup/ui/activity/ImageViewerScreen.kt b/app/src/main/kotlin/io/sweers/catchup/ui/activity/ImageViewerScreen.kt index 9886b2636..d79d131c3 100644 --- a/app/src/main/kotlin/io/sweers/catchup/ui/activity/ImageViewerScreen.kt +++ b/app/src/main/kotlin/io/sweers/catchup/ui/activity/ImageViewerScreen.kt @@ -155,10 +155,12 @@ fun ImageViewer(state: ImageViewerScreen.State, modifier: Modifier = Modifier) { // Set BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE so the UI doesn't jump when it hides systemUiController.systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE + val originalIsDarkContent = systemUiController.systemBarsDarkContentEnabled + systemUiController.systemBarsDarkContentEnabled = false onDispose { - // TODO this is too late for some reason systemUiController.isSystemBarsVisible = true systemUiController.systemBarsBehavior = originalSystemBarsBehavior + systemUiController.systemBarsDarkContentEnabled = originalIsDarkContent } } From b4e39578d0a3d17af690fa9eb67dc42f5a18c5b9 Mon Sep 17 00:00:00 2001 From: Zac Sweers Date: Mon, 28 Aug 2023 10:21:38 -0400 Subject: [PATCH 4/7] Replace Flick with upstream impl --- app/build.gradle.kts | 2 + .../catchup/ui/activity/FlickToDismiss.kt | 159 ------------------ .../catchup/ui/activity/ImageViewerScreen.kt | 118 ++++++++++--- gradle/libs.versions.toml | 4 +- 4 files changed, 102 insertions(+), 181 deletions(-) delete mode 100644 app/src/main/kotlin/io/sweers/catchup/ui/activity/FlickToDismiss.kt diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 3df6b2624..ab96688f3 100755 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -486,6 +486,7 @@ dependencies { implementation(libs.androidx.compose.materialIcons) implementation(libs.androidx.compose.runtime) implementation(libs.androidx.compose.ui) + implementation(libs.androidx.compose.ui.util) implementation(libs.androidx.core) implementation(libs.androidx.coreKtx) implementation(libs.androidx.customTabs) @@ -551,6 +552,7 @@ dependencies { implementation(libs.sqldelight.paging) implementation(libs.sqldelight.primitiveAdapters) implementation(libs.sqldelight.runtime) + implementation(libs.telephoto.flick) implementation(libs.telephoto.zoomableImageCoil) implementation(libs.xmlutil.serialization) implementation(projects.libraries.appconfig) diff --git a/app/src/main/kotlin/io/sweers/catchup/ui/activity/FlickToDismiss.kt b/app/src/main/kotlin/io/sweers/catchup/ui/activity/FlickToDismiss.kt deleted file mode 100644 index bd939f302..000000000 --- a/app/src/main/kotlin/io/sweers/catchup/ui/activity/FlickToDismiss.kt +++ /dev/null @@ -1,159 +0,0 @@ -// Adapted with permission from https://gist.github.com/saket/94ddc78c4d96902ec3be71e916a03d06 -package io.sweers.catchup.ui.activity - -import androidx.annotation.FloatRange -import androidx.compose.animation.core.Animatable -import androidx.compose.animation.core.AnimationConstants -import androidx.compose.animation.core.tween -import androidx.compose.foundation.MutatePriority -import androidx.compose.foundation.gestures.DraggableState -import androidx.compose.foundation.gestures.Orientation -import androidx.compose.foundation.gestures.draggable -import androidx.compose.foundation.interaction.MutableInteractionSource -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.BoxScope -import androidx.compose.foundation.layout.offset -import androidx.compose.runtime.Composable -import androidx.compose.runtime.Stable -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.Modifier -import androidx.compose.ui.graphics.graphicsLayer -import androidx.compose.ui.layout.onGloballyPositioned -import androidx.compose.ui.unit.IntOffset -import androidx.compose.ui.unit.IntSize -import io.sweers.catchup.ui.activity.FlickToDismissState.FlickGestureState.Dismissed -import io.sweers.catchup.ui.activity.FlickToDismissState.FlickGestureState.Dragging -import io.sweers.catchup.ui.activity.FlickToDismissState.FlickGestureState.Idle -import kotlin.math.abs - -@Composable -fun FlickToDismiss( - modifier: Modifier = Modifier, - state: FlickToDismissState = rememberFlickToDismissState(), - interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }, - content: @Composable BoxScope.() -> Unit -) { - val dragStartedOnLeftSide = remember { mutableStateOf(false) } - - Box( - modifier = - modifier - .offset { IntOffset(x = 0, y = state.offset.toInt()) } - .graphicsLayer { - rotationZ = state.offsetRatio * if (dragStartedOnLeftSide.value) -20F else 20F - } - .draggable( - enabled = state.enabled, - state = state.draggableState, - orientation = Orientation.Vertical, - interactionSource = interactionSource, - startDragImmediately = state.isResettingOnRelease, - onDragStarted = { startedPosition -> - dragStartedOnLeftSide.value = startedPosition.x < (state.contentSize.value!!.width / 2f) - }, - onDragStopped = { - if (state.willDismissOnRelease) { - state.animateDismissal() - state.gestureState = Dismissed - } else { - state.resetOffset() - } - } - ) - .onGloballyPositioned { coordinates -> state.contentSize.value = coordinates.size }, - content = content - ) -} - -@Composable -fun rememberFlickToDismissState(): FlickToDismissState { - return remember { FlickToDismissState() } -} - -/** - * @param dismissThresholdRatio Minimum distance the user's finger should move as a ratio to the - * content's dimensions after which it can be dismissed. - */ -@Stable -data class FlickToDismissState( - val enabled: Boolean = true, - val dismissThresholdRatio: Float = 0.15f, - val rotateOnDrag: Boolean = true, -) { - val offset: Float - get() = offsetState.value - - val offsetState = mutableStateOf(0f) - - /** Distance dragged as a ratio of the content's height. */ - @get:FloatRange(from = -1.0, to = 1.0) - val offsetRatio: Float by derivedStateOf { - val contentHeight = contentSize.value?.height - if (contentHeight == null) { - 0f - } else { - offset / contentHeight.toFloat() - } - } - - var isResettingOnRelease: Boolean by mutableStateOf(false) - private set - - var gestureState: FlickGestureState by mutableStateOf(Idle) - internal set - - val willDismissOnRelease: Boolean by derivedStateOf { - when (gestureState) { - is Dismissed -> true - is Dragging, - is Idle -> abs(offsetRatio) > dismissThresholdRatio - } - } - - internal var contentSize = mutableStateOf(null as IntSize?) - - internal val draggableState = DraggableState { dy -> - offsetState.value += dy - - gestureState = - when { - gestureState is Dismissed -> gestureState - offset == 0f -> Idle - else -> Dragging - } - } - - internal suspend fun resetOffset() { - draggableState.drag(MutatePriority.PreventUserInput) { - isResettingOnRelease = true - try { - Animatable(offset).animateTo(targetValue = 0f) { dragBy(value - offset) } - } finally { - isResettingOnRelease = false - } - } - } - - internal suspend fun animateDismissal() { - draggableState.drag(MutatePriority.PreventUserInput) { - Animatable(offset).animateTo( - targetValue = contentSize.value!!.height * if (offset > 0f) 1f else -1f, - animationSpec = tween(AnimationConstants.DefaultDurationMillis) - ) { - dragBy(value - offset) - } - } - } - - sealed interface FlickGestureState { - object Idle : FlickGestureState - - object Dragging : FlickGestureState - - object Dismissed : FlickGestureState - } -} diff --git a/app/src/main/kotlin/io/sweers/catchup/ui/activity/ImageViewerScreen.kt b/app/src/main/kotlin/io/sweers/catchup/ui/activity/ImageViewerScreen.kt index d79d131c3..785f90dcf 100644 --- a/app/src/main/kotlin/io/sweers/catchup/ui/activity/ImageViewerScreen.kt +++ b/app/src/main/kotlin/io/sweers/catchup/ui/activity/ImageViewerScreen.kt @@ -1,22 +1,27 @@ package io.sweers.catchup.ui.activity +import androidx.annotation.ColorInt import androidx.compose.animation.AnimatedVisibility -import androidx.compose.animation.animateContentSize -import androidx.compose.animation.core.animateFloatAsState -import androidx.compose.animation.core.tween +import androidx.compose.animation.core.animateDpAsState import androidx.compose.animation.fadeIn import androidx.compose.animation.fadeOut +import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.WindowInsets import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.statusBarsPadding -import androidx.compose.material3.Surface +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Scaffold import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.DisposableEffect +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 @@ -24,11 +29,15 @@ import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.graphicsLayer import androidx.compose.ui.graphics.toArgb import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.colorResource import androidx.compose.ui.unit.dp +import androidx.compose.ui.util.lerp +import androidx.compose.ui.zIndex import androidx.core.view.WindowInsetsControllerCompat import coil.request.ImageRequest import com.google.accompanist.systemuicontroller.rememberSystemUiController @@ -56,10 +65,15 @@ import io.sweers.catchup.base.ui.NavButton import io.sweers.catchup.base.ui.NavButtonType import io.sweers.catchup.data.LinkManager import io.sweers.catchup.service.api.UrlMeta -import io.sweers.catchup.ui.activity.FlickToDismissState.FlickGestureState.Dismissed import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.delay import kotlinx.coroutines.launch import kotlinx.parcelize.Parcelize +import me.saket.telephoto.flick.FlickToDismiss +import me.saket.telephoto.flick.FlickToDismissState +import me.saket.telephoto.flick.FlickToDismissState.GestureState +import me.saket.telephoto.flick.FlickToDismissState.GestureState.Dismissing +import me.saket.telephoto.flick.rememberFlickToDismissState import me.saket.telephoto.zoomable.ZoomSpec import me.saket.telephoto.zoomable.coil.ZoomableAsyncImage import me.saket.telephoto.zoomable.rememberZoomableImageState @@ -165,27 +179,69 @@ fun ImageViewer(state: ImageViewerScreen.State, modifier: Modifier = Modifier) { } CatchUpTheme(useDarkTheme = true) { - val backgroundAlpha: Float by - animateFloatAsState(targetValue = 1f, animationSpec = tween(), label = "backgroundAlpha") - Surface( - modifier.fillMaxSize().animateContentSize(), - color = Color.Black.copy(alpha = backgroundAlpha), - contentColor = Color.White - ) { - Box(Modifier.fillMaxSize()) { + Scaffold( + contentWindowInsets = WindowInsets(0, 0, 0, 0), + containerColor = Color.Transparent, + contentColor = Color.White, + ) { contentPadding -> + val flickState = rememberFlickToDismissState(rotateOnDrag = false) + val backgroundColor = + if (state.backgroundColor == Color.Unspecified) { + MaterialTheme.colorScheme.background + } else { + state.backgroundColor + } + Box( + modifier + .padding(contentPadding) + .fillMaxSize() + .background(backgroundColor.copy(alpha = 1f - flickState.offsetFraction)) + ) { // Image + scrim - - val dismissState = rememberFlickToDismissState() - if (dismissState.gestureState is Dismissed) { + CloseScreenOnFlickDismissEffect(flickState) { state.eventSink(ImageViewerScreen.Event.Close) } - // TODO bind scrim with flick. animate scrim out after flick finishes? Or with flick? - FlickToDismiss(state = dismissState) { + + // TODO + // corner shape on drag offset + // dropshadow on dragging + FlickToDismiss(state = flickState) { val overlayHost = LocalOverlayHost.current val scope = rememberStableCoroutineScope() val zoomableState = rememberZoomableState(ZoomSpec(maxZoomFactor = 2f)) val imageState = rememberZoomableImageState(zoomableState) // TODO loading loading indicator if there's no memory cached alias + + // TODO elevation and corner radius don't actually work currently + val targetElevation = + if (flickState.gestureState is GestureState.Dragging) { + 32.dp + } else { + 0.dp + } + val targetRadius = + if (flickState.gestureState is GestureState.Dragging) { + 32.dp + } else { + 0.dp + } + + val elevation by animateDpAsState(targetElevation, label = "Animated elevation") + val cornerRadius by animateDpAsState(targetRadius, label = "Animated corner radius") + + // Scale x/y based on the flick offset + // We scale at most to 0.95f, and lerp this within the first 30% of the offset fraction + val scale by remember { + derivedStateOf { + val adjustedFraction = + when { + flickState.offsetFraction <= 0f -> 0f + flickState.offsetFraction >= 0.3f -> 1f + else -> flickState.offsetFraction / 0.3f + } + lerp(1f, 0.95f, adjustedFraction) + } + } ZoomableAsyncImage( model = ImageRequest.Builder(LocalContext.current) @@ -193,16 +249,21 @@ fun ImageViewer(state: ImageViewerScreen.State, modifier: Modifier = Modifier) { .apply { state.alias?.let(::placeholderMemoryCacheKey) } .build(), contentDescription = "TODO", - modifier = Modifier.fillMaxSize(), + modifier = + Modifier.fillMaxSize() + .graphicsLayer(scaleX = scale, scaleY = scale) + .zIndex(elevation.value) + .clip(RoundedCornerShape(cornerRadius)), state = imageState, onClick = { showChrome = !showChrome }, onLongClick = { launchShareSheet(scope, overlayHost, state) }, ) } - // TODO pick color based on if image is underneath it or not. Similar to badges + // TODO pick color based on if image is underneath it or not. Similar to badges? + // Alternatively make this just a very small button? AnimatedVisibility( - showChrome, + showChrome && flickState.gestureState == GestureState.Idle, enter = fadeIn(), exit = fadeOut(), ) { @@ -218,6 +279,21 @@ fun ImageViewer(state: ImageViewerScreen.State, modifier: Modifier = Modifier) { } } +@Composable +private fun CloseScreenOnFlickDismissEffect( + flickState: FlickToDismissState, + onDismiss: () -> Unit +) { + val gestureState = flickState.gestureState + + if (gestureState is Dismissing) { + LaunchedEffect(Unit) { + delay(gestureState.animationDuration / 2) + onDismiss() + } + } +} + private fun launchShareSheet( scope: CoroutineScope, overlayHost: OverlayHost, diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 9f4e60b42..167d160ee 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -41,7 +41,7 @@ sortDependencies = "0.4" sgp = "0.10.5" spotless = "6.20.0" sqldelight = "2.0.0" -telephoto = "1.0.0-alpha02" +telephoto = "0.6.0-SNAPSHOT" tikxml = "0.8.15" xerial = "3.42.0.1" collapsingToolbar = "2.3.5" @@ -108,6 +108,7 @@ androidx-compose-animation-graphics = { module = "androidx.compose.animation:ani # Here to trigger renovate updates androidx-compose-compiler = { module = "androidx.compose.compiler:compiler", version.ref = "compose-compiler" } androidx-compose-ui = { module = "androidx.compose.ui:ui", version.ref = "compose" } +androidx-compose-ui-util = { module = "androidx.compose.ui:ui-util", version.ref = "compose" } androidx-compose-uiTooling = { module = "androidx.compose.ui:ui-tooling", version.ref = "compose" } androidx-compose-foundation = { module = "androidx.compose.foundation:foundation", version.ref = "compose" } androidx-compose-googleFonts = "androidx.compose.ui:ui-text-google-fonts:1.5.0" @@ -238,6 +239,7 @@ sqldelight-runtime = { module = "app.cash.sqldelight:runtime", version.ref = "sq sqlite-xerial = { module = "org.xerial:sqlite-jdbc", version.ref = "xerial" } +telephoto-flick = { module = "me.saket.telephoto:flick", version.ref = "telephoto" } telephoto-zoomableImageCoil = { module = "me.saket.telephoto:zoomable-image-coil", version.ref = "telephoto" } tikxml-htmlEscape = { module = "com.tickaroo.tikxml:converter-htmlescape", version.ref = "tikxml" } From 0b90334efee4ec131ddcb29f9b1df863a23b0418 Mon Sep 17 00:00:00 2001 From: Zac Sweers Date: Thu, 21 Sep 2023 00:55:17 -0400 Subject: [PATCH 5/7] Fixes --- .../kotlin/catchup/app/ui/activity/ImageViewerScreen.kt | 9 --------- 1 file changed, 9 deletions(-) diff --git a/app/src/main/kotlin/catchup/app/ui/activity/ImageViewerScreen.kt b/app/src/main/kotlin/catchup/app/ui/activity/ImageViewerScreen.kt index ef524dea8..a590972a0 100644 --- a/app/src/main/kotlin/catchup/app/ui/activity/ImageViewerScreen.kt +++ b/app/src/main/kotlin/catchup/app/ui/activity/ImageViewerScreen.kt @@ -41,7 +41,6 @@ import androidx.compose.ui.zIndex import androidx.core.view.WindowInsetsControllerCompat import catchup.app.data.LinkManager import catchup.app.service.UrlMeta -import catchup.app.ui.activity.FlickToDismissState.FlickGestureState.Dismissed import catchup.app.ui.activity.ImageViewerScreen.Event import catchup.app.ui.activity.ImageViewerScreen.Event.Close import catchup.app.ui.activity.ImageViewerScreen.Event.CopyImage @@ -75,14 +74,6 @@ import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject import dev.zacsweers.catchup.R import kotlinx.collections.immutable.ImmutableList -import dev.zacsweers.catchup.compose.CatchUpTheme -import dev.zacsweers.catchup.compose.rememberStableCoroutineScope -import dev.zacsweers.catchup.di.AppScope -import io.sweers.catchup.R -import io.sweers.catchup.base.ui.NavButton -import io.sweers.catchup.base.ui.NavButtonType -import io.sweers.catchup.data.LinkManager -import io.sweers.catchup.service.api.UrlMeta import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.delay import kotlinx.coroutines.launch From e5eeefdb7f48ad46f59fbdffc6af37e4bf28a17b Mon Sep 17 00:00:00 2001 From: Zac Sweers Date: Sun, 18 Feb 2024 23:45:58 -0500 Subject: [PATCH 6/7] Fixes from main merge --- app-scaffold/build.gradle.kts | 1 + .../catchup/app/ui/activity/ImageViewerScreen.kt | 12 +++++++----- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/app-scaffold/build.gradle.kts b/app-scaffold/build.gradle.kts index 1def8f8b6..5fd6e85bf 100755 --- a/app-scaffold/build.gradle.kts +++ b/app-scaffold/build.gradle.kts @@ -190,6 +190,7 @@ dependencies { implementation(libs.sqldelight.paging) implementation(libs.sqldelight.primitiveAdapters) implementation(libs.sqldelight.runtime) + implementation(libs.telephoto.flick) implementation(libs.telephoto.zoomable) implementation(libs.telephoto.zoomableImage) implementation(libs.telephoto.zoomableImageCoil) diff --git a/app-scaffold/src/main/kotlin/catchup/app/ui/activity/ImageViewerScreen.kt b/app-scaffold/src/main/kotlin/catchup/app/ui/activity/ImageViewerScreen.kt index 4ad63730b..27b5b47cb 100644 --- a/app-scaffold/src/main/kotlin/catchup/app/ui/activity/ImageViewerScreen.kt +++ b/app-scaffold/src/main/kotlin/catchup/app/ui/activity/ImageViewerScreen.kt @@ -40,8 +40,6 @@ import androidx.compose.ui.zIndex import androidx.core.view.WindowInsetsControllerCompat import catchup.app.data.LinkManager import catchup.app.service.openUrl -import catchup.app.ui.activity.FlickToDismissState.FlickGestureState.Dismissed -import catchup.app.service.UrlMeta import catchup.app.ui.activity.ImageViewerScreen.Event import catchup.app.ui.activity.ImageViewerScreen.Event.Close import catchup.app.ui.activity.ImageViewerScreen.Event.CopyImage @@ -95,7 +93,7 @@ data class ImageViewerScreen( val isBitmap: Boolean, val alias: String?, val sourceUrl: String, - @ColorInt val backgroundColor: Int = Color.Unspecified.toArgb() + @ColorInt val backgroundColor: Int = Color.Unspecified.toArgb(), ) : Screen { data class State( val id: String, @@ -268,7 +266,11 @@ fun ImageViewer(state: State, modifier: Modifier = Modifier) { // TODO pick color based on if image is underneath it or not. Similar to badges? // Alternatively make this just a very small button? - AnimatedVisibility(showChrome && flickState.gestureState == GestureState.Idle, enter = fadeIn(), exit = fadeOut()) { + AnimatedVisibility( + showChrome && flickState.gestureState == GestureState.Idle, + enter = fadeIn(), + exit = fadeOut(), + ) { NavButton(Modifier.align(Alignment.TopStart).padding(16.dp).statusBarsPadding(), CLOSE) { state.eventSink(Close) } @@ -281,7 +283,7 @@ fun ImageViewer(state: State, modifier: Modifier = Modifier) { @Composable private fun CloseScreenOnFlickDismissEffect( flickState: FlickToDismissState, - onDismiss: () -> Unit + onDismiss: () -> Unit, ) { val gestureState = flickState.gestureState From 723eacd5d89ad185e492984dd28b1322fd50a072 Mon Sep 17 00:00:00 2001 From: Zac Sweers Date: Sun, 18 Feb 2024 23:49:55 -0500 Subject: [PATCH 7/7] Another main fix --- .../src/main/kotlin/catchup/app/service/ServiceScreen.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/app-scaffold/src/main/kotlin/catchup/app/service/ServiceScreen.kt b/app-scaffold/src/main/kotlin/catchup/app/service/ServiceScreen.kt index 140ddaeb0..84334c153 100644 --- a/app-scaffold/src/main/kotlin/catchup/app/service/ServiceScreen.kt +++ b/app-scaffold/src/main/kotlin/catchup/app/service/ServiceScreen.kt @@ -31,6 +31,7 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.toArgb import androidx.compose.ui.res.colorResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextAlign