@craft-native/ios 0.0.189 → 0.0.191

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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@craft-native/ios",
3
- "version": "0.0.189",
3
+ "version": "0.0.191",
4
4
  "homepage": "https://github.com/craft-native/craft/tree/main/packages/ios#readme",
5
5
  "repository": {
6
6
  "type": "git",
@@ -614,7 +614,10 @@ final class CraftChrome: ObservableObject {
614
614
  let id: String
615
615
  let title: String
616
616
  let symbol: String
617
- let badge: String?
617
+ var badge: String?
618
+ var iconText: String? = nil
619
+ var accessibilityLabel: String? = nil
620
+ var image: String? = nil
618
621
  }
619
622
 
620
623
  @Published var tabs: [Tab] = []
@@ -668,6 +671,23 @@ final class CraftChrome: ObservableObject {
668
671
  /// the bar away while it shows (`tabBarHidden`, CraftNativeScreen.swift);
669
672
  /// the next screen shown says again. The page's own hideTabBar is apart.
670
673
  private(set) var hiddenByScreen = false
674
+
675
+ /// Change one tab's icon without replacing tabs, navigation stacks or selection.
676
+ func updateTab(_ item: [String: Any]) {
677
+ guard let id = item["id"] as? String, let index = tabs.firstIndex(where: { $0.id == id }) else { return }
678
+ if item.keys.contains("iconText") {
679
+ tabs[index].iconText = (item["iconText"] as? String).flatMap { $0.isEmpty ? nil : String($0.prefix(8)) }
680
+ }
681
+ if item.keys.contains("accessibilityLabel") {
682
+ tabs[index].accessibilityLabel = (item["accessibilityLabel"] as? String).map { String($0.prefix(160)) }
683
+ }
684
+ if item.keys.contains("image") {
685
+ tabs[index].image = (item["image"] as? String).flatMap { URL(string: $0)?.scheme == "https" ? $0 : nil }
686
+ }
687
+ if item.keys.contains("badge") {
688
+ tabs[index].badge = (item["badge"] as? String).flatMap { $0.isEmpty ? nil : String($0.prefix(8)) }
689
+ }
690
+ }
671
691
  func setHiddenByScreen(_ hidden: Bool) {
672
692
  guard hiddenByScreen != hidden else { return }
673
693
  hiddenByScreen = hidden
@@ -941,9 +961,28 @@ struct CraftTabBarView: View {
941
961
  Button { chrome.tap(tab) } label: {
942
962
  VStack(spacing: 3) {
943
963
  ZStack(alignment: .topTrailing) {
944
- Image(systemName: symbol(tab.symbol, selected: isSelected))
945
- .font(.system(size: iconSize, weight: isSelected ? .semibold : .regular))
964
+ if let image = tab.image, let url = URL(string: image) {
965
+ AsyncImage(url: url) { image in
966
+ image.resizable().scaledToFill()
967
+ } placeholder: {
968
+ Image(systemName: symbol(tab.symbol, selected: isSelected))
969
+ }
970
+ .frame(width: iconSize + 4, height: iconSize + 4)
971
+ .clipShape(Circle())
946
972
  .frame(height: iconSize + 6)
973
+ } else if let text = tab.iconText {
974
+ Text(text)
975
+ .font(.system(size: iconSize, weight: .semibold, design: .rounded))
976
+ .monospacedDigit()
977
+ .foregroundStyle(Color.red)
978
+ .lineLimit(1)
979
+ .minimumScaleFactor(0.7)
980
+ .frame(height: iconSize + 6)
981
+ } else {
982
+ Image(systemName: symbol(tab.symbol, selected: isSelected))
983
+ .font(.system(size: iconSize, weight: isSelected ? .semibold : .regular))
984
+ .frame(height: iconSize + 6)
985
+ }
947
986
  if let badge = tab.badge {
948
987
  Text(badge)
949
988
  .font(.system(size: badgeSize, weight: .bold))
@@ -975,7 +1014,7 @@ struct CraftTabBarView: View {
975
1014
  Image(systemName: symbol(tab.symbol, selected: isSelected))
976
1015
  Text(tab.title)
977
1016
  }
978
- .accessibilityLabel(tab.badge.map { "\(tab.title), \($0)" } ?? tab.title)
1017
+ .accessibilityLabel(tab.accessibilityLabel ?? tab.badge.map { "\(tab.title), \($0)" } ?? tab.title)
979
1018
  .accessibilityAddTraits(isSelected ? [.isSelected, .isButton] : .isButton)
980
1019
  }
981
1020
  }
@@ -4355,6 +4355,9 @@ final class CraftNativeScreenController: UIViewController, UIScrollViewDelegate,
4355
4355
  /// `craft.navigation.setOptions`: this screen's bar. Every key is
4356
4356
  /// optional and only the keys given change.
4357
4357
  private func applyNavigationOptions(_ options: [String: Any]) {
4358
+ if let tab = options["tabItem"] as? [String: Any] {
4359
+ CraftChrome.shared.updateTab(tab)
4360
+ }
4358
4361
  // The app script has no screen, so no bar and no tab bar to change.
4359
4362
  guard !isAppScript else { return }
4360
4363
  if options.keys.contains("title") {