| 
					
				 | 
			
			
				@@ -1,158 +0,0 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-/* 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- * Copyright 2021 The Android Open Source Project 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- * Licensed under the Apache License, Version 2.0 (the "License"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- * you may not use this file except in compliance with the License. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- * You may obtain a copy of the License at 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- *      http://www.apache.org/licenses/LICENSE-2.0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- * Unless required by applicable law or agreed to in writing, software 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- * distributed under the License is distributed on an "AS IS" BASIS, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- * See the License for the specific language governing permissions and 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- * limitations under the License. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-package eu.kanade.presentation.util 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-import androidx.compose.animation.core.AnimationState 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-import androidx.compose.animation.core.DecayAnimationSpec 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-import androidx.compose.animation.core.animateDecay 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-import androidx.compose.material3.TopAppBarScrollBehavior 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-import androidx.compose.material3.TopAppBarScrollState 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-import androidx.compose.ui.geometry.Offset 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-import androidx.compose.ui.input.nestedscroll.NestedScrollConnection 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-import androidx.compose.ui.input.nestedscroll.NestedScrollSource 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-import androidx.compose.ui.unit.Velocity 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-import kotlin.math.abs 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-/** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- * A [TopAppBarScrollBehavior] that adjusts its properties to affect the colors and height of a top 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- * app bar. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- * A top app bar that is set up with this [TopAppBarScrollBehavior] will immediately collapse when 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- * the nested content is pulled up, and will expand back the collapsed area when the content is 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- * pulled all the way down. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- * @param decayAnimationSpec a [DecayAnimationSpec] that will be used by the top app bar motion 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- * when the user flings the content. Preferably, this should match the animation spec used by the 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- * scrollable content. See also [androidx.compose.animation.rememberSplineBasedDecay] for a 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- * default [DecayAnimationSpec] that can be used with this behavior. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- * @param canScroll a callback used to determine whether scroll events are to be 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- * handled by this [ExitUntilCollapsedScrollBehavior] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-class ExitUntilCollapsedScrollBehavior( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    override val state: TopAppBarScrollState, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    val decayAnimationSpec: DecayAnimationSpec<Float>, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    val canScroll: () -> Boolean = { true }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-) : TopAppBarScrollBehavior { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    override val scrollFraction: Float 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        get() = if (state.offsetLimit != 0f) state.offset / state.offsetLimit else 0f 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    override var nestedScrollConnection = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        object : NestedScrollConnection { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            override fun onPreScroll(available: Offset, source: NestedScrollSource): Offset { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                // Don't intercept if scrolling down. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                if (!canScroll() || available.y > 0f) return Offset.Zero 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                val newOffset = (state.offset + available.y) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                val coerced = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    newOffset.coerceIn(minimumValue = state.offsetLimit, maximumValue = 0f) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                return if (newOffset == coerced) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    // Nothing coerced, meaning we're in the middle of top app bar collapse or 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    // expand. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    state.offset = coerced 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    // Consume only the scroll on the Y axis. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    available.copy(x = 0f) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    Offset.Zero 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            override fun onPostScroll( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                consumed: Offset, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                available: Offset, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                source: NestedScrollSource, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            ): Offset { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                if (!canScroll()) return Offset.Zero 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                state.contentOffset += consumed.y 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                if (available.y < 0f || consumed.y < 0f) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    // When scrolling up, just update the state's offset. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    val oldOffset = state.offset 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    state.offset = (state.offset + consumed.y).coerceIn( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                        minimumValue = state.offsetLimit, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                        maximumValue = 0f, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    return Offset(0f, state.offset - oldOffset) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                if (consumed.y == 0f && available.y > 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    // Reset the total offset to zero when scrolling all the way down. This will 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    // eliminate some float precision inaccuracies. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    state.contentOffset = 0f 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                if (available.y > 0f) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    // Adjust the offset in case the consumed delta Y is less than what was recorded 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    // as available delta Y in the pre-scroll. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    val oldOffset = state.offset 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    state.offset = (state.offset + available.y).coerceIn( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                        minimumValue = state.offsetLimit, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                        maximumValue = 0f, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    return Offset(0f, state.offset - oldOffset) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                return Offset.Zero 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            override suspend fun onPostFling(consumed: Velocity, available: Velocity): Velocity { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                val result = super.onPostFling(consumed, available) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                if ((available.y < 0f && state.contentOffset == 0f) || 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    (available.y > 0f && state.offset < 0f) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                ) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    return result + 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                        onTopBarFling( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                            scrollBehavior = this@ExitUntilCollapsedScrollBehavior, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                            initialVelocity = available.y, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                            decayAnimationSpec = decayAnimationSpec, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                        ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                return result 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-/** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- * Tachiyomi: Remove snap behavior 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-private suspend fun onTopBarFling( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    scrollBehavior: TopAppBarScrollBehavior, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    initialVelocity: Float, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    decayAnimationSpec: DecayAnimationSpec<Float>, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-): Velocity { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if (abs(initialVelocity) > 1f) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        var remainingVelocity = initialVelocity 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        var lastValue = 0f 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        AnimationState( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            initialValue = 0f, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            initialVelocity = initialVelocity, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            .animateDecay(decayAnimationSpec) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                val delta = value - lastValue 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                val initialOffset = scrollBehavior.state.offset 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                scrollBehavior.state.offset = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    (initialOffset + delta).coerceIn( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                        minimumValue = scrollBehavior.state.offsetLimit, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                        maximumValue = 0f, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                val consumed = abs(initialOffset - scrollBehavior.state.offset) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                lastValue = value 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                remainingVelocity = this.velocity 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                // avoid rounding errors and stop if anything is unconsumed 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                if (abs(delta - consumed) > 0.5f) this.cancelAnimation() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        return Velocity(0f, remainingVelocity) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    return Velocity.Zero 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-} 
			 |