Make widget data more flexible

This commit is contained in:
david-swift 2024-08-15 10:44:43 +02:00
parent 7b26dce977
commit 4e205397ca
14 changed files with 153 additions and 103 deletions

View File

@ -78,10 +78,10 @@ public struct VStack: Wrapper, TermKitWidget {
} }
public func container<Data>( public func container<Data>(
modifiers: [(any AnyView) -> any AnyView], data: WidgetData,
type: Data.Type type: Data.Type
) -> ViewStorage where Data: ViewRenderData { ) -> ViewStorage where Data: ViewRenderData {
let storages = content.storages(modifiers: modifiers, type: type) // Get the storages of child views let storages = content.storages(data: data, type: type) // Get the storages of child views
if storages.count == 1 { if storages.count == 1 {
return .init(storages[0].pointer, content: [.mainContent: storages]) return .init(storages[0].pointer, content: [.mainContent: storages])
} }
@ -99,14 +99,14 @@ public struct VStack: Wrapper, TermKitWidget {
public func update<Data>( public func update<Data>(
_ storage: ViewStorage, _ storage: ViewStorage,
modifiers: [(any AnyView) -> any AnyView], data: WidgetData,
updateProperties: Bool, updateProperties: Bool,
type: Data.Type type: Data.Type
) where Data: ViewRenderData { ) where Data: ViewRenderData {
guard let storages = storage.content[.mainContent] else { guard let storages = storage.content[.mainContent] else {
return return
} }
content.update(storages, modifiers: modifiers, updateProperties: updateProperties, type: type) // Update the storages of child views content.update(storages, data: data, updateProperties: updateProperties, type: type) // Update the storages of child views
} }
} }
@ -123,7 +123,7 @@ It indicates that a state variable (see <doc:StateConcept>) of an ancestor view
If state doesn't change, it is impossible for the UI to change. If state doesn't change, it is impossible for the UI to change.
However, consider the following exceptions: However, consider the following exceptions:
- _Always_ update view content (using ``AnyView/updateStorage(_:modifiers:updateProperties:type:)`` or ``Swift/Array/storages(modifiers:type:)``). Child views may contain own state. - _Always_ update view content (using ``AnyView/updateStorage(_:data:updateProperties:type:)`` or ``Swift/Array/storages(data:type:)``). Child views may contain own state.
- _Always_ update closures (such as the action of a button widget). They may contain reference to state which is updated whenever a view update takes place. - _Always_ update closures (such as the action of a button widget). They may contain reference to state which is updated whenever a view update takes place.
- _Always_ update bindings. As one can see when looking at ``Binding/init(get:set:)``, they contain two closures which, in most cases, contain a reference to state. - _Always_ update bindings. As one can see when looking at ``Binding/init(get:set:)``, they contain two closures which, in most cases, contain a reference to state.

View File

@ -14,19 +14,19 @@ extension Array: AnyView where Element == AnyView {
/// Get a widget from a collection of views. /// Get a widget from a collection of views.
/// - Parameters: /// - Parameters:
/// - modifiers: Modify views before being updated. /// - data: Modify views before being updated.
/// - type: The app storage type. /// - type: The app storage type.
/// - Returns: A widget. /// - Returns: A widget.
public func widget<Data>( public func widget<Data>(
modifiers: [(AnyView) -> AnyView], data: WidgetData,
type: Data.Type type: Data.Type
) -> Widget where Data: ViewRenderData { ) -> Widget where Data: ViewRenderData {
if count == 1, let widget = self[safe: 0]?.widget(modifiers: modifiers, type: type) { if count == 1, let widget = self[safe: 0]?.widget(data: data, type: type) {
return widget return widget
} else { } else {
var modified = self var modified = self
for (index, view) in modified.enumerated() { for (index, view) in modified.enumerated() {
modified[safe: index] = view.getModified(modifiers: modifiers, type: type) modified[safe: index] = view.getModified(data: data, type: type)
} }
return Data.WrapperType { modified } return Data.WrapperType { modified }
} }
@ -35,35 +35,35 @@ extension Array: AnyView where Element == AnyView {
/// Update a collection of views with a collection of view storages. /// Update a collection of views with a collection of view storages.
/// - Parameters: /// - Parameters:
/// - storages: The collection of view storages. /// - storages: The collection of view storages.
/// - modifiers: Modify views before being updated. /// - data: Modify views before being updated.
/// - updateProperties: Whether to update properties. /// - updateProperties: Whether to update properties.
/// - type: The type of the app storage. /// - type: The type of the app storage.
public func update<Data>( public func update<Data>(
_ storages: [ViewStorage], _ storages: [ViewStorage],
modifiers: [(AnyView) -> AnyView], data: WidgetData,
updateProperties: Bool, updateProperties: Bool,
type: Data.Type type: Data.Type
) where Data: ViewRenderData { ) where Data: ViewRenderData {
for (index, element) in filter({ $0.renderable(type: type, modifiers: modifiers) }).enumerated() { for (index, element) in filter({ $0.renderable(type: type, data: data) }).enumerated() {
if let storage = storages[safe: index] { if let storage = storages[safe: index] {
element element
.widget(modifiers: modifiers, type: type) .widget(data: data, type: type)
.updateStorage(storage, modifiers: modifiers, updateProperties: updateProperties, type: type) .updateStorage(storage, data: data, updateProperties: updateProperties, type: type)
} }
} }
} }
/// Get the view storages of a collection of views. /// Get the view storages of a collection of views.
/// - Parameters: /// - Parameters:
/// - modifiers: Modify views before generating the storages. /// - data: Modify views before generating the storages.
/// - type: The type of the app storage. /// - type: The type of the app storage.
/// - Returns: The storages. /// - Returns: The storages.
public func storages<Data>( public func storages<Data>(
modifiers: [(AnyView) -> AnyView], data: WidgetData,
type: Data.Type type: Data.Type
) -> [ViewStorage] where Data: ViewRenderData { ) -> [ViewStorage] where Data: ViewRenderData {
compactMap { view in compactMap { view in
view.renderable(type: type, modifiers: modifiers) ? view.storage(modifiers: modifiers, type: type) : nil view.renderable(type: type, data: data) ? view.storage(data: data, type: type) : nil
} }
} }

View File

@ -15,9 +15,9 @@ public protocol AnyView {
extension AnyView { extension AnyView {
func getModified<Data>(modifiers: [(AnyView) -> AnyView], type: Data.Type) -> AnyView where Data: ViewRenderData { func getModified<Data>(data: WidgetData, type: Data.Type) -> AnyView where Data: ViewRenderData {
var modified: AnyView = self var modified: AnyView = self
for modifier in modifiers { for modifier in data.modifiers {
modified = modifier(modified) modified = modifier(modified)
} }
return modified return modified
@ -26,48 +26,48 @@ extension AnyView {
/// Update a storage to a view. /// Update a storage to a view.
/// - Parameters: /// - Parameters:
/// - storage: The storage. /// - storage: The storage.
/// - modifiers: Modify views before being updated. /// - data: Modify views before being updated.
/// - updateProperties: Whether to update properties. /// - updateProperties: Whether to update properties.
/// - type: The type of the app storage. /// - type: The type of the app storage.
public func updateStorage<Data>( public func updateStorage<Data>(
_ storage: ViewStorage, _ storage: ViewStorage,
modifiers: [(AnyView) -> AnyView], data: WidgetData,
updateProperties: Bool, updateProperties: Bool,
type: Data.Type type: Data.Type
) where Data: ViewRenderData { ) where Data: ViewRenderData {
widget(modifiers: modifiers, type: type) widget(data: data, type: type)
.update(storage, modifiers: modifiers, updateProperties: updateProperties, type: type) .update(storage, data: data, updateProperties: updateProperties, type: type)
} }
/// Get a storage. /// Get a storage.
/// - Parameters: /// - Parameters:
/// - modifiers: Modify views before being updated. /// - data: Modify views before being updated.
/// - type: The widget types. /// - type: The widget types.
/// - Returns: The storage. /// - Returns: The storage.
public func storage<Data>( public func storage<Data>(
modifiers: [(AnyView) -> AnyView], data: WidgetData,
type: Data.Type type: Data.Type
) -> ViewStorage where Data: ViewRenderData { ) -> ViewStorage where Data: ViewRenderData {
widget(modifiers: modifiers, type: type).container(modifiers: modifiers, type: type) widget(data: data, type: type).container(data: data, type: type)
} }
/// Wrap the view into a widget. /// Wrap the view into a widget.
/// - Parameter modifiers: Modify views before being updated. /// - Parameter data: Modify views before being updated.
/// - Returns: The widget. /// - Returns: The widget.
func widget<Data>(modifiers: [(AnyView) -> AnyView], type: Data.Type) -> Widget where Data: ViewRenderData { func widget<Data>(data: WidgetData, type: Data.Type) -> Widget where Data: ViewRenderData {
let modified = getModified(modifiers: modifiers, type: type) let modified = getModified(data: data, type: type)
if let peer = modified as? Widget { if let peer = modified as? Widget {
return peer return peer
} }
if let array = modified as? Body { if let array = modified as? Body {
return Data.WrapperType { array } return Data.WrapperType { array }
} }
return Data.WrapperType { viewContent.map { $0.getModified(modifiers: modifiers, type: type) } } return Data.WrapperType { viewContent.map { $0.getModified(data: data, type: type) } }
} }
/// Whether the view can be rendered in a certain environment. /// Whether the view can be rendered in a certain environment.
func renderable<Data>(type: Data.Type, modifiers: [(AnyView) -> AnyView]) -> Bool where Data: ViewRenderData { func renderable<Data>(type: Data.Type, data: WidgetData) -> Bool where Data: ViewRenderData {
let result = getModified(modifiers: modifiers, type: type) let result = getModified(data: data, type: type)
return result as? Data.WidgetType != nil return result as? Data.WidgetType != nil
|| result as? SimpleView != nil || result as? SimpleView != nil
|| result as? View != nil || result as? View != nil

View File

@ -13,23 +13,23 @@ public protocol Widget: AnyView {
/// The view storage. /// The view storage.
/// - Parameters: /// - Parameters:
/// - modifiers: Modify views before being updated. /// - data: Modify views before being updated.
/// - type: The type of the app storage. /// - type: The type of the app storage.
/// - Returns: The view storage. /// - Returns: The view storage.
func container<Data>( func container<Data>(
modifiers: [(AnyView) -> AnyView], data: WidgetData,
type: Data.Type type: Data.Type
) -> ViewStorage where Data: ViewRenderData ) -> ViewStorage where Data: ViewRenderData
/// Update the stored content. /// Update the stored content.
/// - Parameters: /// - Parameters:
/// - storage: The storage to update. /// - storage: The storage to update.
/// - modifiers: Modify views before being updated /// - data: Modify views before being updated
/// - updateProperties: Whether to update the view's properties. /// - updateProperties: Whether to update the view's properties.
/// - type: The type of the app storage. /// - type: The type of the app storage.
func update<Data>( func update<Data>(
_ storage: ViewStorage, _ storage: ViewStorage,
modifiers: [(AnyView) -> AnyView], data: WidgetData,
updateProperties: Bool, updateProperties: Bool,
type: Data.Type type: Data.Type
) where Data: ViewRenderData ) where Data: ViewRenderData

View File

@ -0,0 +1,43 @@
//
// WidgetData.swift
// Meta
//
// Created by david-swift on 15.08.24.
//
/// Data passed to widgets when initializing or updating the container.
public struct WidgetData {
/// The view modifiers.
public var modifiers: [(AnyView) -> AnyView] = []
/// The scene storage of the parent scene element.
public var sceneStorage: SceneStorage
/// The app storage of the parent app.
public var appStorage: any AppStorage
/// Fields for custom data.
public var fields: [String: Any] = [:]
/// Modify the data so that there are no modifiers.
public var noModifiers: Self {
modify { $0.modifiers = [] }
}
/// Initialize widget data.
/// - Parameters:
/// - sceneStorage: The storage of the parent scene element.
/// - appStorage: The storage of the parent app.
public init(sceneStorage: SceneStorage, appStorage: any AppStorage) {
self.sceneStorage = sceneStorage
self.appStorage = appStorage
}
/// Modify the widget data.
/// - Parameter action: The modification action.
/// - Returns: The data.
public func modify(action: (inout Self) -> Void) -> Self {
var newSelf = self
action(&newSelf)
return newSelf
}
}

View File

@ -15,14 +15,14 @@ struct AppearObserver: ConvenienceWidget {
/// The view storage. /// The view storage.
/// - Parameters: /// - Parameters:
/// - modifiers: Modify views before being updated. /// - data: Modify views before being updated.
/// - type: The type of the app storage. /// - type: The type of the app storage.
/// - Returns: The view storage. /// - Returns: The view storage.
func container<Data>( func container<Data>(
modifiers: [(any AnyView) -> any AnyView], data: WidgetData,
type: Data.Type type: Data.Type
) -> ViewStorage where Data: ViewRenderData { ) -> ViewStorage where Data: ViewRenderData {
let storage = content.storage(modifiers: modifiers, type: type) let storage = content.storage(data: data, type: type)
modify(storage) modify(storage)
return storage return storage
} }
@ -30,16 +30,16 @@ struct AppearObserver: ConvenienceWidget {
/// Update the stored content. /// Update the stored content.
/// - Parameters: /// - Parameters:
/// - storage: The storage to update. /// - storage: The storage to update.
/// - modifiers: Modify views before being updated /// - data: Modify views before being updated
/// - updateProperties: Whether to update the view's properties. /// - updateProperties: Whether to update the view's properties.
/// - type: The type of the app storage. /// - type: The type of the app storage.
func update<Data>( func update<Data>(
_ storage: ViewStorage, _ storage: ViewStorage,
modifiers: [(any AnyView) -> any AnyView], data: WidgetData,
updateProperties: Bool, updateProperties: Bool,
type: Data.Type type: Data.Type
) where Data: ViewRenderData { ) where Data: ViewRenderData {
content.updateStorage(storage, modifiers: modifiers, updateProperties: updateProperties, type: type) content.updateStorage(storage, data: data, updateProperties: updateProperties, type: type)
} }
} }

View File

@ -15,30 +15,35 @@ struct ContentModifier<Content>: ConvenienceWidget where Content: AnyView {
/// The view storage. /// The view storage.
/// - Parameters: /// - Parameters:
/// - modifiers: Modify views before being updated. /// - data: Modify views before being updated.
/// - type: The type of the app storage. /// - type: The type of the app storage.
/// - Returns: The view storage. /// - Returns: The view storage.
func container<Data>( func container<Data>(
modifiers: [(any AnyView) -> any AnyView], data: WidgetData,
type: Data.Type type: Data.Type
) -> ViewStorage where Data: ViewRenderData { ) -> ViewStorage where Data: ViewRenderData {
content.storage(modifiers: modifiers + [modifyView], type: type) content.storage(data: data.modify { $0.modifiers += [modifyView] }, type: type)
} }
/// Update the stored content. /// Update the stored content.
/// - Parameters: /// - Parameters:
/// - storage: The storage to update. /// - storage: The storage to update.
/// - modifiers: Modify views before being updated /// - data: Modify views before being updated
/// - updateProperties: Whether to update the view's properties. /// - updateProperties: Whether to update the view's properties.
/// - type: The type of the app storage. /// - type: The type of the app storage.
func update<Data>( func update<Data>(
_ storage: ViewStorage, _ storage: ViewStorage,
modifiers: [(any AnyView) -> any AnyView], data: WidgetData,
updateProperties: Bool, updateProperties: Bool,
type: Data.Type type: Data.Type
) where Data: ViewRenderData { ) where Data: ViewRenderData {
content content
.updateStorage(storage, modifiers: modifiers + [modifyView], updateProperties: updateProperties, type: type) .updateStorage(
storage,
data: data.modify { $0.modifiers += [modifyView] },
updateProperties: updateProperties,
type: type
)
} }
/// Apply the modifier to a view. /// Apply the modifier to a view.

View File

@ -17,32 +17,32 @@ struct DummyEitherView: Widget {
/// The view storage. /// The view storage.
/// - Parameters: /// - Parameters:
/// - modifiers: Modify views before being updated. /// - data: Modify views before being updated.
/// - type: The type of the app storage. /// - type: The type of the app storage.
/// - Returns: The view storage. /// - Returns: The view storage.
func container<Data>( func container<Data>(
modifiers: [(any AnyView) -> any AnyView], data: WidgetData,
type: Data.Type type: Data.Type
) -> ViewStorage where Data: ViewRenderData { ) -> ViewStorage where Data: ViewRenderData {
let content = type.EitherViewType(condition) { view1 ?? [] } else: { view2 ?? [] } let content = type.EitherViewType(condition) { view1 ?? [] } else: { view2 ?? [] }
let storage = content.storage(modifiers: modifiers, type: type) let storage = content.storage(data: data, type: type)
return storage return storage
} }
/// Update the stored content. /// Update the stored content.
/// - Parameters: /// - Parameters:
/// - storage: The storage to update. /// - storage: The storage to update.
/// - modifiers: Modify views before being updated /// - data: Modify views before being updated
/// - updateProperties: Whether to update the view's properties. /// - updateProperties: Whether to update the view's properties.
/// - type: The type of the app storage. /// - type: The type of the app storage.
func update<Data>( func update<Data>(
_ storage: ViewStorage, _ storage: ViewStorage,
modifiers: [(any AnyView) -> any AnyView], data: WidgetData,
updateProperties: Bool, updateProperties: Bool,
type: Data.Type type: Data.Type
) where Data: ViewRenderData { ) where Data: ViewRenderData {
let content = type.EitherViewType(condition) { view1 ?? [] } else: { view2 ?? [] } let content = type.EitherViewType(condition) { view1 ?? [] } else: { view2 ?? [] }
content.updateStorage(storage, modifiers: modifiers, updateProperties: updateProperties, type: type) content.updateStorage(storage, data: data, updateProperties: updateProperties, type: type)
} }
} }

View File

@ -15,32 +15,32 @@ struct Freeze: ConvenienceWidget {
/// The view storage. /// The view storage.
/// - Parameters: /// - Parameters:
/// - modifiers: Modify views before being updated. /// - data: Modify views before being updated.
/// - type: The type of the app storage. /// - type: The type of the app storage.
/// - Returns: The view storage. /// - Returns: The view storage.
func container<Data>( func container<Data>(
modifiers: [(any AnyView) -> any AnyView], data: WidgetData,
type: Data.Type type: Data.Type
) -> ViewStorage where Data: ViewRenderData { ) -> ViewStorage where Data: ViewRenderData {
content.storage(modifiers: modifiers, type: type) content.storage(data: data, type: type)
} }
/// Update the stored content. /// Update the stored content.
/// - Parameters: /// - Parameters:
/// - storage: The storage to update. /// - storage: The storage to update.
/// - modifiers: Modify views before being updated /// - data: Modify views before being updated
/// - updateProperties: Whether to update the view's properties. /// - updateProperties: Whether to update the view's properties.
/// - type: The type of the app storage. /// - type: The type of the app storage.
func update<Data>( func update<Data>(
_ storage: ViewStorage, _ storage: ViewStorage,
modifiers: [(any AnyView) -> any AnyView], data: WidgetData,
updateProperties: Bool, updateProperties: Bool,
type: Data.Type type: Data.Type
) where Data: ViewRenderData { ) where Data: ViewRenderData {
guard !freeze else { guard !freeze else {
return return
} }
content.updateStorage(storage, modifiers: modifiers, updateProperties: updateProperties, type: type) content.updateStorage(storage, data: data, updateProperties: updateProperties, type: type)
} }
} }

View File

@ -15,14 +15,14 @@ struct InspectorWrapper: ConvenienceWidget {
/// The view storage. /// The view storage.
/// - Parameters: /// - Parameters:
/// - modifiers: Modify views before being updated. /// - data: Modify views before being updated.
/// - type: The type of the app storage. /// - type: The type of the app storage.
/// - Returns: The view storage. /// - Returns: The view storage.
func container<Data>( func container<Data>(
modifiers: [(any AnyView) -> any AnyView], data: WidgetData,
type: Data.Type type: Data.Type
) -> ViewStorage where Data: ViewRenderData { ) -> ViewStorage where Data: ViewRenderData {
let storage = content.storage(modifiers: modifiers, type: type) let storage = content.storage(data: data, type: type)
modify(storage, true) modify(storage, true)
return storage return storage
} }
@ -30,16 +30,16 @@ struct InspectorWrapper: ConvenienceWidget {
/// Update the stored content. /// Update the stored content.
/// - Parameters: /// - Parameters:
/// - storage: The storage to update. /// - storage: The storage to update.
/// - modifiers: Modify views before being updated /// - data: Modify views before being updated
/// - updateProperties: Whether to update the view's properties. /// - updateProperties: Whether to update the view's properties.
/// - type: The type of the app storage. /// - type: The type of the app storage.
func update<Data>( func update<Data>(
_ storage: ViewStorage, _ storage: ViewStorage,
modifiers: [(any AnyView) -> any AnyView], data: WidgetData,
updateProperties: Bool, updateProperties: Bool,
type: Data.Type type: Data.Type
) where Data: ViewRenderData { ) where Data: ViewRenderData {
content.updateStorage(storage, modifiers: modifiers, updateProperties: updateProperties, type: type) content.updateStorage(storage, data: data, updateProperties: updateProperties, type: type)
modify(storage, updateProperties) modify(storage, updateProperties)
} }

View File

@ -5,7 +5,7 @@
// Created by david-swift on 29.06.24. // Created by david-swift on 29.06.24.
// //
/// Remove all of the content modifiers for the wrapped views. /// Remove all of the content data for the wrapped views.
struct ModifierStopper: ConvenienceWidget { struct ModifierStopper: ConvenienceWidget {
/// The wrapped view. /// The wrapped view.
@ -13,36 +13,36 @@ struct ModifierStopper: ConvenienceWidget {
/// The view storage. /// The view storage.
/// - Parameters: /// - Parameters:
/// - modifiers: Modify views before being updated. /// - data: Modify views before being updated.
/// - type: The type of the app storage. /// - type: The type of the app storage.
/// - Returns: The view storage. /// - Returns: The view storage.
func container<Data>( func container<Data>(
modifiers: [(any AnyView) -> any AnyView], data: WidgetData,
type: Data.Type type: Data.Type
) -> ViewStorage where Data: ViewRenderData { ) -> ViewStorage where Data: ViewRenderData {
content.storage(modifiers: [], type: type) content.storage(data: data.noModifiers, type: type)
} }
/// Update the stored content. /// Update the stored content.
/// - Parameters: /// - Parameters:
/// - storage: The storage to update. /// - storage: The storage to update.
/// - modifiers: Modify views before being updated /// - data: Modify views before being updated
/// - updateProperties: Whether to update the view's properties. /// - updateProperties: Whether to update the view's properties.
/// - type: The type of the app storage. /// - type: The type of the app storage.
func update<Data>( func update<Data>(
_ storage: ViewStorage, _ storage: ViewStorage,
modifiers: [(any AnyView) -> any AnyView], data: WidgetData,
updateProperties: Bool, updateProperties: Bool,
type: Data.Type type: Data.Type
) where Data: ViewRenderData { ) where Data: ViewRenderData {
content.updateStorage(storage, modifiers: [], updateProperties: updateProperties, type: type) content.updateStorage(storage, data: data.noModifiers, updateProperties: updateProperties, type: type)
} }
} }
extension AnyView { extension AnyView {
/// Remove all of the content modifiers for the wrapped views. /// Remove all of the content data for the wrapped views.
/// - Returns: A view. /// - Returns: A view.
public func stopModifiers() -> AnyView { public func stopModifiers() -> AnyView {
ModifierStopper(content: self) ModifierStopper(content: self)

View File

@ -31,13 +31,13 @@ struct StateWrapper: ConvenienceWidget {
/// Update a view storage. /// Update a view storage.
/// - Parameters: /// - Parameters:
/// - storage: The view storage. /// - storage: The view storage.
/// - modifiers: Modify views before being updated. /// - data: Modify views before being updated.
/// - updateProperties: Whether to update properties. /// - updateProperties: Whether to update properties.
/// - type: The type of the app storage. /// - type: The type of the app storage.
/// - Returns: The view storage. /// - Returns: The view storage.
func update<Data>( func update<Data>(
_ storage: ViewStorage, _ storage: ViewStorage,
modifiers: [(AnyView) -> AnyView], data: WidgetData,
updateProperties: Bool, updateProperties: Bool,
type: Data.Type type: Data.Type
) where Data: ViewRenderData { ) where Data: ViewRenderData {
@ -54,19 +54,19 @@ struct StateWrapper: ConvenienceWidget {
guard let storage = storage.content[.mainContent]?.first else { guard let storage = storage.content[.mainContent]?.first else {
return return
} }
content().updateStorage(storage, modifiers: modifiers, updateProperties: updateProperties, type: type) content().updateStorage(storage, data: data, updateProperties: updateProperties, type: type)
} }
/// Get a view storage. /// Get a view storage.
/// - Parameters: /// - Parameters:
/// - modifiers: Modify views before being updated. /// - data: Modify views before being updated.
/// - type: The type of the app storage. /// - type: The type of the app storage.
/// - Returns: The view storage. /// - Returns: The view storage.
func container<Data>( func container<Data>(
modifiers: [(AnyView) -> AnyView], data: WidgetData,
type: Data.Type type: Data.Type
) -> ViewStorage where Data: ViewRenderData { ) -> ViewStorage where Data: ViewRenderData {
let content = content().storage(modifiers: modifiers, type: type) let content = content().storage(data: data, type: type)
let storage = ViewStorage(content.pointer, content: [.mainContent: [content]]) let storage = ViewStorage(content.pointer, content: [.mainContent: [content]])
storage.state = state storage.state = state
return storage return storage

View File

@ -6,14 +6,14 @@ public enum Backend1 {
public init() { } public init() { }
public func container<Data>(modifiers: [(AnyView) -> AnyView], type: Data.Type) -> ViewStorage where Data: ViewRenderData { public func container<Data>(data: WidgetData, type: Data.Type) -> ViewStorage where Data: ViewRenderData {
print("Init test widget 1") print("Init test widget 1")
let storage = ViewStorage(nil) let storage = ViewStorage(nil)
storage.fields["test"] = 0 storage.fields["test"] = 0
return storage return storage
} }
public func update<Data>(_ storage: ViewStorage, modifiers: [(AnyView) -> AnyView], updateProperties: Bool, type: Data.Type) { public func update<Data>(_ storage: ViewStorage, data: WidgetData, updateProperties: Bool, type: Data.Type) {
print("Update test widget 1 (#\(storage.fields["test"] ?? ""))") print("Update test widget 1 (#\(storage.fields["test"] ?? ""))")
storage.fields["test"] = (storage.fields["test"] as? Int ?? 0) + 1 storage.fields["test"] = (storage.fields["test"] as? Int ?? 0) + 1
} }
@ -24,14 +24,14 @@ public enum Backend1 {
public init() { } public init() { }
public func container<Data>(modifiers: [(AnyView) -> AnyView], type: Data.Type) -> ViewStorage where Data: ViewRenderData { public func container<Data>(data: WidgetData, type: Data.Type) -> ViewStorage where Data: ViewRenderData {
print("Init test widget 3") print("Init test widget 3")
let storage = ViewStorage(nil) let storage = ViewStorage(nil)
storage.fields["test"] = 0 storage.fields["test"] = 0
return storage return storage
} }
public func update<Data>(_ storage: ViewStorage, modifiers: [(AnyView) -> AnyView], updateProperties: Bool, type: Data.Type) { public func update<Data>(_ storage: ViewStorage, data: WidgetData, updateProperties: Bool, type: Data.Type) {
print("Update test widget 3 (#\(storage.fields["test"] ?? ""))") print("Update test widget 3 (#\(storage.fields["test"] ?? ""))")
storage.fields["test"] = (storage.fields["test"] as? Int ?? 0) + 1 storage.fields["test"] = (storage.fields["test"] as? Int ?? 0) + 1
} }
@ -48,7 +48,7 @@ public enum Backend1 {
self.action = action self.action = action
} }
public func container<Data>(modifiers: [(any AnyView) -> any AnyView], type: Data.Type) -> ViewStorage where Data: ViewRenderData { public func container<Data>(data: WidgetData, type: Data.Type) -> ViewStorage where Data: ViewRenderData {
print("Init button") print("Init button")
let storage = ViewStorage(nil) let storage = ViewStorage(nil)
Task { Task {
@ -59,7 +59,7 @@ public enum Backend1 {
return storage return storage
} }
public func update<Data>(_ storage: ViewStorage, modifiers: [(any AnyView) -> any AnyView], updateProperties: Bool, type: Data.Type) { public func update<Data>(_ storage: ViewStorage, data: WidgetData, updateProperties: Bool, type: Data.Type) {
storage.fields["action"] = action storage.fields["action"] = action
if updateProperties { if updateProperties {
if (storage.previousState as? Self)?.label != label { if (storage.previousState as? Self)?.label != label {
@ -92,10 +92,12 @@ public enum Backend1 {
public func container<Storage>(app: Storage) -> SceneStorage where Storage: AppStorage { public func container<Storage>(app: Storage) -> SceneStorage where Storage: AppStorage {
print("Show \(id)") print("Show \(id)")
let viewStorage = content.storage(modifiers: [], type: MainViewRenderData.self) let storage = SceneStorage(id: id, pointer: nil) {
return .init(id: id, pointer: nil, content: [.mainContent : [viewStorage]]) {
print("Make visible") print("Make visible")
} }
let viewStorage = content.storage(data: .init(sceneStorage: storage, appStorage: app), type: MainViewRenderData.self)
storage.content[.mainContent] = [viewStorage]
return storage
} }
public func update<Storage>(_ storage: SceneStorage, app: Storage, updateProperties: Bool) where Storage: AppStorage { public func update<Storage>(_ storage: SceneStorage, app: Storage, updateProperties: Bool) where Storage: AppStorage {
@ -103,7 +105,7 @@ public enum Backend1 {
guard let viewStorage = storage.content[.mainContent]?.first else { guard let viewStorage = storage.content[.mainContent]?.first else {
return return
} }
content.updateStorage(viewStorage, modifiers: [], updateProperties: updateProperties, type: MainViewRenderData.self) content.updateStorage(viewStorage, data: .init(sceneStorage: storage, appStorage: app), updateProperties: updateProperties, type: MainViewRenderData.self)
} }
} }
@ -116,17 +118,17 @@ public enum Backend1 {
self.content = content() self.content = content()
} }
public func container<Data>(modifiers: [(any Meta.AnyView) -> any Meta.AnyView], type: Data.Type) -> Meta.ViewStorage where Data: ViewRenderData { public func container<Data>(data: WidgetData, type: Data.Type) -> Meta.ViewStorage where Data: ViewRenderData {
let storage = ViewStorage(nil) let storage = ViewStorage(nil)
storage.content = [.mainContent: content.storages(modifiers: modifiers, type: type)] storage.content = [.mainContent: content.storages(data: data, type: type)]
return storage return storage
} }
public func update<Data>(_ storage: Meta.ViewStorage, modifiers: [(any Meta.AnyView) -> any Meta.AnyView], updateProperties: Bool, type: Data.Type) where Data: ViewRenderData { public func update<Data>(_ storage: Meta.ViewStorage, data: WidgetData, updateProperties: Bool, type: Data.Type) where Data: ViewRenderData {
guard let storages = storage.content[.mainContent] else { guard let storages = storage.content[.mainContent] else {
return return
} }
content.update(storages, modifiers: modifiers, updateProperties: updateProperties, type: type) content.update(storages, data: data, updateProperties: updateProperties, type: type)
} }
} }
@ -136,11 +138,11 @@ public enum Backend1 {
public init(_ condition: Bool, view1: () -> Body, else view2: () -> Body) { public init(_ condition: Bool, view1: () -> Body, else view2: () -> Body) {
} }
public func container<Data>(modifiers: [(any AnyView) -> any AnyView], type: Data.Type) -> ViewStorage where Data : ViewRenderData { public func container<Data>(data: WidgetData, type: Data.Type) -> ViewStorage where Data : ViewRenderData {
.init(nil) .init(nil)
} }
public func update<Data>(_ storage: ViewStorage, modifiers: [(any AnyView) -> any AnyView], updateProperties: Bool, type: Data.Type) where Data : ViewRenderData { public func update<Data>(_ storage: ViewStorage, data: WidgetData, updateProperties: Bool, type: Data.Type) where Data : ViewRenderData {
} }
} }

View File

@ -6,14 +6,14 @@ public enum Backend2 {
public init() { } public init() { }
public func container<Data>(modifiers: [(AnyView) -> AnyView], type: Data.Type) -> ViewStorage where Data: ViewRenderData { public func container<Data>(data: WidgetData, type: Data.Type) -> ViewStorage where Data: ViewRenderData {
print("Init test widget 2") print("Init test widget 2")
let storage = ViewStorage(nil) let storage = ViewStorage(nil)
storage.fields["test"] = 0 storage.fields["test"] = 0
return storage return storage
} }
public func update<Data>(_ storage: ViewStorage, modifiers: [(AnyView) -> AnyView], updateProperties: Bool, type: Data.Type) { public func update<Data>(_ storage: ViewStorage, data: WidgetData, updateProperties: Bool, type: Data.Type) {
print("Update test widget 2 (#\(storage.fields["test"] ?? ""))") print("Update test widget 2 (#\(storage.fields["test"] ?? ""))")
storage.fields["test"] = (storage.fields["test"] as? Int ?? 0) + 1 storage.fields["test"] = (storage.fields["test"] as? Int ?? 0) + 1
} }
@ -24,14 +24,14 @@ public enum Backend2 {
public init() { } public init() { }
public func container<Data>(modifiers: [(AnyView) -> AnyView], type: Data.Type) -> ViewStorage where Data: ViewRenderData { public func container<Data>(data: WidgetData, type: Data.Type) -> ViewStorage where Data: ViewRenderData {
print("Init test widget 4") print("Init test widget 4")
let storage = ViewStorage(nil) let storage = ViewStorage(nil)
storage.fields["test"] = 0 storage.fields["test"] = 0
return storage return storage
} }
public func update<Data>(_ storage: ViewStorage, modifiers: [(AnyView) -> AnyView], updateProperties: Bool, type: Data.Type) { public func update<Data>(_ storage: ViewStorage, data: WidgetData, updateProperties: Bool, type: Data.Type) {
print("Update test widget 4 (#\(storage.fields["test"] ?? ""))") print("Update test widget 4 (#\(storage.fields["test"] ?? ""))")
storage.fields["test"] = (storage.fields["test"] as? Int ?? 0) + 1 storage.fields["test"] = (storage.fields["test"] as? Int ?? 0) + 1
} }
@ -46,17 +46,17 @@ public enum Backend2 {
self.content = content() self.content = content()
} }
public func container<Data>(modifiers: [(any Meta.AnyView) -> any Meta.AnyView], type: Data.Type) -> Meta.ViewStorage where Data: ViewRenderData { public func container<Data>(data: WidgetData, type: Data.Type) -> Meta.ViewStorage where Data: ViewRenderData {
let storage = ViewStorage(nil) let storage = ViewStorage(nil)
storage.content = [.mainContent: content.storages(modifiers: modifiers, type: type)] storage.content = [.mainContent: content.storages(data: data, type: type)]
return storage return storage
} }
public func update<Data>(_ storage: Meta.ViewStorage, modifiers: [(any Meta.AnyView) -> any Meta.AnyView], updateProperties: Bool, type: Data.Type) where Data: ViewRenderData { public func update<Data>(_ storage: Meta.ViewStorage, data: WidgetData, updateProperties: Bool, type: Data.Type) where Data: ViewRenderData {
guard let storages = storage.content[.mainContent] else { guard let storages = storage.content[.mainContent] else {
return return
} }
content.update(storages, modifiers: modifiers, updateProperties: updateProperties, type: type) content.update(storages, data: data, updateProperties: updateProperties, type: type)
} }
} }