From 53c4a546a8e8fb42e76e75d3f370461f74ec7312 Mon Sep 17 00:00:00 2001 From: Kyle Van Essen Date: Mon, 10 Jun 2024 20:24:11 -0700 Subject: [PATCH 01/13] Add priority to allow adjusting how extra space in a run/row in a flow should be used. --- BlueprintUI/Sources/Layout/Flow.swift | 152 ++++++++++++++---- .../Tests/Sources/FlowTests.swift | 58 +++++++ .../test_priority_one-scaling_iOS-15.png | Bin 0 -> 963 bytes .../test_priority_one-scaling_iOS-16.png | Bin 0 -> 951 bytes .../test_priority_one-scaling_iOS-17.png | Bin 0 -> 1036 bytes .../test_priority_two-even-scaling_iOS-15.png | Bin 0 -> 911 bytes .../test_priority_two-even-scaling_iOS-16.png | Bin 0 -> 899 bytes .../test_priority_two-even-scaling_iOS-17.png | Bin 0 -> 984 bytes .../test_priority_two-scaling_iOS-15.png | Bin 0 -> 904 bytes .../test_priority_two-scaling_iOS-16.png | Bin 0 -> 892 bytes .../test_priority_two-scaling_iOS-17.png | Bin 0 -> 977 bytes CHANGELOG.md | 2 + 12 files changed, 182 insertions(+), 30 deletions(-) create mode 100644 BlueprintUICommonControls/Tests/Sources/Resources/ReferenceImages/FlowTests/test_priority_one-scaling_iOS-15.png create mode 100644 BlueprintUICommonControls/Tests/Sources/Resources/ReferenceImages/FlowTests/test_priority_one-scaling_iOS-16.png create mode 100644 BlueprintUICommonControls/Tests/Sources/Resources/ReferenceImages/FlowTests/test_priority_one-scaling_iOS-17.png create mode 100644 BlueprintUICommonControls/Tests/Sources/Resources/ReferenceImages/FlowTests/test_priority_two-even-scaling_iOS-15.png create mode 100644 BlueprintUICommonControls/Tests/Sources/Resources/ReferenceImages/FlowTests/test_priority_two-even-scaling_iOS-16.png create mode 100644 BlueprintUICommonControls/Tests/Sources/Resources/ReferenceImages/FlowTests/test_priority_two-even-scaling_iOS-17.png create mode 100644 BlueprintUICommonControls/Tests/Sources/Resources/ReferenceImages/FlowTests/test_priority_two-scaling_iOS-15.png create mode 100644 BlueprintUICommonControls/Tests/Sources/Resources/ReferenceImages/FlowTests/test_priority_two-scaling_iOS-16.png create mode 100644 BlueprintUICommonControls/Tests/Sources/Resources/ReferenceImages/FlowTests/test_priority_two-scaling_iOS-17.png diff --git a/BlueprintUI/Sources/Layout/Flow.swift b/BlueprintUI/Sources/Layout/Flow.swift index a1adffb70..aa014b809 100644 --- a/BlueprintUI/Sources/Layout/Flow.swift +++ b/BlueprintUI/Sources/Layout/Flow.swift @@ -116,6 +116,25 @@ extension Flow { case bottom } + /// When there is extra space in a run, how the extra space should be used. + public enum Priority { + + public static let `default` = Self.fixed + + /// The item will take up only the space it asked for. + case fixed + + /// The item will be stretched to fill any extra space in each run. + case grows + + var scales: Bool { + switch self { + case .fixed: false + case .grows: true + } + } + } + /// A child placed within the flow layout. public struct Child: ElementBuilderChild { @@ -136,13 +155,21 @@ extension Flow { } /// Creates a new child item with the given element. - public init(_ element: Element, key: AnyHashable? = nil) { + public init(_ element: Element, key: AnyHashable? = nil, priority: Priority = .default) { self.key = key - traits = .init() self.element = element + + traits = .init(priority: priority) } - public struct Traits {} + public struct Traits { + + public var priority: Priority + + public init(priority: Flow.Priority = .default) { + self.priority = priority + } + } } } @@ -150,8 +177,11 @@ extension Flow { extension Element { /// Wraps the element in a `Flow.Child` to allow customizing the item in the flow layout. - public func flowChild(key: AnyHashable? = nil) -> Flow.Child { - .init(self, key: key) + public func flowChild( + priority: Flow.Priority = .default, + key: AnyHashable? = nil + ) -> Flow.Child { + .init(self, key: key, priority: priority) } } @@ -178,7 +208,12 @@ extension Flow { cache: inout () ) -> CGSize { size( - for: subelements.map { $0.sizeThatFits(_:) }, + for: subelements.map { + .init( + traits: $0.traits(forLayoutType: Self.self), + size: $0.sizeThatFits(_:) + ) + }, in: proposal ) } @@ -191,7 +226,12 @@ extension Flow { ) { zip( frames( - for: subelements.map { $0.sizeThatFits(_:) }, + for: subelements.map { + .init( + traits: $0.traits(forLayoutType: Self.self), + size: $0.sizeThatFits(_:) + ) + }, in: .init(size) ), subelements @@ -200,10 +240,17 @@ extension Flow { } } - typealias ElementSize = (SizeConstraint) -> CGSize + + /// Shim type. Once legacy layout is removed, we can remove this shim and just use `Child` directly. + private struct FlowChild { + typealias ElementSize = (SizeConstraint) -> CGSize + + var traits: Traits + var size: ElementSize + } private func frames( - for elements: [ElementSize], + for elements: [FlowChild], in constraint: SizeConstraint ) -> [CGRect] { @@ -217,7 +264,7 @@ extension Flow { for element in elements { let elementSize: CGSize = { - let size = element(constraint) + let size = element.size(constraint) return CGSize( width: min(size.width, constraint.width.maximum), @@ -237,14 +284,19 @@ extension Flow { ) } - row.addItem(of: elementSize) + row.add( + .init( + size: elementSize, + traits: element.traits + ) + ) } return frames + row.itemFrames() } private func size( - for elements: [ElementSize], + for elements: [FlowChild], in constraint: SizeConstraint ) -> CGSize { frames( @@ -268,7 +320,12 @@ extension Flow { )] ) -> CGSize { size( - for: items.map { $0.content.measure(in:) }, + for: items.map { + .init( + traits: $0.traits, + size: $0.content.measure(in:) + ) + }, in: constraint ) } @@ -281,7 +338,12 @@ extension Flow { )] ) -> [LayoutAttributes] { frames( - for: items.map { $0.content.measure(in:) }, + for: items.map { + .init( + traits: $0.traits, + size: $0.content.measure(in:) + ) + }, in: .init(size) ).map(LayoutAttributes.init(frame:)) } @@ -336,7 +398,7 @@ extension Flow.Layout { struct Item { let size: CGSize - let xOffset: CGFloat + let traits: Flow.Layout.Traits } /// `True` if we can fit an item of the given size in the row. @@ -347,32 +409,58 @@ extension Flow.Layout { } /// Adds item of given size to the row layout. - mutating func addItem(of size: CGSize) { - items.append( - .init( - size: size, - xOffset: totalItemWidth + itemSpacing * CGFloat(items.count) - ) - ) - totalItemWidth += size.width - height = max(size.height, height) + mutating func add(_ item: Item) { + items.append(item) + + totalItemWidth += item.size.width + height = max(item.size.height, height) } - /// Compute frames for the items in the row layout. func itemFrames() -> [CGRect] { + let totalSpacing = (CGFloat(items.count) - 1) * itemSpacing + + let scalingConstant: CGFloat = items + .map { + switch $0.traits.priority { + case .fixed: 0.0 + case .grows: 1.0 + } + } + .reduce(0, +) + + let scalableWidth = items + .filter(\.traits.priority.scales) + .map(\.size.width) + .reduce(0, +) + + let hasScalingItems = scalingConstant > 0.0 + let extraWidth = maxWidth - totalItemWidth - totalSpacing - let firstItemX: CGFloat = { + + let firstItemX: CGFloat = if hasScalingItems { + 0.0 + } else { switch lineAlignment { case .center: extraWidth / 2.0 case .trailing: extraWidth case .leading: 0.0 } - }() + } + + var xOrigin: CGFloat = firstItemX return items.map { item in - .init( - x: firstItemX + item.xOffset, + let percentOfScalableWidth = item.size.width / scalableWidth + + let width = if item.traits.priority.scales { + item.size.width + (extraWidth * percentOfScalableWidth) + } else { + item.size.width + } + + let frame = CGRect( + x: xOrigin, y: { switch itemAlignment { case .fill: origin @@ -381,7 +469,7 @@ extension Flow.Layout { case .bottom: origin + (height - item.size.height) } }(), - width: item.size.width, + width: width, height: { switch itemAlignment { case .fill: height @@ -389,6 +477,10 @@ extension Flow.Layout { } }() ) + + xOrigin = frame.maxX + itemSpacing + + return frame } } } diff --git a/BlueprintUICommonControls/Tests/Sources/FlowTests.swift b/BlueprintUICommonControls/Tests/Sources/FlowTests.swift index 05d839006..8035b420e 100644 --- a/BlueprintUICommonControls/Tests/Sources/FlowTests.swift +++ b/BlueprintUICommonControls/Tests/Sources/FlowTests.swift @@ -57,6 +57,64 @@ class FlowTests: XCTestCase { compareSnapshot(of: flow) } + + func test_priority() { + func flow( + lineAlignment: Flow.LineAlignment, + itemAlignment: Flow.ItemAlignment, + @ElementBuilder _ children: () -> [Flow.Child] + ) -> Element { + Flow( + lineAlignment: lineAlignment, + lineSpacing: 10, + itemAlignment: itemAlignment, + itemSpacing: 2 + ) { + children() + } + .constrainedTo(width: .absolute(200)) + } + + compareSnapshot( + of: flow(lineAlignment: .leading, itemAlignment: .center) { + ConstrainedSize(width: 100, height: 40, color: .green) + ConstrainedSize(width: 90, height: 40, color: .red) + ConstrainedSize(width: 40, height: 40, color: .purple) + + ConstrainedSize(width: 80, height: 40, color: .lightGray) + .flowChild(priority: .grows) + }, + identifier: "one-scaling" + ) + + compareSnapshot( + of: flow(lineAlignment: .leading, itemAlignment: .center) { + ConstrainedSize(width: 100, height: 40, color: .green) + ConstrainedSize(width: 90, height: 40, color: .red) + + ConstrainedSize(width: 40, height: 40, color: .purple) + .flowChild(priority: .grows) + + ConstrainedSize(width: 40, height: 40, color: .lightGray) + .flowChild(priority: .grows) + }, + identifier: "two-even-scaling" + ) + + compareSnapshot( + of: flow(lineAlignment: .leading, itemAlignment: .center) { + ConstrainedSize(width: 100, height: 40, color: .green) + ConstrainedSize(width: 90, height: 40, color: .red) + + ConstrainedSize(width: 40, height: 40, color: .purple) + .flowChild(priority: .grows) + + ConstrainedSize(width: 80, height: 40, color: .lightGray) + .flowChild(priority: .grows) + }, + identifier: "two-scaling" + ) + } } extension ConstrainedSize { diff --git a/BlueprintUICommonControls/Tests/Sources/Resources/ReferenceImages/FlowTests/test_priority_one-scaling_iOS-15.png b/BlueprintUICommonControls/Tests/Sources/Resources/ReferenceImages/FlowTests/test_priority_one-scaling_iOS-15.png new file mode 100644 index 0000000000000000000000000000000000000000..1611fb53363262ffc5a67d353bf74639754be086 GIT binary patch literal 963 zcmeAS@N?(olHy`uVBq!ia0vp^CxAGLgAGXj{U&)0NHG=%xjQkeJ16rJ$Z<)H@J#dd zWzYh$IT#q*GZ|PwN`P1jh#44|7cep~18GK(*a9ZF?1=@;aCQ_(p}}0wr$9<3)5Sjo zNHc-NfIt_BHJ~(*&A3|h!Q;6=y4=&nF{Fa=&E11t%>g1V2mk!{w>Ivc|(>l+dd2vZs%;}wl!vSIOlVA7AF4z zI|IZ2|7%>ty@65C1d4*US2yM|2MRD>)QPFKv4Bgs*T8EBx?-?+u= z@3$zhY*d)Y*u*lYGV)C8fxUiI e3Fa8QUat@P#1VNoU}*{{r+B*hxvX16El3Oqbb(j{ zN(0%9t3@9?o(rVQJzX3_Dj46~J=oP8AmVcH&wqbw2ZjDd+m;q@Xmpit*wHU|dAl-MgEp~4#sKoi$= zO96#c_@qH5mIg8pkR=uWF#P|&#zov4 z7zItBD0q8yV=i-`0P{ud*sm*27C#9P7LvAM?$V1$wrj76tLISoF!{je&)xh$hL8(~ z00$Ebr-hxOgMg%i0*B4~=bz*L{r&&`{`>D=4=2oJY!dMQ=)%S!RB$c#>Ak(JDjbeF z9w`k9jP8r?XMg!RTcAZjOvT7yLc``f?eFh&#T+@39F>@X21@;nTfF{$ivr6=g^7$! zEOSbucb4aGH+f|?`V!{aqN2Wfv z{nuZ-Hdln%mVP(v-Q8%NCV?YOV8@vJ+Upj-pA&A|>up8v?^%t+_JHc!_w`=X4-P-5^-Mg<&7;YQb>qnJfj=}5o`mj$N Uk%t48rhsyar>mdKI;Vst0Ay@IUYh$`Yd`A* z{r_8Y9;|Ox?@&Kc{_aY6tPlD1*)(u+v8Yp;o`=TP`C`M~GT-TXj?kPC+Z z2NMgYg`J{{`|n>5C(LDR67c`%!p0#~a4q-gy}hj}9F963 zDGdsY?u+kdfB8CFphZDU#mHeo!{$8g@9%WQ966F4m6(ABO8t#ny#9WR0?S5)iHuDw zb4sIkmgjHea1!7al2q_GaPh@=soKA4EQ%ehojd|657yj1wYR$4RiG(i!U+aPrarg* z*I&FgSA^M?emCsh-DsUAfg?>|$C&)u>lVMC6K>ng1V2mk!{w>Ivc|(>l+dd2vZs%;}wl!vSIOlVA7AF4z zI|IZ2|7%>ty@65S2a1BXHw?KB8wjvC*xr5rQGKe`gk#UsxLfBsXf-;Bzweu~wbthV zi=6rfxp18s4V*cQ9|dL{FkobqY)d}L!g9nof$1>IwXN&kRv+WpxBqhO{oCJrBsoqv zvMMU1w>;WDhsDJq!?Z(Jfk{b$spy#XvD>@nX;0IhX3xU55hw*j|6X}LmrbcixWCTj zWoeT@i-NNPD_A0Cf#g{f zJ$6M#e^cfFtJz{w_iGMFp2KNE$>wcu+`(qBWM=;PV#x_H@MT)=&3>>M9G5Qrcv&n2 zG4RsaTbtw|_AFWY@$z#Oh=EIHZ%ws_+T;Cr`FT%>fu82sr|ZD>dVfg3y$hdFm Rj7U(b_jL7hS?83{1OS>16El3Oqbb(j{ zN(0%9t3@9?o(rVQJzX3_Dj46~J=oP8AmVcH&wqbw2ZjDd+m;q@Xmpit*wHU|dAl-MgEp~4#sKoi$= zO96#c_@qH5mIg8pkR=uWF#P|&#zov4 z7zKWyD0q9rkn6C40E>g|-S;2Wr)o_&_B@Tdb*_U}ql5VSzByZKeGah5sc(=A*O}44 znZx)|V8#IhMn=iDs(%zHVL#SI4iJ% zC1N&S3h$rxm%~W_B&ypx-%i~T%u%_!M)$X1ivo)xhhvnKeXSozo<-4PS7h`zWe%{K zEhcrp=78imoFC%sv#X=ARFP*)$NgiU) zlBFLnKUaYmxMcR$RC}mB-jA1`_kUYh$`Yd`A* z{r_8Y9;|Ox?@&Kc{_aY6t#%_Ui-Yam_aD`#YE3xyJdL|`u7g&igZTTtIa_Oe4zS3nZ;%VunbE+R z!}w8P#sLFHM#;A1lPoMpj1!m+vs~M{?rrrko_+f-*WSPVy+@Mcgd?k>LVC-i?Q>XM z95PHhbQPGC6qt&RSs%N-d!F_*?P>NbY#V`6K=kjG*K^sFiiG>?Twazo3A89UE3kqk zVm4k1@1ORU!$|-ns@pr?PTdjAQMtQD_qSk+0*fMtW0aJAtsh99MbTqdWb`*>4zQXn zCUw8&faE!xCX{U6_QoA-21{ng1V2mk!{w>Ivc|(>l+dd2vZs%;}wl!vSIOlVA7AF4z zI|IZ2|7%>ty@65S4vK=e*AH?YHV|NOn7Xd&%95sor?S`PCNQZL{L{T9U72Ig>G8n0 z@#D{9+?*Z>+8xdcjowULMV!aAIW;*y%r;wZADK7D7>&Y-2)rj8s=0!;!cx$c|SsX^E+VzJ#*1d+tKhLHG# aZUy_aWem25oMe`RlDns?pUXO@geCwz01|@$ literal 0 HcmV?d00001 diff --git a/BlueprintUICommonControls/Tests/Sources/Resources/ReferenceImages/FlowTests/test_priority_two-scaling_iOS-16.png b/BlueprintUICommonControls/Tests/Sources/Resources/ReferenceImages/FlowTests/test_priority_two-scaling_iOS-16.png new file mode 100644 index 0000000000000000000000000000000000000000..7c8baf90413c6d4c37c3c8d5ed1451aa1b3452d5 GIT binary patch literal 892 zcmeAS@N?(olHy`uVBq!ia0vp^CxAGLgAGXj{U&)0NHG=%xjQkeJ16rJ$gxO`@J#dd zWzYh$IT#q*GZ|PwN`P1jh#44|7BIm@PAp)Cv!g(g!lBvsfs{<9i+>16El3Oqbb(j{ zN(0%9t3@9?o(rVQJzX3_Dj46~J=oP8AmVcH&wqbw2ZjDd+m;q@Xmpit*wHU|dAl-MgEp~4#sKoi$= zO96#c_@qH5mIg8pkR=uWF#P|&#zov4 z7zOU2D0qAQAm?EN0Tzd;>#D9SX*zf+du?t4lUl()-CNR?Irf|$4~!c>{yfIb>5-t_ z;jGZ;&BRs2d0d-Qqr(`)N$%Te`&s^CRCaYr!MTQ}J=~8>p0GTQ_nc?EK!MBY%;~j` zjv_9OB1`JicP8x&TAFR@$l)Z=B%qS(zImM*gxw+*+dV}PNt|m4iBITOuuogYV0*|( RW;rOid%F6$taD0e0swN45r+T( literal 0 HcmV?d00001 diff --git a/BlueprintUICommonControls/Tests/Sources/Resources/ReferenceImages/FlowTests/test_priority_two-scaling_iOS-17.png b/BlueprintUICommonControls/Tests/Sources/Resources/ReferenceImages/FlowTests/test_priority_two-scaling_iOS-17.png new file mode 100644 index 0000000000000000000000000000000000000000..899002598714751a8526f7590809ef893c65caee GIT binary patch literal 977 zcmeAS@N?(olHy`uVBq!ia0vp^CxAGLgAGXj{U&)0NHG=%xjQkeJ16rJ$f-z;@J#dd zWzYh$IT%UYh$`Yd`A* z{r_8Y9;|Ox?@&Kc{_aY6tFc6Ca@xrU}a+>cD2usn|UoM*g1fy?R4>9vlI zA})?1OX|~iChZJbnr-UH;Uv%`ppxspd7T=B-69s-Jw*^noNEY)Pv};#Pg}-dd&o&< QIVin*y85}Sb4q9e0AuYJBme*a literal 0 HcmV?d00001 diff --git a/CHANGELOG.md b/CHANGELOG.md index 0deac32a0..c843f3b5a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added +- `Flow` children now support a layout `priority`, to specify if they should grow to use the extra space in a row. + ### Removed ### Changed From 23637714bf49ea64166fc819294378107882a59d Mon Sep 17 00:00:00 2001 From: Robert MacEachern Date: Tue, 29 Oct 2024 14:46:29 -0500 Subject: [PATCH 02/13] Bump CI Xcode to 15.4 (from 15.1) --- .github/workflows/env.properties | 2 +- CHANGELOG.md | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/env.properties b/.github/workflows/env.properties index d1fa2bd69..405177060 100644 --- a/.github/workflows/env.properties +++ b/.github/workflows/env.properties @@ -1 +1 @@ -xcode_version=15.1 +xcode_version=15.4.0 diff --git a/CHANGELOG.md b/CHANGELOG.md index a2f8d843e..6591cd3ce 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Internal +- Bump CI Xcode version to 15.4. + # Past Releases ## [4.3.0] - 2024-09-18 From de144c86eab81c89c0264aae85dee347298b3ab5 Mon Sep 17 00:00:00 2001 From: Robert MacEachern Date: Tue, 29 Oct 2024 14:54:08 -0500 Subject: [PATCH 03/13] Bump Github jobs to use macos-14 --- .github/workflows/docs.yml | 2 +- .github/workflows/lint.yml | 2 +- .github/workflows/tests.yaml | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 25a910e9c..4a11b8022 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -7,7 +7,7 @@ on: jobs: build: name: Generate docs with jazzy and publish to Github pages - runs-on: macos-13-xlarge + runs-on: macos-14-xlarge steps: - name: Checkout diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 89ab28de3..201ff1434 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -9,7 +9,7 @@ on: jobs: lint: name: Lint Swift code with SwiftFormat - runs-on: macos-13-xlarge + runs-on: macos-14-xlarge steps: - name: Checkout diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index 8a4c520a3..2ac73dd31 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -10,7 +10,7 @@ jobs: spm: name: "iOS ${{ matrix.sdk }}" - runs-on: macos-13-xlarge + runs-on: macos-14-xlarge strategy: fail-fast: false # Don’t fail-fast so that we get all snapshot test changes @@ -66,7 +66,7 @@ jobs: cocoapods: name: "CocoaPods" - runs-on: macos-13-xlarge + runs-on: macos-14-xlarge steps: - uses: actions/checkout@v4 From 50e97b263cc612a0b7a243c4f74b5d4174417a0e Mon Sep 17 00:00:00 2001 From: Robert MacEachern Date: Tue, 29 Oct 2024 09:41:04 -0500 Subject: [PATCH 04/13] Annotate `updateViewHierarchyIfNeeded` and `update(node:context:)` with @MainActor and add `preconditionIsolated` runtime check --- BlueprintUI/Sources/BlueprintView/BlueprintView.swift | 5 +++++ CHANGELOG.md | 2 ++ 2 files changed, 7 insertions(+) diff --git a/BlueprintUI/Sources/BlueprintView/BlueprintView.swift b/BlueprintUI/Sources/BlueprintView/BlueprintView.swift index 3b978ed03..a716d4ccd 100644 --- a/BlueprintUI/Sources/BlueprintView/BlueprintView.swift +++ b/BlueprintUI/Sources/BlueprintView/BlueprintView.swift @@ -364,7 +364,10 @@ public final class BlueprintView: UIView { setNeedsLayout() } + @MainActor private func updateViewHierarchyIfNeeded() { + MainActor.preconditionIsolated("updateViewHierarchyIfNeeded must only execute on the main actor.") + guard needsViewHierarchyUpdate || bounds != lastViewHierarchyUpdateBounds else { return } precondition( @@ -612,7 +615,9 @@ extension BlueprintView { node.viewDescription.viewType == type(of: view) } + @MainActor fileprivate func update(node: NativeViewNode, context: UpdateContext) -> UpdateResult { + MainActor.preconditionIsolated("BlueprintView.NativeViewController.update(node:context:) must only execute on the main actor.") assert(node.viewDescription.viewType == type(of: view)) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6591cd3ce..6dc6e5ce6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added +- `BlueprintView` has added preconditions to some methods to ensure they are only invoked on the main queue. + ### Removed ### Changed From 63abb212a7b691bd3e0a51d4d7cdd4caa5bb43c6 Mon Sep 17 00:00:00 2001 From: Alex Odawa Date: Tue, 29 Oct 2024 22:25:09 +0100 Subject: [PATCH 05/13] Renamed accessibility(...) to deprecated_accessibility(...) (#516) Opening up the namespace for a more proper `accessibility(value:label:hint:identifier:traits:)` --- BlueprintUICommonControls/Sources/AccessibilityElement.swift | 2 +- CHANGELOG.md | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/BlueprintUICommonControls/Sources/AccessibilityElement.swift b/BlueprintUICommonControls/Sources/AccessibilityElement.swift index 0decb11f1..014cec888 100644 --- a/BlueprintUICommonControls/Sources/AccessibilityElement.swift +++ b/BlueprintUICommonControls/Sources/AccessibilityElement.swift @@ -204,7 +204,7 @@ extension Element { deprecated, renamed: "accessibilityElement(label:value:traits:hint:identifier:accessibilityFrameSize:)" ) - public func accessibility( + public func deprecated_accessibility( label: String? = nil, value: String? = nil, hint: String? = nil, diff --git a/CHANGELOG.md b/CHANGELOG.md index a2f8d843e..2f4e8116e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Removed ### Changed +Renamed deprecated function `accessibility(label:value:traits:hint:identifier:accessibilityFrameSize:)` to `deprecated_accessibility(label:value:traits:hint:identifier:accessibilityFrameSize:)`. ### Deprecated From d2ded60331e099980432a5fb45b92839342498a5 Mon Sep 17 00:00:00 2001 From: Robert MacEachern Date: Wed, 30 Oct 2024 09:41:27 -0500 Subject: [PATCH 06/13] Add precondition to `setNeedsViewHierarchyUpdate`. Expanded precondition message to encourage self-diagnosis. --- .../Sources/BlueprintView/BlueprintView.swift | 28 +++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/BlueprintUI/Sources/BlueprintView/BlueprintView.swift b/BlueprintUI/Sources/BlueprintView/BlueprintView.swift index a716d4ccd..94ec5cccf 100644 --- a/BlueprintUI/Sources/BlueprintView/BlueprintView.swift +++ b/BlueprintUI/Sources/BlueprintView/BlueprintView.swift @@ -350,7 +350,16 @@ public final class BlueprintView: UIView { /// Clears any sizing caches, invalidates the `intrinsicContentSize` of the /// view, and marks the view as needing a layout. + @MainActor private func setNeedsViewHierarchyUpdate() { + MainActor.preconditionIsolated( + """ + setNeedsViewHierarchyUpdate() must only execute on the main actor. + + Examine your stack trace to determine what caused this to be called + off of the main actor. + """ + ) invalidateIntrinsicContentSize() sizesThatFit.removeAll() @@ -366,7 +375,14 @@ public final class BlueprintView: UIView { @MainActor private func updateViewHierarchyIfNeeded() { - MainActor.preconditionIsolated("updateViewHierarchyIfNeeded must only execute on the main actor.") + MainActor.preconditionIsolated( + """ + updateViewHierarchyIfNeeded() must only execute on the main actor. + + Examine your stack trace to determine what caused this to be called + off of the main actor. + """ + ) guard needsViewHierarchyUpdate || bounds != lastViewHierarchyUpdateBounds else { return } @@ -617,7 +633,15 @@ extension BlueprintView { @MainActor fileprivate func update(node: NativeViewNode, context: UpdateContext) -> UpdateResult { - MainActor.preconditionIsolated("BlueprintView.NativeViewController.update(node:context:) must only execute on the main actor.") + MainActor.preconditionIsolated( + """ + BlueprintView.NativeViewController.update(node:context:) must + only execute on the main actor. + + Examine your stack trace to determine what caused this to be + called off of the main actor. + """ + ) assert(node.viewDescription.viewType == type(of: view)) From 73df5ff72f8e6c24005cda8332d154ebbf8fe0ae Mon Sep 17 00:00:00 2001 From: Robert MacEachern Date: Wed, 30 Oct 2024 14:56:44 -0500 Subject: [PATCH 07/13] Bumping versions to 5.0.0. --- CHANGELOG.md | 16 ++++++++++++---- SampleApp/Podfile.lock | 12 ++++++------ version.rb | 2 +- 3 files changed, 19 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0aab9741a..6325d7427 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,12 +11,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added -- `BlueprintView` has added preconditions to some methods to ensure they are only invoked on the main queue. - ### Removed ### Changed -Renamed deprecated function `accessibility(label:value:traits:hint:identifier:accessibilityFrameSize:)` to `deprecated_accessibility(label:value:traits:hint:identifier:accessibilityFrameSize:)`. ### Deprecated @@ -32,6 +29,16 @@ Renamed deprecated function `accessibility(label:value:traits:hint:identifier:ac # Past Releases +## [5.0.0] - 2024-10-30 + +### Added + +- `BlueprintView` has added preconditions to some methods to ensure they are only invoked on the main queue. + +### Changed + +- Renamed deprecated function `accessibility(label:value:traits:hint:identifier:accessibilityFrameSize:)` to `deprecated_accessibility(label:value:traits:hint:identifier:accessibilityFrameSize:)`. + ## [4.3.0] - 2024-09-18 ### Added @@ -1118,7 +1125,8 @@ searchField - First stable release. -[main]: https://github.com/square/Blueprint/compare/4.3.0...HEAD +[main]: https://github.com/square/Blueprint/compare/5.0.0...HEAD +[5.0.0]: https://github.com/square/Blueprint/compare/4.3.0...5.0.0 [4.3.0]: https://github.com/square/Blueprint/compare/4.2.1...4.3.0 [4.2.1]: https://github.com/square/Blueprint/compare/4.2.0...4.2.1 [4.2.0]: https://github.com/square/Blueprint/compare/4.1.2...4.2.0 diff --git a/SampleApp/Podfile.lock b/SampleApp/Podfile.lock index b953e9405..b38bd5ba1 100644 --- a/SampleApp/Podfile.lock +++ b/SampleApp/Podfile.lock @@ -1,8 +1,8 @@ PODS: - - BlueprintUI (4.3.0) - - BlueprintUI/Tests (4.3.0) - - BlueprintUICommonControls (4.3.0): - - BlueprintUI (= 4.3.0) + - BlueprintUI (5.0.0) + - BlueprintUI/Tests (5.0.0) + - BlueprintUICommonControls (5.0.0): + - BlueprintUI (= 5.0.0) DEPENDENCIES: - BlueprintUI (from `../BlueprintUI.podspec`) @@ -16,8 +16,8 @@ EXTERNAL SOURCES: :path: "../BlueprintUICommonControls.podspec" SPEC CHECKSUMS: - BlueprintUI: be852bd1c895f5405af2c75a6aa8bef0dacf41a8 - BlueprintUICommonControls: 41b66f55f4bbc8454e0e6fa01dbbabdd499accba + BlueprintUI: 0e2d2944bca6c0d6d96df711a43bce01154bb7ef + BlueprintUICommonControls: 8f400ee3ecf2bc58bd21cce29caba9f7c83d22b8 PODFILE CHECKSUM: 1cffac4623851f31dc42270ba99701e3825e6d67 diff --git a/version.rb b/version.rb index 75edce2cd..2b3e90d67 100644 --- a/version.rb +++ b/version.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -BLUEPRINT_VERSION ||= '4.3.0' +BLUEPRINT_VERSION ||= '5.0.0' SWIFT_VERSION ||= File.read(File.join(__dir__, '.swift-version')) From fad14f25ce19f81a86610a9dee97a4ba597ea791 Mon Sep 17 00:00:00 2001 From: Max Goedjen Date: Sun, 3 Nov 2024 16:04:00 -0800 Subject: [PATCH 08/13] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c843f3b5a..d10da53f9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,7 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added -- `Flow` children now support a layout `priority`, to specify if they should grow to use the extra space in a row. +- `Flow` children now support a layout `priority`, to specify if they should grow to use the extra space in a run. ### Removed From 891522cf2bc37579f7ef3015d0caa1c70cb5945e Mon Sep 17 00:00:00 2001 From: Max Goedjen Date: Mon, 4 Nov 2024 12:48:10 -0800 Subject: [PATCH 09/13] Prepare 5.0.1 release (#522) ## [5.0.1] - 2024-11-04 ### Added - `Flow` children now support a layout `priority`, to specify if they should grow to use the extra space in a run. ### Internal - Bump CI Xcode version to 15.4. --- CHANGELOG.md | 17 ++++++++++++----- SampleApp/Podfile.lock | 12 ++++++------ version.rb | 2 +- 3 files changed, 19 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d8686a8b5..4d8f4b3c0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,8 +11,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added -- `Flow` children now support a layout `priority`, to specify if they should grow to use the extra space in a run. - ### Removed ### Changed @@ -27,10 +25,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Internal -- Bump CI Xcode version to 15.4. - # Past Releases +## [5.0.1] - 2024-11-04 + +### Added + +- `Flow` children now support a layout `priority`, to specify if they should grow to use the extra space in a run. + +### Internal + +- Bump CI Xcode version to 15.4. + ## [5.0.0] - 2024-10-30 ### Added @@ -1127,7 +1133,8 @@ searchField - First stable release. -[main]: https://github.com/square/Blueprint/compare/5.0.0...HEAD +[main]: https://github.com/square/Blueprint/compare/5.0.1...HEAD +[5.0.1]: https://github.com/square/Blueprint/compare/5.0.0...5.0.1 [5.0.0]: https://github.com/square/Blueprint/compare/4.3.0...5.0.0 [4.3.0]: https://github.com/square/Blueprint/compare/4.2.1...4.3.0 [4.2.1]: https://github.com/square/Blueprint/compare/4.2.0...4.2.1 diff --git a/SampleApp/Podfile.lock b/SampleApp/Podfile.lock index b38bd5ba1..dc577436e 100644 --- a/SampleApp/Podfile.lock +++ b/SampleApp/Podfile.lock @@ -1,8 +1,8 @@ PODS: - - BlueprintUI (5.0.0) - - BlueprintUI/Tests (5.0.0) - - BlueprintUICommonControls (5.0.0): - - BlueprintUI (= 5.0.0) + - BlueprintUI (5.0.1) + - BlueprintUI/Tests (5.0.1) + - BlueprintUICommonControls (5.0.1): + - BlueprintUI (= 5.0.1) DEPENDENCIES: - BlueprintUI (from `../BlueprintUI.podspec`) @@ -16,8 +16,8 @@ EXTERNAL SOURCES: :path: "../BlueprintUICommonControls.podspec" SPEC CHECKSUMS: - BlueprintUI: 0e2d2944bca6c0d6d96df711a43bce01154bb7ef - BlueprintUICommonControls: 8f400ee3ecf2bc58bd21cce29caba9f7c83d22b8 + BlueprintUI: 8d6991d64adcd61b7421266ccad95b2a3a3ca656 + BlueprintUICommonControls: 060db17f4b9b72920aa950e2dfbd7808840f4b52 PODFILE CHECKSUM: 1cffac4623851f31dc42270ba99701e3825e6d67 diff --git a/version.rb b/version.rb index 2b3e90d67..673865d9e 100644 --- a/version.rb +++ b/version.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -BLUEPRINT_VERSION ||= '5.0.0' +BLUEPRINT_VERSION ||= '5.0.1' SWIFT_VERSION ||= File.read(File.join(__dir__, '.swift-version')) From 925f8cbe7b7f43d7fbb93a744585664bdc23f665 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 28 Oct 2024 18:41:20 +0000 Subject: [PATCH 10/13] Bump rexml from 3.3.6 to 3.3.9 Bumps [rexml](https://github.com/ruby/rexml) from 3.3.6 to 3.3.9. - [Release notes](https://github.com/ruby/rexml/releases) - [Changelog](https://github.com/ruby/rexml/blob/master/NEWS.md) - [Commits](https://github.com/ruby/rexml/compare/v3.3.6...v3.3.9) --- updated-dependencies: - dependency-name: rexml dependency-type: indirect ... Signed-off-by: dependabot[bot] --- Gemfile.lock | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 5eb107e79..e29edb502 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -97,8 +97,7 @@ GEM open4 (1.3.4) public_suffix (4.0.7) redcarpet (3.6.0) - rexml (3.3.6) - strscan + rexml (3.3.9) rouge (4.2.0) ruby-macho (2.5.1) ruby2_keywords (0.0.5) @@ -106,7 +105,6 @@ GEM ffi (~> 1.9) sqlite3 (1.7.0-arm64-darwin) sqlite3 (1.7.0-x86_64-linux) - strscan (3.1.0) typhoeus (1.4.1) ethon (>= 0.9.0) tzinfo (2.0.6) From 594b6c5b816dd4fa09c60e07b31e3ebf755571bd Mon Sep 17 00:00:00 2001 From: Robert MacEachern Date: Thu, 21 Nov 2024 12:26:10 -0600 Subject: [PATCH 11/13] feat: `accessibilityIdentifier` can now be set on `AttributedLabel` (#524) This allows `accessibilityIdentifier` to be set on `AttributedLabel`. --- .../Sources/AttributedLabel.swift | 4 ++++ .../Tests/Sources/AttributedLabelTests.swift | 20 +++++++++++++++++++ CHANGELOG.md | 2 ++ 3 files changed, 26 insertions(+) diff --git a/BlueprintUICommonControls/Sources/AttributedLabel.swift b/BlueprintUICommonControls/Sources/AttributedLabel.swift index ea91fc2f9..a35dc24ae 100644 --- a/BlueprintUICommonControls/Sources/AttributedLabel.swift +++ b/BlueprintUICommonControls/Sources/AttributedLabel.swift @@ -86,6 +86,9 @@ public struct AttributedLabel: Element, Hashable { /// A localized string that describes the result of performing an action on the element, when the result is non-obvious. public var accessibilityHint: String? + /// A string that identifies the element. + public var accessibilityIdentifier: String? + /// An array containing one or more `AccessibilityElement.CustomAction`s, defining additional supported actions. Assistive technologies, such as VoiceOver, will display your custom actions to the user at appropriate times. public var accessibilityCustomActions: [AccessibilityElement.CustomAction] = [] @@ -259,6 +262,7 @@ extension AttributedLabel { isAccessibilityElement = model.isAccessibilityElement accessibilityHint = model.accessibilityHint accessibilityValue = model.accessibilityValue + accessibilityIdentifier = model.accessibilityIdentifier updateAccessibilityTraits(with: model) accessibilityCustomActions = model.accessibilityCustomActions.map { action in UIAccessibilityCustomAction(name: action.name) { _ in action.onActivation() } diff --git a/BlueprintUICommonControls/Tests/Sources/AttributedLabelTests.swift b/BlueprintUICommonControls/Tests/Sources/AttributedLabelTests.swift index b681550d7..8febbfa9d 100644 --- a/BlueprintUICommonControls/Tests/Sources/AttributedLabelTests.swift +++ b/BlueprintUICommonControls/Tests/Sources/AttributedLabelTests.swift @@ -70,6 +70,26 @@ class AttributedLabelTests: XCTestCase { } } + func test_accessibilityConfiguration() { + let string = NSAttributedString(string: "Hello, World!") + + let label = AttributedLabel(attributedText: string) { label in + label.isAccessibilityElement = true + label.accessibilityHint = "Hint" + label.accessibilityValue = "Value" + label.accessibilityIdentifier = "Identifier" + } + + let view = BlueprintView(frame: CGRect(x: 0, y: 0, width: 100, height: 100)) + + label.accessBackingView(in: view) { view in + XCTAssertTrue(view.isAccessibilityElement) + XCTAssertEqual(view.accessibilityHint, "Hint") + XCTAssertEqual(view.accessibilityValue, "Value") + XCTAssertEqual(view.accessibilityIdentifier, "Identifier") + } + } + func test_displaysText() { let string = NSAttributedString() .appending(string: "H", font: .boldSystemFont(ofSize: 24.0), color: .red) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4d8f4b3c0..f6bf8ed03 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added +- The `accessibilityIdentifier` can now be set on `AttributedLabel`. + ### Removed ### Changed From 9b973ebf02c327c21a29c03469bced4f25116d22 Mon Sep 17 00:00:00 2001 From: Robert MacEachern Date: Mon, 25 Nov 2024 14:47:00 -0600 Subject: [PATCH 12/13] chore(ios): Scripts for preparing release and changelog (#529) This adds a script to streamline the release (and changelog management) steps for Blueprint. I used it to generate the release for 5.1.0. https://github.com/square/Blueprint/pull/528 Highlights: - Checks out a new branch and updates the version info - Stamps the changelog and adds a new link reference (and updates the `[Main]` one) - Opens a draft PR (requires `gh` to be installed and authed). - The PR description includes post-merge instructions that still need to be run manually. --- CHANGELOG.md | 2 +- RELEASING.md | 16 +++++- Scripts/release.sh | 107 +++++++++++++++++++++++++++++++++++++ Scripts/stamp-changelog.sh | 79 +++++++++++++++++++++++++++ 4 files changed, 202 insertions(+), 2 deletions(-) create mode 100755 Scripts/release.sh create mode 100755 Scripts/stamp-changelog.sh diff --git a/CHANGELOG.md b/CHANGELOG.md index f6bf8ed03..0b0299152 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,7 +27,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Internal -# Past Releases +- Added release and changelog managements scripts to streamline releases. ## [5.0.1] - 2024-11-04 diff --git a/RELEASING.md b/RELEASING.md index 63b13b5bf..442a44238 100644 --- a/RELEASING.md +++ b/RELEASING.md @@ -1,5 +1,16 @@ # Releasing a new version +1. Prepare a release + + ``` + # Cuts a release off of main with the given version number. + Scripts/release.sh --version 1.2.3 + ``` + +Manual instructions can be found here: + +
+ 1. You must be listed as an owner of the pods `BlueprintUI` and `BlueprintUICommonControls`. To check this run: @@ -17,7 +28,7 @@ 1. Update the library version in `version.rb` if it has not already been updated (it should match the version number that you are about to release). -1. Update `CHANGELOG.md` (in the root of the repo), moving current changes under `Main` to a new section under `Past Releases` for the version you are releasing. +1. Update `CHANGELOG.md` (in the root of the repo), moving current changes under `Main` to a new section for the version you are releasing. The changelog uses [reference links](https://daringfireball.net/projects/markdown/syntax#link) to link each version's changes. Remember to add a link to the new version at the bottom of the file, and to update the link to `[main]`. @@ -32,6 +43,8 @@ 1. Push your branch and open a PR into `main`. +
+ 1. Once the PR is merged, fetch changes and tag the release, using the merge commit: ```bash git fetch @@ -49,3 +62,4 @@ # version of BlueprintUI that we just published. bundle exec pod trunk push --synchronous BlueprintUICommonControls.podspec ``` + \ No newline at end of file diff --git a/Scripts/release.sh b/Scripts/release.sh new file mode 100755 index 000000000..1e801a2b2 --- /dev/null +++ b/Scripts/release.sh @@ -0,0 +1,107 @@ +#!/bin/bash + +set -euo pipefail + +branch="main" +diff_check=false + +# Function to display usage +usage() { + echo "Usage: $0 --version [--branch ] [--no-diff-check]" + exit 1 +} + +# Check if gh CLI is installed +if ! command -v gh &> /dev/null; then + echo "Error: GitHub CLI (gh) is not installed. It is required by this script." + echo "Please install it from https://cli.github.com/, authenticate, and try again." + exit 1 +fi + +# Parse options +while [[ $# -gt 0 ]]; do + case $1 in + -v|--version) version="$2"; shift 2 ;; + -b|--branch) branch="$2"; shift 2 ;; + -n|--no-diff-check) diff_check=false; shift ;; + --) shift; break ;; + -*|--*) echo "Unknown option $1"; usage ;; + *) break ;; + esac +done + +# Check if version argument is provided +if [ -z "${version:-}" ]; then + echo "Error: You must provide a version number." + usage +fi + +# Ensure there are no unstaged changes +if [ "$diff_check" = true ] && ! git diff --quiet origin/"$branch"; then + echo "Error: This branch has differences compared to origin/$branch. Please push or undo these changes before continuing." + echo "You can bypass this check with the --no-diff-check flag." + exit 1 +fi + +# This timestamp is used during branch creation. +# It's helpful in cases where the script fails and a new branch needs to +# be created on a subsequent attempt. +timestamp=$(date +"%Y-%m-%d-%H_%M_%S") + +git checkout "$branch" +git pull + +# Create a new branch with the version and timestamp +branch_name="$(whoami)/release-$version-$timestamp" +git checkout -b "$branch_name" + +# Define the git repo root +repo_root=$(git rev-parse --show-toplevel) + +# Extract the previous version number from version.rb +previous_version=$(grep 'BLUEPRINT_VERSION' "$repo_root/version.rb" | awk -F"'" '{print $2}') + +# Update the library version in version.rb +sed -i '' "s/BLUEPRINT_VERSION ||= .*/BLUEPRINT_VERSION ||= '$version'/" "$repo_root/version.rb" + +# Update CHANGELOG.md using stamp-changelog.sh +"$repo_root/Scripts/stamp-changelog.sh" --version "$version" --previous-version "$previous_version" + +# Change directory into the SampleApp dir and update Podfile.lock using a subshell +( + cd "$repo_root/SampleApp" + bundle exec pod install +) + +# Commit the changes +git add . +git commit -m "Bumping versions to $version." + +# Push the branch and open a PR into main +git push origin "$branch_name" + +pr_body=$(cat <<-END +https://github.com/square/Blueprint/blob/main/CHANGELOG.md + +Post-merge steps: + +- Once the PR is merged, fetch changes and tag the release, using the merge commit: + \`\`\` + git fetch + git tag $version + git push origin $version + \`\`\` + +- Publish to CocoaPods: + \`\`\` + bundle exec pod trunk push BlueprintUI.podspec + bundle exec pod trunk push --synchronous BlueprintUICommonControls.podspec + \`\`\` +END +) + +gh pr create --draft --title "release: Blueprint $version" --body "$pr_body" + +gh pr view --web + +echo "Branch $branch_name created and pushed. A draft PR has been created." diff --git a/Scripts/stamp-changelog.sh b/Scripts/stamp-changelog.sh new file mode 100755 index 000000000..99d908fb6 --- /dev/null +++ b/Scripts/stamp-changelog.sh @@ -0,0 +1,79 @@ +#!/bin/bash + +# Function to display usage +usage() { + echo "Usage: $0 -v -p " + echo " -v, --version Version number (required)" + echo " -p, --previous-version Previous version number (required)" + echo " -d, --release-date The date of the release (optional). Defaults to: date +%Y-%m-%d" + exit 1 +} + +# Parse options +while [[ "$#" -gt 0 ]]; do + case "$1" in + -v|--version) version="$2"; shift 2 ;; + -p|--previous-version) previous_version="$2"; shift 2 ;; + -d|--release-date) release_date="$2"; shift 2 ;; + --) shift; break ;; + -*|--*) echo "Unknown option $1"; usage ;; + *) break ;; + esac +done + +# Check if both version and previous_version arguments are provided +if [ -z "$version" ] || [ -z "$previous_version" ]; then + echo "Error: You must provide both version and previous version numbers." + usage +fi + +if [ -z "$release_date" ]; then + release_date=$(date +%Y-%m-%d) +fi + +repo_root=$(git rev-parse --show-toplevel) +changelog_file="$repo_root/CHANGELOG.md" + +changelog=$(ruby < "$changelog_file" + +echo "CHANGELOG.md updated for version $version." \ No newline at end of file From 89f75bae1891a9021e1462d5e942fd3c1dfe6d18 Mon Sep 17 00:00:00 2001 From: Robert MacEachern Date: Mon, 25 Nov 2024 15:03:58 -0600 Subject: [PATCH 13/13] release: Blueprint 5.1.0 (#528) > [!NOTE] > This PR was generated via the new [release script](https://github.com/square/Blueprint/pull/529). Usage: `Scripts/release.sh --version 5.1.0` https://github.com/square/Blueprint/blob/main/CHANGELOG.md Post-merge steps: - Once the PR is merged, fetch changes and tag the release, using the merge commit: ``` git fetch git tag 5.1.0 git push origin 5.1.0 ``` - Publish to CocoaPods: ``` bundle exec pod trunk push BlueprintUI.podspec bundle exec pod trunk push --synchronous BlueprintUICommonControls.podspec ``` --- CHANGELOG.md | 15 ++++++++++----- SampleApp/Podfile.lock | 12 ++++++------ version.rb | 2 +- 3 files changed, 17 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0b0299152..61564a628 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,8 +11,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added -- The `accessibilityIdentifier` can now be set on `AttributedLabel`. - ### Removed ### Changed @@ -27,6 +25,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Internal +## [5.1.0] - 2024-11-25 + +### Added + +- The `accessibilityIdentifier` can now be set on `AttributedLabel`. + +### Internal + - Added release and changelog managements scripts to streamline releases. ## [5.0.1] - 2024-11-04 @@ -116,8 +122,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `AccessibilityElement` now supports providing arbitrary strings to assistive devices using the `AXCustomContent` protocol. -### Removed - ### Changed - The behavior of `name` of `ElementPreview` has been change, affecting the SwiftUI `previewName`. Instead of including device or size information (i.e. `sizeThatFits - \(name)`), it now either defaults to the Xcode default if given an empty string, and shows _only_ the `name` if `name` is non-empty. @@ -1135,7 +1139,7 @@ searchField - First stable release. -[main]: https://github.com/square/Blueprint/compare/5.0.1...HEAD +[main]: https://github.com/square/Blueprint/compare/5.1.0...HEAD [5.0.1]: https://github.com/square/Blueprint/compare/5.0.0...5.0.1 [5.0.0]: https://github.com/square/Blueprint/compare/4.3.0...5.0.0 [4.3.0]: https://github.com/square/Blueprint/compare/4.2.1...4.3.0 @@ -1273,3 +1277,4 @@ searchField [#19]: https://github.com/square/Blueprint/pull/19 [#18]: https://github.com/square/Blueprint/pull/18 [#15]: https://github.com/square/Blueprint/pull/15 +[5.1.0]: https://github.com/square/Blueprint/compare/5.0.1...5.1.0 diff --git a/SampleApp/Podfile.lock b/SampleApp/Podfile.lock index dc577436e..7f0f9cbe8 100644 --- a/SampleApp/Podfile.lock +++ b/SampleApp/Podfile.lock @@ -1,8 +1,8 @@ PODS: - - BlueprintUI (5.0.1) - - BlueprintUI/Tests (5.0.1) - - BlueprintUICommonControls (5.0.1): - - BlueprintUI (= 5.0.1) + - BlueprintUI (5.1.0) + - BlueprintUI/Tests (5.1.0) + - BlueprintUICommonControls (5.1.0): + - BlueprintUI (= 5.1.0) DEPENDENCIES: - BlueprintUI (from `../BlueprintUI.podspec`) @@ -16,8 +16,8 @@ EXTERNAL SOURCES: :path: "../BlueprintUICommonControls.podspec" SPEC CHECKSUMS: - BlueprintUI: 8d6991d64adcd61b7421266ccad95b2a3a3ca656 - BlueprintUICommonControls: 060db17f4b9b72920aa950e2dfbd7808840f4b52 + BlueprintUI: 9ba3799699c813cf86165fc36e646bb10e7e5b47 + BlueprintUICommonControls: 91307b32a90175365c389ef0a033c516bd56feb7 PODFILE CHECKSUM: 1cffac4623851f31dc42270ba99701e3825e6d67 diff --git a/version.rb b/version.rb index 673865d9e..d3e65e2d9 100644 --- a/version.rb +++ b/version.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -BLUEPRINT_VERSION ||= '5.0.1' +BLUEPRINT_VERSION ||= '5.1.0' SWIFT_VERSION ||= File.read(File.join(__dir__, '.swift-version'))