Add scale gesture to stories.

fork-5.53.8
Alex Hart 2022-09-16 12:35:06 -03:00 zatwierdzone przez Greyson Parrelli
rodzic 9a21f5abca
commit ffa249885e
4 zmienionych plików z 82 dodań i 10 usunięć

Wyświetl plik

@ -14,6 +14,7 @@ import android.os.Build
import android.os.Bundle
import android.view.GestureDetector
import android.view.MotionEvent
import android.view.ScaleGestureDetector
import android.view.View
import android.view.animation.Interpolator
import android.widget.FrameLayout
@ -34,6 +35,7 @@ import io.reactivex.rxjava3.core.Observable
import org.signal.core.util.DimensionUnit
import org.signal.core.util.logging.Log
import org.thoughtcrime.securesms.R
import org.thoughtcrime.securesms.animation.AnimationCompleteListener
import org.thoughtcrime.securesms.components.AvatarImageView
import org.thoughtcrime.securesms.components.segmentedprogressbar.SegmentedProgressBar
import org.thoughtcrime.securesms.components.segmentedprogressbar.SegmentedProgressBarListener
@ -226,9 +228,24 @@ class StoryViewerPageFragment :
)
)
val scaleListener = StoryScaleListener(
viewModel, sharedViewModel, card
)
val scaleDetector = ScaleGestureDetector(
requireContext(),
scaleListener
)
cardWrapper.setOnInterceptTouchEventListener { !storySlate.state.hasClickableContent && childFragmentManager.findFragmentById(R.id.story_content_container) !is StoryTextPostPreviewFragment }
cardWrapper.setOnTouchListener { _, event ->
val result = gestureDetector.onTouchEvent(event)
scaleDetector.onTouchEvent(event)
val result = if (scaleDetector.isInProgress || scaleListener.isPerformingEndAnimation) {
true
} else {
gestureDetector.onTouchEvent(event)
}
if (event.actionMasked == MotionEvent.ACTION_DOWN) {
viewModel.setIsUserTouching(true)
} else if (event.actionMasked == MotionEvent.ACTION_UP || event.actionMasked == MotionEvent.ACTION_CANCEL) {
@ -1026,6 +1043,53 @@ class StoryViewerPageFragment :
}
}
private class StoryScaleListener(
val viewModel: StoryViewerPageViewModel,
val sharedViewModel: StoryViewerViewModel,
val card: View
) : ScaleGestureDetector.SimpleOnScaleGestureListener() {
private var scaleFactor = 1f
var isPerformingEndAnimation: Boolean = false
private set
override fun onScaleBegin(detector: ScaleGestureDetector): Boolean {
viewModel.setIsUserScaling(true)
sharedViewModel.setIsChildScrolling(true)
card.animate().cancel()
card.apply {
pivotX = detector.focusX
pivotY = detector.focusY
}
return true
}
override fun onScale(detector: ScaleGestureDetector): Boolean {
scaleFactor *= detector.scaleFactor
card.apply {
scaleX = max(scaleFactor, 1f)
scaleY = max(scaleFactor, 1f)
}
return true
}
override fun onScaleEnd(detector: ScaleGestureDetector) {
scaleFactor = 1f
isPerformingEndAnimation = true
card.animate().scaleX(1f).scaleY(1f).setListener(object : AnimationCompleteListener() {
override fun onAnimationEnd(animation: Animator?) {
isPerformingEndAnimation = false
viewModel.setIsUserScaling(false)
sharedViewModel.setIsChildScrolling(false)
}
})
}
}
private class StoryGestureListener(
private val container: View,
private val onGoToNext: () -> Unit,
@ -1044,7 +1108,7 @@ class StoryViewerPageFragment :
private val maxSlide = DimensionUnit.DP.toPixels(56f * 2)
override fun onDown(e: MotionEvent?): Boolean {
override fun onDown(e: MotionEvent): Boolean {
return true
}

Wyświetl plik

@ -259,6 +259,10 @@ class StoryViewerPageViewModel(
storyViewerPlaybackStore.update { it.copy(isDisplayingInfoDialog = isDisplayingInfoDialog) }
}
fun setIsUserScaling(isUserScaling: Boolean) {
storyViewerPlaybackStore.update { it.copy(isUserScaling = isUserScaling) }
}
private fun resolveSwipeToReplyState(state: StoryViewerPageState, index: Int): StoryViewerPageState.ReplyState {
if (index !in state.posts.indices) {
return StoryViewerPageState.ReplyState.NONE

Wyświetl plik

@ -19,11 +19,12 @@ data class StoryViewerPlaybackState(
val isDisplayingFirstTimeNavigation: Boolean = false,
val isDisplayingInfoDialog: Boolean = false,
val isUserLongTouching: Boolean = false,
val isUserScrollingChild: Boolean = false
val isUserScrollingChild: Boolean = false,
val isUserScaling: Boolean = false
) {
val hideChromeImmediate: Boolean = isRunningSharedElementAnimation
val hideChrome: Boolean = isRunningSharedElementAnimation || isUserLongTouching || isUserScrollingChild
val hideChrome: Boolean = isRunningSharedElementAnimation || isUserLongTouching || isUserScrollingChild || isUserScaling
val isPaused: Boolean = !areSegmentsInitialized ||
isUserTouching ||
@ -42,5 +43,6 @@ data class StoryViewerPlaybackState(
isDisplayingReactionAnimation ||
isRunningSharedElementAnimation ||
isDisplayingFirstTimeNavigation ||
isDisplayingInfoDialog
isDisplayingInfoDialog ||
isUserScaling
}

Wyświetl plik

@ -1,16 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
tools:viewBindingIgnore="true"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".stories.viewer.StoryViewerActivity">
tools:context=".stories.viewer.StoryViewerActivity"
tools:viewBindingIgnore="true">
<org.thoughtcrime.securesms.util.views.TouchInterceptingFrameLayout
android:id="@+id/story_content_card_touch_interceptor"
android:layout_width="0dp"
android:layout_height="0dp"
android:clipChildren="false"
android:clipToPadding="false"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintDimensionRatio="9:16"
app:layout_constraintEnd_toEndOf="parent"
@ -54,10 +56,10 @@
<org.thoughtcrime.securesms.stories.StoryVolumeOverlayView
android:id="@+id/story_volume_overlay"
android:alpha="0"
android:layout_gravity="center_vertical|end"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
android:layout_height="wrap_content"
android:layout_gravity="center_vertical|end"
android:alpha="0" />
</org.thoughtcrime.securesms.util.views.TouchInterceptingFrameLayout>