richdocuments/src/helpers/mobileFixer.js
Skyler Grey 3864969204 fix(mobile): update resized frame ID
When resizing the frame on mobile we correctly resize the outer <div>
element. We used to also resize the frame, but in ba45233bf (chore:
refactor iframes to load collabora directly, 2023-06-11) the ID of the
iframe was changed without things that depended on it also changing.

In Chrome, this causes the issue that the iframe isn't resized all the
way down, leading to it being possible to scroll the iframe inside the
viewport. This is bad as it means some elements of Collabora Online that
are meant to be stuck to different parts of the screen can go off the
screen edge.

There are some bits of CSS which also refer to this ID. To aid in easy
partial reverting (and as I don't currently have a need for them) I have
not fixed them in this commit

Signed-off-by: Skyler Grey <skyler.grey@collabora.com>
2025-11-05 12:15:41 +00:00

71 lines
1.9 KiB
JavaScript

/**
* SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
let scrollLock = false
let intervalHandler
// Workaround for browsers automatically scrolling the body when the hidden input is focussed
const handleScrollReset = () => {
document.documentElement.scrollTop = 0
document.scrollingElement.scrollTop = 0
}
// Workaround for mobile browsers to resize the iframe to the visual viewport height
// as visual viewport area - which includes OSK, say - is not propagated to iframes
// see https://developer.mozilla.org/en-US/docs/Web/API/VisualViewport
const handleResize = () => {
const expectedHeight = window.visualViewport.height ?? document.documentElement.clientHeight
const frames = document.getElementsByClassName('office-viewer__iframe')
for (const frame of frames) {
frame.style.maxHeight = expectedHeight + 'px'
}
const viewer = document.querySelector('.office-viewer')
if (viewer) {
viewer.style.height = expectedHeight + 'px'
}
}
const fixThemAll = () => {
if (!scrollLock) {
return
}
handleScrollReset()
handleResize()
}
const preventDefault = (e) => e.preventDefault()
export const enableScrollLock = () => {
if (scrollLock) {
return
}
scrollLock = true
window?.visualViewport?.addEventListener('resize', fixThemAll)
|| window.addEventListener('resize', fixThemAll)
document.addEventListener('touchstart', preventDefault, false)
document.addEventListener('touchmove', preventDefault, false)
intervalHandler = setInterval(fixThemAll, 200)
}
export const disableScrollLock = () => {
if (!scrollLock) {
return
}
scrollLock = false
window?.visualViewport?.removeEventListener('resize', fixThemAll)
|| window.removeEventListener('resize', fixThemAll)
document.removeEventListener('touchstart', preventDefault, false)
document.removeEventListener('touchmove', preventDefault, false)
clearInterval(intervalHandler)
}