diff --git a/Sources/SkipUI/SkipUI/Containers/Navigation.swift b/Sources/SkipUI/SkipUI/Containers/Navigation.swift index 713058b0..ed2e2d6e 100644 --- a/Sources/SkipUI/SkipUI/Containers/Navigation.swift +++ b/Sources/SkipUI/SkipUI/Containers/Navigation.swift @@ -3,6 +3,10 @@ // as published by the Free Software Foundation https://fsf.org #if SKIP +import androidx.compose.animation.slideInHorizontally +import androidx.compose.animation.slideOutHorizontally +import androidx.compose.animation.EnterTransition +import androidx.compose.animation.ExitTransition import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box @@ -73,8 +77,14 @@ public struct NavigationStack : View where Root: View { // SKIP INSERT: val providedNavigator = LocalNavigator provides navigator.value CompositionLocalProvider(providedNavigator) { - NavHost(navController: navController, startDestination: Navigator.rootRoute, modifier: context.modifier) { - composable(route: Navigator.rootRoute) { entry in + NavHost(navController: navController, + startDestination: Navigator.rootRoute, + //enterTransition: { EnterTransition.None }, + exitTransition: { ExitTransition.None }, + modifier: context.modifier) { + composable(route: Navigator.rootRoute, + enterTransition: { slideInHorizontally() }, + exitTransition: { slideOutHorizontally() }) { entry in if let state = navigator.value.state(for: entry) { let entryContext = context.content(stateSaver: state.stateSaver) ComposeEntry(navController: navController, destinations: destinations, destinationsDidChange: preferencesDidChange, isRoot: true, context: entryContext) { context in @@ -86,7 +96,11 @@ public struct NavigationStack : View where Root: View { composable(route: Navigator.route(for: destinationIndex, valueString: "{identifier}"), arguments: listOf(navArgument("identifier") { type = NavType.StringType })) { entry in if let state = navigator.value.state(for: entry), let targetValue = state.targetValue { let entryContext = context.content(stateSaver: state.stateSaver) - ComposeEntry(navController: navController, destinations: destinations, destinationsDidChange: preferencesDidChange, isRoot: false, context: entryContext) { context in + ComposeEntry(navController: navController, + destinations: destinations, + destinationsDidChange: preferencesDidChange, + isRoot: false, + context: entryContext) { context in state.destination?(targetValue).Compose(context: context) } } diff --git a/Sources/SkipUI/SkipUI/Containers/TabView.swift b/Sources/SkipUI/SkipUI/Containers/TabView.swift index 1c3136eb..d091a80c 100644 --- a/Sources/SkipUI/SkipUI/Containers/TabView.swift +++ b/Sources/SkipUI/SkipUI/Containers/TabView.swift @@ -3,6 +3,8 @@ // as published by the Free Software Foundation https://fsf.org #if SKIP +import androidx.compose.animation.EnterTransition +import androidx.compose.animation.ExitTransition import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box @@ -21,6 +23,7 @@ import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable import androidx.navigation.compose.currentBackStackEntryAsState import androidx.navigation.compose.rememberNavController + #endif public struct TabView : View where Content : View { @@ -84,7 +87,10 @@ public struct TabView : View where Content : View { } } ) { padding in - NavHost(navController, startDestination: "0") { + NavHost(navController, + startDestination: "0", + enterTransition: { EnterTransition.None }, + exitTransition: { ExitTransition.None }) { // Use a constant number of routes. Changing routes causes a NavHost to reset its state for tabIndex in 0..<100 { composable(String(describing: tabIndex)) { diff --git a/Sources/SkipUI/SkipUI/Properties/AppStorage.swift b/Sources/SkipUI/SkipUI/Properties/AppStorage.swift index 1cc794c0..d32c88f1 100644 --- a/Sources/SkipUI/SkipUI/Properties/AppStorage.swift +++ b/Sources/SkipUI/SkipUI/Properties/AppStorage.swift @@ -2,7 +2,36 @@ // under the terms of the GNU Lesser General Public License 3.0 // as published by the Free Software Foundation https://fsf.org -// TODO: Process for use in SkipUI +#if SKIP +// Model AppStorage as a class rather than struct to avoid copy overhead on mutation +public final class AppStorage { + private var onUpdate: ((Value) -> Void)? + + public init(initialValue: Value) { + wrappedValue = initialValue + } + + public init(wrappedValue: Value) { + self.wrappedValue = wrappedValue + } + + public var wrappedValue: Value { + didSet { + onUpdate?(wrappedValue) + } + } + + public var projectedValue: Binding { + return Binding(get: { self.wrappedValue }, set: { self.wrappedValue = $0 }) + } + + /// Used to keep the state value synchronized with an external Compose value. + public func sync(value: Value, onUpdate: @escaping (Value) -> Void) { + self.wrappedValue = value + self.onUpdate = onUpdate + } +} +#endif #if !SKIP import struct Foundation.URL