Skip to content

Commit 545a9c2

Browse files
committed
add propertiesURL as available additional property type
1 parent c1492eb commit 545a9c2

File tree

5 files changed

+110
-6
lines changed

5 files changed

+110
-6
lines changed

Sources/FoundationEssentials/ProgressManager/ProgressManager+Properties+Accessors.swift

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,10 @@ extension ProgressManager {
5151
return getUpdatedStringSummary(property: MetatypeWrapper(property))
5252
}
5353

54+
public func summary<P: Property>(of property: P.Type) -> P.Summary where P.Value == URL?, P.Summary == [URL?] {
55+
return getUpdatedURLSummary(property: MetatypeWrapper(property))
56+
}
57+
5458
/// Returns the total file count across the progress subtree.
5559
///
5660
/// - Parameter property: The `TotalFileCount` property type.
@@ -145,6 +149,7 @@ extension ProgressManager {
145149
propertiesInt: [:],
146150
propertiesDouble: [:],
147151
propertiesString: [:],
152+
propertiesURL: [:],
148153
observers: [],
149154
interopType: nil,
150155
)
@@ -161,7 +166,8 @@ extension ProgressManager {
161166
estimatedTimeRemaining: ProgressManager.Properties.EstimatedTimeRemaining.defaultValue,
162167
propertiesInt: [:],
163168
propertiesDouble: [:],
164-
propertiesString: [:]
169+
propertiesString: [:],
170+
propertiesURL: [:]
165171
)
166172
#endif
167173
let result = try closure(&values)
@@ -214,6 +220,12 @@ extension ProgressManager {
214220
markSelfDirty(property: property, parents: values.state.parents)
215221
}
216222
}
223+
224+
if values.dirtyPropertiesURL.count > 0 {
225+
for property in values.dirtyPropertiesURL {
226+
markSelfDirty(property: property, parents: values.state.parents)
227+
}
228+
}
217229
#if FOUNDATION_FRAMEWORK
218230
if let observerState = values.observerState {
219231
switch state.interopType {
@@ -250,6 +262,7 @@ extension ProgressManager {
250262
internal var dirtyPropertiesInt: [MetatypeWrapper<Int, Int>] = []
251263
internal var dirtyPropertiesDouble: [MetatypeWrapper<Double, Double>] = []
252264
internal var dirtyPropertiesString: [MetatypeWrapper<String?, [String?]>] = []
265+
internal var dirtyPropertiesURL: [MetatypeWrapper<URL?, [URL?]>] = []
253266
#if FOUNDATION_FRAMEWORK
254267
internal var observerState: ObserverState?
255268
#endif
@@ -491,6 +504,22 @@ extension ProgressManager {
491504
dirtyPropertiesString.append(MetatypeWrapper(P.self))
492505
}
493506
}
507+
508+
public subscript<P: Property>(dynamicMember key: KeyPath<ProgressManager.Properties, P.Type>) -> URL? where P.Value == URL?, P.Summary == [URL?] {
509+
get {
510+
return state.propertiesURL[MetatypeWrapper(P.self)] ?? P.self.defaultValue
511+
}
512+
513+
set {
514+
guard newValue != state.propertiesURL[MetatypeWrapper(P.self)] else {
515+
return
516+
}
517+
518+
state.propertiesURL[MetatypeWrapper(P.self)] = newValue
519+
520+
dirtyPropertiesURL.append(MetatypeWrapper(P.self))
521+
}
522+
}
494523
#if FOUNDATION_FRAMEWORK
495524
private mutating func interopNotifications() {
496525
switch state.interopType {

Sources/FoundationEssentials/ProgressManager/ProgressManager+Properties+Helpers.swift

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,48 @@ extension ProgressManager {
148148
}
149149
}
150150

151+
internal func getUpdatedURLSummary(property: MetatypeWrapper<URL?, [URL?]>) -> [URL?] {
152+
return state.withLock { state in
153+
154+
var value: [URL?] = property.defaultSummary
155+
property.reduce(&value, state.propertiesURL[property] ?? property.defaultValue)
156+
157+
guard !state.children.isEmpty else {
158+
return value
159+
}
160+
161+
for (idx, childState) in state.children.enumerated() {
162+
if let childPropertyState = childState.childPropertiesURL[property] {
163+
if childPropertyState.isDirty {
164+
// Update dirty path
165+
if let child = childState.child {
166+
let updatedSummary = child.getUpdatedURLSummary(property: property)
167+
let newChildPropertyState = PropertyStateURL(value: updatedSummary, isDirty: false)
168+
state.children[idx].childPropertiesURL[property] = newChildPropertyState
169+
value = property.merge(value, updatedSummary)
170+
}
171+
} else {
172+
if let _ = childState.child {
173+
// Merge non-dirty, updated value
174+
value = property.merge(value, childPropertyState.value)
175+
} else {
176+
value = property.terminate(value, childPropertyState.value)
177+
}
178+
}
179+
} else {
180+
// First fetch of value
181+
if let child = childState.child {
182+
let childSummary = child.getUpdatedURLSummary(property: property)
183+
let newChildPropertyState = PropertyStateURL(value: childSummary, isDirty: false)
184+
state.children[idx].childPropertiesURL[property] = newChildPropertyState
185+
value = property.merge(value, childSummary)
186+
}
187+
}
188+
}
189+
return value
190+
}
191+
}
192+
151193
internal func getUpdatedFileCount(type: CountType) -> Int {
152194
switch type {
153195
case .total:
@@ -393,6 +435,12 @@ extension ProgressManager {
393435
}
394436
}
395437

438+
internal func markSelfDirty(property: MetatypeWrapper<URL?, [URL?]>, parents: [ParentState]) {
439+
for parentState in parents {
440+
parentState.parent.markChildDirty(property: property, at: parentState.positionInParent)
441+
}
442+
}
443+
396444
internal func markSelfDirty(property: ProgressManager.Properties.TotalFileCount.Type, parents: [ParentState]) {
397445
for parentState in parents {
398446
parentState.parent.markChildDirty(property: property, at: parentState.positionInParent)
@@ -458,6 +506,14 @@ extension ProgressManager {
458506
}
459507
markSelfDirty(property: property, parents: parents)
460508
}
509+
510+
internal func markChildDirty(property: MetatypeWrapper<URL?, [URL?]>, at position: Int) {
511+
let parents = state.withLock { state in
512+
state.children[position].childPropertiesURL[property]?.isDirty = true
513+
return state.parents
514+
}
515+
markSelfDirty(property: property, parents: parents)
516+
}
461517

462518
internal func markChildDirty(property: ProgressManager.Properties.TotalFileCount.Type, at position: Int) {
463519
let parents = state.withLock { state in
@@ -516,7 +572,7 @@ extension ProgressManager {
516572
}
517573

518574
//MARK: Method to preserve values of properties upon deinit
519-
internal func setChildDeclaredAdditionalProperties(at position: Int, totalFileCount: Int, completedFileCount: Int, totalByteCount: UInt64, completedByteCount: UInt64, throughput: [UInt64], estimatedTimeRemaining: Duration, fileURL: [URL?], propertiesInt: [MetatypeWrapper<Int, Int>: Int], propertiesDouble: [MetatypeWrapper<Double, Double>: Double], propertiesString: [MetatypeWrapper<String?, [String?]>: [String?]]) {
575+
internal func setChildDeclaredAdditionalProperties(at position: Int, totalFileCount: Int, completedFileCount: Int, totalByteCount: UInt64, completedByteCount: UInt64, throughput: [UInt64], estimatedTimeRemaining: Duration, fileURL: [URL?], propertiesInt: [MetatypeWrapper<Int, Int>: Int], propertiesDouble: [MetatypeWrapper<Double, Double>: Double], propertiesString: [MetatypeWrapper<String?, [String?]>: [String?]], propertiesURL: [MetatypeWrapper<URL?, [URL?]>: [URL?]]) {
520576
state.withLock { state in
521577
state.children[position].totalFileCount = PropertyStateInt(value: totalFileCount, isDirty: false)
522578
state.children[position].completedFileCount = PropertyStateInt(value: completedFileCount, isDirty: false)
@@ -537,6 +593,10 @@ extension ProgressManager {
537593
for (propertyKey, propertyValue) in propertiesString {
538594
state.children[position].childPropertiesString[propertyKey] = PropertyStateString(value: propertyValue, isDirty: false)
539595
}
596+
597+
for (propertyKey, propertyValue) in propertiesURL {
598+
state.children[position].childPropertiesURL[propertyKey] = PropertyStateURL(value: propertyValue, isDirty: false)
599+
}
540600
}
541601
}
542602
}

Sources/FoundationEssentials/ProgressManager/ProgressManager+State.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ extension ProgressManager {
9393
var childPropertiesInt: [MetatypeWrapper<Int, Int>: PropertyStateInt]
9494
var childPropertiesDouble: [MetatypeWrapper<Double, Double>: PropertyStateDouble]
9595
var childPropertiesString: [MetatypeWrapper<String?, [String?]>: PropertyStateString]
96+
var childPropertiesURL: [MetatypeWrapper<URL?, [URL?]>: PropertyStateURL]
9697
}
9798

9899
internal struct ParentState {
@@ -126,6 +127,7 @@ extension ProgressManager {
126127
var propertiesInt: [MetatypeWrapper<Int, Int>: Int]
127128
var propertiesDouble: [MetatypeWrapper<Double, Double>: Double]
128129
var propertiesString: [MetatypeWrapper<String?, [String?]>: String?]
130+
var propertiesURL: [MetatypeWrapper<URL?, [URL?]>: URL?]
129131
#if FOUNDATION_FRAMEWORK
130132
var observers: [@Sendable (ObserverState) -> Void]
131133
var interopType: InteropType?

Sources/FoundationEssentials/ProgressManager/ProgressManager.swift

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ internal import _FoundationCollections
9393
propertiesInt: [:],
9494
propertiesDouble: [:],
9595
propertiesString: [:],
96+
propertiesURL: [:],
9697
observers: [],
9798
interopType: .interopObservation(InteropObservation(subprogressBridge: subprogressBridge))
9899
)
@@ -243,7 +244,8 @@ internal import _FoundationCollections
243244
fileURL: PropertyStateURL(value: ProgressManager.Properties.FileURL.defaultSummary, isDirty: false),
244245
childPropertiesInt: [:],
245246
childPropertiesDouble: [:],
246-
childPropertiesString: [:])
247+
childPropertiesString: [:],
248+
childPropertiesURL: [:])
247249
state.children.append(childState)
248250
return (state.children.count - 1, state.parents)
249251
}
@@ -301,8 +303,8 @@ internal import _FoundationCollections
301303
}
302304
}
303305

304-
let (propertiesInt, propertiesDouble, propertiesString, parents) = state.withLock { state in
305-
return (state.propertiesInt, state.propertiesDouble, state.propertiesString, state.parents)
306+
let (propertiesInt, propertiesDouble, propertiesString, propertiesURL, parents) = state.withLock { state in
307+
return (state.propertiesInt, state.propertiesDouble, state.propertiesString, state.propertiesURL, state.parents)
306308
}
307309

308310
var finalSummaryInt: [MetatypeWrapper<Int, Int>: Int] = [:]
@@ -323,6 +325,12 @@ internal import _FoundationCollections
323325
finalSummaryString[property] = updatedSummary
324326
}
325327

328+
var finalSummaryURL: [MetatypeWrapper<URL?, [URL?]>: [URL?]] = [:]
329+
for property in propertiesURL.keys {
330+
let updatedSummary = self.getUpdatedURLSummary(property: property)
331+
finalSummaryURL[property] = updatedSummary
332+
}
333+
326334
let totalFileCount = self.getUpdatedFileCount(type: .total)
327335
let completedFileCount = self.getUpdatedFileCount(type: .completed)
328336
let totalByteCount = self.getUpdatedByteCount(type: .total)
@@ -343,7 +351,8 @@ internal import _FoundationCollections
343351
fileURL: fileURL,
344352
propertiesInt: finalSummaryInt,
345353
propertiesDouble: finalSummaryDouble,
346-
propertiesString: finalSummaryString
354+
propertiesString: finalSummaryString,
355+
propertiesURL: finalSummaryURL
347356
)
348357
}
349358
}

Sources/FoundationEssentials/ProgressManager/ProgressReporter.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,10 @@ import Observation
114114
return manager.summary(of: property)
115115
}
116116

117+
public func summary<P: ProgressManager.Property>(of property: P.Type) -> [URL?] where P.Value == URL?, P.Summary == [URL?] {
118+
return manager.summary(of: property)
119+
}
120+
117121
/// Returns the total file count across the progress subtree.
118122
///
119123
/// - Parameter property: The `TotalFileCount` property type.

0 commit comments

Comments
 (0)