Skip to content

Commit

Permalink
a11ySnapshot (#91)
Browse files Browse the repository at this point in the history
  • Loading branch information
noahsmartin authored Feb 3, 2024
1 parent d6673e1 commit 55f75e3
Show file tree
Hide file tree
Showing 7 changed files with 87 additions and 9 deletions.
6 changes: 5 additions & 1 deletion DemoApp/DemoApp/TestViews/PreviewVariants.swift
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,15 @@ extension NamedViewModifier {
static var xxlTextSize: NamedViewModifier {
.init(name: "XXL Text Size", value: { $0.dynamicTypeSize(.xxxLarge) })
}

static var accessibility: NamedViewModifier {
.init(name: "Accessibility", value: { $0.emergeAccessibility(true) })
}
}

extension [NamedViewModifier] {
/// The default named view modifiers in a ``PreviewVariants``.
static var previewDefault: [NamedViewModifier] {
[.unmodified, .darkMode, .xxlTextSize]
[.unmodified, .darkMode, .xxlTextSize, .accessibility]
}
}
9 changes: 9 additions & 0 deletions DemoApp/DemoApp/TestViews/RideShareButton.swift
Original file line number Diff line number Diff line change
Expand Up @@ -45,5 +45,14 @@ struct RideShareButtonView_Previews: PreviewProvider {
.preferredColorScheme(.dark)
.previewLayout(.sizeThatFits)
.padding()

RideShareButtonView(title: "Request Ride") {
print("Button tapped")
}
.previewLayout(.sizeThatFits)
.padding()
.previewDisplayName("Ride Share Button View - Light")
.emergeRenderingMode(.coreAnimation)
.emergeAccessibility(true)
}
}
3 changes: 2 additions & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,15 @@ let package = Package(
],
dependencies: [
.package(url: "https://github.com/swhitty/FlyingFox.git", exact: "0.12.2"),
.package(url: "https://github.com/EmergeTools/AccessibilitySnapshot.git", exact: "1.0.0"),
],
targets: [
// Targets are the basic building blocks of a package, defining a module or a test suite.
// Targets can depend on other targets in this package and products from dependencies.
// Target that provides the XCTest
.target(name: "SnapshottingTests"),
// Core functionality
.target(name: "SnapshotPreviewsCore", dependencies: ["PreviewsSupport"]),
.target(name: "SnapshotPreviewsCore", dependencies: ["PreviewsSupport", .product(name: "AccessibilitySnapshotCore", package: "AccessibilitySnapshot")]),
.target(name: "SnapshotPreferences", dependencies: ["SnapshotPreviewsCore"]),
// Inserted dylib
.target(name: "Snapshotting", dependencies: ["SnapshottingSwift"]),
Expand Down
25 changes: 25 additions & 0 deletions Sources/SnapshotPreferences/AccessibiltyPreference.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
//
// AccessibiltyPreference.swift
//
//
// Created by Noah Martin on 2/2/24.
//

import Foundation
import SwiftUI

struct AccessibilityPreferenceKey: PreferenceKey {
static func reduce(value: inout Bool?, nextValue: () -> Bool?) {
if value == nil {
value = nextValue()
}
}

static var defaultValue: Bool? = nil
}

extension View {
public func emergeAccessibility(_ enabled: Bool?) -> some View {
preference(key: AccessibilityPreferenceKey.self, value: enabled)
}
}
5 changes: 5 additions & 0 deletions Sources/SnapshotPreferences/EmergeModifierFinder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,13 @@ class EmergeModifierState: NSObject {
expansionPreference = nil
renderingMode = nil
precision = nil
accessibilityEnabled = nil
}

var expansionPreference: Bool?
var renderingMode: EmergeRenderingMode.RawValue?
var precision: Float?
var accessibilityEnabled: Bool?
}

@objc(EmergeModifierFinder)
Expand All @@ -44,5 +46,8 @@ class EmergeModifierFinder: NSObject {
.onPreferenceChange(PrecisionPreferenceKey.self, perform: { value in
EmergeModifierState.shared.precision = value
})
.onPreferenceChange(AccessibilityPreferenceKey.self, perform: { value in
EmergeModifierState.shared.accessibilityEnabled = value
})
}
}
5 changes: 3 additions & 2 deletions Sources/SnapshotPreviewsCore/ExpandingViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ public final class ExpandingViewController: UIHostingController<AnyView> {

private var heightAnchor: NSLayoutConstraint?

var expansionSettled: ((EmergeRenderingMode?, Float?) -> Void)?
var expansionSettled: ((EmergeRenderingMode?, Float?, Bool?) -> Void)?

init<Content: View>(rootView: Content, layout: PreviewLayout) {
let newView = finder?(rootView)
Expand Down Expand Up @@ -81,7 +81,8 @@ public final class ExpandingViewController: UIHostingController<AnyView> {
didCall = true
let renderingMode = stateMirror?.descendant("renderingMode") as? EmergeRenderingMode.RawValue
let emergeRenderingMode = renderingMode != nil ? EmergeRenderingMode(rawValue: renderingMode!) : nil
expansionSettled?(emergeRenderingMode, stateMirror?.descendant("precision") as? Float)
let accessibilityEnabled = stateMirror?.descendant("accessibilityEnabled") as? Bool
expansionSettled?(emergeRenderingMode, stateMirror?.descendant("precision") as? Float, accessibilityEnabled)
}

public override func viewDidLayoutSubviews() {
Expand Down
43 changes: 38 additions & 5 deletions Sources/SnapshotPreviewsCore/View+Snapshot.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import Foundation
import SwiftUI
import UIKit
import AccessibilitySnapshotCore

public enum RenderingError: Error {
case failedRendering(CGSize)
Expand All @@ -35,16 +36,38 @@ extension View {

let (windowRootVC, containerVC) = Self.setupRootVC(subVC: controller)
window.rootViewController = windowRootVC
controller.expansionSettled = { [weak containerVC, weak controller] renderingMode, precision in
controller.expansionSettled = { [weak containerVC, weak controller] renderingMode, precision, accessibilityEnabled in
guard let containerVC, let controller else { return }

if async {
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
completion(Self.takeSnapshot(layout: layout, renderingMode: renderingMode, rootVC: containerVC, controller: controller), precision)
completion(Self.takeSnapshot(layout: layout, renderingMode: renderingMode, rootVC: containerVC, targetView: controller.view), precision)
}
} else {
DispatchQueue.main.async {
completion(Self.takeSnapshot(layout: layout, renderingMode: renderingMode, rootVC: containerVC, controller: controller), precision)
if let accessibilityEnabled, accessibilityEnabled {
let containedView: UIView
switch layout {
case .device:
containedView = containerVC.view
default:
containedView = view
}
let a11yView = AccessibilitySnapshotView(
containedView: containedView,
viewRenderingMode: renderingMode?.a11yRenderingMode ?? .drawHierarchyInRect,
activationPointDisplayMode: .never,
showUserInputLabels: true)

a11yView.center = window.center
window.addSubview(a11yView)

try? a11yView.parseAccessibility(useMonochromeSnapshot: false)
a11yView.sizeToFit()
completion(Self.takeSnapshot(layout: .sizeThatFits, renderingMode: renderingMode, rootVC: containerVC, targetView: a11yView), precision)
} else {
completion(Self.takeSnapshot(layout: layout, renderingMode: renderingMode, rootVC: containerVC, targetView: view), precision)
}
}
}
}
Expand Down Expand Up @@ -82,9 +105,9 @@ extension View {
layout: PreviewLayout,
renderingMode: EmergeRenderingMode?,
rootVC: UIViewController,
controller: UIViewController) -> Result<UIImage, RenderingError>
targetView: UIView) -> Result<UIImage, RenderingError>
{
let view = controller.view!
let view = targetView
let drawCode: (CGContext) -> Void

CATransaction.commit()
Expand Down Expand Up @@ -142,6 +165,16 @@ extension UIView {
}
}

extension EmergeRenderingMode {
var a11yRenderingMode: AccessibilitySnapshotView.ViewRenderingMode {
switch self {
case .coreAnimation:
return .renderLayerInContext
case .uiView:
return .drawHierarchyInRect
}
}
}

extension CALayer {

Expand Down

0 comments on commit 55f75e3

Please sign in to comment.