Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ccd9843c authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Clean up computeValue()" into main

parents 48b4b671 2d23c9e6
Loading
Loading
Loading
Loading
+195 −154
Original line number Diff line number Diff line
@@ -1307,8 +1307,7 @@ private inline fun <T> computeValue(

    val currentContent = currentContentState.contents.last()

    // The element is shared: interpolate between the value in fromContent and the value in
    // toContent.
    // The element is shared: interpolate between the value in fromContent and toContent.
    // TODO(b/290184746): Support non linear shared paths as well as a way to make sure that shared
    // elements follow the finger direction.
    val isSharedElement = fromState != null && toState != null
@@ -1343,28 +1342,133 @@ private inline fun <T> computeValue(
    // The content for which we compute the transformation. Note that this is not necessarily
    // [currentContent] because [currentContent] could be a different content than the transition
    // fromContent or toContent during interruptions or when a ancestor transition is running.
    val content: ContentKey
    val transformationContentKey: ContentKey =
        getTransformationContentKey(
            isDisabledSharedElement = isSharedElement,
            currentContent = currentContent,
            layoutImpl = layoutImpl,
            transition = transition,
            element = element,
            currentSceneState = currentSceneState,
        )
    // Get the transformed value, i.e. the target value at the beginning (for entering elements) or
    // end (for leaving elements) of the transition.
    val contentState: Element.State
    val targetState: Element.State = element.stateByContent.getValue(transformationContentKey)
    val idleValue = contentValue(targetState)

    val transformationWithRange =
        transformation(
            transition.transformationSpec.transformations(element.key, transformationContentKey)
        )

    val isElementEntering =
        when {
        isSharedElement -> {
            content = currentContent
            contentState = currentContentState
            transformationContentKey == toContent -> true
            transformationContentKey == fromContent -> false
            isAncestorTransition(layoutImpl, transition) ->
                isEnteringAncestorTransition(layoutImpl, transition)
            transformationContentKey == transition.currentScene -> toState == null
            else -> transformationContentKey == toContent
        }

    val previewTransformation =
        transition.previewTransformationSpec?.let {
            transformation(it.transformations(element.key, transformationContentKey))
        }

    if (previewTransformation != null) {
        return computePreviewTransformationValue(
            transition,
            idleValue,
            transformationContentKey,
            isElementEntering,
            previewTransformation,
            element,
            layoutImpl,
            transformationWithRange,
            lerp,
        )
    }

    if (transformationWithRange == null) {
        // If there is no transformation explicitly associated to this element value, let's use
        // the value given by the system (like the current position and size given by the layout
        // pass).
        return currentValue()
    }

    val transformation = transformationWithRange.transformation
    when (transformation) {
        is CustomPropertyTransformation ->
            return with(transformation) {
                layoutImpl.propertyTransformationScope.transform(
                    transformationContentKey,
                    element.key,
                    transition,
                    transition.coroutineScope,
                )
            }
        is InterpolatedPropertyTransformation -> {
            /* continue */
        }
    }

    val targetValue =
        with(transformation) {
            layoutImpl.propertyTransformationScope.transform(
                transformationContentKey,
                element.key,
                transition,
                idleValue,
            )
        }

    // Make sure we don't read progress if values are the same and we don't need to interpolate, so
    // we don't invalidate the phase where this is read.
    if (targetValue == idleValue) {
        return targetValue
    }

    val progress = transition.progress
    // TODO(b/290184746): Make sure that we don't overflow transformations associated to a range.
    val rangeProgress = transformationWithRange.range?.progress(progress) ?: progress

    return if (isElementEntering) {
        lerp(targetValue, idleValue, rangeProgress)
    } else {
        lerp(idleValue, targetValue, rangeProgress)
    }
}

private fun getTransformationContentKey(
    isDisabledSharedElement: Boolean,
    currentContent: ContentKey,
    layoutImpl: SceneTransitionLayoutImpl,
    transition: TransitionState.Transition,
    element: Element,
    currentSceneState: Element.State?,
): ContentKey {
    return when {
        isDisabledSharedElement -> {
            currentContent
        }
        isAncestorTransition(layoutImpl, transition) -> {
            if (
                fromState != null &&
                    transition.transformationSpec.hasTransformation(element.key, fromContent)
                element.stateByContent[transition.fromContent] != null &&
                    transition.transformationSpec.hasTransformation(
                        element.key,
                        transition.fromContent,
                    )
            ) {
                content = fromContent
                contentState = fromState
                transition.fromContent
            } else if (
                toState != null &&
                    transition.transformationSpec.hasTransformation(element.key, toContent)
                element.stateByContent[transition.toContent] != null &&
                    transition.transformationSpec.hasTransformation(
                        element.key,
                        transition.toContent,
                    )
            ) {
                content = toContent
                contentState = toState
                transition.toContent
            } else {
                throw IllegalStateException(
                    "Ancestor transition is active but no transformation " +
@@ -1374,31 +1478,30 @@ private inline fun <T> computeValue(
            }
        }
        currentSceneState != null && currentContent == transition.currentScene -> {
            content = currentContent
            contentState = currentSceneState
            currentContent
        }
        fromState != null -> {
            content = fromContent
            contentState = fromState
        element.stateByContent[transition.fromContent] != null -> {
            transition.fromContent
        }
        else -> {
            content = toContent
            contentState = toState!!
            transition.toContent
        }
    }

    val transformationWithRange =
        transformation(transition.transformationSpec.transformations(element.key, content))

    val previewTransformation =
        transition.previewTransformationSpec?.let {
            transformation(it.transformations(element.key, content))
}
    if (previewTransformation != null) {

private inline fun <T> computePreviewTransformationValue(
    transition: TransitionState.Transition,
    idleValue: T,
    transformationContentKey: ContentKey,
    isEntering: Boolean,
    previewTransformation: TransformationWithRange<PropertyTransformation<T>>,
    element: Element,
    layoutImpl: SceneTransitionLayoutImpl,
    transformationWithRange: TransformationWithRange<PropertyTransformation<T>>?,
    lerp: (T, T, Float) -> T,
): T {
    val isInPreviewStage = transition.isInPreviewStage

        val idleValue = contentValue(contentState)
        val isEntering = content == toContent
    val previewTargetValue =
        with(
            previewTransformation.transformation.requireInterpolatedTransformation(
@@ -1409,7 +1512,7 @@ private inline fun <T> computeValue(
            }
        ) {
            layoutImpl.propertyTransformationScope.transform(
                    content,
                transformationContentKey,
                element.key,
                transition,
                idleValue,
@@ -1427,7 +1530,7 @@ private inline fun <T> computeValue(
                }
            ) {
                layoutImpl.propertyTransformationScope.transform(
                        content,
                    transformationContentKey,
                    element.key,
                    transition,
                    idleValue,
@@ -1485,74 +1588,12 @@ private inline fun <T> computeValue(
            lerp(
                lerp(idleValue, previewTargetValue, previewRangeProgress),
                targetValueOrNull,
                    transformationWithRange.range?.progress(transition.progress)
                        ?: transition.progress,
                transformationWithRange.range?.progress(transition.progress) ?: transition.progress,
            )
        }
    }
}

    if (transformationWithRange == null) {
        // If there is no transformation explicitly associated to this element value, let's use
        // the value given by the system (like the current position and size given by the layout
        // pass).
        return currentValue()
    }

    val transformation = transformationWithRange.transformation
    when (transformation) {
        is CustomPropertyTransformation ->
            return with(transformation) {
                layoutImpl.propertyTransformationScope.transform(
                    content,
                    element.key,
                    transition,
                    transition.coroutineScope,
                )
            }
        is InterpolatedPropertyTransformation -> {
            /* continue */
        }
    }

    val idleValue = contentValue(contentState)
    val targetValue =
        with(transformation) {
            layoutImpl.propertyTransformationScope.transform(
                content,
                element.key,
                transition,
                idleValue,
            )
        }

    // Make sure we don't read progress if values are the same and we don't need to interpolate, so
    // we don't invalidate the phase where this is read.
    if (targetValue == idleValue) {
        return targetValue
    }

    val progress = transition.progress
    // TODO(b/290184746): Make sure that we don't overflow transformations associated to a range.
    val rangeProgress = transformationWithRange.range?.progress(progress) ?: progress

    // Interpolate between the value at rest and the value before entering/after leaving.
    val isEntering =
        when {
            content == toContent -> true
            content == fromContent -> false
            isAncestorTransition(layoutImpl, transition) ->
                isEnteringAncestorTransition(layoutImpl, transition)
            content == transition.currentScene -> toState == null
            else -> content == toContent
        }
    return if (isEntering) {
        lerp(targetValue, idleValue, rangeProgress)
    } else {
        lerp(idleValue, targetValue, rangeProgress)
    }
}

private fun isAncestorTransition(
    layoutImpl: SceneTransitionLayoutImpl,
    transition: TransitionState.Transition,
@@ -1564,7 +1605,7 @@ private fun isAncestorTransition(

private fun isEnteringAncestorTransition(
    layoutImpl: SceneTransitionLayoutImpl,
    transition: TransitionState.Transition
    transition: TransitionState.Transition,
): Boolean {
    return layoutImpl.ancestors.fastAny { it.inContent == transition.toContent }
}