Skip to content
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
28 changes: 28 additions & 0 deletions Example/OpenSwiftUIUITests/UITests/SnapshotTesting+Testing.swift
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,34 @@ func openSwiftUIAssertSnapshot<V: View, Format>(
)
}

// FIXME: Should remove controller in name
func openSwiftUIControllerAssertSnapshot<V: PlatformViewController, Format>(
of value: @autoclosure () -> V,
as snapshotting: Snapshotting<PlatformViewController, Format>,
named name: String? = nil,
record recording: Bool? = shouldRecord,
timeout: TimeInterval = 5,
fileID: StaticString = #fileID,
file filePath: StaticString = #filePath,
testName: String = #function,
line: UInt = #line,
column: UInt = #column
) {
openSwiftUIAssertSnapshot(
of: value(),
as: snapshotting,
named: name,
record: recording,
timeout: timeout,
fileID: fileID,
file: filePath,
testName: testName,
line: line,
column: column
)
}

// FIXME: Should be internal, private due to conflict infer
private func openSwiftUIAssertSnapshot<Value, Format>(
of value: @autoclosure () -> Value,
as snapshotting: Snapshotting<Value, Format>,
Expand Down
45 changes: 45 additions & 0 deletions Example/OpenSwiftUIUITests/View/Image/AsyncImageUITests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
//
// AsyncImageUITests.swift
// OpenSwiftUIUITests

import Foundation
import SnapshotTesting
import Testing

@MainActor
@Suite(.snapshots(record: .never, diffTool: diffTool))
struct AsyncImageUITests {
@Test
func localLogoImage() async throws {
struct ContentView: View {
var body: some View {
AsyncImage(url: Bundle.main.url(forResource: "logo", withExtension: "png")) { phase in
switch phase {
case .empty:
Color.red
case .success(let image):
image
.resizable()
.frame(width: 100, height: 100)
case .failure:
Color.yellow
@unknown default:
Color.yellow
}
}
}
}
// FIXME:
// 1. SUI can screenshot without manully set frame for placeholder state while OSUI need it
// let controller = PlatformHostingController(rootView: ContentView())
// openSwiftUIControllerAssertSnapshot(of: controller, as: .image, named: "placeholder")
// openSwiftUIControllerAssertSnapshot(of: controller, as: .wait(for: 5, on: .image), named: "logo")
// 2. OSUI can screenshot correctly using .wait(for: 1, on: .image) while SUI need to use try await Task.sleep
// Those mismatch behavior is PlatformViewController issue
let controller = PlatformHostingController(rootView: ContentView())
controller.view.frame = CGRect(origin: .zero, size: CGSize(width: 200, height: 200))
openSwiftUIControllerAssertSnapshot(of: controller, as: .image, named: "placeholder")
try await Task.sleep(for: .seconds(1))
openSwiftUIControllerAssertSnapshot(of: controller, as: .image, named: "logo")
}
}
Binary file added Example/TestingHost/images/logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions Sources/COpenSwiftUI/Overlay/AppKit/OpenSwiftUI+NSView.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#if OPENSWIFTUI_TARGET_OS_OSX

#import <AppKit/AppKit.h>
#import <QuartzCore/CALayer.h>

OPENSWIFTUI_ASSUME_NONNULL_BEGIN

Expand All @@ -24,6 +25,8 @@ OPENSWIFTUI_ASSUME_NONNULL_BEGIN

@end

void _SetLayerViewDelegate(CALayer *layer, id view);

OPENSWIFTUI_ASSUME_NONNULL_END

#endif /* OPENSWIFTUI_TARGET_OS_OSX */
Expand Down
4 changes: 4 additions & 0 deletions Sources/COpenSwiftUI/Overlay/AppKit/OpenSwiftUI+NSView.m
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,8 @@

#if OPENSWIFTUI_TARGET_OS_OSX

void _SetLayerViewDelegate(CALayer *layer, id view) {
layer.delegate = view;
}

#endif
23 changes: 23 additions & 0 deletions Sources/COpenSwiftUI/Overlay/UIKit/OpenSwiftUI+UIView.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
//
// OpenSwiftUI+UIView.h
// COpenSwiftUI

#ifndef OpenSwiftUI_UIView_h
#define OpenSwiftUI_UIView_h

#include "OpenSwiftUIBase.h"

#if OPENSWIFTUI_TARGET_OS_IOS || OPENSWIFTUI_TARGET_OS_VISION

#import <UIKit/UIKit.h>

OPENSWIFTUI_ASSUME_NONNULL_BEGIN

UIView * _UIKitCreateCustomView(Class class, CALayer *layer);

OPENSWIFTUI_ASSUME_NONNULL_END

#endif /* OPENSWIFTUI_TARGET_OS_IOS || OPENSWIFTUI_TARGET_OS_VISION */

#endif /* OpenSwiftUI_UIView_h */

16 changes: 16 additions & 0 deletions Sources/COpenSwiftUI/Overlay/UIKit/OpenSwiftUI+UIView.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
//
// OpenSwiftUI+UIView.m
// COpenSwiftUI

#import "OpenSwiftUI+UIView.h"

#if OPENSWIFTUI_TARGET_OS_IOS || OPENSWIFTUI_TARGET_OS_VISION

#include "Shims/UIKit/UIKit_Private.h"

UIView * _UIKitCreateCustomView(Class class, CALayer *layer) {
return [[class alloc] _initWithLayer:layer];
}

#endif /* OPENSWIFTUI_TARGET_OS_IOS || OPENSWIFTUI_TARGET_OS_VISION */

2 changes: 2 additions & 0 deletions Sources/COpenSwiftUI/Shims/AppKit/AppKit_Private.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ typedef OPENSWIFTUI_ENUM(NSInteger, NSViewVibrantBlendingStyle) {
@interface NSView ()
@property (getter=isOpaque) BOOL opaque;
- (void)_updateLayerGeometryFromView;
- (void)_updateLayerShadowFromView;
- (void)_updateLayerShadowColorFromView;
@end

@interface NSAppearance (OpenSwiftUI_SPI)
Expand Down
2 changes: 0 additions & 2 deletions Sources/COpenSwiftUI/Shims/UIKit/UIKit_Private.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,6 @@ bool UIViewIgnoresTouchEvents(UIView *view);
OPENSWIFTUI_EXPORT
float UIAnimationDragCoefficient(void);

UIView * _UIKitCreateCustomView(Class class, CALayer *layer);

// MARK: - UIUpdate related private API from UIKitCore

OPENSWIFTUI_EXPORT
Expand Down
4 changes: 0 additions & 4 deletions Sources/COpenSwiftUI/Shims/UIKit/UIKit_Private.m
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,4 @@ - (NSObject *)_environmentWrapper_openswiftui_safe_wrapper {
}
@end

UIView * _UIKitCreateCustomView(Class class, CALayer *layer) {
return [[class alloc] _initWithLayer:layer];
}

#endif /* __has_include(<UIKit/UIKit.h>) */
61 changes: 60 additions & 1 deletion Sources/OpenSwiftUI/Render/DisplayList/AppKitDisplayList.swift
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,22 @@ final class NSViewPlatformViewDefinition: PlatformViewDefinition, @unchecked Sen
}
}

// Audited for 6.5.4
override static func makeLayerView(type: CALayer.Type, kind: PlatformViewDefinition.ViewKind) -> AnyObject {
_openSwiftUIUnimplementedFailure()
let cls: NSView.Type
if kind == .shape {
cls = _NSShapeHitTestingView.self
} else if kind == .platformLayer {
cls = _NSPlatformLayerView.self
} else {
cls = kind.isContainer ? _NSInheritedView.self : _NSGraphicsView.self
}
let view = cls.init()
let layer = type.init()
_SetLayerViewDelegate(layer, view)
view.layer = layer
initView(view, kind: kind)
return view
}

override class func makePlatformView(view: AnyObject, kind: PlatformViewDefinition.ViewKind) {
Expand Down Expand Up @@ -142,4 +156,49 @@ private class _NSProjectionView: _NSInheritedView {
layer?.transform = .init(projectionTransform)
}
}

// MARK: - _NSShapeHitTestingView [WIP]

@objc
private class _NSShapeHitTestingView: _NSGraphicsView {
var path: Path

override init(frame frameRect: NSRect) {
path = .init()
super.init(frame: frameRect)
}

required init?(coder: NSCoder) {
path = .init()
super.init(coder: coder)
}

override func hitTest(_ point: NSPoint) -> NSView? {
// path.contains(, eoFill: false)
_openSwiftUIUnimplementedWarning()
return nil
}
}

// MARK: - _NSPlatformLayerView

@objc
private class _NSPlatformLayerView: _NSGraphicsView {
override init(frame frameRect: NSRect) {
super.init(frame: frameRect)
}

required init?(coder: NSCoder) {
super.init(coder: coder)
}

override func _updateLayerShadowFromView() {
_openSwiftUIEmptyStub()
}

override func _updateLayerShadowColorFromView() {
_openSwiftUIEmptyStub()
}
}

#endif
Loading
Loading