Skip to content

Commit

Permalink
Merge branch 'develop' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexGladkov committed Aug 15, 2022
2 parents 3f4d794 + 824f2cb commit 996a7b9
Show file tree
Hide file tree
Showing 10 changed files with 71 additions and 52 deletions.
2 changes: 1 addition & 1 deletion buildSrc/buildSrc/src/main/kotlin/Dependencies.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
object Dependencies {

val odyssey = "1.0.0-beta14"
val odyssey = "1.0.0-beta15"
val odysseyPackage = "io.github.alexgladkov"

object DI {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,9 @@ fun ActionsScreen(count: Int?) {
item {
val modalSheetConfiguration = ModalSheetConfiguration(maxHeight = 0.7f, cornerRadius = 16)
ActionCell("Present Modal Screen", icon = Icons.Filled.ArrowCircleUp) {
modalController.present(modalSheetConfiguration) {
modalController.present(modalSheetConfiguration) { key ->
ModalSheetScreen {
modalController.popBackStack()
modalController.popBackStack(key)
}
}
}
Expand All @@ -59,9 +59,9 @@ fun ActionsScreen(count: Int?) {
item {
ActionCell("Show Alert Dialog", icon = Icons.Filled.AddAlert) {
val alertConfiguration = AlertConfiguration(maxHeight = 0.7f, maxWidth = 0.8f, cornerRadius = 4)
modalController.present(alertConfiguration) {
modalController.present(alertConfiguration) { key ->
AlertDialogScreen {
modalController.popBackStack()
modalController.popBackStack(key)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@ fun ModalSheetScreen(onCloseClick: () -> Unit) {
}
ActionCell(text = "Show one more Modal", icon = Icons.Filled.ArrowCircleUp) {
val modalSheetConfiguration = ModalSheetConfiguration(maxHeight = Random.nextFloat(), cornerRadius = 16)
modalController.present(modalSheetConfiguration) {
modalController.present(modalSheetConfiguration) { key ->
ModalSheetScreen {
modalController.popBackStack()
modalController.popBackStack(key)
}
}
}
Expand All @@ -47,19 +47,19 @@ fun ModalSheetScreen(onCloseClick: () -> Unit) {
// close by next modal
}
}
modalController.present(modalSheetConfiguration.copy(maxHeight = height - 0.1f)) {
modalController.present(modalSheetConfiguration.copy(maxHeight = height - 0.1f)) { key ->
ModalSheetScreen {
modalController.popBackStack()
modalController.popBackStack()
modalController.popBackStack(key)
modalController.popBackStack(key)
}
}
}

ActionCell(text = "Modal screen without closing animation", icon = Icons.Filled.ArrowCircleUp) {
val modalSheetConfiguration = ModalSheetConfiguration(maxHeight = Random.nextFloat(), cornerRadius = 16)
modalController.present(modalSheetConfiguration) {
modalController.present(modalSheetConfiguration) { key ->
ModalSheetScreen {
modalController.popBackStack(animate = false)
modalController.popBackStack(key, animate = false)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,9 @@ fun PresentedActionsScreen(count: Int?) {
item {
val modalSheetConfiguration = ModalSheetConfiguration(maxHeight = 0.7f, cornerRadius = 16)
ActionCell("Present Modal Screen", icon = Icons.Filled.ArrowCircleUp) {
modalController.present(modalSheetConfiguration) {
modalController.present(modalSheetConfiguration) { key ->
ModalSheetScreen {
modalController.popBackStack()
modalController.popBackStack(key)
}
}
}
Expand All @@ -55,9 +55,9 @@ fun PresentedActionsScreen(count: Int?) {
item {
ActionCell("Show Alert Dialog", icon = Icons.Filled.AddAlert) {
val alertConfiguration = AlertConfiguration(maxHeight = 0.7f, maxWidth = 0.8f, cornerRadius = 4)
modalController.present(alertConfiguration) {
modalController.present(alertConfiguration) { key ->
AlertDialogScreen {
modalController.popBackStack()
modalController.popBackStack(key)
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions documentation/GETTING_STARTED.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ Add dependencies to gradle
```kotlin
named("commonMain") {
dependencies {
implementation("io.github.alexgladkov:odyssey-core:1.0.0-beta14") // For core classes
implementation("io.github.alexgladkov:odyssey-compose:1.0.0-beta14") // For compose extensions
implementation("io.github.alexgladkov:odyssey-core:1.0.0-beta15") // For core classes
implementation("io.github.alexgladkov:odyssey-compose:1.0.0-beta15") // For compose extensions
}
}
```
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import ru.alexgladkov.odyssey.core.wrap
import kotlin.collections.HashMap

typealias RenderWithParams<T> = @Composable (T) -> Unit
typealias Render = @Composable () -> Unit
typealias Render = @Composable (key: String) -> Unit

sealed class ScreenType {
object Simple : ScreenType()
Expand Down Expand Up @@ -523,9 +523,8 @@ open class RootController(
}
}

private fun randomizeKey(key: String): String = createUniqueKey(key)

companion object {
internal fun randomizeKey(key: String): String = createUniqueKey(key)
private const val flowKey = "odyssey_flow_reserved_type"
private const val multiStackKey = "odyssey_multi_stack_reserved_type"
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package ru.alexgladkov.odyssey.compose.controllers

import kotlinx.coroutines.flow.MutableStateFlow
import ru.alexgladkov.odyssey.compose.Render
import ru.alexgladkov.odyssey.compose.RootController
import ru.alexgladkov.odyssey.compose.navigation.modal_navigation.AlertConfiguration
import ru.alexgladkov.odyssey.compose.navigation.modal_navigation.CustomModalConfiguration
import ru.alexgladkov.odyssey.compose.navigation.modal_navigation.ModalSheetConfiguration
Expand All @@ -25,6 +26,7 @@ sealed class ModalDialogState {
* @param content - composable content
*/
internal data class ModalSheetBundle(
override val key: String,
override val dialogState: ModalDialogState,
override val animationTime: Int,
override val content: Render,
Expand All @@ -47,6 +49,7 @@ internal data class ModalSheetBundle(
* @param content - composable content
*/
internal data class AlertBundle(
override val key: String,
override val dialogState: ModalDialogState,
override val animationTime: Int,
override val content: Render,
Expand All @@ -61,6 +64,7 @@ internal data class AlertBundle(
* Class helper to use with modal for custom modal
*/
internal data class CustomModalBundle(
override val key: String,
override val dialogState: ModalDialogState,
override val animationTime: Int,
override val content: Render
Expand All @@ -71,6 +75,8 @@ internal data class CustomModalBundle(
* @see ModalDialogState
*/
sealed interface ModalBundle {
val key: String

/**
* composable content
*/
Expand All @@ -87,7 +93,7 @@ sealed interface ModalBundle {
val dialogState: ModalDialogState
}

@Deprecated("see ModalSheetController", ReplaceWith("ModalSheetController"))
@Deprecated("see ModalController", ReplaceWith("ModalController"))
class ModalSheetController : ModalController()

/**
Expand All @@ -102,37 +108,44 @@ open class ModalController {
modalSheetConfiguration: ModalSheetConfiguration,
content: Render
) {
_backStack.add(modalSheetConfiguration.wrap(content))
_backStack.add(modalSheetConfiguration.wrap(randomizeKey(), content))
redrawStack()
}

internal fun presentNew(
alertConfiguration: AlertConfiguration,
content: Render
) {
_backStack.add(alertConfiguration.wrap(content))
_backStack.add(alertConfiguration.wrap(randomizeKey(), content))
redrawStack()
}

internal fun presentNew(
customConfiguration: CustomModalConfiguration,
content: Render
) {
_backStack.add(customConfiguration.wrap(content))
_backStack.add(customConfiguration.wrap(randomizeKey(), content))
redrawStack()
}

@Deprecated("@see popBackStack with key param", ReplaceWith("popBackStack(key = KEY)"))
fun popBackStack(animate: Boolean = true) {
setTopDialogState(modalDialogState = ModalDialogState.Close(animate))
popBackStack(key = null, animate = animate)
}

fun popBackStack(key: String? = null, animate: Boolean = true) {
setTopDialogState(modalDialogState = ModalDialogState.Close(animate), key)
}

internal fun setTopDialogState(modalDialogState: ModalDialogState) {
internal fun setTopDialogState(modalDialogState: ModalDialogState, key: String? = null) {
if (modalDialogState is ModalDialogState.Close && !modalDialogState.animate) {
finishCloseAction()
finishCloseAction(key)
return
}
val last =
_backStack.last { modalDialogState !is ModalDialogState.Close || it.dialogState != modalDialogState }
val last = if (key != null) _backStack.firstOrNull { it.key == key }
else _backStack
.lastOrNull { modalDialogState !is ModalDialogState.Close || it.dialogState != modalDialogState }
if (last == null) return
val index = _backStack.indexOf(last)
val newState =
when (last) {
Expand All @@ -146,16 +159,18 @@ open class ModalController {
}

/** Removes last modal from backstack */
internal fun finishCloseAction() {
if (_backStack.isNotEmpty()) _backStack.removeLast()
internal fun finishCloseAction(key: String?) {
when {
key != null -> {
val index = _backStack.indexOfFirst { it.key == key }
if (index != -1)
_backStack.removeAt(index)
}
_backStack.isNotEmpty() -> _backStack.removeLast()
}
redrawStack()
}

@Deprecated("@see popBackStack", ReplaceWith("popBackStack()"))
fun removeTopScreen() {
popBackStack()
}

fun clearBackStack() {
_backStack.clear()
}
Expand All @@ -168,9 +183,13 @@ open class ModalController {
}
_currentStack.value = newStack
}
companion object{
internal fun randomizeKey() = RootController.randomizeKey("modal_")
}
}

internal fun ModalSheetConfiguration.wrap(with: Render): ModalBundle = ModalSheetBundle(
internal fun ModalSheetConfiguration.wrap(key: String, with: Render): ModalBundle = ModalSheetBundle(
key = key,
maxHeight = maxHeight,
closeOnBackdropClick = closeOnBackdropClick,
closeOnSwipe = closeOnSwipe,
Expand All @@ -183,7 +202,8 @@ internal fun ModalSheetConfiguration.wrap(with: Render): ModalBundle = ModalShee
content = with
)

internal fun AlertConfiguration.wrap(with: Render): ModalBundle = AlertBundle(
internal fun AlertConfiguration.wrap(key: String, with: Render): ModalBundle = AlertBundle(
key = key,
maxHeight = maxHeight,
maxWidth = maxWidth,
animationTime = animationTime,
Expand All @@ -195,6 +215,6 @@ internal fun AlertConfiguration.wrap(with: Render): ModalBundle = AlertBundle(
)

@Suppress("unused")
internal fun CustomModalConfiguration.wrap(with: Render): ModalBundle = CustomModalBundle(
content = with, dialogState = ModalDialogState.Idle, animationTime = animationTime
internal fun CustomModalConfiguration.wrap(key: String, with: Render): ModalBundle = CustomModalBundle(
key = key, content = with, dialogState = ModalDialogState.Idle, animationTime = animationTime
)
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ fun ModalNavigator(
AlertDialog(bundle, modalController)
}
is CustomModalBundle -> {
bundle.content.invoke()
bundle.content(bundle.key)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ internal fun BoxScope.AlertDialog(
animationSpec = bundle.animationTime.asTween(),
finishedListener = {
if (bundle.dialogState == ModalDialogState.Idle) {
modalController.setTopDialogState(ModalDialogState.Open)
modalController.setTopDialogState(ModalDialogState.Open, bundle.key)
}
}
)
Expand All @@ -58,22 +58,22 @@ internal fun BoxScope.AlertDialog(
animationSpec = bundle.animationTime.asTween(),
finishedListener = {
if (bundle.dialogState is ModalDialogState.Close) {
modalController.finishCloseAction()
modalController.finishCloseAction(bundle.key)
}
}
)

Screamer(backdropAlpha) {
if (bundle.closeOnBackdropClick && bundle.dialogState !is ModalDialogState.Close) {
modalController.popBackStack()
modalController.popBackStack(key = bundle.key)
}
}

Card(
modifier = modifier.alpha(dialogAlpha).offset { IntOffset(x = 0, y = offset) },
shape = RoundedCornerShape(corner = CornerSize(bundle.cornerRadius))
) {
bundle.content.invoke()
bundle.content.invoke(bundle.key)
}

LaunchedEffect(bundle.dialogState) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,18 +53,18 @@ internal fun BoxScope.BottomModalSheet(
animationSpec = bundle.animationTime.asTween(),
finishedListener = {
when (bundle.dialogState) {
ModalDialogState.Idle -> modalController.setTopDialogState(ModalDialogState.Open)
is ModalDialogState.Close -> modalController.finishCloseAction()
ModalDialogState.Idle -> modalController.setTopDialogState(ModalDialogState.Open, bundle.key)
is ModalDialogState.Close -> modalController.finishCloseAction(bundle.key)
}
}
)

if (bundle.backContent != null) {
bundle.backContent.invoke()
bundle.backContent.invoke(bundle.key)
} else {
Screamer(backdropAlpha) {
if (bundle.closeOnBackdropClick && bundle.dialogState !is ModalDialogState.Close) {
modalController.popBackStack()
modalController.popBackStack(key = bundle.key)
}
}
}
Expand All @@ -90,13 +90,13 @@ internal fun BoxScope.BottomModalSheet(
topEnd = bundle.cornerRadius.dp
)
) {
bundle.content.invoke()
bundle.content.invoke(bundle.key)
}
}

LaunchedEffect(bundle.dialogState, swipeableState.offset.value) {
if (swipeableState.offset.value == viewHeight && bundle.dialogState !is ModalDialogState.Close) {
modalController.setTopDialogState(ModalDialogState.Close())
modalController.setTopDialogState(ModalDialogState.Close(), bundle.key)
}

when (bundle.dialogState) {
Expand Down

0 comments on commit 996a7b9

Please sign in to comment.