Skip to content

Commit

Permalink
feat: add better support for keyboard info
Browse files Browse the repository at this point in the history
  • Loading branch information
gtokman committed May 3, 2021
1 parent 9def8e2 commit a37670d
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 23 deletions.
18 changes: 18 additions & 0 deletions Sources/ExtensionKit/Combine/Publisher.swift
@@ -1,5 +1,6 @@
import Combine
import Foundation
import UIKit

public extension Publisher where Failure == Never {

Expand All @@ -22,4 +23,21 @@ public extension Publisher where Failure == Never {
result(.success(output))
})
}

}

extension Publisher where Failure == Never {

/// Subscribe to keyboard notifications and receive `Notification.KeyboardInfo` on updates
static var keyboardInfo: AnyPublisher<Notification.KeyboardInfo, Never> {
let willShow = NotificationCenter.default.publisher(for: UIApplication.keyboardWillShowNotification)
.map { $0.keyboardInfo }

let willHide = NotificationCenter.default.publisher(for: UIApplication.keyboardWillHideNotification)
.map { _ in Notification.KeyboardInfo() }

return Publishers.MergeMany(willShow, willHide)
.eraseToAnyPublisher()
}

}
36 changes: 36 additions & 0 deletions Sources/ExtensionKit/Foundation/Notification.swift
@@ -0,0 +1,36 @@
import Foundation
import UIKit

extension Notification {

/// Struct modeling keyboard updates
public struct KeyboardInfo {
/// Keyboard height
public var height: CGFloat = 0
/// Keyboard animation curve
public var animationCurve: UIView.AnimationCurve = UIView.AnimationCurve.easeInOut
/// Keyboard animation duration
public var animationDuration: TimeInterval = 0.0
/// Is the keyboard visible
public var isVisible: Bool {
height != 0
}
}

/// Get keyboard info updates
var keyboardInfo: KeyboardInfo {
var info = KeyboardInfo()
if let value = userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect {
info.height = value.height
}
if let value = userInfo?[UIResponder.keyboardAnimationCurveUserInfoKey] as? NSNumber {
if let curve = UIView.AnimationCurve(rawValue: value.intValue) {
info.animationCurve = curve
}
}
if let value = userInfo?[UIResponder.keyboardAnimationDurationUserInfoKey] as? NSNumber {
info.animationDuration = value.doubleValue
}
return info
}
}
36 changes: 15 additions & 21 deletions Sources/ExtensionKit/SwiftUI/KeyboardStateModifier.swift
@@ -1,26 +1,20 @@
import Combine
import SwiftUI

/// Get keyboard status updates
struct KeyboardStateModifier: ViewModifier {

@Binding var isVisible: Bool

init(_ isVisible: Binding<Bool>) {
_isVisible = isVisible
}

private let keyboardWillAppear = NotificationCenter.default
.publisher(for: UIResponder.keyboardWillShowNotification)
.map { _ -> Bool in true }

private let keyboardWillHide = NotificationCenter.default
.publisher(for: UIResponder.keyboardWillHideNotification)
.map { _ -> Bool in false }

func body(content: Content) -> some View {
content
.onReceive(keyboardWillAppear.merge(with: keyboardWillHide)) {
self.isVisible = $0
}
}

@Binding var keyboardInfo: Notification.KeyboardInfo

init(_ keyboardInfo: Binding<Notification.KeyboardInfo>) {
_keyboardInfo = keyboardInfo
}

func body(content: Content) -> some View {
content
.onReceive(
AnyPublisher<Notification.KeyboardInfo, Never>.keyboardInfo,
assignTo: $keyboardInfo
)
}
}
4 changes: 2 additions & 2 deletions Sources/ExtensionKit/SwiftUI/View.swift
Expand Up @@ -341,8 +341,8 @@ public extension View {
/// Receive keyboard status updates
/// - Parameter isVisible: is keyboard visible
/// - Returns: View
func keyboardState(isVisible: Binding<Bool>) -> some View {
self.modifier(KeyboardStateModifier(isVisible))
func keyboardState(info: Binding<Notification.KeyboardInfo>) -> some View {
self.modifier(KeyboardStateModifier(info))
}

/// Debug print
Expand Down

0 comments on commit a37670d

Please sign in to comment.