Skip to content

Commit 6a7d5d1

Browse files
authored
Merge pull request #48 from chenhaiteng/feature/update-to-swift-6.1
Feature/update to swift 6.1
2 parents ee8eb1b + 839c9d2 commit 6a7d5d1

8 files changed

Lines changed: 91 additions & 49 deletions

File tree

Package.swift

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// swift-tools-version:5.9
1+
// swift-tools-version:6.1
22
// The swift-tools-version declares the minimum version of Swift required to build this package.
33

44
import PackageDescription
@@ -18,13 +18,13 @@ let package = Package(
1818
dependencies: [
1919
// Dependencies declare other packages that this package depends on.
2020
// .package(url: /* package url */, from: "1.0.0"),
21-
.package(url: "https://github.com/chenhaiteng/CoreGraphicsExtension.git", from: "0.4.0"),
22-
.package(url: "https://github.com/chenhaiteng/ArchimedeanSpiral.git", from: "1.0.12"),
23-
.package(url: "https://github.com/chenhaiteng/GradientBuilder.git", from: "1.0.0"),
21+
.package(url: "https://github.com/chenhaiteng/CoreGraphicsExtension.git", from: "0.5.0"),
22+
.package(url: "https://github.com/chenhaiteng/ArchimedeanSpiral.git", from: "1.1.0"),
23+
.package(url: "https://github.com/chenhaiteng/GradientBuilder.git", from: "1.2.0"),
2424
.package(url: "https://github.com/andtie/SequenceBuilder.git", from: "0.0.7"),
2525
.package(url: "https://github.com/GeorgeElsham/ViewExtractor", from: "2.0.0"),
2626
.package(url: "https://github.com/apple/swift-docc-plugin", from: "1.1.0"),
27-
.package(url: "https://github.com/chenhaiteng/SwiftClamping", from: "1.0.0")
27+
.package(url: "https://github.com/chenhaiteng/SwiftClamping", from: "1.1.0")
2828
],
2929
targets: [
3030
// Targets are the basic building blocks of a package. A target can define a module or a test suite.

Sources/Rings/HandAiguille.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ extension HandAiguille {
100100
}
101101

102102
public enum HandFactory {
103-
public static func makeAppleWatchStyleHand<T: BinaryFloatingPoint>(size: CGSize = CGSize(width: 4.0, height: 60.0), timeProvider: Binding<T>, unit: TimeUnit = .second) -> some View {
103+
@MainActor public static func makeAppleWatchStyleHand<T: BinaryFloatingPoint>(size: CGSize = CGSize(width: 4.0, height: 60.0), timeProvider: Binding<T>, unit: TimeUnit = .second) -> some View {
104104
HandAiguille(size: size, offset: 1.5, time: timeProvider, unit: unit) {
105105
VStack(spacing: 0) {
106106
Capsule().stroke().frame(width: size.width)

Sources/Rings/KnobComponents/Layers/CustomViewLayer.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ import SwiftUI
99
import Common
1010
import SwiftClamping
1111

12-
struct CustomViewLayer<V: View>: AngularLayer {
12+
@MainActor
13+
struct CustomViewLayer<V: View>: @preconcurrency AngularLayer {
1314
private var content: () -> V
1415
public var isFixed: Bool = false
1516
public var offset: CGPoint = .zero

Sources/Rings/KnobComponents/Layers/GauageNeedleLayer.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ import CoreGraphics
1111
import CoreGraphicsExtension
1212
import SwiftClamping
1313

14-
public struct GauageNeedleLayer<V> : AngularLayer where V: View {
14+
@MainActor
15+
public struct GauageNeedleLayer<V> : @preconcurrency AngularLayer where V: View {
1516
var content: () -> V
1617
public var isFixed: Bool = false
1718
private var blueprint: Bool = false

Sources/Rings/KnobComponents/Mappings/KnobMapping.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@ public enum Default {
1717
case Max = 1.0
1818
}
1919

20-
public static var degreeRange: ClosedRange<Double> = Degree.Min.rawValue...Degree.Max.rawValue
20+
public static let degreeRange: ClosedRange<Double> = Degree.Min.rawValue...Degree.Max.rawValue
2121

22-
public static var valueRange: ClosedRange<Double> = Value.Min.rawValue...Value.Max.rawValue
22+
public static let valueRange: ClosedRange<Double> = Value.Min.rawValue...Value.Max.rawValue
2323
}
2424

2525
public struct KnobGestureRecord {

Sources/Rings/Sizing.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
import SwiftUI
1414

1515
struct ViewSizeKey : PreferenceKey {
16-
static var defaultValue: [CGSize] = []
16+
static let defaultValue: [CGSize] = []
1717
static func reduce(value: inout [CGSize], nextValue: () -> [CGSize]) {
1818
value.append(contentsOf: nextValue())
1919
}

Sources/Rings/SphericText.swift

Lines changed: 77 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -12,35 +12,49 @@ public enum WritingDirection {
1212
case LeftToRight, RightToLeft
1313
}
1414

15+
public struct TextComponent {
16+
let text: String
17+
let color: Color
18+
let font: Font?
19+
}
20+
1521
public struct SphericText<T:BinaryFloatingPoint>: View {
1622

17-
@Binding var offsetDegree: T
23+
let rotateDegree: T
24+
private let textComponents: [TextComponent]
1825

19-
private let stringTable: [(offset: Int, element:String)]
20-
private var wordSpacing: Double = 30.0
26+
private var textSpacing: Double = 30.0
2127
private var font: Font?
2228
private var wordColor = Color.white
2329
private var wordBackground = Color.clear
2430
private var hideOpposite = false
2531
private var blurMinors = false
26-
private var oppositeRange = 150...210
32+
private var oppositeRange = -90...90
2733
private var frontMostRange = -10...10
2834
private var perspective: CGFloat = 0.0
29-
private var anchorZ: CGFloat = 100.0
35+
private var radius: CGFloat = 0.0
3036
private var writingDirection: WritingDirection = .LeftToRight
3137
@State private var estHeight: CGFloat = 30.0
3238
@State private var estWidth: CGFloat = 30.0
3339

40+
41+
public init(_ components: [TextComponent], rotateDegree: T) {
42+
textComponents = components
43+
font = .system(size: 40.0)
44+
self.rotateDegree = rotateDegree
45+
}
46+
3447
public init(words: [String], word_spacing: T = 30.0 , font: Font? = nil, word_color: Color = Color.white, word_background: Color = Color.clear, hide_opposite: Bool = false, degree_offset: Binding<T> = .constant(0)) {
35-
stringTable = words.enumerated().map { (i, e) in
36-
return (i, e)
37-
}
38-
_offsetDegree = degree_offset
39-
wordSpacing = Double(word_spacing)
40-
self.font = font ?? .system(size: 20.0)
48+
textSpacing = Double(word_spacing)
49+
let defaultFont = font ?? .system(size: 40.0)
50+
self.font = defaultFont
4151
wordColor = word_color
4252
wordBackground = word_background
4353
hideOpposite = hide_opposite
54+
self.textComponents = words.map { word in
55+
TextComponent(text: word,color: word_color, font:defaultFont)
56+
}
57+
self.rotateDegree = degree_offset.wrappedValue
4458
}
4559

4660
public init(_ text: String, _ rotateDegree: Binding<T> = .constant(0)) {
@@ -69,35 +83,32 @@ public struct SphericText<T:BinaryFloatingPoint>: View {
6983
let frameL = geo.frame(in: .local)
7084
ZStack(alignment: .center) {
7185
//hide text to caculate height
72-
Sizing {
73-
Text("A").font(font).opacity(0.0)
74-
}
75-
ForEach(stringTable, id: \.self.offset) { i, element in
76-
let positionInDegree = Double(offsetDegree) + (writingDirection == .LeftToRight ? -1.0 : 1.0)*Double(i)*wordSpacing
77-
let _ = print("degrees: \(positionInDegree)")
86+
let anchorZ = radius > 0 ? radius : w/2.0
87+
ForEach(0..<textComponents.count, id:\.self) { index in
88+
let component = textComponents[index]
89+
let positionInDegree = Double(rotateDegree) + (writingDirection == .LeftToRight ? 1.0 : -1.0)*Double(index)*textSpacing
7890
let normalizedD = Int(positionInDegree)%360
7991
let shouldBlur = blurMinors ? !(frontMostRange ~= abs(normalizedD)) : false
8092
let shouldHide = hideOpposite ? (oppositeRange ~= abs(normalizedD)) : false
8193

82-
let text = writingDirection == .RightToLeft ? String(element.reversed()) : element
83-
Text(text).frame(width: estWidth*CGFloat(text.count), height: 50, alignment: Alignment(horizontal: .center, vertical: .center))
84-
.font(font)
85-
.foregroundColor(wordColor)
86-
.background(wordBackground)
87-
.rotation3DEffect(
94+
let text = writingDirection == .RightToLeft ? String(component.text.reversed()) : component.text
95+
VStack {
96+
Text(text)
97+
.font(component.font)
98+
.foregroundColor(component.color)
99+
.border(Color.blue)
100+
Text("\(positionInDegree)")
101+
}.rotation3DEffect(
88102
.degrees(positionInDegree),
89103
axis: (x: 0.0, y: 1.0, z: 0.0),
90104
anchor: .center,
91105
anchorZ: anchorZ,
92106
perspective: perspective
93107
).opacity(shouldHide ? 0.0 : (shouldBlur ? 0.5 : 1.0))
94-
.blur(radius: (shouldBlur ? 1.0 : 0.0))
95-
}.frame(width: w, height: estHeight, alignment: .center)
96-
97-
}.frame(width: frameL.size.width, height: frameL.size.height).onPreferenceChange(ViewSizeKey.self) { sizes in
98-
estHeight = (sizes.reduce(0, {$0 + $1.height}))/CGFloat(sizes.count)*CGFloat(1.1)
99-
estWidth = (sizes.reduce(0, {$0 + $1.width}))/CGFloat(sizes.count)
100-
}
108+
.blur(radius: (shouldBlur ? 1.0 : 0.0)).frame(alignment: .center)
109+
110+
}
111+
}.frame(width: frameL.size.width, height: frameL.size.height).clipped()
101112

102113
}
103114
}
@@ -106,7 +117,7 @@ public struct SphericText<T:BinaryFloatingPoint>: View {
106117
extension SphericText : Adjustable {
107118
public func wordSpacing(_ spacing: T) -> SphericText {
108119
setProperty { tmp in
109-
tmp.wordSpacing = Double(spacing)
120+
tmp.textSpacing = Double(spacing)
110121
}
111122
}
112123

@@ -154,7 +165,7 @@ extension SphericText : Adjustable {
154165

155166
public func radius(_ value: T) -> SphericText {
156167
setProperty { tmp in
157-
tmp.anchorZ = CGFloat(value)
168+
tmp.radius = CGFloat(value)
158169
}
159170
}
160171

@@ -172,11 +183,39 @@ extension SphericText : Adjustable {
172183

173184
@available(tvOS, unavailable)
174185
struct SphericTextDemo: View {
186+
var demoData: [TextComponent] {
187+
let font = Font.system(size: 48)
188+
if #available(iOS 15.0, *) {
189+
return [
190+
TextComponent(text: "A", color: .red, font: font),
191+
TextComponent(text: "B", color: .green, font: font),
192+
TextComponent(text: "C", color: .blue, font: font),
193+
TextComponent(text: "D", color: .yellow, font: font),
194+
TextComponent(text: "E", color: .pink, font: font),
195+
TextComponent(text: "F", color: .gray, font: font),
196+
TextComponent(text: "G", color: .purple, font: font),
197+
TextComponent(text: "H", color: .cyan, font: font),
198+
TextComponent(text: "I", color: .white, font: font)
199+
]
200+
} else {
201+
// Fallback on earlier versions
202+
return [
203+
TextComponent(text: "A", color: .red, font: font),
204+
TextComponent(text: "B", color: .green, font: font),
205+
TextComponent(text: "C", color: .blue, font: font),
206+
TextComponent(text: "D", color: .yellow, font: font),
207+
TextComponent(text: "E", color: .pink, font: font),
208+
TextComponent(text: "F", color: .gray, font: font),
209+
TextComponent(text: "G", color: .purple, font: font),
210+
TextComponent(text: "I", color: .white, font: font)
211+
]
212+
}
213+
}
175214
@State var rotateDeg: CGFloat = 0.0
176215
@State var showModifier: Bool = false
177216
@State var radius: CGFloat = 40.0
178217
@State var perspective: CGFloat = 0.0
179-
@State var characters = "ABCDE"
218+
@State var characters = "ABCDEGMS"
180219
@State var wordsInput = "Test\n100"
181220
@State var words = ["Test", "100"]
182221
@State var blurMinors: Bool = false
@@ -200,12 +239,13 @@ struct SphericTextDemo: View {
200239
let width = geo.size.width/2
201240
VStack {
202241
ZStack {
203-
SphericText(characters, $rotateDeg).rangeOfOpposite(in: 145...210)
204-
.radius(radius)
242+
SphericText(demoData, rotateDegree: rotateDeg)
243+
.rangeOfOpposite(in: 145...210)
205244
.perspective(perspective)
206245
.blurMinors(blurMinors)
207246
.hideOpposite(hideOpposite)
208247
.frame(width: width)
248+
.border(Color.blue, width: 1.0)
209249
}
210250
HStack {
211251
Spacer()
@@ -219,7 +259,7 @@ struct SphericTextDemo: View {
219259
}
220260
Divider().background(Color.white)
221261
VStack {
222-
SphericText(words: words, degree_offset: $rotateDeg).wordSpacing(wordSpacing).font( .system(size: 32.0)).wordColor(textColor).wordBackground(backgroundColor).hideOpposite(false).perspective(perspective).radius(radius).frame(width: width)
262+
SphericText(words: words, degree_offset: $rotateDeg).wordSpacing(wordSpacing).font( .system(size: 32.0)).wordColor(textColor).wordBackground(backgroundColor).hideOpposite(false).perspective(perspective).frame(width: width).border(Color.blue, width: 1.0)
223263
#if os(iOS)
224264
if #available(macOS 11.0, iOS 14.0, *) {
225265
TextEditor(text: wordsInputBinding).textFieldStyle(RoundedBorderTextFieldStyle()).frame(width: 100, height: 80, alignment: .center)
@@ -272,7 +312,7 @@ struct SphericTextDemo: View {
272312
}, label: {
273313
Text("Rotate")
274314
})
275-
Slider(value: $rotateDeg, in: -360.0...360.0)
315+
Slider(value: $rotateDeg, in: 0.0...360.0)
276316
Text("\(rotateDeg, specifier: "%.2f")").foregroundColor(.white)
277317
Spacer(minLength: 20)
278318
}

Sources/Rings/Types/RingLayoutDirection.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import Foundation
99
import CoreGraphicsExtension
1010
import SwiftUI
1111

12-
public enum RingLayoutDirection : Hashable {
12+
public enum RingLayoutDirection : Hashable, Sendable {
1313
case related(degrees: Double)
1414
case fixed(degrees: Double)
1515

0 commit comments

Comments
 (0)