Skip to content

Commit

Permalink
fix: check keyboard presence for OverKeyboardView (#636)
Browse files Browse the repository at this point in the history
## 📜 Description

Attach `OverKeyboardView` to `keyboardWindow` only if keyboard is
visible.

## 💡 Motivation and Context

The problem was because of the fact, that when we open a `WebBrowser`
then `UIRemoteKeyboardWindow` from browser gets registered. And the
problem is that when we close browser the window is not getting
deregistered and we are attaching a view to invisible `keyboardWindow`.
And view is not visible.

To fix this problem initially I decided to check if the `keyboardView`
instance is retrievable. And first testing showed that it fixes a
problem. I. e. we:
- open browser;
- close browser;
- show `OverKeyboardView` (it works);

But if we add more scenarios, like opening a keyboard, closing keyboard,
opening a browser, opening/closing keyboard, showing `OverKeyboardView`
the check can be broken, because we have invalid
`UIRemoteKeyboardWindow` and we already have a reference to keyboard
instance, so we'll attach view to invalid window.

To overcome this problem we need to check for actual keyboard visibility
and attach a view to `keyboardWindow` only if:
- `keyboardWindow` is available;
- `keyboardView` is visible.

To check if view is visible I added new extension `isVisibleInHierarchy`
to `UIView`. I added both implementations, to optional and non-optional
extension.

Closes
#635

## 📢 Changelog

### iOS

- add `isVisibleInHierarchy` to `UIView` extension;
- check that `KeyboardView.find().isVisibleInHierarchy() == true` before
returning `keyboardWindow`.

## 🤔 How Has This Been Tested?

Tested in reproduction project on iPhone 15 Pro (iOS 17.5).

## 📸 Screenshots (if appropriate):

|Before|After|
|-------|-----|
|<video
src="https://github.com/user-attachments/assets/a78baaa4-e1bd-43d4-ad76-853193461b76">|<video
src="https://github.com/user-attachments/assets/b8ea5dd5-019b-4d5e-b247-b7aeac93ba01">|

## 📝 Checklist

- [x] CI successfully passed
- [x] I added new mocks and corresponding unit-tests if library API was
changed
  • Loading branch information
kirillzyusko authored Oct 15, 2024
1 parent c068c2a commit d1df467
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 2 deletions.
27 changes: 27 additions & 0 deletions ios/extensions/UIView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,26 @@ public extension UIView {
let rootView = UIApplication.shared.activeWindow?.rootViewController?.view
return superview?.convert(frame, to: rootView)
}

func isVisibleInHierarchy(initial: Bool = true) -> Bool {
guard let window = window else {
return false
}
if isHidden || alpha == 0.0 {
return false
}
if superview === window {
return true
} else if let superview = superview {
if initial, frame.minY >= superview.frame.height {
return false
} else {
return superview.isVisibleInHierarchy(initial: false)
}
} else {
return false
}
}
}

public extension Optional where Wrapped == UIView {
Expand All @@ -32,4 +52,11 @@ public extension Optional where Wrapped == UIView {

return (position, frameY)
}

func isVisibleInHierarchy(initial: Bool = true) -> Bool {
guard let view = self else {
return false
}
return view.isVisibleInHierarchy(initial: initial)
}
}
7 changes: 5 additions & 2 deletions ios/extensions/UIWindow.swift
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,11 @@ public extension UIWindow {
}

func getTopWindow() -> UIWindow? {
// Return the keyboard window if it's available, otherwise return the last window
return keyboardWindow ?? UIApplication.shared.activeWindow
let keyboardView = KeyboardView.find()
// return the keyboard window if it's available and keyboard is visible, otherwise return the last window
return (keyboardWindow != nil && keyboardView.isVisibleInHierarchy())
? keyboardWindow
: UIApplication.shared.activeWindow
}
}

Expand Down

0 comments on commit d1df467

Please sign in to comment.