@craft-native/ios 0.0.242 → 0.0.243
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
CHANGED
package/templates/CraftApp.swift
CHANGED
|
@@ -896,12 +896,9 @@ final class CraftChrome: ObservableObject {
|
|
|
896
896
|
// stack. Cancellation belongs to the stack the finger left.
|
|
897
897
|
tabSwipePrevious = previous
|
|
898
898
|
tabSwipeTarget = id
|
|
899
|
-
// Only the indicator moves now. The highlight follows it across the
|
|
900
|
-
// midpoint (updateTabSwipe), as iOS's own tab bar lens does; turning
|
|
901
|
-
// it at once rebuilt every tab in the swipe's first frame, which is
|
|
902
|
-
// also when UIKit puts the incoming screen on screen.
|
|
903
899
|
withAnimation(nil) {
|
|
904
900
|
tabSwipePosition = tabs.firstIndex(where: { $0.id == previous }).map { CGFloat($0) }
|
|
901
|
+
selected = id
|
|
905
902
|
}
|
|
906
903
|
}
|
|
907
904
|
|
|
@@ -913,14 +910,11 @@ final class CraftChrome: ObservableObject {
|
|
|
913
910
|
let to = tabs.firstIndex(where: { $0.id == target }) else { return }
|
|
914
911
|
let position = CGFloat(from) + CGFloat(to - from) * min(1, max(0, progress))
|
|
915
912
|
if tabSwipePosition != position { withAnimation(nil) { tabSwipePosition = position } }
|
|
916
|
-
let lit = progress >= 0.5 ? target : previous
|
|
917
|
-
if selected != lit { withAnimation(nil) { selected = lit } }
|
|
918
913
|
}
|
|
919
914
|
|
|
920
915
|
func settleTabSwipe(completed: Bool, duration: TimeInterval) {
|
|
921
916
|
guard let id = completed ? tabSwipeTarget : tabSwipePrevious,
|
|
922
917
|
let index = tabs.firstIndex(where: { $0.id == id }) else { return }
|
|
923
|
-
if selected != id { withAnimation(nil) { selected = id } }
|
|
924
918
|
withAnimation(Self.motion(.easeOut(duration: duration))) { tabSwipePosition = CGFloat(index) }
|
|
925
919
|
}
|
|
926
920
|
|
|
@@ -1402,7 +1402,10 @@ final class CraftHybridController: UIViewController, UINavigationControllerDeleg
|
|
|
1402
1402
|
|
|
1403
1403
|
// MARK: Stacks
|
|
1404
1404
|
|
|
1405
|
-
|
|
1405
|
+
/// `hidden`: a stack prepared off screen. It is hidden before it joins
|
|
1406
|
+
/// the view hierarchy, so its screen never takes the shell's chrome (the
|
|
1407
|
+
/// bar, the tab accessory) from the one on screen.
|
|
1408
|
+
private func makeStack(tab: String, rootPath: String, hidden: Bool = false) -> UINavigationController {
|
|
1406
1409
|
let nav = UINavigationController(rootViewController: entry(for: rootPath, isTabRoot: true, depth: nil))
|
|
1407
1410
|
nav.delegate = self
|
|
1408
1411
|
nav.view.backgroundColor = config.resolvedBackgroundColor
|
|
@@ -1411,6 +1414,7 @@ final class CraftHybridController: UIViewController, UINavigationControllerDeleg
|
|
|
1411
1414
|
addChild(nav)
|
|
1412
1415
|
nav.view.frame = view.bounds
|
|
1413
1416
|
nav.view.autoresizingMask = [.flexibleWidth, .flexibleHeight]
|
|
1417
|
+
nav.view.isHidden = hidden
|
|
1414
1418
|
view.addSubview(nav.view)
|
|
1415
1419
|
nav.didMove(toParent: self)
|
|
1416
1420
|
// Only once the stack's view has loaded: the recognizer is made then,
|
|
@@ -1515,8 +1519,7 @@ final class CraftHybridController: UIViewController, UINavigationControllerDeleg
|
|
|
1515
1519
|
let id = tabs[next]
|
|
1516
1520
|
guard self.stacks[id] == nil else { self.prepareAdjacentNativeTabs(); return }
|
|
1517
1521
|
let nav = CraftFramePacing.shared.measure("prepare \(id)") { () -> UINavigationController in
|
|
1518
|
-
let nav = self.makeStack(tab: id, rootPath: id)
|
|
1519
|
-
nav.view.isHidden = true
|
|
1522
|
+
let nav = self.makeStack(tab: id, rootPath: id, hidden: true)
|
|
1520
1523
|
nav.view.layoutIfNeeded()
|
|
1521
1524
|
// Draw its text and pictures now. A hidden layer is not
|
|
1522
1525
|
// drawn at commit, so the first swipe to this tab drew
|
|
@@ -1752,7 +1755,7 @@ final class CraftHybridController: UIViewController, UINavigationControllerDeleg
|
|
|
1752
1755
|
// Keep this screen up until the page has switched, rather than
|
|
1753
1756
|
// showing it half way.
|
|
1754
1757
|
cancelPendingTab()
|
|
1755
|
-
if stacks[id] == nil { _ = makeStack(tab: id, rootPath: id
|
|
1758
|
+
if stacks[id] == nil { _ = makeStack(tab: id, rootPath: id, hidden: true); view.bringSubviewToFront(visibleStack?.view ?? view) }
|
|
1756
1759
|
let deadline = DispatchWorkItem { [weak self] in self?.show(tab: id) }
|
|
1757
1760
|
pendingTab = (id, deadline)
|
|
1758
1761
|
DispatchQueue.main.asyncAfter(deadline: .now() + 0.45, execute: deadline)
|
|
@@ -4598,11 +4598,25 @@ final class CraftNativeScreenController: UIViewController, UIScrollViewDelegate,
|
|
|
4598
4598
|
}
|
|
4599
4599
|
applyNavigationBarAppearance()
|
|
4600
4600
|
// Each screen says whether it wants the tab bar, so one that hid it
|
|
4601
|
-
// never leaves it hidden for the next.
|
|
4602
|
-
|
|
4601
|
+
// never leaves it hidden for the next. Only the screen on screen:
|
|
4602
|
+
// UIKit tells a tab's screen prepared in a hidden stack that it
|
|
4603
|
+
// appears too, and that one took the accessory of the screen showing.
|
|
4604
|
+
if isShownOnScreen { restoreShellChrome() }
|
|
4603
4605
|
refreshTraitDefaults()
|
|
4604
4606
|
}
|
|
4605
4607
|
|
|
4608
|
+
/// In the window with nothing above it hidden: the screen the person
|
|
4609
|
+
/// sees, not a tab prepared behind it.
|
|
4610
|
+
private var isShownOnScreen: Bool {
|
|
4611
|
+
guard let window = view.window else { return false }
|
|
4612
|
+
var candidate: UIView? = view
|
|
4613
|
+
while let current = candidate, current !== window {
|
|
4614
|
+
if current.isHidden { return false }
|
|
4615
|
+
candidate = current.superview
|
|
4616
|
+
}
|
|
4617
|
+
return true
|
|
4618
|
+
}
|
|
4619
|
+
|
|
4606
4620
|
override func viewWillDisappear(_ animated: Bool) {
|
|
4607
4621
|
super.viewWillDisappear(animated)
|
|
4608
4622
|
screenVisibilityChanged(false)
|
|
@@ -4620,11 +4634,15 @@ final class CraftNativeScreenController: UIViewController, UIScrollViewDelegate,
|
|
|
4620
4634
|
|
|
4621
4635
|
override func viewDidAppear(_ animated: Bool) {
|
|
4622
4636
|
super.viewDidAppear(animated)
|
|
4623
|
-
|
|
4624
|
-
//
|
|
4625
|
-
|
|
4626
|
-
|
|
4627
|
-
|
|
4637
|
+
// A tab prepared in a hidden stack "appears" to UIKit as well; the
|
|
4638
|
+
// shell says when it really shows (screenVisibilityChanged).
|
|
4639
|
+
if isShownOnScreen {
|
|
4640
|
+
screenVisibilityChanged(true)
|
|
4641
|
+
// A navigation breadcrumb for the crash reporter: the trail a
|
|
4642
|
+
// crash report carries is the screens that led to it.
|
|
4643
|
+
if !isAppScript, let routeName, !routeName.isEmpty {
|
|
4644
|
+
CraftCrashReporter.shared.screenAppeared(routeName)
|
|
4645
|
+
}
|
|
4628
4646
|
}
|
|
4629
4647
|
// onLayout reports views that are on screen: a pushed screen lays
|
|
4630
4648
|
// out before it has a window, and nothing moved again once it had
|