FIX: improves modal on iOS when input is focused (#35619)

This commit removes various hacks and replace them by using the new
modifier: `{{preventScrollOnFocus}}`.

Applied this fix to:
- emoji picker modal
- fast edit modal
- add post notice

We might have other modals to fix in the future. Generally the fix
should be the same, order matters though, and the modifier has to be
before any `{{autoFocus}}` or similar behavior.
This commit is contained in:
Joffrey JAFFEUX
2025-10-27 10:46:47 +01:00
committed by GitHub
parent 51501cb281
commit 0804046ef6
6 changed files with 15 additions and 32 deletions
@@ -18,7 +18,6 @@ import {
disableBodyScroll,
enableBodyScroll,
} from "discourse/lib/body-scroll-lock";
import { bind } from "discourse/lib/decorators";
import { getMaxAnimationTimeMs } from "discourse/lib/swipe-events";
import swipe from "discourse/modifiers/swipe";
import trapTab from "discourse/modifiers/trap-tab";
@@ -34,8 +33,6 @@ const SWIPE_VELOCITY_THRESHOLD = 0.4;
export default class DModal extends Component {
@service modal;
@service site;
@service appEvents;
@service capabilities;
@tracked wrapperElement;
@tracked animating = false;
@@ -63,11 +60,6 @@ export default class DModal extends Component {
this.handleDocumentKeydown
);
this.appEvents.on(
"keyboard-visibility-change",
this.handleKeyboardVisibilityChange
);
if (this.site.mobileView) {
this.animating = true;
@@ -94,11 +86,6 @@ export default class DModal extends Component {
"keydown",
this.handleDocumentKeydown
);
this.appEvents.off(
"keyboard-visibility-change",
this.handleKeyboardVisibilityChange
);
}
get dismissable() {
@@ -248,13 +235,6 @@ export default class DModal extends Component {
return element(tagName);
}
@bind
handleKeyboardVisibilityChange(visible) {
if (visible && this.capabilities.isIOS && !this.capabilities.isIpadOS) {
window.scrollTo(0, 0);
}
}
#animateBackdropOpacity(position) {
const backdrop = this.wrapperElement.nextElementSibling;
@@ -30,6 +30,8 @@ import { INPUT_DELAY } from "discourse/lib/environment";
import { makeArray } from "discourse/lib/helpers";
import loadEmojiSearchAliases from "discourse/lib/load-emoji-search-aliases";
import { emojiUrlFor } from "discourse/lib/text";
import autoFocus from "discourse/modifiers/auto-focus";
import preventScrollOnFocus from "discourse/modifiers/prevent-scroll-on-focus";
import { i18n } from "discourse-i18n";
import DiversityMenu from "./diversity-menu";
@@ -53,8 +55,8 @@ const tonableEmojiUrl = (emoji, scale) => {
};
export default class EmojiPicker extends Component {
@service emojiStore;
@service capabilities;
@service emojiStore;
@service site;
@tracked isFiltering = false;
@@ -169,10 +171,6 @@ export default class EmojiPicker extends Component {
@action
focusFilter(target) {
if (this.capabilities.isIOS) {
return;
}
target?.focus({ preventScroll: true });
}
@@ -468,7 +466,8 @@ export default class EmojiPicker extends Component {
}}
>
<FilterInput
{{didInsert this.focusFilter}}
{{preventScrollOnFocus}}
{{autoFocus}}
{{didInsert this.registerFilterInput}}
@value={{this.term}}
@filterAction={{withEventValue this.didInputFilter}}
@@ -9,6 +9,7 @@ import { ajax } from "discourse/lib/ajax";
import { popupAjaxError } from "discourse/lib/ajax-error";
import { translateModKey } from "discourse/lib/utilities";
import autoFocus from "discourse/modifiers/auto-focus";
import preventScrollOnFocus from "discourse/modifiers/prevent-scroll-on-focus";
import { i18n } from "discourse-i18n";
export default class FastEdit extends Component {
@@ -76,6 +77,7 @@ export default class FastEdit extends Component {
<textarea
{{on "input" this.updateValue}}
id="fast-edit-input"
{{preventScrollOnFocus}}
{{autoFocus}}
>{{this.value}}</textarea>
@@ -9,6 +9,7 @@ import DButton from "discourse/components/d-button";
import DModal from "discourse/components/d-modal";
import DModalCancel from "discourse/components/d-modal-cancel";
import withEventValue from "discourse/helpers/with-event-value";
import preventScrollOnFocus from "discourse/modifiers/prevent-scroll-on-focus";
import { i18n } from "discourse-i18n";
export default class ChangePostNoticeModal extends Component {
@@ -84,6 +85,7 @@ export default class ChangePostNoticeModal extends Component {
<:body>
<form>
<textarea
{{preventScrollOnFocus}}
value={{this.notice}}
{{on "input" (withEventValue (fn (mut this.notice)))}}
/>
@@ -3,10 +3,10 @@ import Modifier from "ember-modifier";
export default class AutoFocusModifier extends Modifier {
didFocus = false;
modify(element, _, { selectText }) {
modify(element, _, { selectText, preventScroll }) {
if (!this.didFocus) {
element.autofocus = true;
element.focus();
element.focus({ preventScroll: preventScroll ?? true });
if (selectText) {
element.select();
@@ -55,12 +55,12 @@ export default class PreventScrollOnFocus extends Modifier {
return;
}
const textarea = event.target;
textarea.style.transform = "translateY(-99999px)";
textarea.focus({ preventScroll: true });
const target = event.target;
target.style.transform = "translateY(-99999px)";
target.focus({ preventScroll: true });
window.requestAnimationFrame(() => {
window.requestAnimationFrame(() => {
textarea.style.transform = "";
target.style.transform = "";
});
});
}