@craft-native/ios 0.0.497 → 0.0.500
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/templates/CraftApp.swift +25 -1
- package/templates/CraftHybrid.swift +63 -22
- package/templates/CraftNativeActions.swift +47 -3
- package/templates/CraftNativeFiles.swift +160 -8
- package/templates/CraftNativeFlatList.swift +43 -6
- package/templates/CraftNativeScreen.swift +222 -69
- package/templates/CraftPersistentStorage.swift +28 -5
- package/templates/CraftScheduledWorkouts.swift +11 -4
- package/templates/CraftWebAudio.swift +20 -1
|
@@ -316,7 +316,8 @@ final class CraftNativeFlatList: UICollectionView, UICollectionViewDelegateFlowL
|
|
|
316
316
|
rows += (pending + columns - 1) / columns
|
|
317
317
|
content = CGFloat(rows) * 44 + CGFloat(max(0, rows - 1)) * flowLayout.minimumLineSpacing
|
|
318
318
|
}
|
|
319
|
-
|
|
319
|
+
// Its rows and its own padding: not the room left for what floats over it.
|
|
320
|
+
return max(0, ceil(content + contentPadding.top + contentPadding.bottom))
|
|
320
321
|
}
|
|
321
322
|
|
|
322
323
|
/// The width a row gets: the list's own width inside its content padding,
|
|
@@ -406,6 +407,24 @@ final class CraftNativeFlatList: UICollectionView, UICollectionViewDelegateFlowL
|
|
|
406
407
|
bottom: nonNegative(raw?["paddingBottom"]) ?? vertical,
|
|
407
408
|
right: nonNegative(raw?["paddingRight"]) ?? horizontal
|
|
408
409
|
)
|
|
410
|
+
guard contentPadding != inset else { return }
|
|
411
|
+
contentPadding = inset
|
|
412
|
+
applyContentInsets()
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
/// `contentContainerStyle`'s padding, which the list draws as its insets.
|
|
416
|
+
private var contentPadding: UIEdgeInsets = .zero
|
|
417
|
+
|
|
418
|
+
/// How far the compact tab actions reach over the end of this list. The
|
|
419
|
+
/// rows get that much more room at the end, so the last one can be
|
|
420
|
+
/// brought clear of them (#523).
|
|
421
|
+
var floatingCover: CGFloat = 0 {
|
|
422
|
+
didSet { if abs(oldValue - floatingCover) > 0.5 { applyContentInsets() } }
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
private func applyContentInsets() {
|
|
426
|
+
var inset = contentPadding
|
|
427
|
+
if flowLayout.scrollDirection == .vertical { inset.bottom += floatingCover }
|
|
409
428
|
guard contentInset != inset else { return }
|
|
410
429
|
contentInset = inset
|
|
411
430
|
scrollIndicatorInsets = inset
|
|
@@ -507,11 +526,10 @@ final class CraftNativeFlatList: UICollectionView, UICollectionViewDelegateFlowL
|
|
|
507
526
|
let oldItems = itemsByIdentity
|
|
508
527
|
let viewportAnchor = currentViewportAnchor()
|
|
509
528
|
var seen: [String: Int] = [:]
|
|
529
|
+
var taken = Set<String>()
|
|
510
530
|
var next = nodes.enumerated().map { index, node -> Item in
|
|
511
531
|
let base = Self.identity(for: node) ?? "index:\(index)"
|
|
512
|
-
let
|
|
513
|
-
seen[base] = occurrence + 1
|
|
514
|
-
let identity = occurrence == 0 ? base : "\(base)#\(occurrence)"
|
|
532
|
+
let identity = Self.uniqueIdentity(base, seen: &seen, taken: &taken)
|
|
515
533
|
let props = node["props"] as? [String: Any] ?? [:]
|
|
516
534
|
let role = props["listRole"] as? String
|
|
517
535
|
let signature = (try? JSONSerialization.data(withJSONObject: node, options: [.sortedKeys])) ?? Data()
|
|
@@ -532,7 +550,7 @@ final class CraftNativeFlatList: UICollectionView, UICollectionViewDelegateFlowL
|
|
|
532
550
|
return dataItemCount - 1
|
|
533
551
|
}
|
|
534
552
|
items = next
|
|
535
|
-
itemsByIdentity = Dictionary(
|
|
553
|
+
itemsByIdentity = Dictionary(next.map { ($0.identity, $0) }, uniquingKeysWith: { first, _ in first })
|
|
536
554
|
|
|
537
555
|
flowLayout.scrollDirection = horizontal ? .horizontal : .vertical
|
|
538
556
|
alwaysBounceHorizontal = horizontal
|
|
@@ -680,7 +698,7 @@ final class CraftNativeFlatList: UICollectionView, UICollectionViewDelegateFlowL
|
|
|
680
698
|
let lastDataOrdinal = dataOrdinals[lastVisible]
|
|
681
699
|
guard lastDataOrdinal >= 0 else { return }
|
|
682
700
|
let remaining = dataItemCount - lastDataOrdinal - 1
|
|
683
|
-
let thresholdItems = max(1,
|
|
701
|
+
let thresholdItems = max(1, craftNativeInt(ceil(Double(dataItemCount) * endReachedThreshold)))
|
|
684
702
|
guard remaining <= thresholdItems else { return }
|
|
685
703
|
let signature = dataContentSignature
|
|
686
704
|
guard endReachedSignature != signature else { return }
|
|
@@ -864,6 +882,25 @@ final class CraftNativeFlatList: UICollectionView, UICollectionViewDelegateFlowL
|
|
|
864
882
|
setContentOffset(clamped(offset), animated: false)
|
|
865
883
|
}
|
|
866
884
|
|
|
885
|
+
/// A row's identity, its own in this list.
|
|
886
|
+
///
|
|
887
|
+
/// Rows that share a key are told apart by a suffix: `run`, then `run#1`.
|
|
888
|
+
/// A row whose own key was `run#1` then had the identity of the second
|
|
889
|
+
/// `run`, and the list's table and its snapshot both trap on a repeated
|
|
890
|
+
/// identity: three tags keyed `run`, `run` and `run#1` ended the process.
|
|
891
|
+
/// The suffix counts on until the identity is one no row has taken. A
|
|
892
|
+
/// list with no such key has the identities it always had.
|
|
893
|
+
static func uniqueIdentity(_ base: String, seen: inout [String: Int], taken: inout Set<String>) -> String {
|
|
894
|
+
var occurrence = seen[base, default: 0]
|
|
895
|
+
var identity = occurrence == 0 ? base : "\(base)#\(occurrence)"
|
|
896
|
+
while !taken.insert(identity).inserted {
|
|
897
|
+
occurrence += 1
|
|
898
|
+
identity = "\(base)#\(occurrence)"
|
|
899
|
+
}
|
|
900
|
+
seen[base] = occurrence + 1
|
|
901
|
+
return identity
|
|
902
|
+
}
|
|
903
|
+
|
|
867
904
|
private static func identity(for node: [String: Any]) -> String? {
|
|
868
905
|
let props = node["props"] as? [String: Any] ?? [:]
|
|
869
906
|
return [node["key"], props["key"], props["testID"], node["id"]]
|