From abdc26b130f8933474fbcae7092d518e74ccb28e Mon Sep 17 00:00:00 2001 From: Brandon McAnsh Date: Mon, 14 Sep 2026 16:11:19 -0400 Subject: [PATCH] feat(nav): reorder the tab bar, and give the scanner and You new glyphs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The scanner tab wore a viewfinder, which named the camera rather than what it is for: reading someone's tip card. It now carries the tip card glyph, and the You tab takes the people circle the scanner's slot left free — the icon it draws when there is no profile photo to draw instead (node 10000:111297). Chat also moves from third to second, beside the scanner that feeds it, so the bar reads scan, chat, wallet, You. `HomeTab`'s declaration order is the bar's order, and the launch tab is `initial`, so moving the cases does not change where the app opens. `NavBarButton.tabs` on Android holds the same four in the same order. The people circle gets a filled twin for its selected state. The design file draws the You tab only as an outline, so that weight comes from Material Icons' `account_circle` — the same glyph solid, and the same place Android's people circle takes its selected weight from, so the two bars fill alike. Both tab-bar paths — the SwiftUI pill and the iOS 26 `UITabBarItem` bar — take their glyphs from `HomeTab.iconName(isSelected:)`, so the pair covers both. `NavScan`/`NavScanSelected` are now unreferenced and go with it; the new-user tutorial's "Scan a Tip Card" row takes `NavTipCard`, the same glyph as the tab it points at. --- Flipcash/Core/Screens/Main/Home/HomeTab.swift | 26 ++++++++++++++----- .../Core/Screens/Main/Home/HomeTabView.swift | 4 +-- .../Screens/Main/Home/NewUserTutorial.swift | 2 +- .../Contents.json | 2 +- .../NavPeople.imageset/nav_people.svg | 4 +++ .../Contents.json | 2 +- .../nav_people_selected.svg | 6 +++++ .../NavScan.imageset/nav_scan.svg | 5 ---- .../nav_scan_selected.svg | 4 --- 9 files changed, 34 insertions(+), 21 deletions(-) rename Flipcash/Supporting Files/Assets.xcassets/{NavScan.imageset => NavPeople.imageset}/Contents.json (86%) create mode 100644 Flipcash/Supporting Files/Assets.xcassets/NavPeople.imageset/nav_people.svg rename Flipcash/Supporting Files/Assets.xcassets/{NavScanSelected.imageset => NavPeopleSelected.imageset}/Contents.json (83%) create mode 100644 Flipcash/Supporting Files/Assets.xcassets/NavPeopleSelected.imageset/nav_people_selected.svg delete mode 100644 Flipcash/Supporting Files/Assets.xcassets/NavScan.imageset/nav_scan.svg delete mode 100644 Flipcash/Supporting Files/Assets.xcassets/NavScanSelected.imageset/nav_scan_selected.svg diff --git a/Flipcash/Core/Screens/Main/Home/HomeTab.swift b/Flipcash/Core/Screens/Main/Home/HomeTab.swift index 6c78efe1a..a4f823e03 100644 --- a/Flipcash/Core/Screens/Main/Home/HomeTab.swift +++ b/Flipcash/Core/Screens/Main/Home/HomeTab.swift @@ -5,15 +5,17 @@ import SwiftUI -/// The tabs of the v2 tab-bar UI, in display order (left → right). The app -/// launches on `.wallet` (wallet-first), mirroring the Android v2 UI. +/// The tabs of the v2 tab-bar UI, in display order (left → right). Chat sits +/// second, beside the scanner that feeds it, and the app still launches on +/// `.wallet` — declaration order is the bar's order, not the launch tab. Matches +/// Android's `NavBarButton.tabs`. /// /// Icons are the Figma tab-bar glyphs (`Nav*` template imagesets, from the same /// vectors as Android's `ic_nav_*`), tinted white at the call site. enum HomeTab: Int, CaseIterable, Identifiable, Hashable { case scan - case wallet case chat + case wallet case tipCard var id: Int { rawValue } @@ -23,12 +25,22 @@ enum HomeTab: Int, CaseIterable, Identifiable, Hashable { /// The asset-catalog name of the tab's template glyph. Selected tabs use a /// filled glyph and the rest an outline, per the tab bar spec. + /// + /// The scanner reads tip cards, so it carries the tip card itself rather + /// than a viewfinder, and You takes the people-circle the scanner's slot + /// left free — the glyph it shows when there is no profile photo to draw in + /// its place (node 10000:111297). + /// + /// That fallback's filled weight comes from Material Icons' `account_circle` + /// rather than from the design file, which draws the You tab only as an + /// outline. It is the same glyph solid, and Android's people circle takes its + /// selected weight from the same place, so the two bars fill alike. func iconName(isSelected: Bool) -> String { switch self { - case .scan: return isSelected ? "NavScanSelected" : "NavScan" - case .wallet: return isSelected ? "NavWalletSelected" : "NavWallet" + case .scan: return isSelected ? "NavTipCardSelected" : "NavTipCard" case .chat: return isSelected ? "NavChatSelected" : "NavChat" - case .tipCard: return isSelected ? "NavTipCardSelected" : "NavTipCard" + case .wallet: return isSelected ? "NavWalletSelected" : "NavWallet" + case .tipCard: return isSelected ? "NavPeopleSelected" : "NavPeople" } } @@ -36,8 +48,8 @@ enum HomeTab: Int, CaseIterable, Identifiable, Hashable { var accessibilityLabel: String { switch self { case .scan: return "Scan" - case .wallet: return "Wallet" case .chat: return "Chat" + case .wallet: return "Wallet" case .tipCard: return "You" } } diff --git a/Flipcash/Core/Screens/Main/Home/HomeTabView.swift b/Flipcash/Core/Screens/Main/Home/HomeTabView.swift index 1c770fd01..d539fd9e2 100644 --- a/Flipcash/Core/Screens/Main/Home/HomeTabView.swift +++ b/Flipcash/Core/Screens/Main/Home/HomeTabView.swift @@ -123,8 +123,8 @@ struct HomeTabView: View { /// Derived in the body rather than waited on: the profile is hydrated from /// the database before the first paint, so a cold launch knows a picture is /// coming — and can decode its BlurHash — while the thumbnail is still being - /// read back. Keying only on the loaded photo would show the glyph until it - /// landed, which is the tip card's icon on somebody who has a picture. + /// read back. Keying only on the loaded photo would show the no-photo glyph + /// until it landed, on somebody who has a picture. private var profileSlot: ProfileTabSlot? { if let photo = profilePhoto.photo { return .photo(photo) } guard let picture = profilePicture, picture.thumbnailBlobID != nil else { return nil } diff --git a/Flipcash/Core/Screens/Main/Home/NewUserTutorial.swift b/Flipcash/Core/Screens/Main/Home/NewUserTutorial.swift index f9f32e484..7f216b0a2 100644 --- a/Flipcash/Core/Screens/Main/Home/NewUserTutorial.swift +++ b/Flipcash/Core/Screens/Main/Home/NewUserTutorial.swift @@ -37,7 +37,7 @@ nonisolated enum TutorialItem: TutorialItemPresentable { var icon: Image { switch self { case .addMoney: return Image(systemName: "plus.circle") - case .scanTipCard: return Image("NavScan") + case .scanTipCard: return Image("NavTipCard") } } } diff --git a/Flipcash/Supporting Files/Assets.xcassets/NavScan.imageset/Contents.json b/Flipcash/Supporting Files/Assets.xcassets/NavPeople.imageset/Contents.json similarity index 86% rename from Flipcash/Supporting Files/Assets.xcassets/NavScan.imageset/Contents.json rename to Flipcash/Supporting Files/Assets.xcassets/NavPeople.imageset/Contents.json index 62f705563..4189e278b 100644 --- a/Flipcash/Supporting Files/Assets.xcassets/NavScan.imageset/Contents.json +++ b/Flipcash/Supporting Files/Assets.xcassets/NavPeople.imageset/Contents.json @@ -1,7 +1,7 @@ { "images" : [ { - "filename" : "nav_scan.svg", + "filename" : "nav_people.svg", "idiom" : "universal" } ], diff --git a/Flipcash/Supporting Files/Assets.xcassets/NavPeople.imageset/nav_people.svg b/Flipcash/Supporting Files/Assets.xcassets/NavPeople.imageset/nav_people.svg new file mode 100644 index 000000000..f1008f359 --- /dev/null +++ b/Flipcash/Supporting Files/Assets.xcassets/NavPeople.imageset/nav_people.svg @@ -0,0 +1,4 @@ + + + + diff --git a/Flipcash/Supporting Files/Assets.xcassets/NavScanSelected.imageset/Contents.json b/Flipcash/Supporting Files/Assets.xcassets/NavPeopleSelected.imageset/Contents.json similarity index 83% rename from Flipcash/Supporting Files/Assets.xcassets/NavScanSelected.imageset/Contents.json rename to Flipcash/Supporting Files/Assets.xcassets/NavPeopleSelected.imageset/Contents.json index 122376f54..8be4f43e5 100644 --- a/Flipcash/Supporting Files/Assets.xcassets/NavScanSelected.imageset/Contents.json +++ b/Flipcash/Supporting Files/Assets.xcassets/NavPeopleSelected.imageset/Contents.json @@ -1,7 +1,7 @@ { "images" : [ { - "filename" : "nav_scan_selected.svg", + "filename" : "nav_people_selected.svg", "idiom" : "universal" } ], diff --git a/Flipcash/Supporting Files/Assets.xcassets/NavPeopleSelected.imageset/nav_people_selected.svg b/Flipcash/Supporting Files/Assets.xcassets/NavPeopleSelected.imageset/nav_people_selected.svg new file mode 100644 index 000000000..6576209da --- /dev/null +++ b/Flipcash/Supporting Files/Assets.xcassets/NavPeopleSelected.imageset/nav_people_selected.svg @@ -0,0 +1,6 @@ + + + + diff --git a/Flipcash/Supporting Files/Assets.xcassets/NavScan.imageset/nav_scan.svg b/Flipcash/Supporting Files/Assets.xcassets/NavScan.imageset/nav_scan.svg deleted file mode 100644 index 0b6c9f781..000000000 --- a/Flipcash/Supporting Files/Assets.xcassets/NavScan.imageset/nav_scan.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/Flipcash/Supporting Files/Assets.xcassets/NavScanSelected.imageset/nav_scan_selected.svg b/Flipcash/Supporting Files/Assets.xcassets/NavScanSelected.imageset/nav_scan_selected.svg deleted file mode 100644 index d5d146feb..000000000 --- a/Flipcash/Supporting Files/Assets.xcassets/NavScanSelected.imageset/nav_scan_selected.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - -