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

Changes to use uniffi bindings for liveview-native-core #1287

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
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
12 changes: 6 additions & 6 deletions Package.resolved
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
{
"pins" : [
{
"identity" : "liveview-native-core-swift",
"identity" : "liveview-native-core",
"kind" : "remoteSourceControl",
"location" : "https://github.com/liveview-native/liveview-native-core-swift.git",
"location" : "https://github.com/liveview-native/liveview-native-core.git",
"state" : {
"revision" : "339594b395938e38f1fb2216a31c8791030ec9ba",
"version" : "0.2.1"
"revision" : "ced90995fda19a1b4eba0ea379112822246ee7ce",
"version" : "0.4.0-alpha-1"
}
},
{
Expand Down Expand Up @@ -86,8 +86,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/davidstump/SwiftPhoenixClient.git",
"state" : {
"revision" : "613989bf2e562d8a851ea83741681c3439353b45",
"version" : "5.0.0"
"revision" : "588bf6baab5d049752748e19a4bff32421ea40ec",
"version" : "5.3.2"
}
},
{
Expand Down
6 changes: 3 additions & 3 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ let package = Package(
.package(url: "https://github.com/scinfu/SwiftSoup.git", from: "2.3.2"),
.package(url: "https://github.com/davidstump/SwiftPhoenixClient.git", .upToNextMinor(from: "5.3.2")),
.package(url: "https://github.com/apple/swift-async-algorithms", from: "0.1.0"),
.package(url: "https://github.com/liveview-native/liveview-native-core-swift.git", exact: "0.2.1"),
.package(url: "https://github.com/liveview-native/liveview-native-core.git", exact: "0.4.0-alpha-1"),

.package(url: "https://github.com/apple/swift-argument-parser", from: "1.2.2"),
.package(url: "https://github.com/apple/swift-markdown.git", from: "0.2.0"),
Expand All @@ -45,7 +45,7 @@ let package = Package(
"SwiftSoup",
"SwiftPhoenixClient",
.product(name: "AsyncAlgorithms", package: "swift-async-algorithms"),
.product(name: "LiveViewNativeCore", package: "liveview-native-core-swift"),
.product(name: "LiveViewNativeCore", package: "liveview-native-core"),
"LiveViewNativeMacros",
"LiveViewNativeStylesheet"
],
Expand Down Expand Up @@ -146,7 +146,7 @@ let package = Package(
name: "LiveViewNativeStylesheet",
dependencies: [
"LiveViewNativeStylesheetMacros",
.product(name: "LiveViewNativeCore", package: "liveview-native-core-swift"),
.product(name: "LiveViewNativeCore", package: "liveview-native-core"),
.product(name: "Parsing", package: "swift-parsing"),
]
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,12 @@ public class LiveSessionCoordinator<R: RootRegistry>: ObservableObject {
@Published private(set) var stylesheet: Stylesheet<R>?

// Socket connection
var socket: Socket?
var socket: SwiftPhoenixClient.Socket?

private var domValues: DOMValues!

private var liveReloadSocket: Socket?
private var liveReloadChannel: Channel?
private var liveReloadSocket: SwiftPhoenixClient.Socket?
private var liveReloadChannel: SwiftPhoenixClient.Channel?

private var cancellables = Set<AnyCancellable>()

Expand Down
19 changes: 8 additions & 11 deletions Sources/LiveViewNative/Coordinators/LiveViewCoordinator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public class LiveViewCoordinator<R: RootRegistry>: ObservableObject {
@_spi(LiveForm) public let session: LiveSessionCoordinator<R>
var url: URL

private var channel: Channel?
private var channel: SwiftPhoenixClient.Channel?

@Published var document: LiveViewNativeCore.Document?
private var elementChangedSubjects = [NodeRef:ObjectWillChangePublisher]()
Expand Down Expand Up @@ -197,9 +197,7 @@ public class LiveViewCoordinator<R: RootRegistry>: ObservableObject {

private func handleDiff(payload: Payload, baseURL: URL) throws {
handleEvents(payload: payload)
let diff = try RootDiff(from: FragmentDecoder(data: payload))
self.rendered = try self.rendered.merge(with: diff)
self.document?.merge(with: try Document.parse(self.rendered.buildString()))
try self.document?.mergeFragmentJson(payload)
}

private func handleEvents(payload: Payload) {
Expand Down Expand Up @@ -329,7 +327,7 @@ public class LiveViewCoordinator<R: RootRegistry>: ObservableObject {
case redirect(LiveRedirect)
}

private func join(channel: Channel) -> AsyncThrowingStream<JoinResult, Error> {
private func join(channel: SwiftPhoenixClient.Channel) -> AsyncThrowingStream<JoinResult, Error> {
return AsyncThrowingStream<JoinResult, Error> { [weak channel] (continuation: AsyncThrowingStream<JoinResult, Error>.Continuation) -> Void in
channel?.join()
.receive("ok") { [weak self, weak channel] message in
Expand Down Expand Up @@ -385,21 +383,20 @@ public class LiveViewCoordinator<R: RootRegistry>: ObservableObject {

private func handleJoinPayload(renderedPayload: Payload) {
// todo: what should happen if decoding or parsing fails?
self.rendered = try! Root(from: FragmentDecoder(data: renderedPayload))
self.document = try! LiveViewNativeCore.Document.parse(rendered.buildString())
self.document?.on(.changed) { [unowned self] doc, nodeRef in
switch doc[nodeRef].data {
self.document = try! LiveViewNativeCore.Document.parseFragmentJson(payload: renderedPayload)
self.document?.on(.changed) { nodeRef, nodeData, parent in
switch nodeData {
case .root:
// when the root changes, update the `NavStackEntry` itself.
self.objectWillChange.send()
case .leaf:
// text nodes don't have their own views, changes to them need to be handled by the parent Text view
if let parent = doc.getParent(nodeRef) {
if let parent = parent {
self.elementChanged(nodeRef).send()
} else {
self.elementChanged(nodeRef).send()
}
case .element:
case .nodeElement:
// when a single element changes, send an update only to that element.
self.elementChanged(nodeRef).send()
}
Expand Down
8 changes: 4 additions & 4 deletions Sources/LiveViewNative/Live/LiveElement.swift
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ public extension _LiveElementTracked {
///
/// - Parameter predicate: The filter used to select child nodes for render.
func children(_ predicate: (Node) -> Bool = { node in
!node.attributes.contains(where: { $0.name.namespace == nil && $0.name.name == "template" })
!node.attributes().contains(where: { $0.name.namespace == nil && $0.name.name == "template" })
}) -> some View {
context.coordinator.builder.fromNodes(_element.children.filter(predicate), context: context.storage)
}
Expand All @@ -126,9 +126,9 @@ public extension _LiveElementTracked {
/// - Parameter includeDefault: Whether elements without a `template` attribute should be included in the filter. Defaults to `false`.
func children(in template: Template, default includeDefault: Bool = false) -> some View {
children {
$0.attributes.contains(where: {
$0.attributes().contains(where: {
$0 == template
}) || (includeDefault && !$0.attributes.contains(where: { $0.name.namespace == nil && $0.name.name == "template" }))
}) || (includeDefault && !$0.attributes().contains(where: { $0.name.namespace == nil && $0.name.name == "template" }))
}
}

Expand All @@ -138,7 +138,7 @@ public extension _LiveElementTracked {
/// - Parameter includeDefault: Whether elements without a `template` attribute should be included in the filter. Defaults to `false`.
func hasTemplate(_ template: Template, default includeDefault: Bool = false) -> Bool {
_element.children.contains(where: {
for attribute in $0.attributes {
for attribute in $0.attributes() {
if attribute == template {
return true
} else if includeDefault && attribute.name.namespace == nil && attribute.name.name == "template" {
Expand Down
10 changes: 5 additions & 5 deletions Sources/LiveViewNative/Property Wrappers/LiveContext.swift
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ public struct LiveContext<R: RootRegistry>: DynamicProperty {
/// Ignores any children with a `template` attribute.
public func buildChildren(of element: ElementNode) -> some View {
return coordinator.builder.fromNodes(element.children().filter({
if case let .element(element) = $0.data {
if case let .nodeElement(element) = $0.data() {
return !element.attributes.contains(where: { $0.name == "template" })
} else {
return true
Expand All @@ -70,7 +70,7 @@ public struct LiveContext<R: RootRegistry>: DynamicProperty {
_ template: String
) -> (NodeChildrenSequence.Element) -> Bool {
{ child in
if case let .element(element) = child.data,
if case let .nodeElement(element) = child.data(),
element.attributes.first(where: { $0.name == "template" })?.value == template
{
return true
Expand All @@ -81,7 +81,7 @@ public struct LiveContext<R: RootRegistry>: DynamicProperty {
}

private static func hasTemplateAttribute(_ child: NodeChildrenSequence.Element) -> Bool {
if case let .element(element) = child.data,
if case let .nodeElement(element) = child.data(),
element.attributes.contains(where: { $0.name == "template" })
{
return true
Expand Down Expand Up @@ -127,7 +127,7 @@ public struct LiveContext<R: RootRegistry>: DynamicProperty {
let namedSlotChildren = children.filter(Self.isTemplateElement(template))
if namedSlotChildren.isEmpty && includeDefaultSlot {
let defaultSlotChildren = children.filter({
if case let .element(element) = $0.data {
if case let .nodeElement(element) = $0.data() {
return !element.attributes.contains(where: {
$0.name.rawValue == "template"
})
Expand Down Expand Up @@ -169,7 +169,7 @@ public struct LiveContext<R: RootRegistry>: DynamicProperty {
of element: ElementNode
) -> [NodeChildrenSequence.Element] {
element.children().filter {
!$0.attributes.contains(where: { $0.name.rawValue == "template" })
!$0.attributes().contains(where: { $0.name.rawValue == "template" })
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ extension ObservedElement {
if let _resolvedChildIDs {
return _resolvedChildIDs
} else {
let result = Set(self.resolvedChildren.map(\.id))
let result = Set(self.resolvedChildren.map { $0.id()})
_resolvedChildIDs = result
return result
}
Expand Down Expand Up @@ -183,3 +183,9 @@ extension ObservedElement {
}
}
}

private extension Optional where Wrapped == ElementNode {
var nodeRef: NodeRef? {
self?.node.id()
}
}
14 changes: 7 additions & 7 deletions Sources/LiveViewNative/Protocols/ContentBuilder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -501,14 +501,14 @@ public extension ContentBuilder {
return try build(
element
.children()
.filter({ $0.attributes.contains(where: { $0.name == "template" && $0.value == template }) }),
.filter({ $0.attributes().contains(where: { $0.name == "template" && $0.value == template }) }),
in: context
)
} else {
return try build(
element
.children()
.filter({ !$0.attributes.contains(where: { $0.name == "template" }) }),
.filter({ !$0.attributes().contains(where: { $0.name == "template" }) }),
in: context
)
}
Expand All @@ -522,7 +522,7 @@ public extension ContentBuilder {
return try build(
element
.children()
.filter({ $0.attributes.contains(where: { $0.name == "template" && template.value.contains($0.value ?? "") }) }),
.filter({ $0.attributes().contains(where: { $0.name == "template" && template.value.contains($0.value ?? "") }) }),
in: context
)
}
Expand Down Expand Up @@ -569,15 +569,15 @@ public extension ContentBuilder {
if let template {
ViewTreeBuilder().fromNodes(
element.children()
.filter({ $0.attributes.contains(where: { $0.name == "template" && $0.value == template }) }),
.filter({ $0.attributes().contains(where: { $0.name == "template" && $0.value == template }) }),
context: context.context
)
.environment(\.coordinatorEnvironment, context.coordinatorEnvironment)
.environment(\.anyLiveContextStorage, context.context)
} else {
ViewTreeBuilder().fromNodes(
element.children()
.filter({ !$0.attributes.contains(where: { $0.name == "template" }) }),
.filter({ !$0.attributes().contains(where: { $0.name == "template" }) }),
context: context.context
)
.environment(\.coordinatorEnvironment, context.coordinatorEnvironment)
Expand All @@ -593,7 +593,7 @@ public extension ContentBuilder {
) -> some View {
ViewTreeBuilder().fromNodes(
element.children()
.filter({ $0.attributes.contains(where: { $0.name == "template" && template.value.contains($0.value ?? "") }) }),
.filter({ $0.attributes().contains(where: { $0.name == "template" && template.value.contains($0.value ?? "") }) }),
context: context.context
)
.environment(\.coordinatorEnvironment, context.coordinatorEnvironment)
Expand All @@ -608,7 +608,7 @@ public extension ContentBuilder {
) -> SwiftUI.Text {
element.children()
.lazy
.filter({ $0.attributes.contains(where: { $0.name == "template" && template.value.contains($0.value ?? "") }) })
.filter({ $0.attributes().contains(where: { $0.name == "template" && template.value.contains($0.value ?? "") }) })
.first?.asElement().flatMap({ Text<R>(element: $0, overrideStylesheet: context.stylesheet).body })
?? SwiftUI.Text("")
}
Expand Down
4 changes: 2 additions & 2 deletions Sources/LiveViewNative/Stylesheets/ViewReference.swift
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ struct ToolbarTreeBuilder<R: RootRegistry> {
// ToolbarTreeBuilder.fromNode may not be called with a root or leaf node
switch node {
case let .n(node):
if case .element(let element) = node.data {
if case .nodeElement(let element) = node.data() {
Self.lookup(ElementNode(node: node, data: element))
}
case let .e(error):
Expand Down Expand Up @@ -271,7 +271,7 @@ struct CustomizableToolbarTreeBuilder<R: RootRegistry> {
// CustomizableToolbarTreeBuilder.fromNode may not be called with a root or leaf node
switch node {
case let .n(node):
if case .element(let element) = node.data {
if case .nodeElement(let element) = node.data() {
Self.lookup(ElementNode(node: node, data: element))
}
case let .e(error):
Expand Down
14 changes: 7 additions & 7 deletions Sources/LiveViewNative/Utils/DOM.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@ import LiveViewNativeCore
/// - ``elementChildren()``
/// - ``innerText()``
public struct ElementNode: Identifiable {
public let node: Node
public let data: ElementData
let node: Node
let data: Element

init(node: Node, data: ElementData) {
init(node: Node, data: Element) {
self.node = node
self.data = data
}
Expand All @@ -42,9 +42,9 @@ public struct ElementNode: Identifiable {
public func elementChildren() -> [ElementNode] { node.children().compactMap({ $0.asElement() }) }

/// The namespace of the element.
public var namespace: String? { data.namespace }
public var namespace: String? { data.name.namespace }
/// The tag name of the element.
public var tag: String { data.tag }
public var tag: String { data.name.name }
/// The list of attributes present on this element.
public var attributes: [LiveViewNativeCore.Attribute] { data.attributes }
/// The attribute with the given name, or `nil` if there is no such attribute.
Expand Down Expand Up @@ -93,7 +93,7 @@ public struct ElementNode: Identifiable {
public func innerText() -> String {
// TODO: should follow the spec and insert/collapse whitespace around elements
self.children().compactMap { node in
if case .leaf(let content) = node.data {
if case .leaf(let content) = node.data() {
return content
} else {
return nil
Expand All @@ -115,7 +115,7 @@ public struct ElementNode: Identifiable {

extension Node {
public func asElement() -> ElementNode? {
if case .element(let data) = self.data {
if case .nodeElement(let data) = self.data() {
return ElementNode(node: self, data: data)
} else {
return nil
Expand Down
8 changes: 4 additions & 4 deletions Sources/LiveViewNative/ViewTree.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,12 @@ struct ViewTreeBuilder<R: RootRegistry> {
let context: LiveContextStorage<R>

var body: some View {
switch node.data {
switch node.data() {
case .root:
fatalError("ViewTreeBuilder.fromNode may not be called with the root node")
case .leaf(let content):
SwiftUI.Text(content)
case .element(let element):
case .nodeElement(let element):
context.coordinator.builder.fromElement(ElementNode(node: node, data: element), context: context)
}
}
Expand All @@ -48,7 +48,7 @@ struct ViewTreeBuilder<R: RootRegistry> {
let withID = applyID(element: element, to: bound)
let withIDAndTag = applyTag(element: element, to: withID)

return ObservedElement.Observer.Applicator(element.node.id) {
return ObservedElement.Observer.Applicator(element.node.id()) {
withIDAndTag
.environment(\.element, element)
}
Expand Down Expand Up @@ -288,7 +288,7 @@ private enum ForEachElement: Identifiable {
case let .keyed(_, id):
return id
case let .unkeyed(node):
return "\(node.id)"
return "\(node.id().ref())"
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,8 @@ struct ShareLink<Root: RootRegistry>: View {
public var body: some View {
#if !os(tvOS)
let useDefaultLabel = $liveElement.childNodes.filter({
guard case let .element(data) = $0.data else { return true }
return data.tag != "SharePreview"
guard case let .nodeElement(data) = $0.data() else { return true }
return data.name.name != "SharePreview"
}).isEmpty

let subject = self.subject.flatMap(SwiftUI.Text.init)
Expand Down
4 changes: 2 additions & 2 deletions Sources/LiveViewNative/Views/Images/ImageView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -129,8 +129,8 @@ struct ImageView<Root: RootRegistry>: View {

var label: SwiftUI.Text? {
if let labelNode = $liveElement.childNodes.first {
switch labelNode.data {
case let .element(element):
switch labelNode.data() {
case let .nodeElement(element):
return Text<Root>(element: ElementNode(node: labelNode, data: element), overrideStylesheet: nil).body
case let .leaf(label):
return .init(label)
Expand Down
Loading
Loading