Skip to content

Commit

Permalink
Merge pull request #151 from liveviewnative/macos
Browse files Browse the repository at this point in the history
Fix macOS build
  • Loading branch information
carson-katri authored Jan 26, 2023
2 parents a2a18c2 + 5124af6 commit 8db6e44
Show file tree
Hide file tree
Showing 12 changed files with 112 additions and 58 deletions.
10 changes: 9 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,12 @@ jobs:
shell: bash
run: |
sudo xcode-select --switch /Applications/Xcode_14.2.app
xcodebuild test -scheme LiveViewNative -sdk iphonesimulator16.2 -destination "OS=16.2,name=iPhone 14 Pro"
xcodebuild test -scheme LiveViewNative -sdk iphonesimulator16.2 -destination "OS=16.2,name=iPhone 14 Pro"
- name: Build for macOS
shell: bash
run: |
xcodebuild -scheme LiveViewNative -sdk macosx13.1 -destination "platform=macOS"
- name: Build for watchOS
shell: bash
run: |
xcodebuild -scheme LiveViewNative -sdk watchsimulator9.1 -destination "OS=9.1,name=Apple Watch Series 8 (45mm)"
2 changes: 1 addition & 1 deletion Package.resolved
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"location" : "https://github.com/liveviewnative/liveview-native-core-swift.git",
"state" : {
"branch" : "main",
"revision" : "144e9e6ef84d5fb37dea201ab06f80f6ae5fc292"
"revision" : "0387adcfead5e4d6b84e3edf2f675aa333648451"
}
},
{
Expand Down
7 changes: 5 additions & 2 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ import PackageDescription
let package = Package(
name: "LiveViewNative",
platforms: [
.iOS("16.0")
.iOS("16.0"),
.macOS("13.0"),
.watchOS("9.0"),
],
products: [
// Products define the executables and libraries a package produces, and make them visible to other packages.
Expand All @@ -32,7 +34,8 @@ let package = Package(
]),
.testTarget(
name: "LiveViewNativeTests",
dependencies: ["LiveViewNative"]),
dependencies: ["LiveViewNative"]
),
.testTarget(
name: "RenderingTests",
dependencies: ["LiveViewNative"]
Expand Down
4 changes: 4 additions & 0 deletions Sources/LiveViewNative/BuiltinRegistry.swift
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,16 @@ struct BuiltinRegistry {
ProgressView(element: element, context: context)
case "divider":
Divider()
#if os(iOS)
case "edit-button":
EditButton()
#endif
case "toggle":
Toggle(element: element, context: context)
#if !os(watchOS)
case "menu":
Menu(element: element, context: context)
#endif
case "slider":
Slider(element: element, context: context)
case "phx-form":
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,11 @@ struct ListRowSeparatorModifier: ViewModifier, Decodable, Equatable {
}

func body(content: Content) -> some View {
#if !os(watchOS)
content.listRowSeparator(visibility, edges: edges)
#else
content
#endif
}

private enum CodingKeys: String, CodingKey {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
//
// Created by Carson Katri on 1/19/23.
//

#if !os(watchOS)
import SwiftUI

struct Menu<R: CustomRegistry>: View {
Expand Down Expand Up @@ -43,3 +43,4 @@ fileprivate extension View {
}
}
}
#endif
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,12 @@ private extension SwiftUI.List {
switch element.attributeValue(for: "style") {
case nil, "plain":
self.listStyle(.plain)
#if os(iOS)
case "grouped":
self.listStyle(.grouped)
case "inset-grouped":
self.listStyle(.insetGrouped)
#endif
default:
fatalError("Invalid list style '\(element.attributeValue(for: "name")!)'")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,10 @@ struct SecureField<R: CustomRegistry>: TextFieldProtocol {
.focused($isFocused)
.applyTextFieldStyle(textFieldStyle)
.applyAutocorrectionDisabled(disableAutocorrection)
#if os(iOS) || os(tvOS)
.textInputAutocapitalization(autocapitalization)
.applyKeyboardType(keyboard)
#endif
.applySubmitLabel(submitLabel)
.onChange(of: isFocused, perform: handleFocus)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,12 @@ struct TextField<R: CustomRegistry>: TextFieldProtocol {
.focused($isFocused)
.applyTextFieldStyle(textFieldStyle)
.applyAutocorrectionDisabled(disableAutocorrection)
#if !os(macOS)
.textInputAutocapitalization(autocapitalization)
#endif
#if os(iOS) || os(tvOS)
.applyKeyboardType(keyboard)
#endif
.applySubmitLabel(submitLabel)
.onChange(of: isFocused, perform: handleFocus)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ extension TextFieldProtocol {
}
}

#if !os(macOS)
var autocapitalization: TextInputAutocapitalization? {
switch element.attributeValue(for: "autocapitalization") {
case "sentences":
Expand All @@ -105,7 +106,9 @@ extension TextFieldProtocol {
return nil
}
}
#endif

#if os(iOS) || os(tvOS)
var keyboard: UIKeyboardType? {
switch element.attributeValue(for: "keyboard") {
case "ascii-capable":
Expand Down Expand Up @@ -134,6 +137,7 @@ extension TextFieldProtocol {
return nil
}
}
#endif

var submitLabel: SubmitLabel? {
switch element.attributeValue(for: "submit-label") {
Expand Down Expand Up @@ -164,8 +168,12 @@ extension TextFieldProtocol {
enum TextFieldStyle: String {
case automatic
case plain
#if !os(watchOS)
case roundedBorder = "rounded-border"
#endif
#if os(macOS)
case squareBorder = "square-border"
#endif
}

extension View {
Expand All @@ -176,14 +184,14 @@ extension View {
self.textFieldStyle(.automatic)
case .plain:
self.textFieldStyle(.plain)
#if !os(watchOS)
case .roundedBorder:
self.textFieldStyle(.roundedBorder)
#endif
#if os(macOS)
case .squareBorder:
#if os(macOS)
self.textFieldStyle(.squareBorder)
#else
self
#endif
#endif
}
}

Expand All @@ -196,6 +204,7 @@ extension View {
}
}

#if os(iOS) || os(tvOS)
@ViewBuilder
func applyKeyboardType(_ keyboardType: UIKeyboardType?) -> some View {
if let keyboardType {
Expand All @@ -204,6 +213,7 @@ extension View {
self
}
}
#endif

@ViewBuilder
func applySubmitLabel(_ submitLabel: SubmitLabel?) -> some View {
Expand Down
6 changes: 3 additions & 3 deletions Tests/RenderingTests/ProgressViewTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,14 @@ import SwiftUI
@MainActor
final class ProgressViewTests: XCTestCase {
func testValue() throws {
try assertMatch(#"<progressview value="0.5" />"#) {
try assertMatch(#"<progress-view value="0.5" />"#, size: .init(width: 200, height: 200)) {
ProgressView(value: 0.5)
}
}

func testTotal() throws {
try assertMatch(#"<progressview value="2.5" total="5" />"#) {
ProgressView(value: 0.5, total: 5)
try assertMatch(#"<progress-view value="2.5" total="5" />"#, size: .init(width: 200, height: 200)) {
ProgressView(value: 2.5, total: 5)
}
}
}
108 changes: 62 additions & 46 deletions Tests/RenderingTests/assertMatch.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,56 +11,71 @@ import Foundation
@testable import LiveViewNative
import LiveViewNativeCore

@MainActor
func assertMatch(
_ markup: String,
_ file: String = #file,
_ line: Int = #line,
_ function: StaticString = #function,
environment: @escaping (inout EnvironmentValues) -> () = { _ in },
size: CGSize? = nil,
@ViewBuilder _ view: () -> some View
) throws {
try assertMatch(name: "\(URL(filePath: file).lastPathComponent)-\(line)-\(function)", markup, environment: environment, size: size, view)
}

@MainActor
func assertMatch(
name: String,
_ markup: String,
environment: @escaping (inout EnvironmentValues) -> () = { _ in },
size: CGSize? = nil,
@ViewBuilder _ view: () -> some View
) throws {
let session = LiveSessionCoordinator(URL(string: "http://localhost")!)
let document = try LiveViewNativeCore.Document.parse(markup)
let viewTree = session.rootCoordinator.builder.fromNodes(
document[document.root()].children(),
context: LiveContext(coordinator: session.rootCoordinator, url: session.url)
).environment(\.coordinatorEnvironment, CoordinatorEnvironment(session.rootCoordinator, document: document))

let markupImage = snapshot(
viewTree
.transformEnvironment(\.self, transform: environment),
size: size
)?.pngData()
let viewImage = snapshot(
view()
.transformEnvironment(\.self, transform: environment),
size: size
)?.pngData()
extension XCTestCase {
@MainActor
func assertMatch(
_ markup: String,
_ file: String = #file,
_ line: Int = #line,
_ function: StaticString = #function,
environment: @escaping (inout EnvironmentValues) -> () = { _ in },
size: CGSize? = nil,
@ViewBuilder _ view: () -> some View
) throws {
try assertMatch(name: "\(URL(filePath: file).lastPathComponent)-\(line)-\(function)", markup, environment: environment, size: size, view)
}

if markupImage == viewImage {
XCTAssert(true)
} else {
let markupURL = URL.temporaryDirectory.appendingPathComponent("\(name)_markup", conformingTo: .png)
let viewURL = URL.temporaryDirectory.appendingPathComponent("\(name)_view", conformingTo: .png)
try markupImage?.write(to: markupURL)
try viewImage?.write(to: viewURL)
XCTAssert(false, "Rendered views did not match. Outputs saved to \(markupURL.path()) and \(viewURL.path())")
@MainActor
func assertMatch(
name: String,
_ markup: String,
environment: @escaping (inout EnvironmentValues) -> () = { _ in },
size: CGSize? = nil,
@ViewBuilder _ view: () -> some View
) throws {
#if !os(iOS)
fatalError("Rendering tests not supported on platforms other than iOS at this time")
#else
let session = LiveSessionCoordinator(URL(string: "http://localhost")!)
let document = try LiveViewNativeCore.Document.parse(markup)
let viewTree = session.rootCoordinator.builder.fromNodes(
document[document.root()].children(),
context: LiveContext(coordinator: session.rootCoordinator, url: session.url)
).environment(\.coordinatorEnvironment, CoordinatorEnvironment(session.rootCoordinator, document: document))

guard let markupImage = snapshot(
viewTree
.transformEnvironment(\.self, transform: environment),
size: size
)
else {
return XCTAssert(false, "Markup failed to render an image")
}
guard let viewImage = snapshot(
view()
.transformEnvironment(\.self, transform: environment),
size: size
)
else {
return XCTAssert(false, "View failed to render an image")
}

self.add(XCTAttachment(image: markupImage))
self.add(XCTAttachment(image: viewImage))

let markupData = markupImage.pngData()
let viewData = viewImage.pngData()

if markupData == viewData {
XCTAssert(true)
} else {
XCTAssert(false, "Rendered views did not match. Attachments can be viewed in the Report navigator.")
}
#endif
}
}

#if os(iOS)
private class SnapshotWindow: UIWindow {
override var safeAreaInsets: UIEdgeInsets {
.zero
Expand All @@ -86,3 +101,4 @@ private func snapshot(_ view: some View, size: CGSize?) -> UIImage? {
uiView.layer.render(in: context.cgContext)
}
}
#endif

0 comments on commit 8db6e44

Please sign in to comment.