mirror of
https://github.com/Sonarr/Sonarr.git
synced 2024-12-14 11:23:42 +02:00
Fixed: Modal scrolling causing app to scroll on iOS
This commit is contained in:
parent
c65452bb01
commit
341773830b
@ -4,7 +4,7 @@ import React, { Component } from 'react';
|
|||||||
import { Manager, Popper, Reference } from 'react-popper';
|
import { Manager, Popper, Reference } from 'react-popper';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import getUniqueElememtId from 'Utilities/getUniqueElementId';
|
import getUniqueElememtId from 'Utilities/getUniqueElementId';
|
||||||
import isMobileUtil from 'Utilities/isMobile';
|
import { isMobile as isMobileUtil } from 'Utilities/mobile';
|
||||||
import * as keyCodes from 'Utilities/Constants/keyCodes';
|
import * as keyCodes from 'Utilities/Constants/keyCodes';
|
||||||
import { icons, sizes, scrollDirections } from 'Helpers/Props';
|
import { icons, sizes, scrollDirections } from 'Helpers/Props';
|
||||||
import Icon from 'Components/Icon';
|
import Icon from 'Components/Icon';
|
||||||
|
@ -29,6 +29,12 @@
|
|||||||
overflow: hidden !important;
|
overflow: hidden !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.modalOpenIOS {
|
||||||
|
position: fixed;
|
||||||
|
right: 0;
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Sizes
|
* Sizes
|
||||||
*/
|
*/
|
||||||
|
@ -4,6 +4,8 @@ import ReactDOM from 'react-dom';
|
|||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import elementClass from 'element-class';
|
import elementClass from 'element-class';
|
||||||
import getUniqueElememtId from 'Utilities/getUniqueElementId';
|
import getUniqueElememtId from 'Utilities/getUniqueElementId';
|
||||||
|
import { isIOS } from 'Utilities/mobile';
|
||||||
|
import { setScrollLock } from 'Utilities/scrollLock';
|
||||||
import * as keyCodes from 'Utilities/Constants/keyCodes';
|
import * as keyCodes from 'Utilities/Constants/keyCodes';
|
||||||
import { sizes } from 'Helpers/Props';
|
import { sizes } from 'Helpers/Props';
|
||||||
import ErrorBoundary from 'Components/Error/ErrorBoundary';
|
import ErrorBoundary from 'Components/Error/ErrorBoundary';
|
||||||
@ -69,7 +71,14 @@ class Modal extends Component {
|
|||||||
window.addEventListener('keydown', this.onKeyDown);
|
window.addEventListener('keydown', this.onKeyDown);
|
||||||
|
|
||||||
if (openModals.length === 1) {
|
if (openModals.length === 1) {
|
||||||
elementClass(document.body).add(styles.modalOpen);
|
if (isIOS()) {
|
||||||
|
setScrollLock(true);
|
||||||
|
const offset = document.body.scrollTop;
|
||||||
|
document.body.style.top = `${offset * -1}px`;
|
||||||
|
elementClass(document.body).add(styles.modalOpenIOS);
|
||||||
|
} else {
|
||||||
|
elementClass(document.body).add(styles.modalOpen);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -78,7 +87,15 @@ class Modal extends Component {
|
|||||||
window.removeEventListener('keydown', this.onKeyDown);
|
window.removeEventListener('keydown', this.onKeyDown);
|
||||||
|
|
||||||
if (openModals.length === 0) {
|
if (openModals.length === 0) {
|
||||||
elementClass(document.body).remove(styles.modalOpen);
|
setScrollLock(false);
|
||||||
|
|
||||||
|
if (isIOS()) {
|
||||||
|
const offset = parseInt(document.body.style.top);
|
||||||
|
elementClass(document.body).remove(styles.modalOpenIOS);
|
||||||
|
document.body.scrollTop = (offset * -1);
|
||||||
|
} else {
|
||||||
|
elementClass(document.body).remove(styles.modalOpen);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
|
import { isLocked } from 'Utilities/scrollLock';
|
||||||
import { scrollDirections } from 'Helpers/Props';
|
import { scrollDirections } from 'Helpers/Props';
|
||||||
import OverlayScroller from 'Components/Scroller/OverlayScroller';
|
import OverlayScroller from 'Components/Scroller/OverlayScroller';
|
||||||
import Scroller from 'Components/Scroller/Scroller';
|
import Scroller from 'Components/Scroller/Scroller';
|
||||||
@ -7,6 +8,17 @@ import styles from './PageContentBody.css';
|
|||||||
|
|
||||||
class PageContentBody extends Component {
|
class PageContentBody extends Component {
|
||||||
|
|
||||||
|
//
|
||||||
|
// Listeners
|
||||||
|
|
||||||
|
onScroll = (props) => {
|
||||||
|
const { onScroll } = this.props;
|
||||||
|
|
||||||
|
if (this.props.onScroll && !isLocked()) {
|
||||||
|
onScroll(props);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Render
|
// Render
|
||||||
|
|
||||||
@ -27,6 +39,7 @@ class PageContentBody extends Component {
|
|||||||
className={className}
|
className={className}
|
||||||
scrollDirection={scrollDirections.VERTICAL}
|
scrollDirection={scrollDirections.VERTICAL}
|
||||||
{...otherProps}
|
{...otherProps}
|
||||||
|
onScroll={this.onScroll}
|
||||||
>
|
>
|
||||||
<div className={innerClassName}>
|
<div className={innerClassName}>
|
||||||
{children}
|
{children}
|
||||||
@ -41,6 +54,7 @@ PageContentBody.propTypes = {
|
|||||||
innerClassName: PropTypes.string,
|
innerClassName: PropTypes.string,
|
||||||
isSmallScreen: PropTypes.bool.isRequired,
|
isSmallScreen: PropTypes.bool.isRequired,
|
||||||
children: PropTypes.node.isRequired,
|
children: PropTypes.node.isRequired,
|
||||||
|
onScroll: PropTypes.func,
|
||||||
dispatch: PropTypes.func
|
dispatch: PropTypes.func
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@ import PropTypes from 'prop-types';
|
|||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import ReactDOM from 'react-dom';
|
import ReactDOM from 'react-dom';
|
||||||
import { WindowScroller } from 'react-virtualized';
|
import { WindowScroller } from 'react-virtualized';
|
||||||
|
import { isLocked } from 'Utilities/scrollLock';
|
||||||
import { scrollDirections } from 'Helpers/Props';
|
import { scrollDirections } from 'Helpers/Props';
|
||||||
import Measure from 'Components/Measure';
|
import Measure from 'Components/Measure';
|
||||||
import Scroller from 'Components/Scroller/Scroller';
|
import Scroller from 'Components/Scroller/Scroller';
|
||||||
@ -83,6 +84,16 @@ class VirtualTable extends Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onScroll = (props) => {
|
||||||
|
if (isLocked()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { onScroll } = this.props;
|
||||||
|
|
||||||
|
onScroll(props);
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Render
|
// Render
|
||||||
|
|
||||||
@ -107,7 +118,7 @@ class VirtualTable extends Component {
|
|||||||
<Measure onMeasure={this.onMeasure}>
|
<Measure onMeasure={this.onMeasure}>
|
||||||
<WindowScroller
|
<WindowScroller
|
||||||
scrollElement={isSmallScreen ? undefined : this._contentBodyNode}
|
scrollElement={isSmallScreen ? undefined : this._contentBodyNode}
|
||||||
onScroll={onScroll}
|
onScroll={this.onScroll}
|
||||||
>
|
>
|
||||||
{({ height, isScrolling }) => {
|
{({ height, isScrolling }) => {
|
||||||
return (
|
return (
|
||||||
|
@ -2,7 +2,7 @@ import PropTypes from 'prop-types';
|
|||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import { Manager, Popper, Reference } from 'react-popper';
|
import { Manager, Popper, Reference } from 'react-popper';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import isMobileUtil from 'Utilities/isMobile';
|
import { isMobile as isMobileUtil } from 'Utilities/mobile';
|
||||||
import { kinds, tooltipPositions } from 'Helpers/Props';
|
import { kinds, tooltipPositions } from 'Helpers/Props';
|
||||||
import Portal from 'Components/Portal';
|
import Portal from 'Components/Portal';
|
||||||
import styles from './Tooltip.css';
|
import styles from './Tooltip.css';
|
||||||
|
@ -1,7 +0,0 @@
|
|||||||
import MobileDetect from 'mobile-detect';
|
|
||||||
|
|
||||||
export default function isMobile() {
|
|
||||||
const mobileDetect = new MobileDetect(window.navigator.userAgent);
|
|
||||||
|
|
||||||
return mobileDetect.mobile() != null;
|
|
||||||
}
|
|
12
frontend/src/Utilities/mobile.js
Normal file
12
frontend/src/Utilities/mobile.js
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import MobileDetect from 'mobile-detect';
|
||||||
|
|
||||||
|
const mobileDetect = new MobileDetect(window.navigator.userAgent);
|
||||||
|
|
||||||
|
export function isMobile() {
|
||||||
|
|
||||||
|
return mobileDetect.mobile() != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isIOS() {
|
||||||
|
return mobileDetect.is('iOS');
|
||||||
|
}
|
13
frontend/src/Utilities/scrollLock.js
Normal file
13
frontend/src/Utilities/scrollLock.js
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
// Allow iOS devices to disable scrolling of the body/virtual table
|
||||||
|
// when a modal is open. This will prevent focusing an input in a
|
||||||
|
// modal causing the modal to close due to scrolling.
|
||||||
|
|
||||||
|
let scrollLock = false;
|
||||||
|
|
||||||
|
export function isLocked() {
|
||||||
|
return scrollLock;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setScrollLock(locked) {
|
||||||
|
scrollLock = locked;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user