Move from renderable elements to views

This commit is contained in:
david-swift 2024-07-18 16:07:37 +02:00
parent 1b4621c03a
commit 21e28344c1
23 changed files with 335 additions and 160 deletions

View File

@ -0,0 +1,59 @@
//
// ButtonCollection.swift
// TermKitBackend
//
// Created by david-swift on 18.07.2024.
//
import TermKit
/// A menu is an item of a ``MenuBar``.
public struct ButtonCollection: ButtonContext.Widget, Wrapper {
/// The content of the menu.
var content: Body
/// Initialize a menu.
/// - Parameters:
/// - label: The menu's label, displayed in the menu bar.
/// - content: The content of the menu.
public init(@ViewBuilder content: @escaping () -> Body) {
self.content = content()
}
/// The view storage.
/// - Parameters:
/// - modifiers: Modify the views before updating.
/// - type: The type of the views.
/// - Returns: The view storage.
public func container<Data>(
modifiers: [(any AnyView) -> any AnyView],
type: Data.Type
) -> ViewStorage where Data: ViewRenderData {
var buttons: [Button] = []
for element in content.storages(modifiers: modifiers, type: type) {
if let button = element.pointer as? Button {
buttons.append(button)
} else if let collection = element.pointer as? [Button] {
buttons += collection
}
}
return .init(buttons, content: [.mainContent: content.storages(modifiers: modifiers, type: type)])
}
/// Update the stored content.
/// - Parameters:
/// - storage: The storage to update.
/// - modifiers: Modify the views before updating.
/// - updateProperties: Whether to update the properties.
/// - type: The type of the views.
public func update<Data>(
_ storage: ViewStorage,
modifiers: [(AnyView) -> AnyView],
updateProperties: Bool,
type: Data.Type
) where Data: ViewRenderData {
// Buttons in dialogs cannot be updated
}
}

View File

@ -0,0 +1,21 @@
//
// ButtonContext.swift
// TermKitBackend
//
// Created by david-swift on 18.07.2024.
//
import TermKit
/// The menu items view context.
public enum ButtonContext: ViewRenderData {
/// The type of the widgets.
public typealias WidgetType = Widget
/// The wrapper type.
public typealias WrapperType = ButtonCollection
/// The type of the widgets.
public protocol Widget: Meta.Widget { }
}

View File

@ -8,48 +8,52 @@
import TermKit
/// A menu is an item of a ``MenuBar``.
public struct Menu: Renderable {
public struct Menu: MenuContext.Widget {
/// The menu's label, displayed in the menu bar.
var label: String
/// The content of the menu.
var content: [Button]
var content: Body
/// Initialize a menu.
/// - Parameters:
/// - label: The menu's label, displayed in the menu bar.
/// - content: The content of the menu.
public init(_ label: String, @Builder<Button> content: () -> [Button]) {
public init(_ label: String, @ViewBuilder content: () -> Body) {
self.label = label
self.content = content()
}
/// The view storage.
/// - Parameters:
/// - type: The type of the renderable elements.
/// - fields: More information.
public func container<RenderableType>(type: RenderableType.Type, fields: [String: Any]) -> RenderableStorage {
let children = (content as [Renderable]).storages(type: Button.self, fields: [:])
/// - modifiers: Modify the views before updating.
/// - type: The type of the views.
/// - Returns: The view storage.
public func container<Data>(
modifiers: [(any AnyView) -> any AnyView],
type: Data.Type
) -> ViewStorage where Data: ViewRenderData {
let children = content.storages(modifiers: modifiers, type: type)
let menu = MenuBarItem(title: label, children: children.compactMap { $0.pointer as? MenuItem })
return .init(menu, content: [.mainContent: children])
}
/// Update the stored content.
/// Update the view storage.
/// - Parameters:
/// - storage: The storage to update.
/// - modifiers: Modify the views before updating.
/// - updateProperties: Whether to update the properties.
/// - type: The type of the renderable elements.
/// - fields: More information.
public func update<RenderableType>(
_ storage: RenderableStorage,
/// - type: The type of the views.
public func update<Data>(
_ storage: ViewStorage,
modifiers: [(AnyView) -> AnyView],
updateProperties: Bool,
type: RenderableType.Type,
fields: [String: Any]
) {
type: Data.Type
) where Data: ViewRenderData {
guard let storages = storage.content[.mainContent] else {
return
}
(content as [Renderable]).update(storages, updateProperties: updateProperties, type: type, fields: [:])
content.update(storages, modifiers: modifiers, updateProperties: updateProperties, type: type)
}
}

View File

@ -0,0 +1,72 @@
//
// MenuCollection.swift
// TermKitBackend
//
// Created by david-swift on 13.07.2024.
//
import TermKit
/// A menu is an item of a ``MenuBar``.
public struct MenuCollection: MenuContext.Widget, Wrapper {
/// The content of the menu.
var content: Body
/// Initialize a menu.
/// - Parameters:
/// - label: The menu's label, displayed in the menu bar.
/// - content: The content of the menu.
public init(@ViewBuilder content: @escaping () -> Body) {
self.content = content()
}
/// The view storage.
/// - Parameters:
/// - modifiers: Modify the views before updating.
/// - type: The type of the views.
/// - Returns: The view storage.
public func container<Data>(
modifiers: [(any AnyView) -> any AnyView],
type: Data.Type
) -> ViewStorage where Data: ViewRenderData {
var storages: [ViewStorage] = []
forEachMenu { menu in
storages.append(menu.container(modifiers: modifiers, type: type))
}
return .init(storages.compactMap { $0.pointer }, content: [.mainContent: storages])
}
/// Update the stored content.
/// - Parameters:
/// - storage: The storage to update.
/// - modifiers: Modify the views before updating.
/// - updateProperties: Whether to update the properties.
/// - type: The type of the views.
public func update<Data>(
_ storage: ViewStorage,
modifiers: [(AnyView) -> AnyView],
updateProperties: Bool,
type: Data.Type
) where Data: ViewRenderData {
// Menus cannot be updated
}
/// Run a function for each menu.
/// - Parameter closure: The function.
func forEachMenu(closure: @escaping (Menu) -> Void) {
var index = 0
for element in content {
if let menu = element as? Menu {
closure(menu)
index += 1
} else if let collection = element as? [Menu] {
for menu in collection {
closure(menu)
index += 1
}
}
}
}
}

View File

@ -0,0 +1,21 @@
//
// MenuContext.swift
// TermKitBackend
//
// Created by david-swift on 13.07.2024.
//
import TermKit
/// The menu items view context.
public enum MenuContext: ViewRenderData {
/// The type of the widgets.
public typealias WidgetType = Widget
/// The wrapper type.
public typealias WrapperType = MenuCollection
/// The type of the widgets.
public protocol Widget: Meta.Widget { }
}

View File

@ -1,47 +0,0 @@
//
// Button.swift
// TermKitBackend
//
// Created by david-swift on 07.07.2024.
//
import TermKit
extension Button: Renderable {
/// An identifier for the button's action.
var actionID: String { "action" }
/// The view storage.
/// - Parameters:
/// - type: The type of the renderable elements.
/// - fields: More information.
public func container<RenderableType>(type: RenderableType.Type, fields: [String: Any]) -> RenderableStorage {
let storage = RenderableStorage(nil)
let menuItem = MenuItem(title: label) {
(storage.fields[actionID] as? () -> Void)?()
}
storage.pointer = menuItem
storage.fields[actionID] = action
return storage
}
/// Update the stored content.
/// - Parameters:
/// - storage: The storage to update.
/// - updateProperties: Whether to update the properties.
/// - type: The type of the renderable elements.
/// - fields: More information.
public func update<RenderableType>(
_ storage: RenderableStorage,
updateProperties: Bool,
type: RenderableType.Type,
fields: [String: Any]
) {
guard updateProperties else {
return
}
storage.fields[actionID] = action
}
}

View File

@ -18,8 +18,6 @@ public class TermKitApp: AppStorage {
/// The wrapper type of the TermKit backend.
public typealias WrapperType = VStack
/// The application.
public var app: () -> any App
/// The app storage.
public var storage: StandardAppStorage = .init()
@ -27,9 +25,7 @@ public class TermKitApp: AppStorage {
/// - Parameters:
/// - id: The identifier.
/// - app: The application.
public required init(id: String, app: @escaping () -> any App) {
self.app = app
}
public required init(id: String) { }
/// Execute the app.
/// - Parameter setup: Set the scene elements up.

View File

@ -0,0 +1,16 @@
//
// TermKitMainView.swift
// TermKitBackend
//
// Created by david-swift on 13.07.2024.
//
/// The type of widgets of the TermKit backend.
public enum TermKitMainView: ViewRenderData {
/// The type of the widgets.
public typealias WidgetType = TermKitWidget
/// The wrapper type.
public typealias WrapperType = VStack
}

View File

@ -13,13 +13,13 @@ public struct MenuBar: TermKitSceneElement {
/// The identifier of the menu bar.
public var id: String
/// The menu bar's content.
var content: [Menu]
var content: Body
/// Initialize the menu bar.
/// - Parameters:
/// - id: The identifier of the menu bar.
/// - content: The menu bar's content.
public init(id: String = "main-menu", @Builder<Menu> content: () -> [Menu]) {
public init(id: String = "main-menu", @ViewBuilder content: () -> Body) {
self.id = id
self.content = content()
}
@ -33,8 +33,9 @@ public struct MenuBar: TermKitSceneElement {
/// The scene storage.
/// - Parameter app: The app storage.
public func container<Storage>(app: Storage) -> SceneStorage where Storage: AppStorage {
let items = MenuCollection { content }.container(modifiers: [], type: MenuContext.self)
let menubar = TermKit.MenuBar(
menus: content.compactMap { $0.container(type: Menu.self, fields: [:]).pointer as? MenuBarItem }
menus: items.pointer as? [TermKit.MenuBarItem] ?? []
)
Task {
try await Task.sleep(nanoseconds: 1)

View File

@ -40,7 +40,7 @@ public struct Window: TermKitSceneElement {
let win = TermKit.Window(title)
win.fill()
Application.top.addSubview(win)
let viewStorage = content.storage(modifiers: [], type: Storage.self)
let viewStorage = content.storage(modifiers: [], type: TermKitMainView.self)
if let pointer = viewStorage.pointer as? TermKit.View {
win.addSubview(pointer)
}
@ -62,7 +62,8 @@ public struct Window: TermKitSceneElement {
guard let viewStorage = storage.content[.mainContent]?.first else {
return
}
content.updateStorage(viewStorage, modifiers: [], updateProperties: updateProperties, type: Storage.self)
content
.updateStorage(viewStorage, modifiers: [], updateProperties: updateProperties, type: TermKitMainView.self)
Application.refresh()
}

View File

@ -8,13 +8,16 @@
import TermKit
/// A simple button widget.
public struct Button: TermKitWidget {
public struct Button: TermKitWidget, ButtonContext.Widget, MenuContext.Widget {
/// The button's label.
var label: String
/// The action.
var action: () -> Void
/// The identifier for the action closure.
let actionID = "action"
/// Initialize a button.
/// - Parameters:
/// - The button's label.
@ -28,10 +31,22 @@ public struct Button: TermKitWidget {
/// - Parameters:
/// - modifiers: Modify views before being updated.
/// - type: The type of the app storage.
public func container<Storage>(
/// - Returns: The view storage.
public func container<Data>(
modifiers: [(any AnyView) -> any AnyView],
type: Storage.Type
) -> ViewStorage where Storage: AppStorage {
type: Data.Type
) -> ViewStorage where Data: ViewRenderData {
if type == MenuContext.self {
let storage = ViewStorage(nil)
let menuItem = MenuItem(title: label) {
(storage.fields[actionID] as? () -> Void)?()
}
storage.pointer = menuItem
storage.fields[actionID] = action
return storage
} else if type == ButtonContext.self {
return ViewStorage(self)
}
let button = TermKit.Button(label, clicked: action)
return .init(button)
}
@ -42,12 +57,15 @@ public struct Button: TermKitWidget {
/// - modifiers: Modify views before being updated
/// - updateProperties: Whether to update the view's properties.
/// - type: The type of the app storage.
public func update<Storage>(
public func update<Data>(
_ storage: ViewStorage,
modifiers: [(any AnyView) -> any AnyView],
updateProperties: Bool,
type: Storage.Type
) where Storage: AppStorage {
type: Data.Type
) where Data: ViewRenderData {
if type == MenuContext.self {
storage.fields[actionID] = action
}
guard let storage = storage.pointer as? TermKit.Button else {
return
}

View File

@ -28,10 +28,11 @@ public struct Checkbox: TermKitWidget {
/// - Parameters:
/// - modifiers: Modify views before being updated.
/// - type: The type of the app storage.
public func container<Storage>(
/// - Returns: The view storage.
public func container<Data>(
modifiers: [(any AnyView) -> any AnyView],
type: Storage.Type
) -> ViewStorage where Storage: AppStorage {
type: Data.Type
) -> ViewStorage where Data: ViewRenderData {
let button = TermKit.Checkbox(label, checked: isOn.wrappedValue)
button.toggled = { _ in
isOn.wrappedValue = button.checked
@ -45,12 +46,12 @@ public struct Checkbox: TermKitWidget {
/// - modifiers: Modify views before being updated
/// - updateProperties: Whether to update the view's properties.
/// - type: The type of the app storage.
public func update<Storage>(
public func update<Data>(
_ storage: ViewStorage,
modifiers: [(any AnyView) -> any AnyView],
updateProperties: Bool,
type: Storage.Type
) where Storage: AppStorage {
type: Data.Type
) where Data: ViewRenderData {
guard let storage = storage.pointer as? TermKit.Checkbox, updateProperties else {
return
}

View File

@ -17,7 +17,7 @@ struct Box: TermKitWidget {
/// The signal.
var signal: Signal
/// The buttons (info box if none).
var buttons: [Button]
var buttons: Body
/// The content behind the box.
var content: AnyView
/// Whether it is an error box.
@ -30,16 +30,15 @@ struct Box: TermKitWidget {
/// - Parameters:
/// - modifiers: Modify views before being updated.
/// - type: The type of the app storage.
func container<Storage>(
/// - Returns: The view storage.
func container<Data>(
modifiers: [(any AnyView) -> any AnyView],
type: Storage.Type
) -> ViewStorage where Storage: AppStorage {
type: Data.Type
) -> ViewStorage where Data: ViewRenderData {
let storage = ViewStorage(nil)
let contentStorage = content.storage(modifiers: modifiers, type: type)
storage.pointer = contentStorage.pointer
storage.content = [.mainContent: [contentStorage]]
storage.fields[boxButtonsID] = buttons
return storage
return .init(contentStorage.pointer, content: [.mainContent: [contentStorage]])
}
/// Update the stored content.
@ -48,16 +47,18 @@ struct Box: TermKitWidget {
/// - modifiers: Modify views before being updated
/// - updateProperties: Whether to update the view's properties.
/// - type: The type of the app storage.
func update<Storage>(
func update<Data>(
_ storage: ViewStorage,
modifiers: [(any AnyView) -> any AnyView],
updateProperties: Bool,
type: Storage.Type
) where Storage: AppStorage {
type: Data.Type
) where Data: ViewRenderData {
guard let storage = storage.content[.mainContent]?.first else {
return
}
content.updateStorage(storage, modifiers: modifiers, updateProperties: updateProperties, type: type)
let buttons = ButtonCollection { self.buttons }
.storage(modifiers: modifiers, type: ButtonContext.self).pointer as? [Button] ?? []
storage.fields[boxButtonsID] = buttons
if signal.update {
if buttons.isEmpty {
@ -89,7 +90,7 @@ extension AnyView {
_ title: String,
message: String,
signal: Signal,
@Builder<Button> buttons: @escaping () -> [Button]
@ViewBuilder buttons: @escaping () -> Body
) -> AnyView {
Box(title: title, message: message, signal: signal, buttons: buttons(), content: self)
}
@ -105,7 +106,7 @@ extension AnyView {
_ title: String,
message: String,
signal: Signal,
@Builder<Button> buttons: @escaping () -> [Button]
@ViewBuilder buttons: @escaping () -> Body
) -> AnyView {
Box(title: title, message: message, signal: signal, buttons: buttons(), content: self, error: true)
}

View File

@ -28,10 +28,11 @@ public struct Frame: TermKitWidget {
/// - Parameters:
/// - modifiers: Modify views before being updated.
/// - type: The type of the app storage.
public func container<Storage>(
/// - Returns: The view storage.
public func container<Data>(
modifiers: [(any AnyView) -> any AnyView],
type: Storage.Type
) -> ViewStorage where Storage: AppStorage {
type: Data.Type
) -> ViewStorage where Data: ViewRenderData {
let frame = TermKit.Frame(label)
let subview = view.storage(modifiers: modifiers, type: type)
if let pointer = subview.pointer as? TermKit.View {
@ -46,12 +47,12 @@ public struct Frame: TermKitWidget {
/// - modifiers: Modify views before being updated
/// - updateProperties: Whether to update the view's properties.
/// - type: The type of the app storage.
public func update<Storage>(
public func update<Data>(
_ storage: ViewStorage,
modifiers: [(any AnyView) -> any AnyView],
updateProperties: Bool,
type: Storage.Type
) where Storage: AppStorage {
type: Data.Type
) where Data: ViewRenderData {
if let storage = storage.content[.mainContent]?.first {
view.updateStorage(storage, modifiers: modifiers, updateProperties: updateProperties, type: type)
}

View File

@ -23,10 +23,10 @@ public struct HStack: Wrapper, TermKitWidget {
/// - Parameters:
/// - modifiers: Modify views before being updated.
/// - type: The type of the app storage.
public func container<Storage>(
public func container<Data>(
modifiers: [(any AnyView) -> any AnyView],
type: Storage.Type
) -> ViewStorage where Storage: AppStorage {
type: Data.Type
) -> ViewStorage where Data: ViewRenderData {
let storages = content.storages(modifiers: modifiers, type: type)
if storages.count == 1 {
return .init(storages[0].pointer, content: [.mainContent: storages])
@ -49,12 +49,12 @@ public struct HStack: Wrapper, TermKitWidget {
/// - modifiers: Modify views before being updated
/// - updateProperties: Whether to update the view's properties.
/// - type: The type of the app storage.
public func update<Storage>(
public func update<Data>(
_ storage: ViewStorage,
modifiers: [(any AnyView) -> any AnyView],
updateProperties: Bool,
type: Storage.Type
) where Storage: AppStorage {
type: Data.Type
) where Data: ViewRenderData {
guard let storages = storage.content[.mainContent] else {
return
}

View File

@ -23,10 +23,11 @@ public struct Label: TermKitWidget {
/// - Parameters:
/// - modifiers: Modify views before being updated.
/// - type: The type of the app storage.
public func container<Storage>(
/// - Returns: The view storage.
public func container<Data>(
modifiers: [(any AnyView) -> any AnyView],
type: Storage.Type
) -> ViewStorage where Storage: AppStorage {
type: Data.Type
) -> ViewStorage where Data: ViewRenderData {
let button = TermKit.Label(label)
return .init(button)
}
@ -37,12 +38,12 @@ public struct Label: TermKitWidget {
/// - modifiers: Modify views before being updated
/// - updateProperties: Whether to update the view's properties.
/// - type: The type of the app storage.
public func update<Storage>(
public func update<Data>(
_ storage: ViewStorage,
modifiers: [(any AnyView) -> any AnyView],
updateProperties: Bool,
type: Storage.Type
) where Storage: AppStorage {
type: Data.Type
) where Data: ViewRenderData {
guard let storage = storage.pointer as? TermKit.Label, updateProperties else {
return
}

View File

@ -28,10 +28,11 @@ public struct ListView<Element>: TermKitWidget where Element: CustomStringConver
/// - Parameters:
/// - modifiers: Modify views before being updated.
/// - type: The type of the app storage.
public func container<Storage>(
/// - Returns: The view storage.
public func container<Data>(
modifiers: [(any AnyView) -> any AnyView],
type: Storage.Type
) -> ViewStorage where Storage: AppStorage {
type: Data.Type
) -> ViewStorage where Data: ViewRenderData {
let list = TermKit.ListView(items: items.map { $0.description })
setClosure(list: list)
return .init(list)
@ -43,12 +44,12 @@ public struct ListView<Element>: TermKitWidget where Element: CustomStringConver
/// - modifiers: Modify views before being updated
/// - updateProperties: Whether to update the view's properties.
/// - type: The type of the app storage.
public func update<Storage>(
public func update<Data>(
_ storage: ViewStorage,
modifiers: [(any AnyView) -> any AnyView],
updateProperties: Bool,
type: Storage.Type
) where Storage: AppStorage {
type: Data.Type
) where Data: ViewRenderData {
guard let list = storage.pointer as? TermKit.ListView else {
return
}

View File

@ -28,10 +28,11 @@ public struct ProgressBar: TermKitWidget {
/// - Parameters:
/// - modifiers: Modify views before being updated.
/// - type: The type of the app storage.
public func container<Storage>(
/// - Returns: The view storage.
public func container<Data>(
modifiers: [(any AnyView) -> any AnyView],
type: Storage.Type
) -> ViewStorage where Storage: AppStorage {
type: Data.Type
) -> ViewStorage where Data: ViewRenderData {
let bar = TermKit.ProgressBar()
bar.fraction = .init(value / max)
return .init(bar)
@ -43,12 +44,12 @@ public struct ProgressBar: TermKitWidget {
/// - modifiers: Modify views before being updated
/// - updateProperties: Whether to update the view's properties.
/// - type: The type of the app storage.
public func update<Storage>(
public func update<Data>(
_ storage: ViewStorage,
modifiers: [(any AnyView) -> any AnyView],
updateProperties: Bool,
type: Storage.Type
) where Storage: AppStorage {
type: Data.Type
) where Data: ViewRenderData {
guard let storage = storage.pointer as? TermKit.ProgressBar, updateProperties else {
return
}

View File

@ -23,10 +23,11 @@ public struct ScrollView: TermKitWidget {
/// - Parameters:
/// - modifiers: Modify views before being updated.
/// - type: The type of the app storage.
public func container<Storage>(
/// - Returns: The view storage.
public func container<Data>(
modifiers: [(any AnyView) -> any AnyView],
type: Storage.Type
) -> ViewStorage where Storage: AppStorage {
type: Data.Type
) -> ViewStorage where Data: ViewRenderData {
let storages = content.storages(modifiers: modifiers, type: type)
if storages.count == 1 {
return .init(storages[0].pointer, content: [.mainContent: storages])
@ -49,12 +50,12 @@ public struct ScrollView: TermKitWidget {
/// - modifiers: Modify views before being updated
/// - updateProperties: Whether to update the view's properties.
/// - type: The type of the app storage.
public func update<Storage>(
public func update<Data>(
_ storage: ViewStorage,
modifiers: [(any AnyView) -> any AnyView],
updateProperties: Bool,
type: Storage.Type
) where Storage: AppStorage {
type: Data.Type
) where Data: ViewRenderData {
guard let storages = storage.content[.mainContent] else {
return
}

View File

@ -28,10 +28,11 @@ public struct TextField: TermKitWidget {
/// - Parameters:
/// - modifiers: Modify views before being updated.
/// - type: The type of the app storage.
public func container<Storage>(
/// - Returns: The view storage.
public func container<Data>(
modifiers: [(any AnyView) -> any AnyView],
type: Storage.Type
) -> ViewStorage where Storage: AppStorage {
type: Data.Type
) -> ViewStorage where Data: ViewRenderData {
let field = TermKit.TextField(text.wrappedValue)
let storage = ViewStorage(field)
field.secret = secret
@ -52,12 +53,12 @@ public struct TextField: TermKitWidget {
/// - modifiers: Modify views before being updated
/// - updateProperties: Whether to update the view's properties.
/// - type: The type of the app storage.
public func update<Storage>(
public func update<Data>(
_ storage: ViewStorage,
modifiers: [(any AnyView) -> any AnyView],
updateProperties: Bool,
type: Storage.Type
) where Storage: AppStorage {
type: Data.Type
) where Data: ViewRenderData {
guard let field = storage.pointer as? TermKit.TextField else {
return
}

View File

@ -23,10 +23,10 @@ public struct VStack: Wrapper, TermKitWidget {
/// - Parameters:
/// - modifiers: Modify views before being updated.
/// - type: The type of the app storage.
public func container<Storage>(
public func container<Data>(
modifiers: [(any AnyView) -> any AnyView],
type: Storage.Type
) -> ViewStorage where Storage: AppStorage {
type: Data.Type
) -> ViewStorage where Data: ViewRenderData {
let storages = content.storages(modifiers: modifiers, type: type)
if storages.count == 1 {
return .init(storages[0].pointer, content: [.mainContent: storages])
@ -49,12 +49,12 @@ public struct VStack: Wrapper, TermKitWidget {
/// - modifiers: Modify views before being updated
/// - updateProperties: Whether to update the view's properties.
/// - type: The type of the app storage.
public func update<Storage>(
public func update<Data>(
_ storage: ViewStorage,
modifiers: [(any AnyView) -> any AnyView],
updateProperties: Bool,
type: Storage.Type
) where Storage: AppStorage {
type: Data.Type
) where Data: ViewRenderData {
guard let storages = storage.content[.mainContent] else {
return
}

View File

@ -23,10 +23,10 @@ public struct ZStack: Wrapper, TermKitWidget {
/// - Parameters:
/// - modifiers: Modify views before being updated.
/// - type: The type of the app storage.
public func container<Storage>(
public func container<Data>(
modifiers: [(any AnyView) -> any AnyView],
type: Storage.Type
) -> ViewStorage where Storage: AppStorage {
type: Data.Type
) -> ViewStorage where Data: ViewRenderData {
let storages = content.reversed().storages(modifiers: modifiers, type: type)
if storages.count == 1 {
return .init(storages[0].pointer, content: [.mainContent: storages])
@ -46,12 +46,12 @@ public struct ZStack: Wrapper, TermKitWidget {
/// - modifiers: Modify views before being updated
/// - updateProperties: Whether to update the view's properties.
/// - type: The type of the app storage.
public func update<Storage>(
public func update<Data>(
_ storage: ViewStorage,
modifiers: [(any AnyView) -> any AnyView],
updateProperties: Bool,
type: Storage.Type
) where Storage: AppStorage {
type: Data.Type
) where Data: ViewRenderData {
guard let storages = storage.content[.mainContent] else {
return
}

View File

@ -33,20 +33,25 @@ struct TestApp: App {
var menuBar: MenuBar {
.init {
Menu("File") {
Button("_About TermKitBackend") {
about.signal()
}
Button("_Quit") {
app.quit()
}
}
fileMenu
Menu("_Actions") {
Button("_Hello, world!") { }
}
}
}
@ViewBuilder
var fileMenu: Body {
Menu("File") {
Button("_About TermKitBackend") {
about.signal()
}
Button("_Quit") {
app.quit()
}
}
}
var aboutInfo: String {
"""
This is a sample backend for the Meta package of the Aparoksha project.