<!-- Thank you for submitting a Pull Request and helping to improve Home
Assistant. Please complete the following sections to help the processing
and review of your changes. Please do not delete anything from this
template. -->
## Summary
<!-- Provide a brief summary of the changes you have made and most
importantly what they aim to achieve -->
Introduce keyboard handling for WKWebView: add WebViewKeyboardAvoidance
helpers for animation metrics and overlap calculation, a WKWebView
extension to run a JS command that scrolls the focused editable element
into view, and a managed bottom constraint for web views so the view is
animated above the keyboard. Wire up keyboard observers and
DispatchWorkItem scheduling/cleanup in WebViewController and
OnboardingAuthLoginViewController, and add the
scrollFocusedElementIntoView JavaScript to WebViewJavascriptCommands.
Add unit tests verifying the bottom constraint creation and JS contents.
## Screenshots
<!-- If this is a user-facing change not in the frontend, please include
screenshots in light and dark mode. -->
## Link to pull request in Documentation repository
<!-- Pull requests that add, change or remove functionality must have a
corresponding pull request in the Companion App Documentation repository
(https://github.com/home-assistant/companion.home-assistant). Please add
the number of this pull request after the "#" -->
Documentation: home-assistant/companion.home-assistant#
## Any other notes
<!-- If there is any other information of note, like if this Pull
Request is part of a bigger change, please include it here. -->
<!-- Thank you for submitting a Pull Request and helping to improve Home
Assistant. Please complete the following sections to help the processing
and review of your changes. Please do not delete anything from this
template. -->
## Summary
<!-- Provide a brief summary of the changes you have made and most
importantly what they aim to achieve -->
## Screenshots
<!-- If this is a user-facing change not in the frontend, please include
screenshots in light and dark mode. -->
## Link to pull request in Documentation repository
<!-- Pull requests that add, change or remove functionality must have a
corresponding pull request in the Companion App Documentation repository
(https://github.com/home-assistant/companion.home-assistant). Please add
the number of this pull request after the "#" -->
Documentation: home-assistant/companion.home-assistant#
## Any other notes
<!-- If there is any other information of note, like if this Pull
Request is part of a bigger change, please include it here. -->
<!-- Thank you for submitting a Pull Request and helping to improve Home
Assistant. Please complete the following sections to help the processing
and review of your changes. Please do not delete anything from this
template. -->
## Summary
<!-- Provide a brief summary of the changes you have made and most
importantly what they aim to achieve -->
## Screenshots
<!-- If this is a user-facing change not in the frontend, please include
screenshots in light and dark mode. -->
## Link to pull request in Documentation repository
<!-- Pull requests that add, change or remove functionality must have a
corresponding pull request in the Companion App Documentation repository
(https://github.com/home-assistant/companion.home-assistant). Please add
the number of this pull request after the "#" -->
Documentation: home-assistant/companion.home-assistant#
## Any other notes
<!-- If there is any other information of note, like if this Pull
Request is part of a bigger change, please include it here. -->
<!-- Thank you for submitting a Pull Request and helping to improve Home
Assistant. Please complete the following sections to help the processing
and review of your changes. Please do not delete anything from this
template. -->
## Summary
<!-- Provide a brief summary of the changes you have made and most
importantly what they aim to achieve -->
## Screenshots
<!-- If this is a user-facing change not in the frontend, please include
screenshots in light and dark mode. -->
## Link to pull request in Documentation repository
<!-- Pull requests that add, change or remove functionality must have a
corresponding pull request in the Companion App Documentation repository
(https://github.com/home-assistant/companion.home-assistant). Please add
the number of this pull request after the "#" -->
Documentation: home-assistant/companion.home-assistant#
## Any other notes
<!-- If there is any other information of note, like if this Pull
Request is part of a bigger change, please include it here. -->
## Summary
- Kiosk screensaver idle timer was not resetting on user interaction —
`recordKioskActivity()` was defined but never called
- WKWebView consumes touch events before UIKit idle detection, so the
timer counted down from kiosk activation rather than last touch
- Added a tap gesture recognizer on the WebView (`cancelsTouchesInView =
false`) to detect taps without interfering with normal interaction
- Added `scrollViewWillBeginDragging` delegate hook to detect
scroll/drag interactions
## Test plan
- [ ] Enable kiosk mode with 30s screensaver timeout
- [ ] Tap on the WebView dashboard — idle timer should reset
- [ ] Scroll on the dashboard — idle timer should reset
- [ ] Stop interacting — screensaver should appear after configured
timeout
- [ ] Verify normal WebView interaction (taps, links, scrolling) still
works normally
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Nick Stefanelli <nstefanelli@users.noreply.github.com>
## Summary
Reopening kiosk mode PR (previously #4218) after addressing all review
feedback from @bgoncal. Apologies for the delay — some family matters
pulled me away, but I'm excited to get this implemented and am fully
committed to seeing it through.
This PR adds the foundational infrastructure for **kiosk mode** — a
feature designed for wall-mounted iPad displays running Home Assistant
dashboards.
### What's included:
- **KioskModeManager** — Central coordinator singleton with
KioskModeObserver protocol (no NotificationCenter)
- **KioskSettings** — Comprehensive settings model with GRDB persistence
(camelCase columns, Codable)
- **Screensaver system** — Clock screensaver with 4 styles, pixel shift
for OLED burn-in prevention
- **Secret exit gesture** — Configurable corner tap to access settings
when locked down
- **Status bar hiding** — StatusBarForwardingNavigationController for
proper UIKit integration
- **Settings UI** — SwiftUI settings accessible via Settings menu and
secret gesture
- **28 unit tests** — Covering settings serialization, time logic,
orientations, enums
### Changes since #4218 (all review feedback addressed):
- ✅ Fixed settings modal dismissal on iOS 15 (UINavigationController +
explicit onDismiss closure)
- ✅ Fixed status bar hiding (StatusBarForwardingNavigationController +
statusBarView integration)
- ✅ Removed non-functional settings (navigationLockdown,
TouchFeedbackManager, IconMapper)
- ✅ Replaced `Date()` with `Current.date()` for testability
- ✅ GRDB persistence follows CarPlayConfig/WatchConfig pattern with
DatabaseTableProtocol
- ✅ All strings localized via L10n (SwiftGen)
- ✅ SFSafeSymbols used throughout (no string-based systemName)
- ✅ KioskModeObserver protocol (no NotificationCenter)
- ✅ Kiosk files prefixed with `Kiosk`
- ✅ UIKit screensaver container (required for status bar/home indicator
control)
- ✅ macCatalyst filtered out
- ✅ Merged with latest upstream/main (adapted to Frontend/ directory
restructure)
- ✅ Idle timer pauses when settings view is open
- ✅ TODO comments (no PR-specific comments)
### Testing Instructions
1. **Settings → Companion App → Kiosk Mode** → Enable "Enable Kiosk
Mode"
2. Set screensaver timeout to **30 seconds** for quick testing
3. Wait for screensaver → tap to wake
4. Use secret gesture (default: 3 taps in top-left corner) to access
settings
### Previous review context
All feedback from @bgoncal in #4218 has been addressed. See that PR for
full discussion history.
## Test plan
- [ ] Enable/disable kiosk mode from Settings
- [ ] Screensaver activates after timeout
- [ ] Tap to wake from screensaver
- [ ] Secret gesture opens settings
- [ ] Status bar hides when kiosk mode active (full-screen iPad only)
- [ ] Device authentication toggle works
- [ ] Settings persist across app restart
- [ ] Clock screensaver styles (large, minimal, digital, analog)
- [ ] Pixel shift moves clock position periodically
- [ ] Kiosk entry hidden on macCatalyst
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Nick Stefanelli <nstefanelli@users.noreply.github.com>
Split WebViewController functionality into multiple extension files
(Alerts, EmptyState, Gestures, Navigation, Onboarding, Settings,
StatusBar, URLLoading, WebViewSetup) and add FrontEndConnectionState
enum. Update Xcode project to include the new source files and adjust
several Database test file references and a local Swift package path
(Sources/SharedPush). Also add empty input/output path arrays to several
CocoaPods embed phases. This refactors web view features into modular
components and wires them into the project file.
<!-- Thank you for submitting a Pull Request and helping to improve Home
Assistant. Please complete the following sections to help the processing
and review of your changes. Please do not delete anything from this
template. -->
## Summary
<!-- Provide a brief summary of the changes you have made and most
importantly what they aim to achieve -->
## Screenshots
<!-- If this is a user-facing change not in the frontend, please include
screenshots in light and dark mode. -->
## Link to pull request in Documentation repository
<!-- Pull requests that add, change or remove functionality must have a
corresponding pull request in the Companion App Documentation repository
(https://github.com/home-assistant/companion.home-assistant). Please add
the number of this pull request after the "#" -->
Documentation: home-assistant/companion.home-assistant#
## Any other notes
<!-- If there is any other information of note, like if this Pull
Request is part of a bigger change, please include it here. -->
<!-- Thank you for submitting a Pull Request and helping to improve Home
Assistant. Please complete the following sections to help the processing
and review of your changes. Please do not delete anything from this
template. -->
## Summary
<!-- Provide a brief summary of the changes you have made and most
importantly what they aim to achieve -->
Recently it was introduced a feature to reload webview when app has been
backgrounded for more than 5 minutes, this PR adds a layer on top of it
that only reloads if the webview frontend connection state is not
connected.
## Screenshots
<!-- If this is a user-facing change not in the frontend, please include
screenshots in light and dark mode. -->
## Link to pull request in Documentation repository
<!-- Pull requests that add, change or remove functionality must have a
corresponding pull request in the Companion App Documentation repository
(https://github.com/home-assistant/companion.home-assistant). Please add
the number of this pull request after the "#" -->
Documentation: home-assistant/companion.home-assistant#
## Any other notes
<!-- If there is any other information of note, like if this Pull
Request is part of a bigger change, please include it here. -->
---------
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
<!-- Thank you for submitting a Pull Request and helping to improve Home
Assistant. Please complete the following sections to help the processing
and review of your changes. Please do not delete anything from this
template. -->
## Summary
<!-- Provide a brief summary of the changes you have made and most
importantly what they aim to achieve -->
Extracted load/refresh blocks and conditionally invoke
Current.connectivity.syncNetworkInformation only on non-Catalyst
targets. On Catalyst the closures are executed immediately to avoid
unnecessary async network syncs and ensure immediate UI behavior.
Applied to WebViewController and its protocol conformance refresh
handling.
## Screenshots
<!-- If this is a user-facing change not in the frontend, please include
screenshots in light and dark mode. -->
## Link to pull request in Documentation repository
<!-- Pull requests that add, change or remove functionality must have a
corresponding pull request in the Companion App Documentation repository
(https://github.com/home-assistant/companion.home-assistant). Please add
the number of this pull request after the "#" -->
Documentation: home-assistant/companion.home-assistant#
## Any other notes
<!-- If there is any other information of note, like if this Pull
Request is part of a bigger change, please include it here. -->
<!-- Thank you for submitting a Pull Request and helping to improve Home
Assistant. Please complete the following sections to help the processing
and review of your changes. Please do not delete anything from this
template. -->
## Summary
<!-- Provide a brief summary of the changes you have made and most
importantly what they aim to achieve -->
## Screenshots
<!-- If this is a user-facing change not in the frontend, please include
screenshots in light and dark mode. -->
## Link to pull request in Documentation repository
<!-- Pull requests that add, change or remove functionality must have a
corresponding pull request in the Companion App Documentation repository
(https://github.com/home-assistant/companion.home-assistant). Please add
the number of this pull request after the "#" -->
Documentation: home-assistant/companion.home-assistant#
## Any other notes
<!-- If there is any other information of note, like if this Pull
Request is part of a bigger change, please include it here. -->