Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mobile Web Safari: Adds auto scroll back - Issue 5894 #6413

Merged
merged 7 commits into from
Nov 30, 2021
1 change: 1 addition & 0 deletions src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import OnyxProvider from './components/OnyxProvider';
import HTMLEngineProvider from './components/HTMLEngineProvider';
import ComposeProviders from './components/ComposeProviders';
import SafeArea from './components/SafeArea';
import './libs/autoScrollback';

LogBox.ignoreLogs([
// Basically it means that if the app goes in the background and back to foreground on Android,
Expand Down
4 changes: 4 additions & 0 deletions src/libs/autoScrollback/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
/* autoScrollBack address Mobile Safari-specific issues when the user overscrolls the window while the keyboard is visible */
sidferreira marked this conversation as resolved.
Show resolved Hide resolved
/* it has no effect to other platforms */

export default () => {};
56 changes: 56 additions & 0 deletions src/libs/autoScrollback/index.web.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/* autoScrollBack address Mobile Safari-specific issues when the user overscrolls the window while the keyboard is visible */
import Str from 'expensify-common/lib/str';

import getBrowser from '../getBrowser';

const init = () => {
sidferreira marked this conversation as resolved.
Show resolved Hide resolved
sidferreira marked this conversation as resolved.
Show resolved Hide resolved
if (getBrowser() !== 'safari') {
sidferreira marked this conversation as resolved.
Show resolved Hide resolved
return;
}
const userAgent = navigator.userAgent.toLowerCase();

if (Str.contains(userAgent, 'iphone os 1')) {
sidferreira marked this conversation as resolved.
Show resolved Hide resolved
const innterHeightWithoutKeyboard = window.innerHeight;

sidferreira marked this conversation as resolved.
Show resolved Hide resolved
let waitingForScrollAfterFocus = false;

sidferreira marked this conversation as resolved.
Show resolved Hide resolved
let maxScrollY = 0;

sidferreira marked this conversation as resolved.
Show resolved Hide resolved
const isIos15 = Str.contains(userAgent, 'iphone os 15_');

sidferreira marked this conversation as resolved.
Show resolved Hide resolved
let isTouching = false;

const scrollback = () => {
sidferreira marked this conversation as resolved.
Show resolved Hide resolved
if (!maxScrollY) {
return;
}
if (!isTouching && window.scrollY > maxScrollY) {
window.scrollTo({top: maxScrollY, behavior: 'smooth'});
sidferreira marked this conversation as resolved.
Show resolved Hide resolved
}
};

document.addEventListener('touchstart', () => {
isTouching = true;
});
document.addEventListener('touchend', () => {
isTouching = false;
scrollback();
});
document.addEventListener('scroll', () => {
if (waitingForScrollAfterFocus && !maxScrollY) {
waitingForScrollAfterFocus = false;
const keyboardHeight = innterHeightWithoutKeyboard - window.visualViewport.height;
maxScrollY = keyboardHeight + (isIos15 ? 52 : 0);
sidferreira marked this conversation as resolved.
Show resolved Hide resolved
}
scrollback();
});
document.addEventListener('focusin', () => {
waitingForScrollAfterFocus = true;
});
document.addEventListener('focusout', () => {
waitingForScrollAfterFocus = false;
});
}
};

init();
sidferreira marked this conversation as resolved.
Show resolved Hide resolved