mirror of
https://github.com/discourse/discourse.git
synced 2025-01-16 05:32:41 +08:00
FIX: simplify body scroll lock on iOS (#30696)
This will have the following advantages: - removes a very annoying bug which was making text selection super hard on iOS - removes the flashing of header when transitioning from disable to enable body scroll lock
This commit is contained in:
parent
07e5f8907e
commit
b96a9b9896
|
@ -97,37 +97,16 @@ const restoreOverflowSetting = () => {
|
||||||
};
|
};
|
||||||
const setPositionFixed = () =>
|
const setPositionFixed = () =>
|
||||||
window.requestAnimationFrame(() => {
|
window.requestAnimationFrame(() => {
|
||||||
const $html = document.documentElement;
|
|
||||||
const $body = document.body;
|
const $body = document.body;
|
||||||
if (bodyStyle === void 0) {
|
if (bodyStyle === void 0) {
|
||||||
htmlStyle = { ...$html.style };
|
|
||||||
bodyStyle = { ...$body.style };
|
bodyStyle = { ...$body.style };
|
||||||
const { scrollY, scrollX, innerHeight } = window;
|
$body.style.touchAction = "none";
|
||||||
$html.style.height = "100%";
|
|
||||||
$html.style.overflow = "hidden";
|
|
||||||
$body.style.position = "fixed";
|
|
||||||
$body.style.top = `${-scrollY}px`;
|
|
||||||
$body.style.left = `${-scrollX}px`;
|
|
||||||
$body.style.width = "100%";
|
|
||||||
$body.style.height = "auto";
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
const restorePositionSetting = () => {
|
const restorePositionSetting = () => {
|
||||||
if (bodyStyle !== void 0) {
|
if (bodyStyle !== void 0) {
|
||||||
const y = -parseInt(document.body.style.top, 10);
|
|
||||||
const x = -parseInt(document.body.style.left, 10);
|
|
||||||
const $html = document.documentElement;
|
|
||||||
const $body = document.body;
|
const $body = document.body;
|
||||||
$html.style.height = (htmlStyle == null ? void 0 : htmlStyle.height) || "";
|
$body.style.touchAction = bodyStyle.touchAction || "";
|
||||||
$html.style.overflow =
|
|
||||||
(htmlStyle == null ? void 0 : htmlStyle.overflow) || "";
|
|
||||||
$body.style.position = bodyStyle.position || "";
|
|
||||||
$body.style.top = bodyStyle.top || "";
|
|
||||||
$body.style.left = bodyStyle.left || "";
|
|
||||||
$body.style.width = bodyStyle.width || "";
|
|
||||||
$body.style.height = bodyStyle.height || "";
|
|
||||||
$body.style.overflow = bodyStyle.overflow || "";
|
|
||||||
window.scrollTo(x, y);
|
|
||||||
bodyStyle = void 0;
|
bodyStyle = void 0;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -199,43 +178,8 @@ const disableBodyScroll = (targetElement, options) => {
|
||||||
} else {
|
} else {
|
||||||
setOverflowHidden(options);
|
setOverflowHidden(options);
|
||||||
}
|
}
|
||||||
if (isIosDevice) {
|
|
||||||
targetElement.ontouchstart = (event) => {
|
|
||||||
if (event.targetTouches.length === 1) {
|
|
||||||
initialClientY = event.targetTouches[0].clientY;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
targetElement.ontouchmove = (event) => {
|
|
||||||
if (event.targetTouches.length === 1) {
|
|
||||||
handleScroll(event, targetElement, options);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
if (!documentListenerAdded) {
|
|
||||||
document.addEventListener(
|
|
||||||
"touchmove",
|
|
||||||
preventDefault,
|
|
||||||
hasPassiveEvents ? { passive: false } : void 0
|
|
||||||
);
|
|
||||||
documentListenerAdded = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
const clearAllBodyScrollLocks = () => {
|
const clearAllBodyScrollLocks = () => {
|
||||||
if (isIosDevice) {
|
|
||||||
locks.forEach((lock) => {
|
|
||||||
lock.targetElement.ontouchstart = null;
|
|
||||||
lock.targetElement.ontouchmove = null;
|
|
||||||
});
|
|
||||||
if (documentListenerAdded) {
|
|
||||||
document.removeEventListener(
|
|
||||||
"touchmove",
|
|
||||||
preventDefault,
|
|
||||||
hasPassiveEvents ? { passive: false } : void 0
|
|
||||||
);
|
|
||||||
documentListenerAdded = false;
|
|
||||||
}
|
|
||||||
initialClientY = -1;
|
|
||||||
}
|
|
||||||
if (isIosDevice) {
|
if (isIosDevice) {
|
||||||
restorePositionSetting();
|
restorePositionSetting();
|
||||||
} else {
|
} else {
|
||||||
|
@ -261,18 +205,6 @@ const enableBodyScroll = (targetElement) => {
|
||||||
locks = locks.filter((lock) => lock.targetElement !== targetElement);
|
locks = locks.filter((lock) => lock.targetElement !== targetElement);
|
||||||
locksIndex == null ? void 0 : locksIndex.delete(targetElement);
|
locksIndex == null ? void 0 : locksIndex.delete(targetElement);
|
||||||
}
|
}
|
||||||
if (isIosDevice) {
|
|
||||||
targetElement.ontouchstart = null;
|
|
||||||
targetElement.ontouchmove = null;
|
|
||||||
if (documentListenerAdded && locks.length === 0) {
|
|
||||||
document.removeEventListener(
|
|
||||||
"touchmove",
|
|
||||||
preventDefault,
|
|
||||||
hasPassiveEvents ? { passive: false } : void 0
|
|
||||||
);
|
|
||||||
documentListenerAdded = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (locks.length === 0) {
|
if (locks.length === 0) {
|
||||||
if (isIosDevice) {
|
if (isIosDevice) {
|
||||||
restorePositionSetting();
|
restorePositionSetting();
|
||||||
|
|
|
@ -88,6 +88,7 @@ export default class SwipeModifier extends Modifier {
|
||||||
this.element.addEventListener("swipeend", this.onDidEndSwipe);
|
this.element.addEventListener("swipeend", this.onDidEndSwipe);
|
||||||
this.element.addEventListener("swipecancel", this.onDidCancelSwipe);
|
this.element.addEventListener("swipecancel", this.onDidCancelSwipe);
|
||||||
this.element.addEventListener("swipe", this.onDidSwipe);
|
this.element.addEventListener("swipe", this.onDidSwipe);
|
||||||
|
this.element.addEventListener("scroll", this.onScroll);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -138,6 +139,14 @@ export default class SwipeModifier extends Modifier {
|
||||||
this.onDidCancelSwipeCallback?.(event.detail);
|
this.onDidCancelSwipeCallback?.(event.detail);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handler for scroll event. Prevents scrolling while swiping.
|
||||||
|
*/
|
||||||
|
@bind
|
||||||
|
onScroll(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cleans up the swipe modifier.
|
* Cleans up the swipe modifier.
|
||||||
*/
|
*/
|
||||||
|
@ -150,6 +159,7 @@ export default class SwipeModifier extends Modifier {
|
||||||
this.element.removeEventListener("swipeend", this.onDidEndSwipe);
|
this.element.removeEventListener("swipeend", this.onDidEndSwipe);
|
||||||
this.element.removeEventListener("swipecancel", this.onDidCancelSwipe);
|
this.element.removeEventListener("swipecancel", this.onDidCancelSwipe);
|
||||||
this.element.removeEventListener("swipe", this.onDidSwipe);
|
this.element.removeEventListener("swipe", this.onDidSwipe);
|
||||||
|
this.element.removeEventListener("scroll", this.onScroll);
|
||||||
this._swipeEvents.removeTouchListeners();
|
this._swipeEvents.removeTouchListeners();
|
||||||
|
|
||||||
if (this.lockBody) {
|
if (this.lockBody) {
|
||||||
|
|
|
@ -12,10 +12,6 @@ import { Promise } from "rsvp";
|
||||||
import EmojiPickerDetached from "discourse/components/emoji-picker/detached";
|
import EmojiPickerDetached from "discourse/components/emoji-picker/detached";
|
||||||
import InsertHyperlink from "discourse/components/modal/insert-hyperlink";
|
import InsertHyperlink from "discourse/components/modal/insert-hyperlink";
|
||||||
import { SKIP } from "discourse/lib/autocomplete";
|
import { SKIP } from "discourse/lib/autocomplete";
|
||||||
import {
|
|
||||||
disableBodyScroll,
|
|
||||||
enableBodyScroll,
|
|
||||||
} from "discourse/lib/body-scroll-lock";
|
|
||||||
import { setupHashtagAutocomplete } from "discourse/lib/hashtag-autocomplete";
|
import { setupHashtagAutocomplete } from "discourse/lib/hashtag-autocomplete";
|
||||||
import { emojiUrlFor } from "discourse/lib/text";
|
import { emojiUrlFor } from "discourse/lib/text";
|
||||||
import userSearch from "discourse/lib/user-search";
|
import userSearch from "discourse/lib/user-search";
|
||||||
|
@ -285,22 +281,20 @@ export default class ChatComposer extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
@action
|
@action
|
||||||
onTextareaFocusOut(event) {
|
onTextareaFocusOut() {
|
||||||
this.isFocused = false;
|
this.isFocused = false;
|
||||||
enableBodyScroll(event.target);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@action
|
@action
|
||||||
onTextareaFocusIn(event) {
|
onTextareaFocusIn(event) {
|
||||||
this.isFocused = true;
|
this.isFocused = true;
|
||||||
const textarea = event.target;
|
|
||||||
disableBodyScroll(textarea);
|
|
||||||
|
|
||||||
if (!this.capabilities.isIOS) {
|
if (!this.capabilities.isIOS) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// hack to prevent the whole viewport to move on focus input
|
// hack to prevent the whole viewport to move on focus input
|
||||||
|
const textarea = event.target;
|
||||||
textarea.style.transform = "translateY(-99999px)";
|
textarea.style.transform = "translateY(-99999px)";
|
||||||
textarea.focus();
|
textarea.focus();
|
||||||
window.requestAnimationFrame(() => {
|
window.requestAnimationFrame(() => {
|
||||||
|
|
|
@ -22,5 +22,7 @@
|
||||||
color: var(--primary-medium);
|
color: var(--primary-medium);
|
||||||
font-size: var(--font-down-1);
|
font-size: var(--font-down-1);
|
||||||
padding: 0.5em 0.25em 0.25em;
|
padding: 0.5em 0.25em 0.25em;
|
||||||
|
touch-action: none;
|
||||||
|
height: 100%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user