Селектор эмодзи вызывает сбой редактора сообщений в Android / Chrome

Эта проблема существует уже несколько месяцев, и я могу воспроизвести её здесь, в Meta, на устройстве Android/Chrome (обе версии самые последние) — на самом деле это происходит уже несколько месяцев, примерно с января.

Редактор сообщений время от времени «вылетает», когда пользователь выбирает предложенный эмодзи.

Шаги для воспроизведения:

  1. Опубликуйте ответ на тему, добавьте текст.
  2. Начните добавлять «большой палец вверх», введя “:+1”, а затем нажмите на предложенный эмодзи :+1:.

Что происходит:

Редактор как будто вылетает или перерисовывается. Обычно при этом теряется часть введённого текста.

Проблема воспроизводится не в 100 % случаев, но я могу легко столкнуться с ней в течение минуты после начала тестирования.

2 лайка

Какую именно версию Android/Chrome вы используете?

Я могу воспроизвести проблему. Вот трассировка стека:

_application-bfbda341c2eb6dd7d61c681e17bdccec057c30e045ddc332927a7363150e9b1b.js:16386 Uncaught TypeError: Cannot read property '0' of null
    at HTMLLIElement.<anonymous> (application-bfbda341c2eb6dd7d61c681e17bdccec057c30e045ddc332927a7363150e9b1b.br.js:1)
    at HTMLLIElement.dispatch (ember_jquery-36a23101c869ab0dc53fc908de69adb785731593573d32bdeef416acc1076ef4.br.js:1)
    at HTMLLIElement.d.handle (ember_jquery-36a23101c869ab0dc53fc908de69adb785731593573d32bdeef416acc1076ef4.br.js:1)
(anonymous) @ application-bfbda341c2eb6dd7d61c681e17bdccec057c30e045ddc332927a7363150e9b1b.br.js:1
dispatch @ ember_jquery-36a23101c869ab0dc53fc908de69adb785731593573d32bdeef416acc1076ef4.br.js:1
d.handle @ ember_jquery-36a23101c869ab0dc53fc908de69adb785731593573d32bdeef416acc1076ef4.br.js:1

Это происходит в этой строке:

https://github.com/discourse/discourse/blob/master/app/assets/javascripts/discourse/app/lib/autocomplete.js#L308

Ошибка возникает потому, что selectedOption равен 0 (единственное предложение, то есть первое), в то время как autocompleteOptions каким-то образом равен null.

Сейчас исследую причину…

Пока что я не уверен, почему это происходит. Сначала я подозревал этот PR от @Osama:

Но я установил множество точек останова и не могу точно определить, «кто» изменяет autocompleteOptions и устанавливает его в null.

Также довольно странно, что autocompleteOptions берётся из области видимости родительской замыкающей функции, находящейся на два уровня выше, что делает код немного сложным для понимания и отладки.

8 лайков

Android 11/Chrome 89 — самые последние доступные версии.

1 лайк

@ljpp / @falco, вы всё ещё можете воспроизвести эту ошибку? Я попробовал множество вариантов вставки эмодзи, но не смог воспроизвести её ни разу. Если вы всё ещё можете воспроизвести, пожалуйста, поделитесь точными шагами. Спасибо!

1 лайк

Да, у меня всё ещё происходит сбой в Chrome на Android. Чтобы воспроизвести проблему, необходимо строго следовать инструкциям на 100%, так как условия очень специфичны.

1 лайк

Только что попробовал, но не смог легко воспроизвести это. Однако я вполне уверен, что видел это пару раз этим летом, случайно, когда печатал настоящий пост.

Редактирование: Я спрошу наше сообщество, смогут ли они предоставить более подробное покрытие тестами.

Редактирование 2: О да, я теперь сам воспроизвёл это. Наше сообщество сейчас тестирует, и похоже, что есть ещё несколько случаев воспроизведения обычными пользователями.

1 лайк

Случайно воспроизвел это снова, поэтому задача всё ещё открыта.

Это всё ещё есть в нашем списке, но нам невероятно сложно воспроизвести и отладить эту проблему.

Я не могу пометить это как pr-welcome, потому что это слишком сложно. Мы вернёмся к этому в будущем, установив таймер на 6 месяцев.

Проблема всё ещё сохраняется?

Да, сохраняется. Лично мне не удалось воспроизвести её за 15 минут интенсивных попыток, поэтому я обратился за помощью к нашему сообществу. Несколько пользователей смогли воспроизвести проблему, и один даже подтвердил это скриншотом. Симптомы остались прежними: как только вы нажимаете на эмодзи «большой палец вверх» в селекторе, клавиатура сворачивается, и часть введённого текста теряется в редакторе.

Раньше мне удавалось воспроизвести это очень легко, но теперь я не могу точно определить, как это сделать. Проблема существует, но воспроизводится не в 100% случаев. Мы продолжим экспериментировать и постараемся выяснить, какой именно шаг в интерфейсе вызывает это.

1 лайк

Можете попросить того, кто может воспроизвести проблему, проверить, получится ли у него сделать это на try.discourse.org?

Я только что воспроизвёл это, даже не пытаясь.

Firefox 94.1.1 (сборка #2015842491)

И Chrome 95.0.4638.74

2 лайка

Мне кажется, что настоящие баги здесь — это не родные селекторы эмодзи платформы. :wink: Тривиальное решение: используйте встроенный в вашу ОС выборщик эмодзи.

Конечно, обычно существует обходной путь. Однако не всегда: например, в Discourse могут использоваться пользовательские эмодзи.

В любом случае, перезагрузка страницы с потерей введённого текста — это некорректное поведение, которое нам следует исправить.

Хорошо, я ещё раз изучил эту проблему сегодня и смог воспроизвести её после переключения виртуальной клавиатуры на телефоне на Gboard. Gboard иногда дважды генерирует события keydown и keyup на одно нажатие клавиши, и если это происходит с последней нажатой клавишей перед выбором эмодзи из автодополнения, возникает сбой.

Я не уверен, что заставляет Gboard дважды генерировать эти события, но похоже, что это зависит от того, что вы набрали, и от настроек Gboard.

Двойные события вызывают сбой из-за архитектуры нашей библиотеки автодополнения. Библиотека слушает как события keydown, так и keyup: при keydown она очищает подсказки автодополнения, а при keyup предлагает новые подсказки на основе нового термина автодополнения.

Однако существует небольшая защита/оптимизация, предотвращающая выполнение библиотекой дублирующей работы, когда термин не изменился с момента предыдущих подсказок, и именно здесь возникает проблема. Первая пара событий keydown и keyup корректно очищает старые подсказки и предлагает новые, как и ожидалось, но вторая ошибочная пара снова очищает подсказки при keydown, но не предлагает новые при keyup, поскольку термин автодополнения не изменился.

Единственное наименее «костыльное» «исправление», которое я могу придумать, — это убрать защиту/оптимизацию, чтобы библиотека всегда предлагала новые подсказки при keyup, но я не уверен, что это необходимо или оправдано.

Я знаю, что мы планируем переписать нашу библиотеку автодополнения в будущем (это один из самых старых участков кода в кодовой базе и отчаянно нуждается в переписывании), так что, возможно, эту ошибку можно отложить до момента переписывания?

5 лайков

Является ли сбой своего рода «бесконечным циклом»? Можно ли просто отслеживать, что мы попали в петлю обратной связи, и очищать данные?

1 лайк

Нет, краш происходит из-за обращения к переменной, равной null. Когда подсказки очищаются, переменная autocompleteOptions устанавливается в null, а затем, когда вы нажимаете на одну из отрисованных подсказок, мы ожидаем, что autocompleteOptions будет массивом, но она равна null.

Это дает мне еще одну идею: возможно, мы могли бы проверять, равна ли autocompleteOptions null, когда выбирается подсказка, и если переменная равна null, то снова запрашивать подсказки для данного термина?

2 лайка

Да, это звучит как приемлемое временное решение.

2 лайка

Ах, чувствую себя глупо, что не сообщил об этой детали. На моём предыдущем телефоне была чистая версия Android One, где Gboard была клавиатурой по умолчанию, и она перенеслась на следующее устройство (Samsung A42 5G). Однако большинство Android-устройств, продаваемых сегодня, используют по умолчанию клавиатуру от стороннего разработчика.

Отлично видеть этот прогресс.

2 лайка

Я объединил исправление этой ошибки:

Исправление развёрнуто на Meta и на вашем сайте, @ljpp. Дайте знать, если ваши пользователи всё ещё смогут воспроизвести проблему.

5 лайков