ganfra
9 months ago
6 changed files with 213 additions and 0 deletions
@ -0,0 +1,39 @@ |
|||||||
|
/* |
||||||
|
* Copyright (c) 2023 New Vector Ltd |
||||||
|
* |
||||||
|
* 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 io.element.android.libraries.architecture.overlay |
||||||
|
|
||||||
|
import com.bumble.appyx.core.navigation.backpresshandlerstrategies.BaseBackPressHandlerStrategy |
||||||
|
import com.bumble.appyx.navmodel.backstack.BackStack |
||||||
|
import com.bumble.appyx.navmodel.backstack.BackStackElements |
||||||
|
import io.element.android.libraries.architecture.overlay.operation.Hide |
||||||
|
import kotlinx.coroutines.flow.Flow |
||||||
|
import kotlinx.coroutines.flow.map |
||||||
|
|
||||||
|
class HideOverlayBackPressHandler<NavTarget : Any> |
||||||
|
: BaseBackPressHandlerStrategy<NavTarget, BackStack.State>() { |
||||||
|
|
||||||
|
override val canHandleBackPressFlow: Flow<Boolean> by lazy { |
||||||
|
navModel.elements.map(::areThereElements) |
||||||
|
} |
||||||
|
|
||||||
|
private fun areThereElements(elements: BackStackElements<NavTarget>) = |
||||||
|
elements.isNotEmpty() |
||||||
|
|
||||||
|
override fun onBackPressed() { |
||||||
|
navModel.accept(Hide()) |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,49 @@ |
|||||||
|
/* |
||||||
|
* Copyright (c) 2023 New Vector Ltd |
||||||
|
* |
||||||
|
* 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 io.element.android.libraries.architecture.overlay |
||||||
|
|
||||||
|
import com.bumble.appyx.core.navigation.BaseNavModel |
||||||
|
import com.bumble.appyx.core.navigation.NavElements |
||||||
|
import com.bumble.appyx.core.navigation.backpresshandlerstrategies.BackPressHandlerStrategy |
||||||
|
import com.bumble.appyx.core.navigation.onscreen.OnScreenStateResolver |
||||||
|
import com.bumble.appyx.core.navigation.operationstrategies.ExecuteImmediately |
||||||
|
import com.bumble.appyx.core.navigation.operationstrategies.OperationStrategy |
||||||
|
import com.bumble.appyx.core.state.SavedStateMap |
||||||
|
import com.bumble.appyx.navmodel.backstack.BackStack |
||||||
|
import com.bumble.appyx.navmodel.backstack.BackStackOnScreenResolver |
||||||
|
import com.bumble.appyx.navmodel.backstack.backpresshandler.PopBackPressHandler |
||||||
|
import com.bumble.appyx.navmodel.backstack.operation.NewRoot |
||||||
|
import com.bumble.appyx.navmodel.backstack.operation.Push |
||||||
|
|
||||||
|
class Overlay<NavTarget : Any>( |
||||||
|
savedStateMap: SavedStateMap?, |
||||||
|
key: String = requireNotNull(Overlay::class.qualifiedName), |
||||||
|
backPressHandler: BackPressHandlerStrategy<NavTarget, BackStack.State> = HideOverlayBackPressHandler(), |
||||||
|
operationStrategy: OperationStrategy<NavTarget, BackStack.State> = ExecuteImmediately(), |
||||||
|
screenResolver: OnScreenStateResolver<BackStack.State> = BackStackOnScreenResolver, |
||||||
|
) : BaseNavModel<NavTarget, BackStack.State>( |
||||||
|
backPressHandler = backPressHandler, |
||||||
|
screenResolver = screenResolver, |
||||||
|
operationStrategy = operationStrategy, |
||||||
|
finalState = BackStack.State.DESTROYED, |
||||||
|
savedStateMap = savedStateMap, |
||||||
|
key = key, |
||||||
|
) { |
||||||
|
|
||||||
|
override val initialElements: NavElements<NavTarget, BackStack.State> |
||||||
|
get() = emptyList() |
||||||
|
} |
@ -0,0 +1,54 @@ |
|||||||
|
/* |
||||||
|
* Copyright (c) 2023 New Vector Ltd |
||||||
|
* |
||||||
|
* 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 io.element.android.libraries.architecture.overlay.operation |
||||||
|
|
||||||
|
import com.bumble.appyx.navmodel.backstack.BackStack |
||||||
|
import com.bumble.appyx.navmodel.backstack.BackStackElements |
||||||
|
import com.bumble.appyx.navmodel.backstack.activeIndex |
||||||
|
import io.element.android.libraries.architecture.overlay.Overlay |
||||||
|
import kotlinx.parcelize.Parcelize |
||||||
|
|
||||||
|
@Parcelize |
||||||
|
class Hide<T : Any> : OverlayOperation<T> { |
||||||
|
|
||||||
|
override fun isApplicable(elements: BackStackElements<T>): Boolean = |
||||||
|
elements.any { it.targetState == BackStack.State.ACTIVE } |
||||||
|
|
||||||
|
override fun invoke( |
||||||
|
elements: BackStackElements<T> |
||||||
|
): BackStackElements<T> { |
||||||
|
val hideIndex = elements.activeIndex |
||||||
|
require(hideIndex != -1) { "Nothing to hide, state=$elements" } |
||||||
|
return elements.mapIndexed { index, element -> |
||||||
|
when (index) { |
||||||
|
hideIndex -> element.transitionTo( |
||||||
|
newTargetState = BackStack.State.DESTROYED, |
||||||
|
operation = this |
||||||
|
) |
||||||
|
else -> element |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
override fun equals(other: Any?): Boolean = this.javaClass == other?.javaClass |
||||||
|
|
||||||
|
override fun hashCode(): Int = this.javaClass.hashCode() |
||||||
|
} |
||||||
|
|
||||||
|
fun <T : Any> Overlay<T>.hide() { |
||||||
|
accept(Hide()) |
||||||
|
} |
@ -0,0 +1,22 @@ |
|||||||
|
/* |
||||||
|
* Copyright (c) 2023 New Vector Ltd |
||||||
|
* |
||||||
|
* 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 io.element.android.libraries.architecture.overlay.operation |
||||||
|
|
||||||
|
import com.bumble.appyx.core.navigation.Operation |
||||||
|
import com.bumble.appyx.navmodel.backstack.BackStack |
||||||
|
|
||||||
|
interface OverlayOperation<T> : Operation<T, BackStack.State> |
@ -0,0 +1,48 @@ |
|||||||
|
/* |
||||||
|
* Copyright (c) 2023 New Vector Ltd |
||||||
|
* |
||||||
|
* 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 io.element.android.libraries.architecture.overlay.operation |
||||||
|
|
||||||
|
import com.bumble.appyx.core.navigation.NavKey |
||||||
|
import com.bumble.appyx.navmodel.backstack.BackStack |
||||||
|
import com.bumble.appyx.navmodel.backstack.BackStackElement |
||||||
|
import com.bumble.appyx.navmodel.backstack.BackStackElements |
||||||
|
import com.bumble.appyx.navmodel.backstack.activeElement |
||||||
|
import io.element.android.libraries.architecture.overlay.Overlay |
||||||
|
import kotlinx.parcelize.Parcelize |
||||||
|
import kotlinx.parcelize.RawValue |
||||||
|
|
||||||
|
@Parcelize |
||||||
|
data class Show<T : Any>( |
||||||
|
private val element: @RawValue T |
||||||
|
) : OverlayOperation<T> { |
||||||
|
|
||||||
|
override fun isApplicable(elements: BackStackElements<T>): Boolean = |
||||||
|
element != elements.activeElement |
||||||
|
|
||||||
|
override fun invoke(elements: BackStackElements<T>): BackStackElements<T> = listOf( |
||||||
|
BackStackElement( |
||||||
|
key = NavKey(element), |
||||||
|
fromState = BackStack.State.CREATED, |
||||||
|
targetState = BackStack.State.ACTIVE, |
||||||
|
operation = this |
||||||
|
) |
||||||
|
) |
||||||
|
} |
||||||
|
|
||||||
|
fun <T : Any> Overlay<T>.show(element: T) { |
||||||
|
accept(Show(element)) |
||||||
|
} |
Loading…
Reference in new issue