commit 5f928e3589d73d5cb7a2217e3b90b6875d298eb6
parent 7289ab69641337fea1004ac3a77d51f853f70386
Author: Marc Stibane <marc@taler.net>
Date: Tue, 17 Sep 2024 21:28:25 +0200
KeyboardShowingEnvironment
Diffstat:
8 files changed, 90 insertions(+), 21 deletions(-)
diff --git a/TalerWallet.xcodeproj/project.pbxproj b/TalerWallet.xcodeproj/project.pbxproj
@@ -14,6 +14,8 @@
4E16E12329F3BB99008B9C86 /* CurrencySpecification.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E16E12229F3BB99008B9C86 /* CurrencySpecification.swift */; };
4E18539A2BDAE6D40034F3BA /* LocalConsole in Frameworks */ = {isa = PBXBuildFile; productRef = 4E1853992BDAE6D40034F3BA /* LocalConsole */; };
4E18539C2BDAE6E50034F3BA /* LocalConsole in Frameworks */ = {isa = PBXBuildFile; productRef = 4E18539B2BDAE6E50034F3BA /* LocalConsole */; };
+ 4E1A59E12C99C5D700842BBF /* View+Keyboard.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E1A59E02C99C5D700842BBF /* View+Keyboard.swift */; };
+ 4E1A59E22C99C5D700842BBF /* View+Keyboard.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E1A59E02C99C5D700842BBF /* View+Keyboard.swift */; };
4E2254972A822B8100E41D29 /* payment_received.m4a in Resources */ = {isa = PBXBuildFile; fileRef = 4E2254952A822B8100E41D29 /* payment_received.m4a */; };
4E2254982A822B8100E41D29 /* payment_sent.m4a in Resources */ = {isa = PBXBuildFile; fileRef = 4E2254962A822B8100E41D29 /* payment_sent.m4a */; };
4E2B337D2C8B1D5500186A3E /* ActionsSheet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4E2B337C2C8B1D5500186A3E /* ActionsSheet.swift */; };
@@ -355,6 +357,7 @@
4E0A71132C396D86002485BB /* Error+debugDescription.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Error+debugDescription.swift"; sourceTree = "<group>"; };
4E0A71172C3AB099002485BB /* IconBadge.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IconBadge.swift; sourceTree = "<group>"; };
4E16E12229F3BB99008B9C86 /* CurrencySpecification.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CurrencySpecification.swift; sourceTree = "<group>"; };
+ 4E1A59E02C99C5D700842BBF /* View+Keyboard.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "View+Keyboard.swift"; sourceTree = "<group>"; };
4E2254952A822B8100E41D29 /* payment_received.m4a */ = {isa = PBXFileReference; lastKnownFileType = file; path = payment_received.m4a; sourceTree = "<group>"; };
4E2254962A822B8100E41D29 /* payment_sent.m4a */ = {isa = PBXFileReference; lastKnownFileType = file; path = payment_sent.m4a; sourceTree = "<group>"; };
4E2B337C2C8B1D5500186A3E /* ActionsSheet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActionsSheet.swift; sourceTree = "<group>"; };
@@ -689,6 +692,7 @@
4EB095082989CB7C0043A8A1 /* View+dismissTop.swift */,
4E605DB62AB05E48002FB9A7 /* View+flippedDirection.swift */,
4E4F60A72C3BBF9F003BB669 /* View+Condition.swift */,
+ 4E1A59E02C99C5D700842BBF /* View+Keyboard.swift */,
4E3B4BC62A429F2A00CC88B8 /* View+Notification.swift */,
4E605DAE2AADDD13002FB9A7 /* UIScreen+screenSize.swift */,
4E363CBB2A237E0900D7E98C /* URL+id+iban.swift */,
@@ -1202,6 +1206,7 @@
4EC400892AE3E7E800DF72C7 /* AboutView.swift in Sources */,
4E3EAE282A990778009F1BE8 /* BalancesListView.swift in Sources */,
4E3EAE292A990778009F1BE8 /* WalletBackendError.swift in Sources */,
+ 4E1A59E12C99C5D700842BBF /* View+Keyboard.swift in Sources */,
4E3EAE2A2A990778009F1BE8 /* PendingRowView.swift in Sources */,
4E3EAE2B2A990778009F1BE8 /* LoadingView.swift in Sources */,
4E5D2C8B2C574CB0003F7A49 /* GradientBorder.swift in Sources */,
@@ -1334,6 +1339,7 @@
4EC4008A2AE3E7E800DF72C7 /* AboutView.swift in Sources */,
4EB0955D2989CBFE0043A8A1 /* BalancesListView.swift in Sources */,
4EB095212989CBCB0043A8A1 /* WalletBackendError.swift in Sources */,
+ 4E1A59E22C99C5D700842BBF /* View+Keyboard.swift in Sources */,
4EB0955E2989CBFE0043A8A1 /* PendingRowView.swift in Sources */,
4EB0956D2989CBFE0043A8A1 /* LoadingView.swift in Sources */,
4E5D2C8C2C574CB0003F7A49 /* GradientBorder.swift in Sources */,
diff --git a/TalerWallet1/Controllers/PublicConstants.swift b/TalerWallet1/Controllers/PublicConstants.swift
@@ -126,6 +126,4 @@ extension Notification.Name {
static let RequestAction = Notification.Name("requestAction")
static let DepositAction = Notification.Name("depositAction")
static let WithdrawAction = Notification.Name("withdrawAction")
- static let HideTabBarView = Notification.Name("hideTabBarView")
- static let ShowTabBarView = Notification.Name("showTabBarView")
}
diff --git a/TalerWallet1/Controllers/TalerWallet1App.swift b/TalerWallet1/Controllers/TalerWallet1App.swift
@@ -42,6 +42,7 @@ struct TalerWallet1App: App {
.environmentObject(viewState2) // popToRoot
.environmentObject(controller)
.environmentObject(model)
+ .addKeyboardVisibilityToEnvironment()
/// external events are taler:// or payto:// URLs passed to this app
/// we handle them in .onOpenURL in MainView.swift
.handlesExternalEvents(preferring: ["*"], allowing: ["*"])
diff --git a/TalerWallet1/Helper/View+Keyboard.swift b/TalerWallet1/Helper/View+Keyboard.swift
@@ -0,0 +1,78 @@
+// MIT License
+// Copyright Codelaby https://stackoverflow.com/users/3464919/codelaby
+//
+// 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.
+//
+import Foundation
+import SwiftUI
+import Combine
+
+public extension View {
+ /// Sets an environment value for keyboardShowing
+ /// Access this in any child view with
+ /// @Environment(\.keyboardShowing) var keyboardShowing
+ func addKeyboardVisibilityToEnvironment() -> some View {
+ modifier(KeyboardVisibility())
+ }
+}
+
+private struct KeyboardShowingEnvironmentKey: EnvironmentKey {
+ static let defaultValue: Bool = false
+}
+
+extension EnvironmentValues {
+ var keyboardShowing: Bool {
+ get { self[KeyboardShowingEnvironmentKey.self] }
+ set { self[KeyboardShowingEnvironmentKey.self] = newValue }
+ }
+}
+
+private final class KeyboardMonitor: ObservableObject {
+ @Published var isKeyboardShowing: Bool = false
+ private var cancellables = Set<AnyCancellable>()
+
+ init() {
+ NotificationCenter.default.publisher(for: UIResponder.keyboardWillShowNotification)
+ .map { _ in true }
+ .assign(to: \.isKeyboardShowing, on: self)
+ .store(in: &cancellables)
+
+ NotificationCenter.default.publisher(for: UIResponder.keyboardWillHideNotification)
+ .map { _ in false }
+ .assign(to: \.isKeyboardShowing, on: self)
+ .store(in: &cancellables)
+ }
+}
+
+private struct KeyboardVisibility: ViewModifier {
+ @StateObject private var keyboardMonitor = KeyboardMonitor()
+
+ fileprivate func body(content: Content) -> some View {
+ content
+ .environment(\.keyboardShowing, keyboardMonitor.isKeyboardShowing)
+ }
+}
+
+// Usage
+// App
+// WindowGroup {
+// ContentView()
+// .addKeyboardVisibilityToEnvironment()
+//
+// View
+// @Environment(\.keyboardShowing) var keyboardShowing
+// ...
+// Text("Keyboard present: \(keyboardShowing.description)" )
diff --git a/TalerWallet1/Views/Actions/ActionsSheet.swift b/TalerWallet1/Views/Actions/ActionsSheet.swift
@@ -88,10 +88,6 @@ struct ActionsSheet: View {
amountToTransfer: $amountToTransfer) // does still have the wrong currency
.padding(.bottom, 12)
}
- .task {
- print("ActionsSheet.task❓HideTabBarView")
- NotificationCenter.default.post(name: .HideTabBarView, object: nil)
- }
}
}
// MARK: -
diff --git a/TalerWallet1/Views/Banking/ManualWithdraw.swift b/TalerWallet1/Views/Banking/ManualWithdraw.swift
@@ -118,8 +118,6 @@ struct ManualWithdraw: View {
stack: stack.push())
}
symLog.log("❗️ \(navTitle) onAppear")
- print("ManualWithdraw.task❓HideTabBarView")
- NotificationCenter.default.post(name: .HideTabBarView, object: nil)
}
.onDisappear {
symLog.log("❗️ \(navTitle) onDisappear")
diff --git a/TalerWallet1/Views/HelperViews/TabBarView.swift b/TalerWallet1/Views/HelperViews/TabBarView.swift
@@ -11,8 +11,9 @@ struct TabBarView: View {
@Binding var selection: Tab
let onActionTab: () -> Void
+ @Environment(\.keyboardShowing) var keyboardShowing
+
@AppStorage("minimalistic") var minimalistic: Bool = false
- @State private var isHidden = 0
private func tabBarItem(for tab: Tab) -> some View {
VStack(spacing: 0) {
@@ -50,7 +51,7 @@ struct TabBarView: View {
var body: some View {
Group {
- if isHidden > 0 {
+ if keyboardShowing {
EmptyView()
} else {
HStack(alignment: .bottom) {
@@ -70,16 +71,6 @@ struct TabBarView: View {
.background(WalletColors().backgroundColor.edgesIgnoringSafeArea(.bottom))
}
}
- .onNotification(.HideTabBarView) {
- isHidden += 1
- print("❗️HideTabBarView \(isHidden)")
- }
- .onNotification(.ShowTabBarView) {
- if isHidden > 0 {
- isHidden -= 1
- print("❗️ShowTabBarView \(isHidden)")
- }
- }
}
}
// MARK: -
diff --git a/TalerWallet1/Views/Main/MainView.swift b/TalerWallet1/Views/Main/MainView.swift
@@ -395,7 +395,7 @@ extension MainView {
// .ignoresSafeArea(.keyboard, edges: .bottom)
// .padding(.bottom, 10)
tabBarView
-// .ignoresSafeArea(.keyboard, edges: .bottom)
+ .ignoresSafeArea(.keyboard, edges: .bottom)
}
.frame(maxWidth: .infinity, maxHeight: .infinity)
@@ -418,6 +418,7 @@ extension MainView {
actions: { openKycButton
dismissAlertButton },
message: { Text("Tap the button to go to the KYC website.") })
+// .sheet(isPresented: $showActionSheet, onDismiss: { tabBarView.show() }) {
.sheet(isPresented: $showActionSheet) {
let content = VStack {
ActionsSheet(stack: stack.push(),