Skip to content

Commit

Permalink
Finish moving everything from ViewExtensions.swift into the appropria…
Browse files Browse the repository at this point in the history
…te file

and marking unavailable where possible
  • Loading branch information
aabewhite committed Oct 10, 2023
1 parent 2c941ee commit 1d25a31
Show file tree
Hide file tree
Showing 29 changed files with 679 additions and 2,705 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ SkipUI contains stubs for the entire SwiftUI framework. API generally goes throu
1. The first implementation step is to move code out of `#if !SKIP` blocks so that it will be transpiled. This is helpful on its own, even if you just mark the API `@available(*, unavailable)` because you are not ready to implement it for Compose. An `unavailable` attribute will provide Skip users with a clear error message, rather than relying on the Kotlin compiler to complain about unfound API.
- When moving code out of a `#if !SKIP` block, please strip Apple's extensive API comments. There is no reason for Skip to duplicate the official SwiftUI documentation, and it obscures any Skip-specific implementation comments we may add.
- SwiftUI uses complex generics extensively, and the generics systems of Swift and Kotlin have significant differences. You may have to replace some generics or generic constraints with looser typing in order to transpile successfully.
- Reducing the number of Swift extensions and instead folding API into the primary declaration of a type can make Skip's internal symbol storage more efficient. This includes moving general modifier implementations from `ViewExtensions.swift` to `View.swift`. If a modifier is specific to a component - e.g. `.navigationTitle` is specific to `NavigationStack` - then use a `View` extension within the component's source file.
- Reducing the number of Swift extensions and instead folding API into the primary declaration of a type can make Skip's internal symbol storage more efficient. You may, should, however, leave `View` modifiers that are specific to a given component - e.g. `.navigationTitle` is specific to `NavigationStack` - within the component's source file.
1. Finally, we add a Compose implementation and remove any `unavailable` attribute.

Note that SkipUI should remain buildable throughout this process. Being able to successfully compile SkipUI in Xcode helps us validate that our ported components still mesh with the rest of the framework.
Expand Down
65 changes: 65 additions & 0 deletions Sources/SkipUI/SkipUI/Animation/Transition.swift
Original file line number Diff line number Diff line change
Expand Up @@ -668,4 +668,69 @@ extension Transition where Self == PushTransition {
public static func push(from edge: Edge) -> Self { fatalError() }
}

@available(iOS 16.0, macOS 13.0, tvOS 16.0, watchOS 9.0, *)
extension View {

/// Modifies the view to use a given transition as its method of animating
/// changes to the contents of its views.
///
/// This modifier allows you to perform a transition that animates a change
/// within a single view. The provided ``ContentTransition`` can present an
/// opacity animation for content changes, an interpolated animation of
/// the content's paths as they change, or perform no animation at all.
///
/// > Tip: The `contentTransition(_:)` modifier only has an effect within
/// the context of an ``Animation``.
///
/// In the following example, a ``Button`` changes the color and font size
/// of a ``Text`` view. Since both of these properties apply to the paths of
/// the text, the ``ContentTransition/interpolate`` transition can animate a
/// gradual change to these properties through the entire transition. By
/// contrast, the ``ContentTransition/opacity`` transition would simply fade
/// between the start and end states.
///
/// private static let font1 = Font.system(size: 20)
/// private static let font2 = Font.system(size: 45)
///
/// @State private var color = Color.red
/// @State private var currentFont = font1
///
/// var body: some View {
/// VStack {
/// Text("Content transition")
/// .foregroundColor(color)
/// .font(currentFont)
/// .contentTransition(.interpolate)
/// Spacer()
/// Button("Change") {
/// withAnimation(Animation.easeInOut(duration: 5.0)) {
/// color = (color == .red) ? .green : .red
/// currentFont = (currentFont == font1) ? font2 : font1
/// }
/// }
/// }
/// }
///
/// This example uses an ease-in–ease-out animation with a five-second
/// duration to make it easier to see the effect of the interpolation. The
/// figure below shows the `Text` at the beginning of the animation,
/// halfway through, and at the end.
///
/// | Time | Display |
/// | ------- | ------- |
/// | Start | ![The text Content transition in a small red font.](ContentTransition-1) |
/// | Middle | ![The text Content transition in a medium brown font.](ContentTransition-2) |
/// | End | ![The text Content transition in a large green font.](ContentTransition-3) |
///
/// To control whether content transitions use GPU-accelerated rendering,
/// set the value of the
/// ``EnvironmentValues/contentTransitionAddsDrawingGroup`` environment
/// variable.
///
/// - parameter transition: The transition to apply when animating the
/// content change.
public func contentTransition(_ transition: ContentTransition) -> some View { return stubView() }

}

#endif
26 changes: 0 additions & 26 deletions Sources/SkipUI/SkipUI/Commands/Menu.swift
Original file line number Diff line number Diff line change
Expand Up @@ -195,32 +195,6 @@ public struct MenuActionDismissBehavior : Equatable {

}

/// A control group style that presents its content as a menu when the user
/// presses the control, or as a submenu when nested within a larger menu.
///
/// Use ``ControlGroupStyle/menu`` to construct this style.
@available(iOS 16.4, macOS 13.3, tvOS 17.0, *)
@available(watchOS, unavailable)
public struct MenuControlGroupStyle : ControlGroupStyle {

/// Creates a menu control group style.
public init() { fatalError() }

/// Creates a view representing the body of a control group.
///
/// - Parameter configuration: The properties of the control group instance
/// being created.
///
/// This method will be called for each instance of ``ControlGroup`` created
/// within a view hierarchy where this style is the current
/// `ControlGroupStyle`.
@MainActor public func makeBody(configuration: MenuControlGroupStyle.Configuration) -> some View { return stubView() }


/// A view representing the body of a control group.
// public typealias Body = some View
}

/// The order in which a menu presents its content.
///
/// You can configure the preferred menu order using the
Expand Down
7 changes: 5 additions & 2 deletions Sources/SkipUI/SkipUI/Containers/Form.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
// under the terms of the GNU Lesser General Public License 3.0
// as published by the Free Software Foundation https://fsf.org

@available(*, unavailable)
public struct Form<Content> : View where Content : View {
@available(*, unavailable)
public init(@ViewBuilder content: () -> Content) {
}

Expand All @@ -23,12 +23,15 @@ public struct FormStyle: RawRepresentable, Equatable {
}

public static let automatic = FormStyle(rawValue: 0)

@available(*, unavailable)
public static let columns = FormStyle(rawValue: 1)

@available(*, unavailable)
public static let grouped = FormStyle(rawValue: 2)
}

extension View {
@available(*, unavailable)
public func formStyle(_ style: FormStyle) -> some View {
return self
}
Expand Down
26 changes: 0 additions & 26 deletions Sources/SkipUI/SkipUI/Containers/Navigation.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1315,32 +1315,6 @@ extension NavigationBarItem.TitleDisplayMode : Equatable {
extension NavigationBarItem.TitleDisplayMode : Hashable {
}

/// The navigation control group style.
///
/// You can also use ``ControlGroupStyle/navigation`` to construct this style.
@available(iOS 15.0, macOS 12.0, *)
@available(tvOS, unavailable)
@available(watchOS, unavailable)
public struct NavigationControlGroupStyle : ControlGroupStyle {

/// Creates a navigation control group style.
public init() { fatalError() }

/// Creates a view representing the body of a control group.
///
/// - Parameter configuration: The properties of the control group instance
/// being created.
///
/// This method will be called for each instance of ``ControlGroup`` created
/// within a view hierarchy where this style is the current
/// `ControlGroupStyle`.
@MainActor public func makeBody(configuration: NavigationControlGroupStyle.Configuration) -> some View { return stubView() }


/// A view representing the body of a control group.
// public typealias Body = some View
}

/// The default navigation view style.
///
/// You can also use ``NavigationViewStyle/automatic`` to construct this style.
Expand Down
16 changes: 16 additions & 0 deletions Sources/SkipUI/SkipUI/Containers/ScrollView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import androidx.compose.foundation.layout.Box
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
#else
import struct CoreGraphics.CGFloat
import struct CoreGraphics.CGRect
#endif

Expand Down Expand Up @@ -77,6 +78,21 @@ public struct ScrollTarget {
}

extension View {
@available(*, unavailable)
public func contentMargins(_ edges: Edge.Set = .all, _ insets: EdgeInsets, for placement: ContentMarginPlacement = .automatic) -> some View {
return self
}

@available(*, unavailable)
public func contentMargins(_ edges: Edge.Set = .all, _ length: CGFloat?, for placement: ContentMarginPlacement = .automatic) -> some View {
return self
}

@available(*, unavailable)
public func contentMargins(_ length: CGFloat, for placement: ContentMarginPlacement = .automatic) -> some View {
return self
}

@available(*, unavailable)
public func scrollBounceBehavior(_ behavior: ScrollBounceBehavior, axes: Axis.Set = [.vertical]) -> some View {
return self
Expand Down
4 changes: 3 additions & 1 deletion Sources/SkipUI/SkipUI/Containers/TabView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,8 @@ public struct TabViewStyle: RawRepresentable, Equatable {
}

public static let automatic = TabViewStyle(rawValue: 0)

@available(*, unavailable)
public static let page = TabViewStyle(rawValue: 1)
}

Expand All @@ -197,8 +199,8 @@ extension View {
#endif
}

@available(*, unavailable)
public func tabViewStyle(_ style: TabViewStyle) -> some View {
// We only support .automatic
return self
}
}
Expand Down
Loading

0 comments on commit 1d25a31

Please sign in to comment.