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
26 changes: 26 additions & 0 deletions Sources/COpenSwiftUI/UIKit/OpenSwiftUI+UIApplication.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
//
// OpenSwiftUI+UIApplication.h
// COpenSwiftUI
//
// Audited for iOS 18.0
// Status: Complete

#ifndef OpenSwiftUI_UIApplication_h
#define OpenSwiftUI_UIApplication_h

#include "OpenSwiftUIBase.h"

#if OPENSWIFTUI_TARGET_OS_IOS

#import <UIKit/UIKit.h>

OPENSWIFTUI_ASSUME_NONNULL_BEGIN

OPENSWIFTUI_EXPORT
UIContentSizeCategory _UIApplicationDefaultContentSizeCategory();

OPENSWIFTUI_ASSUME_NONNULL_END

#endif /* OPENSWIFTUI_TARGET_OS_IOS */

#endif /* OpenSwiftUI_UIApplication_h */
27 changes: 27 additions & 0 deletions Sources/COpenSwiftUI/UIKit/OpenSwiftUI+UIApplication.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
//
// OpenSwiftUI+UIApplication.m
// COpenSwiftUI
//
// Audited for iOS 18.0
// Status: Complete

#include "OpenSwiftUI+UIApplication.h"

#if OPENSWIFTUI_TARGET_OS_IOS
#include <objc/runtime.h>

UIContentSizeCategory _UIApplicationDefaultContentSizeCategory() {
typedef UIContentSizeCategory (*Func)(Class, SEL);
SEL selector = NSSelectorFromString(@"_defaultContentSizeCategory");
Func func = nil;
if ([UIApplication resolveClassMethod:selector]) {
IMP impl = class_getMethodImplementation(UIApplication.class, selector);
func = (Func)impl;
}
if (func == nil) {
return UIContentSizeCategoryLarge;
}
return func(UIApplication.class, selector);
}

#endif /* OPENSWIFTUI_TARGET_OS_IOS */
2 changes: 1 addition & 1 deletion Sources/COpenSwiftUI/UIKit/OpenSwiftUI+UIColor.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,6 @@ BOOL _UIColorDependsOnTraitCollection(UIColor *color);

OPENSWIFTUI_ASSUME_NONNULL_END

#endif
#endif /* OPENSWIFTUI_TARGET_OS_IOS */

#endif /* OpenSwiftUI_UIColor_h */
33 changes: 33 additions & 0 deletions Sources/COpenSwiftUI/UIKit/OpenSwiftUITesting_Swizzles+UIKit.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
//
// OpenSwiftUITesting_Swizzles+UIKit.h
// COpenSwiftUI
//
// Audited for iOS 18.0
// Status: Complete

#ifndef OpenSwiftUITesting_Swizzles_UIKit_h
#define OpenSwiftUITesting_Swizzles_UIKit_h

#include "OpenSwiftUIBase.h"

#if OPENSWIFTUI_TARGET_OS_IOS
#include <UIKit/UIKit.h>

OPENSWIFTUI_ASSUME_NONNULL_BEGIN

@interface UIScreen (OpenSwiftUITesting_Swizzles)
+ (void)_performOpenSwiftUITestingOverrides;
- (CGFloat)_OpenSwiftUITesting_currentScreenScale;
- (BOOL)_OpenSwiftUITesting_wantsWideContentMargins;
@end

@interface UICollectionView (OpenSwiftUITesting_Swizzles)
+ (void)_performOpenSwiftUITestingOverrides;
- (id)_OpenSwiftUITesting__viewAnimationsForCurrentUpdateWithCollectionViewAnimator:(id)arg1;
@end

OPENSWIFTUI_ASSUME_NONNULL_END

#endif /* OPENSWIFTUI_TARGET_OS_IOS */

#endif /* OpenSwiftUITesting_Swizzles_UIKit_h */
37 changes: 37 additions & 0 deletions Sources/COpenSwiftUI/UIKit/OpenSwiftUITesting_Swizzles+UIKit.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
//
// OpenSwiftUITesting_Swizzles+UIKit.m
// COpenSwiftUI
//
// Audited for iOS 18.0
// Status: Complete

#include "OpenSwiftUITesting_Swizzles+UIKit.h"
#include "OpenSwiftUITesting_Swizzles.h"

#if OPENSWIFTUI_TARGET_OS_IOS

@implementation UIScreen (OpenSwiftUITesting_Swizzles)
+ (void)_performOpenSwiftUITestingOverrides {
_SwizzleMethods(UIScreen.class, @selector(scale), @selector(_OpenSwiftUITesting_currentScreenScale));
_SwizzleMethods(UIScreen.class, @selector(_wantsWideContentMargins), @selector(_OpenSwiftUITesting_wantsWideContentMargins));
}

- (CGFloat)_OpenSwiftUITesting_currentScreenScale {
return 2.0;
}

- (BOOL)_OpenSwiftUITesting_wantsWideContentMargins {
return NO;
}
@end

@implementation UICollectionView (OpenSwiftUITesting_Swizzles)
+ (void)_performOpenSwiftUITestingOverrides {
_SwizzleMethods(UIScreen.class, @selector(_viewAnimationsForCurrentUpdateWithCollectionViewAnimator:), @selector(_OpenSwiftUITesting__viewAnimationsForCurrentUpdateWithCollectionViewAnimator:));
}

- (id)_OpenSwiftUITesting__viewAnimationsForCurrentUpdateWithCollectionViewAnimator:(id)arg1 {
return nil;
}
@end
#endif
27 changes: 27 additions & 0 deletions Sources/COpenSwiftUI/UIKit/OpenSwiftUITesting_Swizzles.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
//
// OpenSwiftUITesting_Swizzles.h
// COpenSwiftUI
//
// Audited for iOS 18.0
// Status: Complete

#ifndef OpenSwiftUITesting_Swizzles_h
#define OpenSwiftUITesting_Swizzles_h

#include "OpenSwiftUIBase.h"

OPENSWIFTUI_ASSUME_NONNULL_BEGIN

#if OPENSWIFTUI_TARGET_OS_IOS

OPENSWIFTUI_EXPORT
void _PerformTestingSwizzles();

OPENSWIFTUI_EXPORT
void _SwizzleMethods(Class class, SEL originalSelector, SEL swizzledSelector);

#endif /* OPENSWIFTUI_TARGET_OS_IOS */

OPENSWIFTUI_ASSUME_NONNULL_END

#endif /* OpenSwiftUITesting_Swizzles_h */
37 changes: 37 additions & 0 deletions Sources/COpenSwiftUI/UIKit/OpenSwiftUITesting_Swizzles.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
//
// OpenSwiftUITesting_Swizzles.m
// COpenSwiftUI
//
// Audited for iOS 18.0
// Status: Complete

#include "OpenSwiftUITesting_Swizzles.h"

#if OPENSWIFTUI_TARGET_OS_IOS
#include <objc/runtime.h>
#include "UIKit/OpenSwiftUITesting_Swizzles+UIKit.h"

void _PerformTestingSwizzles() {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
[UIScreen _performOpenSwiftUITestingOverrides];
[UICollectionView _performOpenSwiftUITestingOverrides];
});
}

void _SwizzleMethods(Class class, SEL originalSelector, SEL swizzledSelector) {
Method originalMethod = class_getInstanceMethod(class, originalSelector);
Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);
IMP swizzledImp = method_getImplementation(swizzledMethod);
const char *swizzledTypeEncoding = method_getTypeEncoding(swizzledMethod);
BOOL success = class_addMethod(class, originalSelector, swizzledImp, swizzledTypeEncoding);
if (success) {
IMP originalImp = method_getImplementation(originalMethod);
const char *originalTypeEncoding = method_getTypeEncoding(originalMethod);
class_replaceMethod(class, swizzledSelector, originalImp, originalTypeEncoding);
} else {
method_exchangeImplementations(originalMethod, swizzledMethod);
}
}

#endif /* OPENSWIFTUI_TARGET_OS_IOS */
75 changes: 71 additions & 4 deletions Sources/OpenSwiftUI/CoreGlue/OpenSwiftUIGlue.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,94 @@
// OpenSwiftUI
//
// Audited for iOS 18.0
// Status: Empty
// Status: WIP

@_spi(ForOpenSwiftUIOnly)
public import OpenSwiftUICore
import COpenSwiftUI

#if canImport(Darwin)

public import Foundation

@_spi(ForOpenSwiftUIOnly)
@_silgen_name("OpenSwiftUIGlueClass")
public func OpenSwiftUIGlueClass() -> CoreGlue.Type {
OpenSwiftUIGlue.self
}

final class OpenSwiftUIGlue: CoreGlue {
override var defaultImplicitRootType: DefaultImplicitRootTypeResult {
@_spi(ForOpenSwiftUIOnly)
@objc(OpenSwiftUIGlue)
final public class OpenSwiftUIGlue: CoreGlue {
override final public var defaultImplicitRootType: DefaultImplicitRootTypeResult {
DefaultImplicitRootTypeResult(_VStackLayout.self)
}

override func makeDefaultLayoutComputer() -> MakeDefaultLayoutComputerResult {
override final public func makeDefaultLayoutComputer() -> MakeDefaultLayoutComputerResult {
MakeDefaultLayoutComputerResult(value: ViewGraph.current.$defaultLayoutComputer)
}
}

@_spi(ForOpenSwiftUIOnly)
@available(*, unavailable)
extension OpenSwiftUIGlue: Sendable {}

@_spi(ForOpenSwiftUIOnly)
@_silgen_name("OpenSwiftUIGlue2Class")
public func OpenSwiftUIGlue2Class() -> CoreGlue2.Type {
OpenSwiftUIGlue2.self
}

@_spi(ForOpenSwiftUIOnly)
@objc(OpenSwiftUIGlue2)
final public class OpenSwiftUIGlue2: CoreGlue2 {
#if os(iOS)
override public final func initializeTestApp() {
_PerformTestingSwizzles()
}
#endif

override public final func isStatusBarHidden() -> Bool? {
#if os(iOS)
guard let scene = UIApplication.shared.connectedScenes.first,
let windowScene = scene as? UIWindowScene
else {
return nil
}
return windowScene.statusBarManager?.isStatusBarHidden ?? false
#else
nil
#endif
}

override public final func configureDefaultEnvironment(_: inout EnvironmentValues) {
}

override public final func makeRootView(base: AnyView, rootFocusScope: Namespace.ID) -> AnyView {
AnyView(base.safeAreaInsets(.zero, next: nil))
}

override public final var systemDefaultDynamicTypeSize: DynamicTypeSize {
#if os(iOS)
let size = _UIApplicationDefaultContentSizeCategory()
let dynamicSize = DynamicTypeSize(size)
return dynamicSize ?? .large
#else
// TODO: macOS
return .large
#endif
}

override public final var codableAttachmentCellType: CodableAttachmentCellTypeResult {
CodableAttachmentCellTypeResult(nil)
}

override public final func linkURL(_ parameters: LinkURLParameters) -> URL? {
preconditionFailure("TODO")
}
}

@_spi(ForOpenSwiftUIOnly)
@available(*, unavailable)
extension OpenSwiftUIGlue2: Sendable {}
#endif
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
//
// OpenSwiftUI+UIKit.swift
// UIKitConversions.swift
// OpenSwiftUI
//
// Audited for iOS 18.0
// Status: WIP
// ID: 6DC24D5146AF4B80347A1025025F68EE (SwiftUI?)
// ID: 6DC24D5146AF4B80347A1025025F68EE (SwiftUI)

#if canImport(UIKit)

public import OpenSwiftUICore
public import UIKit
import COpenSwiftUI

// MARK: - Color + UIColor
// MARK: - UIColor Conversions

@available(*, deprecated, message: "Use Color(uiColor:) when converting a UIColor, or create a standard Color directly")
@available(macOS, unavailable)
Expand Down Expand Up @@ -146,11 +146,13 @@ extension UIColor: ColorProvider {
}
}

public extension ColorScheme {
// MARK: - UIUserInterfaceStyle Conversions

extension ColorScheme {
/// Creates a color scheme from its user interface style equivalent.
@available(macOS, unavailable)
@available(watchOS, unavailable)
init?(_ uiUserInterfaceStyle: UIUserInterfaceStyle) {
public init?(_ uiUserInterfaceStyle: UIUserInterfaceStyle) {
switch uiUserInterfaceStyle {
case .unspecified: return nil
case .light: self = .light
Expand All @@ -160,16 +162,45 @@ public extension ColorScheme {
}
}

public extension UIUserInterfaceStyle {
extension UIUserInterfaceStyle {
/// Creates a user interface style from its ColorScheme equivalent.
@available(macOS, unavailable)
@available(watchOS, unavailable)
init(_ colorScheme: ColorScheme?) {
public init(_ colorScheme: ColorScheme?) {
switch colorScheme {
case .light: self = .light
case .dark: self = .dark
case nil: self = .unspecified
}
}
}

// MARK: - UIAccessibilityContrast Conversions [TODO]

// ColorSchemeContrast
// UIAccessibilityContrast

// MARK: - UIContentSizeCategory Conversions [WIP]

extension DynamicTypeSize {
/// Create a Dynamic Type size from its `UIContentSizeCategory` equivalent.
public init?(_ uiSizeCategory: UIContentSizeCategory) {
switch uiSizeCategory {
case .extraSmall: self = .xSmall
case .small: self = .small
case .medium: self = .medium
case .large: self = .large
case .extraLarge: self = .xLarge
case .extraExtraLarge: self = .xxLarge
case .extraExtraExtraLarge: self = .xxxLarge
case .accessibilityMedium: self = .accessibility1
case .accessibilityLarge: self = .accessibility2
case .accessibilityExtraLarge: self = .accessibility3
case .accessibilityExtraExtraLarge: self = .accessibility4
case .accessibilityExtraExtraExtraLarge: self = .accessibility5
default: return nil
}
}
}

#endif
Loading
Loading