From 21a3cd59f7f1952a546ef198cc9ebe58eda59470 Mon Sep 17 00:00:00 2001 From: Andrew Watt Date: Tue, 11 Apr 2023 14:31:10 -0700 Subject: [PATCH] ScrollView infinity safety --- .../Sources/ScrollView.swift | 10 +++- ..._infiniteContent_fittingContent_iOS-16.png | Bin 0 -> 631 bytes ...t_infiniteContent_fittingHeight_iOS-16.png | Bin 0 -> 631 bytes ...st_infiniteContent_fittingWidth_iOS-16.png | Bin 0 -> 631 bytes .../Tests/Sources/ScrollViewTests.swift | 44 ++++++++++++++++++ .../Tests/Sources/XCTestCaseExtensions.swift | 31 ++++++++---- 6 files changed, 73 insertions(+), 12 deletions(-) create mode 100644 BlueprintUICommonControls/Tests/Sources/Resources/ReferenceImages/ScrollViewTests/test_infiniteContent_fittingContent_iOS-16.png create mode 100644 BlueprintUICommonControls/Tests/Sources/Resources/ReferenceImages/ScrollViewTests/test_infiniteContent_fittingHeight_iOS-16.png create mode 100644 BlueprintUICommonControls/Tests/Sources/Resources/ReferenceImages/ScrollViewTests/test_infiniteContent_fittingWidth_iOS-16.png diff --git a/BlueprintUICommonControls/Sources/ScrollView.swift b/BlueprintUICommonControls/Sources/ScrollView.swift index 60d5990dc..981ed9945 100644 --- a/BlueprintUICommonControls/Sources/ScrollView.swift +++ b/BlueprintUICommonControls/Sources/ScrollView.swift @@ -198,8 +198,12 @@ extension ScrollView { result.width += contentInset.left + contentInset.right result.height += contentInset.top + contentInset.bottom - result.width = min(result.width, proposal.width.maximum) - result.height = min(result.height, proposal.height.maximum) + if let maxWidth = proposal.width.constrainedValue { + result.width = min(result.width, maxWidth) + } + if let maxHeight = proposal.height.constrainedValue { + result.height = min(result.height, maxHeight) + } return result } @@ -210,6 +214,8 @@ extension ScrollView { insetSize.height -= contentInset.top + contentInset.bottom var itemSize = fittedSize(in: .init(insetSize), subelement: subelement) + .replacingInfinity(with: insetSize) + if contentSize == .fittingHeight { itemSize.width = insetSize.width } else if contentSize == .fittingWidth { diff --git a/BlueprintUICommonControls/Tests/Sources/Resources/ReferenceImages/ScrollViewTests/test_infiniteContent_fittingContent_iOS-16.png b/BlueprintUICommonControls/Tests/Sources/Resources/ReferenceImages/ScrollViewTests/test_infiniteContent_fittingContent_iOS-16.png new file mode 100644 index 0000000000000000000000000000000000000000..5c0c0729d4eb5996033af0c790965f76d1f8652b GIT binary patch literal 631 zcmeAS@N?(olHy`uVBq!ia0vp^DImx5*2E{9B$bjv*C{Z>~D>H5&*VIPmBHc!o6kRsNxM{f zx+O#BUzP?2q1g^^taunz%o=Z$N-%lkFl~Ho@MNpQwdr%e|Kl+`_+FanSgpkKH)iv> zBTTXP3pOB14Ga>hnvN~P>*CvJ)g*-kjgp5wp}sR!7hRQ_KTP8k^VrhGI+ZBxvXx5*2E{9B$bjv*C{Z>~D>H5&*VIPmBHc!o6kRsNxM{f zx+O#BUzP?2q1g^^taunz%o=Z$N-%lkFl~Ho@MNpQwdr%e|Kl+`_+FanSgpkKH)iv> zBTTXP3pOB14Ga>hnvN~P>*CvJ)g*-kjgp5wp}sR!7hRQ_KTP8k^VrhGI+ZBxvXx5*2E{9B$bjv*C{Z>~D>H5&*VIPmBHc!o6kRsNxM{f zx+O#BUzP?2q1g^^taunz%o=Z$N-%lkFl~Ho@MNpQwdr%e|Kl+`_+FanSgpkKH)iv> zBTTXP3pOB14Ga>hnvN~P>*CvJ)g*-kjgp5wp}sR!7hRQ_KTP8k^VrhGI+ZBxvX ViewDescription? { + UIView.describe { view in + view[\.backgroundColor] = .red + } + } + } + + compareSnapshot( + of: InfiniteBox() + .scrollable(.fittingContent) + .inset(uniform: 10), + size: CGSize(width: 100, height: 100), + identifier: "fittingContent", + layoutModes: [.caffeinated] + ) + + compareSnapshot( + of: InfiniteBox() + .scrollable(.fittingWidth) + .inset(uniform: 10), + size: CGSize(width: 100, height: 100), + identifier: "fittingWidth", + layoutModes: [.caffeinated] + ) + + compareSnapshot( + of: InfiniteBox() + .scrollable(.fittingHeight) + .inset(uniform: 10), + size: CGSize(width: 100, height: 100), + identifier: "fittingHeight", + layoutModes: [.caffeinated] + ) + } + func test_calculateContentInset() { // No inset diff --git a/BlueprintUICommonControls/Tests/Sources/XCTestCaseExtensions.swift b/BlueprintUICommonControls/Tests/Sources/XCTestCaseExtensions.swift index caeedbe41..ec2892a5e 100644 --- a/BlueprintUICommonControls/Tests/Sources/XCTestCaseExtensions.swift +++ b/BlueprintUICommonControls/Tests/Sources/XCTestCaseExtensions.swift @@ -101,22 +101,33 @@ extension XCTestCase { size: CGSize? = nil, identifier: String? = nil, scale: CGFloat = 1, + layoutModes: [LayoutMode] = LayoutMode.testModes, file: StaticString = #file, testName: String = #function, line: UInt = #line ) { - let view = BlueprintView(element: element) - view.name = "Snapshot Host" + for layoutMode in layoutModes { + let view = BlueprintView(element: element) + view.name = "Snapshot Host" + view.layoutMode = layoutMode - if let size = size { - view.frame = CGRect(origin: .zero, size: size) - } else { - view.sizeToFit() - view.frame.size.width.round(.up, by: scale) - view.frame.size.height.round(.up, by: scale) - } + if let size = size { + view.frame = CGRect(origin: .zero, size: size) + } else { + view.sizeToFit() + view.frame.size.width.round(.up, by: scale) + view.frame.size.height.round(.up, by: scale) + } - compareSnapshot(of: view, identifier: identifier, scale: scale, file: file, testName: testName, line: line) + compareSnapshot( + of: view, + identifier: identifier, + scale: scale, + file: file, + testName: testName, + line: line + ) + } } }