From 4b6866738d6efc2fb5cd3536dff972c651ce021b Mon Sep 17 00:00:00 2001 From: Carson Katri Date: Thu, 29 Jun 2023 14:26:54 -0400 Subject: [PATCH 1/4] Make BuiltinRegistry and ModifierContainer public --- .../BuiltinRegistryGenerator.swift | 2 +- Sources/LiveViewNative/ErrorModifier.swift | 4 ++-- Sources/LiveViewNative/Registries/BuiltinRegistry.swift | 4 ++-- Sources/LiveViewNative/ViewTree.swift | 8 ++++++-- 4 files changed, 11 insertions(+), 7 deletions(-) diff --git a/Sources/BuiltinRegistryGenerator/BuiltinRegistryGenerator.swift b/Sources/BuiltinRegistryGenerator/BuiltinRegistryGenerator.swift index 15a8625d3..02d487231 100644 --- a/Sources/BuiltinRegistryGenerator/BuiltinRegistryGenerator.swift +++ b/Sources/BuiltinRegistryGenerator/BuiltinRegistryGenerator.swift @@ -90,7 +90,7 @@ struct BuiltinRegistryGenerator: ParsableCommand { } } - extension BuiltinRegistry { + public extension BuiltinRegistry { enum ModifierType: String { \(modifierCases) } diff --git a/Sources/LiveViewNative/ErrorModifier.swift b/Sources/LiveViewNative/ErrorModifier.swift index e5509e5df..dc55c6b57 100644 --- a/Sources/LiveViewNative/ErrorModifier.swift +++ b/Sources/LiveViewNative/ErrorModifier.swift @@ -7,11 +7,11 @@ import SwiftUI -struct ErrorModifier: ViewModifier { +public struct ErrorModifier: ViewModifier { let type: String let error: any Error - func body(content: Content) -> some View { + public func body(content: Content) -> some View { content .overlay { ErrorView(error) diff --git a/Sources/LiveViewNative/Registries/BuiltinRegistry.swift b/Sources/LiveViewNative/Registries/BuiltinRegistry.swift index c9ca6f111..2318b6b47 100644 --- a/Sources/LiveViewNative/Registries/BuiltinRegistry.swift +++ b/Sources/LiveViewNative/Registries/BuiltinRegistry.swift @@ -10,13 +10,13 @@ import LiveViewNativeCore /// This protocol provides access to the `ViewModifier` type returned from `decodeModifier` in the `BuiltinRegistry`. /// That type is used by `ModifierContainer.builtin`. -protocol BuiltinRegistryProtocol { +public protocol BuiltinRegistryProtocol { associatedtype BuiltinModifier: ViewModifier associatedtype ModifierType: RawRepresentable where ModifierType.RawValue == String static func decodeModifier(_ type: ModifierType, from decoder: Decoder) throws -> BuiltinModifier } -struct BuiltinRegistry: BuiltinRegistryProtocol { +public struct BuiltinRegistry: BuiltinRegistryProtocol { static func lookup(_ name: String, _ element: ElementNode) -> some View { return BuiltinElement(name: name, element: element) } diff --git a/Sources/LiveViewNative/ViewTree.swift b/Sources/LiveViewNative/ViewTree.swift index ccc2c2280..0e779ea57 100644 --- a/Sources/LiveViewNative/ViewTree.swift +++ b/Sources/LiveViewNative/ViewTree.swift @@ -146,13 +146,13 @@ extension CodingUserInfoKey { static var modifierAnimationScale: Self { .init(rawValue: "modifierAnimationScale")! } } -enum ModifierContainer: Decodable { +public enum ModifierContainer: Decodable { case builtin(BuiltinRegistry.BuiltinModifier) case custom(R.CustomModifier) case error(ErrorModifier) case inert - init(from decoder: Decoder) throws { + public init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) let type = try container.decode(String.self, forKey: .type) if let type = R.ModifierType(rawValue: type) { @@ -260,6 +260,10 @@ extension View { ModifierObserver(parent: self) } + public func _applyModifiers(_ modifiers: ArraySlice>, element: ElementNode, context: LiveContext) -> some View { + applyModifiers(modifiers, element: element, context: context.storage) + } + @ViewBuilder func applyModifiers(_ modifiers: ArraySlice>, element: ElementNode, context: LiveContextStorage) -> some View { if modifiers.isEmpty { From 7b684e4c1334d63f0f8564ff845b89ee2bbf14dd Mon Sep 17 00:00:00 2001 From: Carson Katri Date: Thu, 29 Jun 2023 14:27:39 -0400 Subject: [PATCH 2/4] Revert "Make BuiltinRegistry and ModifierContainer public" This reverts commit 4b6866738d6efc2fb5cd3536dff972c651ce021b. --- .../BuiltinRegistryGenerator.swift | 2 +- Sources/LiveViewNative/ErrorModifier.swift | 4 ++-- Sources/LiveViewNative/Registries/BuiltinRegistry.swift | 4 ++-- Sources/LiveViewNative/ViewTree.swift | 8 ++------ 4 files changed, 7 insertions(+), 11 deletions(-) diff --git a/Sources/BuiltinRegistryGenerator/BuiltinRegistryGenerator.swift b/Sources/BuiltinRegistryGenerator/BuiltinRegistryGenerator.swift index 02d487231..15a8625d3 100644 --- a/Sources/BuiltinRegistryGenerator/BuiltinRegistryGenerator.swift +++ b/Sources/BuiltinRegistryGenerator/BuiltinRegistryGenerator.swift @@ -90,7 +90,7 @@ struct BuiltinRegistryGenerator: ParsableCommand { } } - public extension BuiltinRegistry { + extension BuiltinRegistry { enum ModifierType: String { \(modifierCases) } diff --git a/Sources/LiveViewNative/ErrorModifier.swift b/Sources/LiveViewNative/ErrorModifier.swift index dc55c6b57..e5509e5df 100644 --- a/Sources/LiveViewNative/ErrorModifier.swift +++ b/Sources/LiveViewNative/ErrorModifier.swift @@ -7,11 +7,11 @@ import SwiftUI -public struct ErrorModifier: ViewModifier { +struct ErrorModifier: ViewModifier { let type: String let error: any Error - public func body(content: Content) -> some View { + func body(content: Content) -> some View { content .overlay { ErrorView(error) diff --git a/Sources/LiveViewNative/Registries/BuiltinRegistry.swift b/Sources/LiveViewNative/Registries/BuiltinRegistry.swift index 2318b6b47..c9ca6f111 100644 --- a/Sources/LiveViewNative/Registries/BuiltinRegistry.swift +++ b/Sources/LiveViewNative/Registries/BuiltinRegistry.swift @@ -10,13 +10,13 @@ import LiveViewNativeCore /// This protocol provides access to the `ViewModifier` type returned from `decodeModifier` in the `BuiltinRegistry`. /// That type is used by `ModifierContainer.builtin`. -public protocol BuiltinRegistryProtocol { +protocol BuiltinRegistryProtocol { associatedtype BuiltinModifier: ViewModifier associatedtype ModifierType: RawRepresentable where ModifierType.RawValue == String static func decodeModifier(_ type: ModifierType, from decoder: Decoder) throws -> BuiltinModifier } -public struct BuiltinRegistry: BuiltinRegistryProtocol { +struct BuiltinRegistry: BuiltinRegistryProtocol { static func lookup(_ name: String, _ element: ElementNode) -> some View { return BuiltinElement(name: name, element: element) } diff --git a/Sources/LiveViewNative/ViewTree.swift b/Sources/LiveViewNative/ViewTree.swift index 0e779ea57..ccc2c2280 100644 --- a/Sources/LiveViewNative/ViewTree.swift +++ b/Sources/LiveViewNative/ViewTree.swift @@ -146,13 +146,13 @@ extension CodingUserInfoKey { static var modifierAnimationScale: Self { .init(rawValue: "modifierAnimationScale")! } } -public enum ModifierContainer: Decodable { +enum ModifierContainer: Decodable { case builtin(BuiltinRegistry.BuiltinModifier) case custom(R.CustomModifier) case error(ErrorModifier) case inert - public init(from decoder: Decoder) throws { + init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) let type = try container.decode(String.self, forKey: .type) if let type = R.ModifierType(rawValue: type) { @@ -260,10 +260,6 @@ extension View { ModifierObserver(parent: self) } - public func _applyModifiers(_ modifiers: ArraySlice>, element: ElementNode, context: LiveContext) -> some View { - applyModifiers(modifiers, element: element, context: context.storage) - } - @ViewBuilder func applyModifiers(_ modifiers: ArraySlice>, element: ElementNode, context: LiveContextStorage) -> some View { if modifiers.isEmpty { From 679c4d6f62dbc0b1987be8b04757b49b9ac69449 Mon Sep 17 00:00:00 2001 From: Carson Katri Date: Thu, 29 Jun 2023 14:34:45 -0400 Subject: [PATCH 3/4] Add public `_ModifierStack` type --- Sources/LiveViewNative/ModifierStack.swift | 28 +++++++++++++++++++ .../types/modifier_stack.ex | 7 +++++ 2 files changed, 35 insertions(+) create mode 100644 Sources/LiveViewNative/ModifierStack.swift create mode 100644 lib/live_view_native_swift_ui/types/modifier_stack.ex diff --git a/Sources/LiveViewNative/ModifierStack.swift b/Sources/LiveViewNative/ModifierStack.swift new file mode 100644 index 000000000..b44fa64e5 --- /dev/null +++ b/Sources/LiveViewNative/ModifierStack.swift @@ -0,0 +1,28 @@ +// +// ModifierStack.swift +// +// +// Created by Carson Katri on 6/29/23. +// + +import SwiftUI + +/// A container that decodes a modifier stack. +/// +/// Use ``apply(to:)`` to use the modifier stack on a View. +public struct _ModifierStack: Decodable { + private let stack: [ModifierContainer] + + @ObservedElement private var element + @LiveContext private var context + + public init(from decoder: Decoder) throws { + let container = try decoder.singleValueContainer() + self.stack = try container.decode([ModifierContainer].self) + } + + public func apply(to content: some View) -> some View { + content + .applyModifiers(stack[...], element: element, context: context.storage) + } +} diff --git a/lib/live_view_native_swift_ui/types/modifier_stack.ex b/lib/live_view_native_swift_ui/types/modifier_stack.ex new file mode 100644 index 000000000..093c0ce4d --- /dev/null +++ b/lib/live_view_native_swift_ui/types/modifier_stack.ex @@ -0,0 +1,7 @@ +defmodule LiveViewNativeSwiftUi.Types.ModifierStack do + use LiveViewNativePlatform.Modifier.Type + def type, do: :map + + def cast(%LiveViewNativeSwiftUi.Modifiers{} = value), do: {:ok, Jason.decode!(Jason.encode!(value))} + def cast(_), do: :error +end From 4933a52d47ad541af0b0883e66806e738ca4a923 Mon Sep 17 00:00:00 2001 From: Carson Katri Date: Thu, 29 Jun 2023 14:44:20 -0400 Subject: [PATCH 4/4] Convert to ViewModifier --- Sources/LiveViewNative/ModifierStack.swift | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/Sources/LiveViewNative/ModifierStack.swift b/Sources/LiveViewNative/ModifierStack.swift index b44fa64e5..229c91aad 100644 --- a/Sources/LiveViewNative/ModifierStack.swift +++ b/Sources/LiveViewNative/ModifierStack.swift @@ -9,8 +9,13 @@ import SwiftUI /// A container that decodes a modifier stack. /// -/// Use ``apply(to:)`` to use the modifier stack on a View. -public struct _ModifierStack: Decodable { +/// Use this as a modifier: +/// +/// ```swift +/// content +/// .modifier(modifierStack) +/// ``` +public struct _ModifierStack: Decodable, ViewModifier { private let stack: [ModifierContainer] @ObservedElement private var element @@ -21,7 +26,7 @@ public struct _ModifierStack: Decodable { self.stack = try container.decode([ModifierContainer].self) } - public func apply(to content: some View) -> some View { + public func body(content: Content) -> some View { content .applyModifiers(stack[...], element: element, context: context.storage) }