From 938d951b664ca101b328e5f3d45eac60ebdb7610 Mon Sep 17 00:00:00 2001 From: Max Desiatov Date: Mon, 27 Jul 2020 17:42:34 +0100 Subject: [PATCH 1/2] Add `DefaultApp` type to simplify DOMRenderer.init --- Sources/TokamakCore/App/App.swift | 4 ++-- Sources/TokamakCore/StackReconciler.swift | 4 ++-- Sources/TokamakDOM/App.swift | 18 ++++++++++----- Sources/TokamakDOM/DOMRenderer.swift | 28 +++++++---------------- Sources/TokamakDOM/Views/HTML.swift | 2 +- 5 files changed, 25 insertions(+), 31 deletions(-) diff --git a/Sources/TokamakCore/App/App.swift b/Sources/TokamakCore/App/App.swift index 9e92338d8..98dc6b742 100644 --- a/Sources/TokamakCore/App/App.swift +++ b/Sources/TokamakCore/App/App.swift @@ -29,8 +29,8 @@ public protocol App: _TitledApp { var body: Body { get } /// Implemented by the renderer to mount the `App` - static func _launch(_ app: Self, - _ rootEnvironment: EnvironmentValues) + static func _launch(_ app: Self, _ rootEnvironment: EnvironmentValues) + /// Implemented by the renderer to update the `App` on `ScenePhase` changes var _phasePublisher: CurrentValueSubject { get } diff --git a/Sources/TokamakCore/StackReconciler.swift b/Sources/TokamakCore/StackReconciler.swift index 51b022d32..7d86e1000 100644 --- a/Sources/TokamakCore/StackReconciler.swift +++ b/Sources/TokamakCore/StackReconciler.swift @@ -58,8 +58,8 @@ public final class StackReconciler { rootElement.mount(with: self) if let mountedApp = rootElement as? MountedApp { app._phasePublisher.sink { [weak self] phase in - if mountedApp.environmentValues[keyPath: \.scenePhase] != phase { - mountedApp.environmentValues[keyPath: \.scenePhase] = phase + if mountedApp.environmentValues.scenePhase != phase { + mountedApp.environmentValues.scenePhase = phase self?.queueUpdate(for: mountedApp) } }.store(in: &mountedApp.subscriptions) diff --git a/Sources/TokamakDOM/App.swift b/Sources/TokamakDOM/App.swift index 558a9be48..625777faf 100644 --- a/Sources/TokamakDOM/App.swift +++ b/Sources/TokamakDOM/App.swift @@ -23,7 +23,6 @@ private enum ScenePhaseObserver { static var publisher = CurrentValueSubject(.active) static func observe() { - let document = JSObjectRef.global.document.object! _ = document.addEventListener!("visibilitychange", JSClosure { _ in let visibilityState = document.visibilityState.string if visibilityState == "visible" { @@ -44,11 +43,8 @@ extension App { /// The body is styled with `margin: 0;` to match the `SwiftUI` layout /// system as closely as possible /// - public static func _launch(_ app: Self, - _ rootEnvironment: EnvironmentValues) { - let document = JSObjectRef.global.document.object! - let body = document.body.object! - let head = document.head.object! + public static func _launch(_ app: Self, _ rootEnvironment: EnvironmentValues) { + let body = TokamakDOM.body body.style = "margin: 0;" let rootStyle = document.createElement!("style").object! rootStyle.id = "_tokamak-app-style" @@ -74,3 +70,13 @@ extension App { ScenePhaseObserver.publisher } } + +struct DefaultApp: App { + var content: V? + + var body: some Scene { + WindowGroup { + content + } + } +} diff --git a/Sources/TokamakDOM/DOMRenderer.swift b/Sources/TokamakDOM/DOMRenderer.swift index 31a33ae12..6723e8859 100644 --- a/Sources/TokamakDOM/DOMRenderer.swift +++ b/Sources/TokamakDOM/DOMRenderer.swift @@ -23,17 +23,17 @@ extension EnvironmentValues { static var defaultEnvironment: Self { var environment = EnvironmentValues() environment[_ToggleStyleKey] = _AnyToggleStyle(DefaultToggleStyle()) - environment[keyPath: \._defaultAppStorage] = LocalStorage.standard + environment._defaultAppStorage = LocalStorage.standard _DefaultSceneStorageProvider.default = SessionStorage.standard return environment } } -/** `SpacerContainer` is part of TokamakDOM, as not all renderers will handle flexible - sizing the way browsers do. Their parent element could already know that if a child is +/** `SpacerContainer` is part of TokamakDOM, as not all renderers will handle flexible + sizing the way browsers do. Their parent element could already know that if a child is requesting full width, then it needs to expand. -*/ + */ private extension AnyView { var axes: [SpacerContainerAxis] { var axes = [SpacerContainerAxis]() @@ -55,6 +55,7 @@ private extension AnyView { let log = JSObjectRef.global.console.object!.log.function! let document = JSObjectRef.global.document.object! +let body = document.body.object! let head = document.head.object! let timeoutScheduler = { (closure: @escaping () -> ()) in @@ -77,28 +78,15 @@ public final class DOMRenderer: Renderer { private let rootRef: JSObjectRef - public init( + public convenience init( _ view: V, _ ref: JSObjectRef, _ rootEnvironment: EnvironmentValues? = nil ) { - rootRef = ref - appendRootStyle(ref) - - reconciler = StackReconciler( - view: view, - target: DOMNode(view, ref), - environment: .defaultEnvironment, - renderer: self, - scheduler: timeoutScheduler - ) + self.init(DefaultApp(content: view), ref, rootEnvironment) } - init( - _ app: A, - _ ref: JSObjectRef, - _ rootEnvironment: EnvironmentValues? = nil - ) { + init(_ app: A, _ ref: JSObjectRef, _ rootEnvironment: EnvironmentValues? = nil) { rootRef = ref appendRootStyle(ref) diff --git a/Sources/TokamakDOM/Views/HTML.swift b/Sources/TokamakDOM/Views/HTML.swift index 366cea43d..e787f7703 100644 --- a/Sources/TokamakDOM/Views/HTML.swift +++ b/Sources/TokamakDOM/Views/HTML.swift @@ -45,7 +45,7 @@ extension AnyHTML { // then use the standard lib to get the difference? for (attribute, value) in attributes { - _ = dom.ref[dynamicMember: attribute] = JSValue(stringLiteral: value) + _ = dom.ref[dynamicMember: attribute] = .string(value) } dom.reinstall(listeners) From affc1d25b36efdf2b95563400cc9ed6249155d0e Mon Sep 17 00:00:00 2001 From: Max Desiatov Date: Mon, 27 Jul 2020 21:25:42 +0100 Subject: [PATCH 2/2] Avoid setting `body.style` if value already present --- Sources/TokamakDOM/App.swift | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Sources/TokamakDOM/App.swift b/Sources/TokamakDOM/App.swift index 625777faf..864a48377 100644 --- a/Sources/TokamakDOM/App.swift +++ b/Sources/TokamakDOM/App.swift @@ -45,7 +45,9 @@ extension App { /// public static func _launch(_ app: Self, _ rootEnvironment: EnvironmentValues) { let body = TokamakDOM.body - body.style = "margin: 0;" + if body.style == .undefined { + body.style = "margin: 0;" + } let rootStyle = document.createElement!("style").object! rootStyle.id = "_tokamak-app-style" rootStyle.innerHTML = .string(tokamakStyles)