mirror of
https://github.com/discourse/discourse.git
synced 2025-01-22 21:37:30 +08:00
DEV: move d-composer-position to setupEditor (#30717)
Small refactor to move the `DComposerPosition` component to be a function used on the `setupEditor` editor lifecycle, so it's recycled/re-added whenever the editor component is mounted. Additionally, we reference the passed `editor` instead of the `event.target`, allowing a `contentEditable` editor (which is a DOM tree) to still work with the positioning hack.
This commit is contained in:
parent
7330cfa76a
commit
eb64db828e
|
@ -211,7 +211,6 @@
|
|||
{{/unless}}
|
||||
</div>
|
||||
</ComposerEditor>
|
||||
<DComposerPosition />
|
||||
|
||||
<span>
|
||||
<PluginOutlet
|
||||
|
|
|
@ -10,6 +10,7 @@ import $ from "jquery";
|
|||
import { resolveAllShortUrls } from "pretty-text/upload-short-url";
|
||||
import { ajax } from "discourse/lib/ajax";
|
||||
import { tinyAvatar } from "discourse/lib/avatar-utils";
|
||||
import { setupComposerPosition } from "discourse/lib/composer/composer-position";
|
||||
import discourseComputed, { bind, debounce } from "discourse/lib/decorators";
|
||||
import {
|
||||
fetchUnseenHashtagsInContext,
|
||||
|
@ -200,18 +201,19 @@ export default class ComposerEditor extends Component {
|
|||
|
||||
const input = this.element.querySelector(".d-editor-input");
|
||||
|
||||
input?.addEventListener(
|
||||
"scroll",
|
||||
this._throttledSyncEditorAndPreviewScroll
|
||||
);
|
||||
input.addEventListener("scroll", this._throttledSyncEditorAndPreviewScroll);
|
||||
|
||||
// Focus on the body unless we have a title
|
||||
if (!this.get("composer.model.canEditTitle")) {
|
||||
this.textManipulation.putCursorAtEnd();
|
||||
}
|
||||
|
||||
const destroyComposerPosition = setupComposerPosition(input);
|
||||
|
||||
return () => {
|
||||
input?.removeEventListener(
|
||||
destroyComposerPosition();
|
||||
|
||||
input.removeEventListener(
|
||||
"scroll",
|
||||
this._throttledSyncEditorAndPreviewScroll
|
||||
);
|
||||
|
|
|
@ -1,74 +0,0 @@
|
|||
import Component from "@glimmer/component";
|
||||
import { later } from "@ember/runloop";
|
||||
|
||||
export default class DComposerPosition extends Component {
|
||||
// This component contains two composer positioning adjustments
|
||||
// for Safari iOS/iPad and Firefox on Android
|
||||
// The fixes here go together with styling in base/compose.css
|
||||
constructor() {
|
||||
super(...arguments);
|
||||
|
||||
const html = document.documentElement;
|
||||
|
||||
if (
|
||||
html.classList.contains("mobile-device") ||
|
||||
html.classList.contains("ipados-device")
|
||||
) {
|
||||
window.addEventListener("scroll", this._correctScrollPosition);
|
||||
this._correctScrollPosition();
|
||||
const editor = document.querySelector(".d-editor-input");
|
||||
editor?.addEventListener("touchmove", this._textareaTouchMove);
|
||||
}
|
||||
}
|
||||
|
||||
willDestroy() {
|
||||
super.willDestroy(...arguments);
|
||||
|
||||
const html = document.documentElement;
|
||||
|
||||
if (
|
||||
html.classList.contains("mobile-device") ||
|
||||
html.classList.contains("ipados-device")
|
||||
) {
|
||||
window.removeEventListener("scroll", this._correctScrollPosition);
|
||||
const editor = document.querySelector(".d-editor-input");
|
||||
editor?.removeEventListener("touchmove", this._textareaTouchMove);
|
||||
}
|
||||
}
|
||||
|
||||
_correctScrollPosition() {
|
||||
// In some rare cases, when quoting a large text or
|
||||
// when editing a long topic, Safari/Firefox will scroll
|
||||
// the body so that the input/textarea is centered
|
||||
// This pushes the fixed element offscreen
|
||||
// Here we detect when the composer's top position is above the window's
|
||||
// current scroll offset and correct it
|
||||
later(() => {
|
||||
const el = document.querySelector("#reply-control");
|
||||
const rect = el.getBoundingClientRect();
|
||||
|
||||
if (rect.top < -1) {
|
||||
const scrollAmount = window.scrollY + rect.top;
|
||||
|
||||
window.scrollTo({
|
||||
top: scrollAmount,
|
||||
behavior: "instant",
|
||||
});
|
||||
}
|
||||
}, 150);
|
||||
}
|
||||
|
||||
_textareaTouchMove(event) {
|
||||
// This is an alternative to locking up the body
|
||||
// It stops scrolling in the given element from bubbling up to the body
|
||||
// when the textarea does not have any content to scroll
|
||||
if (event.target) {
|
||||
const notScrollable =
|
||||
event.target.scrollHeight <= event.target.clientHeight;
|
||||
if (notScrollable) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
import { later } from "@ember/runloop";
|
||||
|
||||
export function setupComposerPosition(editor) {
|
||||
// This component contains two composer positioning adjustments
|
||||
// for Safari iOS/iPad and Firefox on Android
|
||||
// The fixes here go together with styling in base/compose.css
|
||||
const html = document.documentElement;
|
||||
|
||||
function editorTouchMove(event) {
|
||||
// This is an alternative to locking up the body
|
||||
// It stops scrolling in the given element from bubbling up to the body
|
||||
// when the editor does not have any content to scroll
|
||||
const notScrollable = editor.scrollHeight <= editor.clientHeight;
|
||||
if (notScrollable) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
html.classList.contains("mobile-device") ||
|
||||
html.classList.contains("ipados-device")
|
||||
) {
|
||||
window.addEventListener("scroll", correctScrollPosition);
|
||||
correctScrollPosition();
|
||||
editor.addEventListener("touchmove", editorTouchMove);
|
||||
}
|
||||
|
||||
// destructor
|
||||
return () => {
|
||||
if (
|
||||
html.classList.contains("mobile-device") ||
|
||||
html.classList.contains("ipados-device")
|
||||
) {
|
||||
window.removeEventListener("scroll", correctScrollPosition);
|
||||
editor.removeEventListener("touchmove", editorTouchMove);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function correctScrollPosition() {
|
||||
// In some rare cases, when quoting a large text or
|
||||
// when editing a long topic, Safari/Firefox will scroll
|
||||
// the body so that the editor is centered
|
||||
// This pushes the fixed element offscreen
|
||||
// Here we detect when the composer's top position is above the window's
|
||||
// current scroll offset and correct it
|
||||
later(() => {
|
||||
const el = document.querySelector("#reply-control");
|
||||
const rect = el.getBoundingClientRect();
|
||||
|
||||
if (rect.top < -1) {
|
||||
const scrollAmount = window.scrollY + rect.top;
|
||||
|
||||
window.scrollTo({
|
||||
top: scrollAmount,
|
||||
behavior: "instant",
|
||||
});
|
||||
}
|
||||
}, 150);
|
||||
}
|
Loading…
Reference in New Issue
Block a user