commit f116d8a368967aaa5cafb9bd6c04181610d595d6
parent c257a73d6ae87e0326f32399224365d20887230e
Author: Marc Stibane <marc@taler.net>
Date: Sat, 15 Mar 2025 20:54:51 +0100
remove TabBarHeight hack
Diffstat:
3 files changed, 4 insertions(+), 136 deletions(-)
diff --git a/TalerWallet.xcodeproj/project.pbxproj b/TalerWallet.xcodeproj/project.pbxproj
@@ -266,8 +266,6 @@
4EB0956E2989CBFE0043A8A1 /* Model+Pending.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EB0954C2989CBFE0043A8A1 /* Model+Pending.swift */; };
4EB230882D5E0FEC007CFBC4 /* View+DeviceRotation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EB230872D5E0FEC007CFBC4 /* View+DeviceRotation.swift */; };
4EB230892D5E0FEC007CFBC4 /* View+DeviceRotation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EB230872D5E0FEC007CFBC4 /* View+DeviceRotation.swift */; };
- 4EB2308B2D607617007CFBC4 /* View+TabBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EB2308A2D607617007CFBC4 /* View+TabBar.swift */; };
- 4EB2308C2D607617007CFBC4 /* View+TabBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EB2308A2D607617007CFBC4 /* View+TabBar.swift */; };
4EB3136129FEE79B007D68BC /* P2PReadyV.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EB3136029FEE79B007D68BC /* P2PReadyV.swift */; };
4EB431672A1E55C700C5690E /* ManualWithdrawDone.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EB431662A1E55C700C5690E /* ManualWithdrawDone.swift */; };
4EBA563F2A7FD9390084948B /* SuperScriptDigits.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4EBA563E2A7FD9390084948B /* SuperScriptDigits.swift */; };
@@ -502,7 +500,6 @@
4EB0954A2989CBFE0043A8A1 /* LoadingView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LoadingView.swift; sourceTree = "<group>"; };
4EB0954C2989CBFE0043A8A1 /* Model+Pending.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Model+Pending.swift"; sourceTree = "<group>"; };
4EB230872D5E0FEC007CFBC4 /* View+DeviceRotation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "View+DeviceRotation.swift"; sourceTree = "<group>"; };
- 4EB2308A2D607617007CFBC4 /* View+TabBar.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "View+TabBar.swift"; sourceTree = "<group>"; };
4EB3136029FEE79B007D68BC /* P2PReadyV.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = P2PReadyV.swift; sourceTree = "<group>"; };
4EB431662A1E55C700C5690E /* ManualWithdrawDone.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ManualWithdrawDone.swift; sourceTree = "<group>"; };
4EBA563E2A7FD9390084948B /* SuperScriptDigits.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SuperScriptDigits.swift; sourceTree = "<group>"; };
@@ -618,7 +615,6 @@
4E1A59E02C99C5D700842BBF /* View+Keyboard.swift */,
4E3B4BC62A429F2A00CC88B8 /* View+Notification.swift */,
4E7F85162D63185E00954C30 /* Environment+EdgeInsets.swift */,
- 4EB2308A2D607617007CFBC4 /* View+TabBar.swift */,
);
path = ViewModifier;
sourceTree = "<group>";
@@ -1271,7 +1267,6 @@
4E3EAE242A990778009F1BE8 /* QRGeneratorView.swift in Sources */,
4E3EAE252A990778009F1BE8 /* WithdrawAcceptDone.swift in Sources */,
4E3EAE262A990778009F1BE8 /* Transaction.swift in Sources */,
- 4EB2308B2D607617007CFBC4 /* View+TabBar.swift in Sources */,
4E8EADA82C64744700C6CDC4 /* QRcodesForPayto.swift in Sources */,
4E605DB72AB05E48002FB9A7 /* View+flippedDirection.swift in Sources */,
4E983C2C2ADC416800FA9CC5 /* View+fitsSideBySide.swift in Sources */,
@@ -1415,7 +1410,6 @@
4EEC157329F8242800D46A03 /* QRGeneratorView.swift in Sources */,
4E5A88F72A3B9E5B00072618 /* WithdrawAcceptDone.swift in Sources */,
4EB095222989CBCB0043A8A1 /* Transaction.swift in Sources */,
- 4EB2308C2D607617007CFBC4 /* View+TabBar.swift in Sources */,
4E8EADA92C64744700C6CDC4 /* QRcodesForPayto.swift in Sources */,
4E605DB82AB05E48002FB9A7 /* View+flippedDirection.swift in Sources */,
4E983C2D2ADC416800FA9CC5 /* View+fitsSideBySide.swift in Sources */,
diff --git a/TalerWallet1/Views/Main/MainView.swift b/TalerWallet1/Views/Main/MainView.swift
@@ -248,7 +248,6 @@ extension MainView {
@State private var shouldReloadBalances = 0
@State private var shouldReloadTransactions = 0
@State private var shouldReloadPending = 0
- @State private var tabBarHeight: CGFloat = 0 // SwiftUI tabBar height
@State private var selectedTab: Tab = .balances
@State private var showKycAlert: Bool = false
@State private var kycURI: URL?
@@ -369,15 +368,12 @@ extension MainView {
balancesStack.id(viewState.rootViewId) // change rootViewId to trigger popToRootView behaviour
.tag(Tab.balances)
.tabItem { a11yBalanceTab }
- .keepTabViewHeight(in: $tabBarHeight)
Color.clear // can't use EmptyView: VoiceOver wouldn't have the Actions tab
.tag(Tab.actions)
.tabItem { a11yActionsTab }
- .keepTabViewHeight(in: $tabBarHeight)
settingsStack.id(viewState2.rootViewId) // change rootViewId to trigger popToRootView behaviour
.tag(Tab.settings)
.tabItem { a11ySettingsTab }
- .keepTabViewHeight(in: $tabBarHeight)
} // TabView
}
@@ -397,7 +393,7 @@ extension MainView {
let delay: UInt = 0 // no delay for release builds
#endif
- /// our custom tabBar with the Actions button in the middle
+ // custom tabBar with the Actions button in the middle
let tabBarView = TabBarView(selection: tabSelection(), userAction: $userAction, hidden: $tabBarModel.tabBarHidden) {
logger.log("onActionTab")
showActionSheet = true
@@ -405,12 +401,10 @@ extension MainView {
logger.log("onActionDrag: showScanner = true")
showScanner = true
}
- /// custom tabBar is rendered on top of the TabView, and overlaps its tabBar
+
ZStack(alignment: .bottom) {
- tabContent
-// .hideTabBar($tabBarModel.tabBarHidden) // OIM?
- .environment(\.tabBarHeight, tabBarHeight)
- tabBarView
+ tabContent // incl. the (transparent) SwiftUI tabBar
+ tabBarView // custom tabBar is rendered on top of the TabView, and overlaps its tabBar
.ignoresSafeArea(.keyboard, edges: .bottom)
.accessibilityHidden(true) // for a11y we use the original tabBar, not our custom one
} // ZStack
diff --git a/TalerWallet1/Views/ViewModifier/View+TabBar.swift b/TalerWallet1/Views/ViewModifier/View+TabBar.swift
@@ -1,120 +0,0 @@
-// MIT License
-// Copyright 2021 alexis https://github.com/alexis-ag/swiftui_classic-tabview_show-hide
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy of this software
-// and associated documentation files (the "Software"), to deal in the Software without restriction,
-// including without limitation the rights to use, copy, modify, merge, publish, distribute,
-// sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all copies or
-// substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
-// BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
-// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-//
-
-/*
- SwiftUI has quite poor TabView, it doesn't allow you to
- set any icon size
- set default colors for system icons and labels
- place more complicated views than simple image
- resize image for icon just in time
- hide the tab bar when you don't need it
- Idea:
- place Swiftui TabView
- hide it's tab bar forever, but use for storing content
- show our own custom tab bar
-*/
-import Foundation
-import SwiftUI
-
-extension EnvironmentValues {
- ///TabView raw height; does not include bottom safe area.
- var tabBarHeight: CGFloat {
- get { self[TabBarHeightEnvironmentKey.self] }
- set { self[TabBarHeightEnvironmentKey.self] = newValue }
- }
-}
-
-struct TabBarHeightEnvironmentKey: EnvironmentKey {
- static var defaultValue: CGFloat = 0
-}
-
-
-
-extension View {
- /// Read TabView height from underlying UITabBarController and keep it in property passed by binding.
- ///
- /// # Usage
- /// ```
- /// @State private var tabViewHeight: CGFloat = 0
- /// TabItem().keepTabViewHeight(in: $tabViewHeight)
- /// ```
- func keepTabViewHeight(
- in storage: Binding<CGFloat>,
- includingSeparator tabViewHeightShouldIncludeSeparator: Bool = true
- ) -> some View {
- background(TabBarAccessor { tabBar in
- let onePixel: CGFloat = 1/3
- let separatorHeight: CGFloat = tabViewHeightShouldIncludeSeparator ? onePixel : 0
- DispatchQueue.main.async {
- // -4 still hides the "visible" SwiftUI tabBar, but leaves it available for A11Y voiceOver
- // no longer necessary if we only hide the SwiftUI tabBar when our custom tabBar is hidden
- storage.wrappedValue = tabBar.bounds.height + separatorHeight // - 4
- }
- })
- }
-}
-
-// Helper bridge to UIViewController to access enclosing UITabBarController
-// and thus its UITabBar
-struct TabBarAccessor: UIViewControllerRepresentable {
- var callback: (UITabBar) -> Void
- private let proxyController = ViewController()
-
- func makeUIViewController(context: UIViewControllerRepresentableContext<TabBarAccessor>) ->
- UIViewController {
- proxyController.callback = callback
- return proxyController
- }
-
- func updateUIViewController(_ uiViewController: UIViewController, context: UIViewControllerRepresentableContext<TabBarAccessor>) {
- }
-
- typealias UIViewControllerType = UIViewController
-
- private class ViewController: UIViewController {
- var callback: (UITabBar) -> Void = { _ in }
-
- override func viewWillAppear(_ animated: Bool) {
- super.viewWillAppear(animated)
- if let tabBar = self.tabBarController {
- self.callback(tabBar.tabBar)
- }
- }
- }
-}
-
-// MARK: - Content
-extension View {
- func hideTabBar(_ hidden: Binding<Int>) -> some View {
- modifier(HideTabBarModifier(tabBarHidden: hidden))
- }
-}
-
-struct HideTabBarModifier: ViewModifier {
- @Binding var tabBarHidden: Int
- @Environment(\.safeAreaEdgeInsets) private var safeAreaEdgeInsets
- @Environment(\.tabBarHeight) private var tabBarHeight
-
- func body(content: Content) -> some View {
- let padding = tabBarHidden == 0 ? 0
- : tabBarHeight
- content
- .padding(.bottom, -safeAreaEdgeInsets.bottom - padding)
- }
-}