Compare commits
4 Commits
main
...
100-percen
Author | SHA1 | Date |
---|---|---|
![]() |
73a00afc04 | |
![]() |
637fdec44c | |
![]() |
e05110825a | |
![]() |
1f48d27c88 |
|
@ -20,34 +20,41 @@
|
|||
/// 2. `MountedHostView.update` when reconciling
|
||||
///
|
||||
protocol EnvironmentReader {
|
||||
mutating func setContent(from values: EnvironmentValues)
|
||||
// mutating func setContent(from values: EnvironmentValues)
|
||||
var environment: EnvironmentValues! { get set }
|
||||
}
|
||||
|
||||
@propertyWrapper public struct Environment<Value>: DynamicProperty {
|
||||
@propertyWrapper public final class Environment<Value>: DynamicProperty {
|
||||
enum Content {
|
||||
case keyPath(KeyPath<EnvironmentValues, Value>)
|
||||
case value(Value)
|
||||
}
|
||||
|
||||
private var content: Content
|
||||
var environment: EnvironmentValues!
|
||||
private let keyPath: KeyPath<EnvironmentValues, Value>
|
||||
public init(_ keyPath: KeyPath<EnvironmentValues, Value>) {
|
||||
content = .keyPath(keyPath)
|
||||
// content = .keyPath(keyPath)
|
||||
self.keyPath = keyPath
|
||||
}
|
||||
|
||||
mutating func setContent(from values: EnvironmentValues) {
|
||||
content = .value(values[keyPath: keyPath])
|
||||
}
|
||||
// mutating func setContent(from values: EnvironmentValues) {
|
||||
// value = values[keyPath: keyPath]
|
||||
// // content = .value(values[keyPath: keyPath])
|
||||
// }
|
||||
|
||||
public var wrappedValue: Value {
|
||||
switch content {
|
||||
case let .value(value):
|
||||
return value
|
||||
case let .keyPath(keyPath):
|
||||
guard let values = environment else {
|
||||
// not bound to a view, return the default value.
|
||||
return EnvironmentValues()[keyPath: keyPath]
|
||||
}
|
||||
return values[keyPath: keyPath]
|
||||
// switch content {
|
||||
// case let .value(value):
|
||||
// return value
|
||||
// case let .keyPath(keyPath):
|
||||
// // not bound to a view, return the default value.
|
||||
// return EnvironmentValues()[keyPath: keyPath]
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -18,28 +18,28 @@ public protocol EnvironmentKey {
|
|||
}
|
||||
|
||||
protocol EnvironmentModifier {
|
||||
func modifyEnvironment(_ values: inout EnvironmentValues)
|
||||
func modifyEnvironment(_ values: EnvironmentValues)
|
||||
}
|
||||
|
||||
public struct _EnvironmentKeyWritingModifier<Value>: ViewModifier, EnvironmentModifier {
|
||||
public let keyPath: WritableKeyPath<EnvironmentValues, Value>
|
||||
public let keyPath: ReferenceWritableKeyPath<EnvironmentValues, Value>
|
||||
public let value: Value
|
||||
|
||||
public init(keyPath: WritableKeyPath<EnvironmentValues, Value>, value: Value) {
|
||||
public init(keyPath: ReferenceWritableKeyPath<EnvironmentValues, Value>, value: Value) {
|
||||
self.keyPath = keyPath
|
||||
self.value = value
|
||||
}
|
||||
|
||||
public typealias Body = Never
|
||||
|
||||
func modifyEnvironment(_ values: inout EnvironmentValues) {
|
||||
func modifyEnvironment(_ values: EnvironmentValues) {
|
||||
values[keyPath: keyPath] = value
|
||||
}
|
||||
}
|
||||
|
||||
public extension View {
|
||||
func environment<V>(
|
||||
_ keyPath: WritableKeyPath<EnvironmentValues, V>,
|
||||
_ keyPath: ReferenceWritableKeyPath<EnvironmentValues, V>,
|
||||
_ value: V
|
||||
) -> some View {
|
||||
modifier(_EnvironmentKeyWritingModifier(keyPath: keyPath, value: value))
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
|
||||
import CombineShim
|
||||
|
||||
@propertyWrapper public struct EnvironmentObject<ObjectType>: DynamicProperty
|
||||
@propertyWrapper public final class EnvironmentObject<ObjectType>: DynamicProperty
|
||||
where ObjectType: ObservableObject
|
||||
{
|
||||
@dynamicMemberLookup public struct Wrapper {
|
||||
|
@ -36,11 +36,10 @@ import CombineShim
|
|||
}
|
||||
|
||||
var _store: ObjectType?
|
||||
var _seed: Int = 0
|
||||
|
||||
mutating func setContent(from values: EnvironmentValues) {
|
||||
_store = values[ObjectIdentifier(ObjectType.self)]
|
||||
}
|
||||
// mutating func setContent(from values: EnvironmentValues) {
|
||||
// _store = values[ObjectIdentifier(ObjectType.self)]
|
||||
// }
|
||||
|
||||
public var wrappedValue: ObjectType {
|
||||
guard let store = _store else { error() }
|
||||
|
@ -63,10 +62,19 @@ import CombineShim
|
|||
public init() {}
|
||||
}
|
||||
|
||||
extension EnvironmentObject: ObservedProperty, EnvironmentReader {}
|
||||
extension EnvironmentObject: ObservedProperty, EnvironmentReader {
|
||||
var environment: EnvironmentValues! {
|
||||
get {
|
||||
fatalError()
|
||||
}
|
||||
set {
|
||||
_store = newValue[ObjectIdentifier(ObjectType.self)]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension ObservableObject {
|
||||
static var environmentStore: WritableKeyPath<EnvironmentValues, Self?> {
|
||||
static var environmentStore: ReferenceWritableKeyPath<EnvironmentValues, Self?> {
|
||||
\.[ObjectIdentifier(self)]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
|
||||
import CombineShim
|
||||
|
||||
public struct EnvironmentValues: CustomStringConvertible {
|
||||
public final class EnvironmentValues: CustomStringConvertible {
|
||||
public var description: String {
|
||||
"EnvironmentValues: \(values.count)"
|
||||
}
|
||||
|
@ -67,8 +67,8 @@ struct _EnvironmentValuesWritingModifier: ViewModifier, EnvironmentModifier {
|
|||
content
|
||||
}
|
||||
|
||||
func modifyEnvironment(_ values: inout EnvironmentValues) {
|
||||
values = environmentValues
|
||||
func modifyEnvironment(_ values: EnvironmentValues) {
|
||||
// values = environmentValues
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -34,9 +34,18 @@ extension ModifiedContent: ModifierContainer {
|
|||
}
|
||||
|
||||
extension ModifiedContent: EnvironmentReader where Modifier: EnvironmentReader {
|
||||
mutating func setContent(from values: EnvironmentValues) {
|
||||
modifier.setContent(from: values)
|
||||
var environment: EnvironmentValues! {
|
||||
get {
|
||||
modifier.environment
|
||||
}
|
||||
set {
|
||||
modifier.environment = newValue
|
||||
}
|
||||
}
|
||||
|
||||
// mutating func setContent(from values: EnvironmentValues) {
|
||||
// modifier.setContent(from: values)
|
||||
// }
|
||||
}
|
||||
|
||||
extension ModifiedContent: View, ParentView where Content: View, Modifier: ViewModifier {
|
||||
|
|
|
@ -9,9 +9,9 @@ public struct _ShadowLayout: ViewModifier, EnvironmentReader {
|
|||
content
|
||||
}
|
||||
|
||||
mutating func setContent(from values: EnvironmentValues) {
|
||||
environment = values
|
||||
}
|
||||
// mutating func setContent(from values: EnvironmentValues) {
|
||||
// environment = values
|
||||
// }
|
||||
}
|
||||
|
||||
public extension View {
|
||||
|
|
|
@ -35,9 +35,9 @@ public struct _BackgroundModifier<Background>: ViewModifier, EnvironmentReader
|
|||
}
|
||||
}
|
||||
|
||||
mutating func setContent(from values: EnvironmentValues) {
|
||||
environment = values
|
||||
}
|
||||
// mutating func setContent(from values: EnvironmentValues) {
|
||||
// environment = values
|
||||
// }
|
||||
}
|
||||
|
||||
extension _BackgroundModifier: Equatable where Background: Equatable {
|
||||
|
@ -78,9 +78,9 @@ public struct _OverlayModifier<Overlay>: ViewModifier, EnvironmentReader
|
|||
}
|
||||
}
|
||||
|
||||
mutating func setContent(from values: EnvironmentValues) {
|
||||
environment = values
|
||||
}
|
||||
// mutating func setContent(from values: EnvironmentValues) {
|
||||
// environment = values
|
||||
// }
|
||||
}
|
||||
|
||||
extension _OverlayModifier: Equatable where Overlay: Equatable {
|
||||
|
|
|
@ -80,7 +80,9 @@ final class MountedCompositeView<R: Renderer>: MountedCompositeElement<R> {
|
|||
}
|
||||
|
||||
override func update(with reconciler: StackReconciler<R>) {
|
||||
print("C.render")
|
||||
let element = reconciler.render(compositeView: self)
|
||||
print("C.recon")
|
||||
reconciler.reconcile(
|
||||
self,
|
||||
with: element,
|
||||
|
@ -91,5 +93,6 @@ final class MountedCompositeView<R: Renderer>: MountedCompositeElement<R> {
|
|||
},
|
||||
mountChild: { $0.makeMountedView(parentTarget, environmentValues, self) }
|
||||
)
|
||||
print("C.done")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -120,12 +120,16 @@ public class MountedElement<R: Renderer> {
|
|||
let type = element.type
|
||||
switch element {
|
||||
case .app:
|
||||
print("case .app")
|
||||
environmentValues.inject(into: &app.app, type)
|
||||
case .scene:
|
||||
print("case .scene")
|
||||
environmentValues.inject(into: &scene.scene, type)
|
||||
case .view:
|
||||
print("case .view")
|
||||
environmentValues.inject(into: &view.view, type)
|
||||
}
|
||||
print("updateEnvironment done")
|
||||
}
|
||||
|
||||
func mount(
|
||||
|
@ -159,34 +163,44 @@ public class MountedElement<R: Renderer> {
|
|||
}
|
||||
|
||||
extension EnvironmentValues {
|
||||
mutating func inject(into element: inout Any, _ type: Any.Type) {
|
||||
func inject(into element: inout Any, _ type: Any.Type) {
|
||||
print("Inj.typeInfo")
|
||||
guard let info = typeInfo(of: type) else { return }
|
||||
|
||||
// Extract the view from the AnyView for modification, apply Environment changes:
|
||||
if let container = element as? ModifierContainer {
|
||||
container.environmentModifier?.modifyEnvironment(&self)
|
||||
print("Inj.container")
|
||||
container.environmentModifier?.modifyEnvironment(self)
|
||||
}
|
||||
|
||||
// Inject @Environment values
|
||||
// swiftlint:disable force_cast
|
||||
// `DynamicProperty`s can have `@Environment` properties contained in them,
|
||||
// so we have to inject into them as well.
|
||||
for dynamicProp in info.properties.filter({ $0.type is DynamicProperty.Type }) {
|
||||
guard let propInfo = typeInfo(of: dynamicProp.type) else { return }
|
||||
var propWrapper = dynamicProp.get(from: element) as! DynamicProperty
|
||||
for prop in propInfo.properties.filter({ $0.type is EnvironmentReader.Type }) {
|
||||
var wrapper = prop.get(from: propWrapper) as! EnvironmentReader
|
||||
wrapper.setContent(from: self)
|
||||
prop.set(value: wrapper, on: &propWrapper)
|
||||
}
|
||||
dynamicProp.set(value: propWrapper, on: &element)
|
||||
}
|
||||
|
||||
// Inject @Environment values. `DynamicProperty`s can have `@Environment` properties
|
||||
// contained in them, so we have to inject into them as well.
|
||||
// for dynamicProp in info.properties.filter({ $0.type is DynamicProperty.Type }) {
|
||||
// guard let propInfo = typeInfo(of: dynamicProp.type) else { return }
|
||||
// var propWrapper = dynamicProp.get(from: element) as! DynamicProperty
|
||||
// print("Inj.prop.pi \(propInfo.properties.count)")
|
||||
// for prop in propInfo.properties.filter({ $0.type is EnvironmentReader.Type }) {
|
||||
// var wrapper = prop.get(from: propWrapper) as! EnvironmentReader
|
||||
// print("*****Inj.prop.pi.prop.setC *****")
|
||||
// wrapper.setContent(from: self)
|
||||
// print("*****Inj.prop.pi.prop.set *****")
|
||||
// prop.set(value: wrapper, on: &propWrapper)
|
||||
// }
|
||||
// print("***** Inj.prop.dynamic.set \(dynamicProp.type) *****")
|
||||
// dynamicProp.set(value: propWrapper, on: &element)
|
||||
// }
|
||||
for prop in info.properties.filter({ $0.type is EnvironmentReader.Type }) {
|
||||
var wrapper = prop.get(from: element) as! EnvironmentReader
|
||||
wrapper.setContent(from: self)
|
||||
prop.set(value: wrapper, on: &element)
|
||||
print("***** Inj.prop.env.setC \(wrapper) *****")
|
||||
wrapper.environment = self
|
||||
// wrapper.setContent(from: self)
|
||||
// print("***** Inj.prop.env.set \(prop.type) *****")
|
||||
// prop.set(value: wrapper, on: &element)
|
||||
}
|
||||
// swiftlint:enable force_cast
|
||||
print("Inj.done")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -214,7 +228,7 @@ extension TypeInfo {
|
|||
// swiftlint:disable:next force_cast
|
||||
var extractedDynamicProp = extracted as! DynamicProperty
|
||||
extractedDynamicProp.update()
|
||||
prop.set(value: extractedDynamicProp, on: &source)
|
||||
// prop.set(value: extractedDynamicProp, on: &source)
|
||||
}
|
||||
return dynamicProps
|
||||
}
|
||||
|
|
|
@ -83,15 +83,25 @@ public final class MountedHostView<R: Renderer>: MountedElement<R> {
|
|||
}
|
||||
}
|
||||
|
||||
private var __mountedChild = 0
|
||||
|
||||
override func update(with reconciler: StackReconciler<R>) {
|
||||
guard let target = target else { return }
|
||||
|
||||
let myStack = __stack
|
||||
__stack += 1
|
||||
|
||||
print("Host.upEnv")
|
||||
updateEnvironment()
|
||||
target.view = view
|
||||
print(
|
||||
"Host.renderer?.update \(reconciler.renderer == nil ? "nil" : "\(Swift.type(of: reconciler.renderer!))")"
|
||||
)
|
||||
reconciler.renderer?.update(target: target, with: self)
|
||||
|
||||
var childrenViews = view.children
|
||||
|
||||
print("Host(\(mountedChildren.isEmpty),\(childrenViews.isEmpty)")
|
||||
switch (mountedChildren.isEmpty, childrenViews.isEmpty) {
|
||||
// if existing children present and new children array is empty
|
||||
// then unmount all existing children
|
||||
|
@ -113,10 +123,17 @@ public final class MountedHostView<R: Renderer>: MountedElement<R> {
|
|||
// run simple update
|
||||
while let mountedChild = mountedChildren.first, let childView = childrenViews.first {
|
||||
let newChild: MountedElement<R>
|
||||
print(
|
||||
"BEGIN todo: \(myStack).\(mountedChildren.count) \(childView.typeConstructorName == mountedChildren[0].view.typeConstructorName ? "a - \(childView.typeConstructorName)" : "b")"
|
||||
)
|
||||
__mountedChild += 1
|
||||
if childView.typeConstructorName == mountedChildren[0].view.typeConstructorName {
|
||||
mountedChild.environmentValues = environmentValues
|
||||
mountedChild.view = childView
|
||||
mountedChild.updateEnvironment()
|
||||
print(
|
||||
"update -> \(Swift.type(of: mountedChild)), recon -> \(Swift.type(of: reconciler)))"
|
||||
)
|
||||
mountedChild.update(with: reconciler)
|
||||
newChild = mountedChild
|
||||
} else {
|
||||
|
@ -131,6 +148,8 @@ public final class MountedHostView<R: Renderer>: MountedElement<R> {
|
|||
newChildren.append(newChild)
|
||||
mountedChildren.removeFirst()
|
||||
childrenViews.removeFirst()
|
||||
|
||||
print("END mountedChild todo: \(myStack).\(mountedChildren.count)")
|
||||
}
|
||||
|
||||
// more mounted views left than views were to be rendered:
|
||||
|
@ -150,6 +169,7 @@ public final class MountedHostView<R: Renderer>: MountedElement<R> {
|
|||
}
|
||||
}
|
||||
|
||||
__stack -= 1
|
||||
mountedChildren = newChildren
|
||||
|
||||
// both arrays are empty, nothing to reconcile
|
||||
|
@ -157,3 +177,5 @@ public final class MountedHostView<R: Renderer>: MountedElement<R> {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
private var __stack = 0
|
||||
|
|
|
@ -27,23 +27,26 @@ public struct PropertyInfo {
|
|||
public let offset: Int
|
||||
public let ownerType: Any.Type
|
||||
|
||||
public func set<TObject>(value: Any, on object: inout TObject) {
|
||||
withValuePointer(of: &object) { pointer in
|
||||
set(value: value, pointer: pointer)
|
||||
}
|
||||
}
|
||||
// public func set<TObject>(value: Any, on object: inout TObject) {
|
||||
// withValuePointer(of: &object) { pointer in
|
||||
// set(value: value, pointer: pointer)
|
||||
// }
|
||||
// }
|
||||
|
||||
public func set(value: Any, on object: inout Any) {
|
||||
withValuePointer(of: &object) { pointer in
|
||||
set(value: value, pointer: pointer)
|
||||
}
|
||||
}
|
||||
// public func set(value: Any, on object: inout Any) {
|
||||
// withValuePointer(of: &object) { pointer in
|
||||
// set(value: value, pointer: pointer)
|
||||
// }
|
||||
// }
|
||||
|
||||
private func set(value: Any, pointer: UnsafeMutableRawPointer) {
|
||||
let valuePointer = pointer.advanced(by: offset)
|
||||
let sets = setters(type: type)
|
||||
sets.set(value: value, pointer: valuePointer)
|
||||
}
|
||||
// private func set(value: Any, pointer: UnsafeMutableRawPointer) {
|
||||
// let valuePointer = pointer.advanced(by: offset)
|
||||
// print(
|
||||
// "using \(type) for the setter, actual type is \(Swift.type(of: value)), offset is \(offset)"
|
||||
// )
|
||||
// let sets = setters(type: type)
|
||||
// sets.set(value: value, pointer: valuePointer)
|
||||
// }
|
||||
|
||||
public func get(from object: Any) -> Any {
|
||||
var object = object
|
||||
|
|
|
@ -50,8 +50,12 @@ public struct TypeInfo {
|
|||
|
||||
public func typeInfo(of type: Any.Type) -> TypeInfo? {
|
||||
guard Kind(type: type) == .struct else {
|
||||
print("TypeInfo: nil")
|
||||
return nil
|
||||
}
|
||||
|
||||
return StructMetadata(type: type).toTypeInfo()
|
||||
print("TypeInfo: \(type)")
|
||||
let result = StructMetadata(type: type).toTypeInfo()
|
||||
print("TypeInfo.done")
|
||||
return result
|
||||
}
|
||||
|
|
|
@ -150,7 +150,7 @@ public final class StackReconciler<R: Renderer> {
|
|||
storage.getter = { compositeElement.storage[id] }
|
||||
|
||||
guard var writableStorage = storage as? WritableValueStorage else {
|
||||
return property.set(value: storage, on: &compositeElement[keyPath: bodyKeypath])
|
||||
return // property.set(value: storage, on: &compositeElement[keyPath: bodyKeypath])
|
||||
}
|
||||
|
||||
// Avoiding an indirect reference cycle here: this closure can be owned by callbacks
|
||||
|
@ -160,7 +160,7 @@ public final class StackReconciler<R: Renderer> {
|
|||
self?.queueStorageUpdate(for: element, id: id) { $0 = newValue }
|
||||
}
|
||||
|
||||
property.set(value: writableStorage, on: &compositeElement[keyPath: bodyKeypath])
|
||||
// property.set(value: writableStorage, on: &compositeElement[keyPath: bodyKeypath])
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -206,27 +206,35 @@ public final class StackReconciler<R: Renderer> {
|
|||
body bodyKeypath: ReferenceWritableKeyPath<MountedCompositeElement<R>, Any>,
|
||||
result: KeyPath<MountedCompositeElement<R>, (Any) -> T>
|
||||
) -> T {
|
||||
print("SR.env")
|
||||
compositeElement.updateEnvironment()
|
||||
print("SR.type")
|
||||
if let info = typeInfo(of: compositeElement.type) {
|
||||
var stateIdx = 0
|
||||
print("SR.dynamicProps")
|
||||
let dynamicProps = info.dynamicProperties(
|
||||
&compositeElement.environmentValues,
|
||||
source: &compositeElement[keyPath: bodyKeypath]
|
||||
)
|
||||
print("SR.dynamicProps.done")
|
||||
|
||||
compositeElement.transientSubscriptions = []
|
||||
for property in dynamicProps {
|
||||
print("SR.begin")
|
||||
// Setup state/subscriptions
|
||||
if property.type is ValueStorage.Type {
|
||||
print("SR.setup storage")
|
||||
setupStorage(id: stateIdx, for: property, of: compositeElement, body: bodyKeypath)
|
||||
stateIdx += 1
|
||||
}
|
||||
if property.type is ObservedProperty.Type {
|
||||
print("SR.setup sub")
|
||||
setupTransientSubscription(for: property, of: compositeElement, body: bodyKeypath)
|
||||
}
|
||||
print("SR.done")
|
||||
}
|
||||
}
|
||||
|
||||
print("SR.type.done")
|
||||
return compositeElement[keyPath: result](compositeElement[keyPath: bodyKeypath])
|
||||
}
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ import TokamakStaticHTML
|
|||
|
||||
extension EnvironmentValues {
|
||||
/// Returns default settings for the DOM environment
|
||||
static var defaultEnvironment: Self {
|
||||
static var defaultEnvironment: EnvironmentValues {
|
||||
var environment = EnvironmentValues()
|
||||
|
||||
// `.toggleStyle` property is internal
|
||||
|
|
|
@ -1,40 +1,21 @@
|
|||
// Copyright 2020 Tokamak contributors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import TokamakShim
|
||||
|
||||
@available(OSX 10.16, iOS 14.0, *)
|
||||
struct CustomScene: Scene {
|
||||
@Environment(\.scenePhase) private var scenePhase
|
||||
|
||||
struct TokamakApp: App {
|
||||
var body: some Scene {
|
||||
print("In CustomScene.body scenePhase is \(scenePhase)")
|
||||
return WindowGroup("Tokamak Demo") {
|
||||
TokamakDemoView()
|
||||
WindowGroup("Spooky Hanger") {
|
||||
NavigationView {
|
||||
List {
|
||||
ForEach(["Item 1"], id: \.self) { childRow in
|
||||
NavigationLink(
|
||||
destination: Text(childRow)
|
||||
) {
|
||||
Text(childRow)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@available(OSX 10.16, iOS 14.0, *)
|
||||
struct TokamakDemoApp: App {
|
||||
var body: some Scene {
|
||||
CustomScene()
|
||||
}
|
||||
}
|
||||
|
||||
// If @main was supported for executable Swift Packages,
|
||||
// this would match SwiftUI 100%
|
||||
if #available(OSX 10.16, iOS 14.0, *) {
|
||||
TokamakDemoApp.main()
|
||||
}
|
||||
TokamakApp.main()
|
||||
|
|
|
@ -19,7 +19,7 @@ import TokamakCore
|
|||
|
||||
extension EnvironmentValues {
|
||||
/// Returns default settings for the static HTML environment
|
||||
static var defaultEnvironment: Self {
|
||||
static var defaultEnvironment: EnvironmentValues {
|
||||
var environment = EnvironmentValues()
|
||||
environment[_ColorSchemeKey] = .light
|
||||
|
||||
|
|
Loading…
Reference in New Issue