diff --git a/app/assets/javascripts/discourse/app/initializers/mobile-keyboard.js b/app/assets/javascripts/discourse/app/initializers/mobile-keyboard.js index 72c343511d..816f8e15b5 100644 --- a/app/assets/javascripts/discourse/app/initializers/mobile-keyboard.js +++ b/app/assets/javascripts/discourse/app/initializers/mobile-keyboard.js @@ -6,9 +6,9 @@ export default { initialize(container) { const site = container.lookup("service:site"); - const capabilities = container.lookup("capabilities:main"); + this.capabilities = container.lookup("capabilities:main"); - if (!capabilities.isIpadOS && !site.mobileView) { + if (!this.capabilities.isIpadOS && !site.mobileView) { return; } @@ -21,27 +21,67 @@ export default { this.onViewportResize(); window.visualViewport.addEventListener("resize", this.onViewportResize); + if ("virtualKeyboard" in navigator) { + navigator.virtualKeyboard.overlaysContent = true; + navigator.virtualKeyboard.addEventListener( + "geometrychange", + this.onViewportResize + ); + } }, teardown() { window.visualViewport.removeEventListener("resize", this.onViewportResize); + if ("virtualKeyboard" in navigator) { + navigator.virtualKeyboard.overlaysContent = false; + navigator.virtualKeyboard.removeEventListener( + "geometrychange", + this.onViewportResize + ); + } }, @bind onViewportResize() { - const composerVH = window.visualViewport.height * 0.01; - const doc = document.documentElement; + const composerVH = window.visualViewport.height * 0.01, + doc = document.documentElement, + KEYBOARD_DETECT_THRESHOLD = 150; doc.style.setProperty("--composer-vh", `${composerVH}px`); - const heightDiff = this.windowInnerHeight - window.visualViewport.height; - doc.classList.toggle("keyboard-visible", heightDiff > 0); + let keyboardVisible = false; + if ("virtualKeyboard" in navigator) { + if (navigator.virtualKeyboard.boundingRect.height > 0) { + keyboardVisible = true; + } + } else if (this.capabilities.isFirefox && this.capabilities.isAndroid) { + if ( + Math.abs( + this.windowInnerHeight - + Math.min(window.innerHeight, window.visualViewport.height) + ) > KEYBOARD_DETECT_THRESHOLD + ) { + keyboardVisible = true; + } + } else { + let viewportWindowDiff = + this.windowInnerHeight - window.visualViewport.height; + if (viewportWindowDiff > 0) { + keyboardVisible = true; + } - // Add bottom padding when using a hardware keyboard and the accessory bar - // is visible accessory bar height is 55px, using 75 allows a small buffer - doc.style.setProperty( - "--composer-ipad-padding", - `${heightDiff < 75 ? heightDiff : 0}px` - ); + // adds bottom padding when using a hardware keyboard and the accessory bar is visible + // accessory bar height is 55px, using 75 allows a small buffer + if (this.capabilities.isIpadOS) { + doc.style.setProperty( + "--composer-ipad-padding", + `${viewportWindowDiff < 75 ? viewportWindowDiff : 0}px` + ); + } + } + + keyboardVisible + ? doc.classList.add("keyboard-visible") + : doc.classList.remove("keyboard-visible"); }, }; diff --git a/app/assets/stylesheets/common/base/compose.scss b/app/assets/stylesheets/common/base/compose.scss index 6aaa9b4632..9966197e26 100644 --- a/app/assets/stylesheets/common/base/compose.scss +++ b/app/assets/stylesheets/common/base/compose.scss @@ -539,6 +539,7 @@ body:not(.ios-safari-composer-hacks) { min-height: calc(var(--min-height) - 4em); } padding-bottom: var(--composer-ipad-padding); + padding-bottom: calc(10px + env(keyboard-inset-height)); } } diff --git a/app/assets/stylesheets/mobile/compose.scss b/app/assets/stylesheets/mobile/compose.scss index 3e610a7c06..31b9b75f56 100644 --- a/app/assets/stylesheets/mobile/compose.scss +++ b/app/assets/stylesheets/mobile/compose.scss @@ -24,6 +24,7 @@ .keyboard-visible &.open { height: 100%; // Android: Reduces composer jumpiness when the keyboard toggles + height: calc(100% - (10px + env(keyboard-inset-height))); } .keyboard-visible body.ios-safari-composer-hacks &.open {