Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove DefaultApp, make DOMRenderer internal #227

Merged
merged 3 commits into from
Aug 1, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 17 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,23 +48,18 @@ struct Counter: View {
}
}
}
```

You can then render your view in any DOM node captured with
[JavaScriptKit](https://github.com/kateinoigakukun/JavaScriptKit/), just
pass it as an argument to the `DOMRenderer` initializer together with your view:

```swift
import JavaScriptKit
import TokamakDOM

let document = JSObjectRef.global.document.object!

let divElement = document.createElement!("div").object!
let renderer = DOMRenderer(Counter(count: 5, limit: 15), divElement)
struct CounterApp: App {
var body: some Scene {
WindowGroup("Counter Demo") {
Counter(count: 5, limit: 15)
}
}
}

let body = document.body.object!
_ = body.appendChild!(divElement)
// @main attribute is not supported in SwiftPM apps.
// See https://bugs.swift.org/browse/SR-12683 for more details.
CounterApp.main()
```

### Arbitrary HTML
Expand Down Expand Up @@ -108,9 +103,9 @@ app.
## Requirements for app developers

- macOS 10.15 and Xcode 11.4/11.5/11.6 for macOS. Xcode betas are currently not supported. You can have
those installed, but please make sure you use
[`xcode-select`](https://developer.apple.com/library/archive/technotes/tn2339/_index.html#//apple_ref/doc/uid/DTS40014588-CH1-HOW_DO_I_SELECT_THE_DEFAULT_VERSION_OF_XCODE_TO_USE_FOR_MY_COMMAND_LINE_TOOLS_)
to point it to a release version of Xcode.
those installed, but please make sure you use
[`xcode-select`](https://developer.apple.com/library/archive/technotes/tn2339/_index.html#//apple_ref/doc/uid/DTS40014588-CH1-HOW_DO_I_SELECT_THE_DEFAULT_VERSION_OF_XCODE_TO_USE_FOR_MY_COMMAND_LINE_TOOLS_)
to point it to a release version of Xcode.
- [Swift 5.2 or later](https://swift.org/download/) for Linux.
carson-katri marked this conversation as resolved.
Show resolved Hide resolved

## Requirements for app users
Expand All @@ -128,7 +123,7 @@ Not all of these were tested though, compatibility reports are very welcome!

Tokamak relies on [`carton`](https://carton.dev) as a primary build tool. As a part of these steps
you'll install `carton` via [Homebrew](https://brew.sh/) on macOS (unfortunately you'll have to build
it manually on Linux). Assuming you already have Homebrew installed, you can create a new Tokamak
it manually on Linux). Assuming you already have Homebrew installed, you can create a new Tokamak
app by following these steps:

1. Install `carton`:
Expand Down Expand Up @@ -156,15 +151,15 @@ carton init --template tokamak
```

4. Build the project and start the development server, `carton dev` can be kept running
during development:
during development:

```
carton dev
```

5. Open [http://127.0.0.1:8080/](http://127.0.0.1:8080/) in your browser to see the app
running. You can edit the app source code in your favorite editor and save it, `carton`
will immediately rebuild the app and reload all browser tabs that have the app open.
running. You can edit the app source code in your favorite editor and save it, `carton`
will immediately rebuild the app and reload all browser tabs that have the app open.

You can also clone this repository and run `carton dev` in its root directory. This
will build the demo app that shows almost all of the currently implemented APIs.
Expand Down
50 changes: 2 additions & 48 deletions Sources/TokamakCore/Target.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,52 +15,6 @@
// Created by Max Desiatov on 10/02/2019.
//

open class Target {
var element: MountedElementKind
public internal(set) var app: _AnyApp {
get {
if case let .app(app) = element {
return app
} else {
fatalError("`Target` has type \(element) not `App`")
}
}
set {
element = .app(newValue)
}
}

public internal(set) var scene: _AnyScene {
get {
if case let .scene(scene) = element {
return scene
} else {
fatalError("`Target` has type \(element) not `Scene`")
}
}
set {
element = .scene(newValue)
}
}

public internal(set) var view: AnyView {
get {
if case let .view(view) = element {
return view
} else {
fatalError("`Target` has type \(element) not `View`")
}
}
set {
element = .view(newValue)
}
}

public init<V: View>(_ view: V) {
element = .view(AnyView(view))
}

public init<A: App>(_ app: A) {
element = .app(_AnyApp(app))
}
public protocol Target: AnyObject {
var view: AnyView { get set }
}
10 changes: 0 additions & 10 deletions Sources/TokamakDOM/App.swift
Original file line number Diff line number Diff line change
Expand Up @@ -72,13 +72,3 @@ extension App {
ScenePhaseObserver.publisher
}
}

struct DefaultApp<V: View>: App {
var content: V?

var body: some Scene {
WindowGroup {
content
}
}
}
12 changes: 6 additions & 6 deletions Sources/TokamakDOM/DOMNode.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,22 +15,22 @@
import JavaScriptKit
import TokamakCore

public final class DOMNode: Target {
final class DOMNode: Target {
let ref: JSObjectRef
private var listeners: [String: JSClosure]
var view: AnyView

init<V: View>(_ view: V, _ ref: JSObjectRef, _ listeners: [String: Listener] = [:]) {
self.ref = ref
self.listeners = [:]
super.init(view)
self.view = AnyView(view)
reinstall(listeners)
}

init<A: App>(_ app: A, _ ref: JSObjectRef, _ listeners: [String: Listener] = [:]) {
init(_ ref: JSObjectRef) {
self.ref = ref
self.listeners = [:]
super.init(app)
reinstall(listeners)
view = AnyView(EmptyView())
listeners = [:]
}

/// Removes all existing event listeners on this DOM node and install new ones from
Expand Down
20 changes: 6 additions & 14 deletions Sources/TokamakDOM/DOMRenderer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -73,33 +73,25 @@ func appendRootStyle(_ rootNode: JSObjectRef) {
_ = head.appendChild!(rootStyle)
}

public final class DOMRenderer: Renderer {
public private(set) var reconciler: StackReconciler<DOMRenderer>?
final class DOMRenderer: Renderer {
private(set) var reconciler: StackReconciler<DOMRenderer>?

private let rootRef: JSObjectRef

public convenience init<V: View>(
_ view: V,
_ ref: JSObjectRef,
_ rootEnvironment: EnvironmentValues? = nil
) {
self.init(DefaultApp(content: view), ref, rootEnvironment)
}

init<A: App>(_ app: A, _ ref: JSObjectRef, _ rootEnvironment: EnvironmentValues? = nil) {
rootRef = ref
appendRootStyle(ref)

reconciler = StackReconciler(
app: app,
target: DOMNode(app, ref),
target: DOMNode(ref),
environment: .defaultEnvironment,
renderer: self,
scheduler: timeoutScheduler
)
}

public func mountTarget(to parent: DOMNode, with host: MountedHost) -> DOMNode? {
func mountTarget(to parent: DOMNode, with host: MountedHost) -> DOMNode? {
guard let (outerHTML, listeners) = mapAnyView(
host.view,
transform: { (html: AnyHTML) in (html.outerHTML, html.listeners) }
Expand Down Expand Up @@ -132,14 +124,14 @@ public final class DOMRenderer: Renderer {
return DOMNode(host.view, lastChild, listeners)
}

public func update(target: DOMNode, with host: MountedHost) {
func update(target: DOMNode, with host: MountedHost) {
guard let html = mapAnyView(host.view, transform: { (html: AnyHTML) in html })
else { return }

html.update(dom: target)
}

public func unmount(
func unmount(
target: DOMNode,
from parent: DOMNode,
with host: MountedHost,
Expand Down