Skip to content

Commit c3150d1

Browse files
committed
fix(android): match iframe size to visual viewport
I've been testing Collabora Online with Nextcloud on Android, and I've noticed some content displaying behind the onscreen keyboard as follows: There are two viewports on the web, the "visual" viewport (what you actually see) and the "layout" viewport (how the browser draws the page). The onscreen keyboard popping up used to resize the layout viewport. In newer Android versions, the onscreen keyboard by default resizes the visual viewport rather than the layout viewport. Unfortunately, the visual viewport isn't propagated through iframes, as per MDN docs which state: > Only the top-level window has a visual viewport that's distinct from > the layout viewport. Therefore, it's generally only the VisualViewport > object of the top-level window that's useful. For an <iframe>, visual > viewport metrics like VisualViewport.width always correspond to layout > viewport metrics like document.documentElement.clientWidth. (Quote from [VisualViewport page on MDN Docs][VV], by Mozilla Contributors under [CC-BY-SA v2.5][VVLICENSE]) [VV]: https://developer.mozilla.org/en-US/docs/Web/API/VisualViewport [VVLICENSE]: https://creativecommons.org/licenses/by-sa/2.5/ This leads to Collabora Online seeing the viewport as the size of its iframe in all cases. When the onscreen keyboard is up, this causes some parts of the app (the bottom toolbar) to be hidden as they are behind the keyboard. The intention is for this toolbar to instead float above the keyboard. I've done some investigation and this would be a problem on iOS/iPadOS too... it would be, except Julius has already written code to fix it (thanks Julius!). The code I'm talking about was in `src/helpers/safariFixer.js`, part of its job was to resize the richdocuments frame in place of the browser. It was previously gated to only running on iOS, but we can make it broader so it encompasses all browsers - including those running on Android devices. If we change that code to fix things other than Safari, the name no longer makes sense. Therefore, let's rename it to `mobileFixer.js` as well Finally, it's worth noting that this doesn't work in every browser I tested. Notably [Fennec][FENNEC] doesn't appear to correctly resize the visual viewport so this fix doesn't work over there. Notwithstanding, this fix does appear to work in both Play Store Chrome and Play Store Firefox which is a lot better than not working at all. Potential fixes for Fennec were considered possibly too risky: we could set a meta tag with `name="viewport"` and `content="interactive-widget=resizes-content"` but this would need to be set even when richdocuments isn't in use (or isn't installed!). Therefore, we'll have to cope with the state of things as they are for now... [FENNEC]: https://f-droid.org/en/packages/org.mozilla.fennec_fdroid/ Signed-off-by: Skyler Grey <[email protected]>
1 parent 2663786 commit c3150d1

File tree

3 files changed

+12
-10
lines changed

3 files changed

+12
-10
lines changed

src/document.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { getRequestToken } from '@nextcloud/auth'
99
import { loadState } from '@nextcloud/initial-state'
1010
import Config from './services/config.tsx'
1111
import { getUIDefaults, generateCSSVarTokens, getCollaboraTheme } from './helpers/coolParameters.js'
12-
import { enableScrollLock } from './helpers/safariFixer.js'
12+
import { enableScrollLock } from './helpers/mobileFixer.js'
1313
import PostMessageService from './services/postMessage.tsx'
1414
import { getCapabilities } from './services/capabilities.ts'
1515
import {

src/helpers/safariFixer.js renamed to src/helpers/mobileFixer.js

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,9 @@ const handleScrollReset = () => {
2121
document.scrollingElement.scrollTop = 0
2222
}
2323

24-
// Workaround for Safari to resize the iframe to the proper height
25-
// as 100vh is not the proper viewport height there
24+
// Workaround for mobile browsers to resize the iframe to the visual viewport height
25+
// as visual viewport area - which includes OSK, say - is not propagated to iframes
26+
// see https://developer.mozilla.org/en-US/docs/Web/API/VisualViewport
2627
const handleResize = () => {
2728
const expectedHeight = window.visualViewport.height ?? document.documentElement.clientHeight
2829
const frame = document.getElementById('richdocumentsframe')
@@ -36,20 +37,21 @@ const handleResize = () => {
3637
}
3738

3839
const fixThemAll = () => {
39-
if (!isiOS) {
40-
return
41-
}
4240
if (!scrollLock) {
4341
return
4442
}
45-
handleScrollReset()
43+
44+
if (isiOS) {
45+
handleScrollReset()
46+
}
47+
4648
handleResize()
4749
}
4850

4951
const preventDefault = (e) => e.preventDefault()
5052

5153
export const enableScrollLock = () => {
52-
if (scrollLock || !isiOS) {
54+
if (scrollLock) {
5355
return
5456
}
5557

@@ -65,7 +67,7 @@ export const enableScrollLock = () => {
6567
}
6668

6769
export const disableScrollLock = () => {
68-
if (!scrollLock || !isiOS) {
70+
if (!scrollLock) {
6971
return
7072
}
7173

src/view/Office.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ import {
9999
import PostMessageService from '../services/postMessage.tsx'
100100
import FilesAppIntegration from './FilesAppIntegration.js'
101101
import { LOADING_ERROR, checkCollaboraConfiguration, checkProxyStatus } from '../services/collabora.js'
102-
import { enableScrollLock, disableScrollLock } from '../helpers/safariFixer.js'
102+
import { enableScrollLock, disableScrollLock } from '../helpers/mobileFixer.js'
103103
import axios from '@nextcloud/axios'
104104
import {
105105
generateUrl,

0 commit comments

Comments
 (0)