Прокрутите к началу пузыря в веб-чате. - PullRequest
4 голосов
/ 03 апреля 2020

Некоторые ответы нашего чат-бота очень длинные. Веб-чат автоматически прокручивается вниз, поэтому пользователям нужно прокрутить вверх, чтобы добраться до вершины пузыря и начать чтение.

Я реализовал пользовательское средство визуализации (реакции), чтобы обернуть ответы в пользовательский компонент, который просто оборачивает ответ в тег div. Я также реализовал простой кусок кода для прокрутки к вершине пузыря.

const MyCustomActivityContainer = ({ children }) => {
    const triggerScrollTo = () => {
        if (scrollRef && scrollRef.current) {
            (scrollRef.current as any).scrollIntoView({
                behavior: 'smooth',
                block: 'start',
            })
        }
    }

    const scrollRef: React.RefObject<HTMLDivElement> = React.createRef()

    return (
        <div ref={ scrollRef } onClick={ triggerScrollTo }>
            { children }
        </div>
    )
}

export const activityMiddleware = () => next => card => {
    if (/* some conditions */) {
        return (
            <MyCustomActivityContainer>
                { next(card) }
            </MyCustomActivityContainer>
        );
    } else {
        return (
            { next(card) }
        )
    }
};

Но это работает только в том случае, если ползунок полосы прокрутки не находится в самом нижнем положении (для прокрутки вниз осталось не менее 1 пикселя, см. Здесь ). Проблема заключается в перехватчике useScrollToBottom, который всегда прокручивается вниз, если полоса прокрутки полностью прокручивается вниз.

Есть ли способ переписать поведение прокрутки или временно отключить функцию scrollToBottom?

Ответы [ 2 ]

1 голос
/ 07 мая 2020

Поскольку нет воспроизводимого примера, я могу только догадываться.
И мне придется также сделать некоторые догадки по этому вопросу.
Поскольку неясно, что именно не работает:

  1. Вы имеете в виду, что нажатие <div> из MyCustomActivityContainer и последующий вызов triggerScrollTo не приводит к прокрутке? Это было бы странно, но кто знает. В этом случае я сомневаюсь, что кто-нибудь поможет вам без воспроизводимого примера.
  2. Или вы имеете в виду, что вы можете прокручивать сообщение в поле зрения, но если оно уже отображается, тогда новые сообщения могут привести к прокручивайте, пока пользователь все еще читает сообщение.
    Это так, но это противоречит вашему заявлению, что ваши сообщения очень длинные, потому что это может быть проблемой с короткими сообщениями, а не с длинными.

    Но в любом случае, вы должны это исправить.
    Если он работает нормально, когда 1 пиксель находится в нижней позиции, просто прокрутите этот 1 пиксель. Вам нужно будет найти прокручиваемый элемент. И сделать scrollable_element.scrollTop -= 1. Я протестировал этот подход здесь . И это сработало (там прокручиваемый элемент является прародителем <p>)

  3. Или вы пытаетесь прокручивать автоматически в момент поступления сообщения? И это реальная проблема, но вы забыли упомянуть об этом и не опубликовали код, который пытается выполнить автоматическую прокрутку?

    В этом случае вы можете попробовать использовать setTimeout() и отложить прокрутку на скажем, 200ms. Это число основано на том, что я собрал из источника:

    1. BotFramework-WebChat использует response-scroll-to-bottom
    2. В реагирует на прокрутку вниз есть некоторые таймауты 100ms и 34ms
    3. BotFramework-WebChat не переопределяет их
    4. В реакция-прокрутка-вниз есть некоторые эвристики, которые, вероятно, преследуют проблему https://github.com/compulim/react-scroll-to-bottom/blob/3eb21bc469ee5f5095a431ac584be29a0d2da950/packages/component/src/ScrollToBottom/Composer.js

      В настоящее время не существует надежного способа проверить, является ли событие «прокрутка» инициируемым из-за жеста пользователя, программной прокрутки c или Chrome -синтезированной прокрутки для компенсации изменения размера. Таким образом, мы делаем все возможное, чтобы угадать, вызвано ли это жестом пользователя, и отключить закрепление, если оно движется в направлении начала.

      И
      https://github.com/compulim/react-scroll-to-bottom/blob/f19b14d6db63dcb07ffa45b4433e72284a9d53b6/packages/component/src/ScrollToBottom/Composer.js#L91

      За то, что мы наблюдали, # 1 срабатывает примерно за 20 мс до # 2. Существует вероятность того, что этот stickyCheckTimeout запланирован между 1 и 2. Это означает, что если мы просто посмотрим на # 1, чтобы решить, следует ли нам прокручивать, мы всегда будем прокручивать, в противоположность намерению пользователя.

      Вот почему я думаю, что вы должны использовать setTimeout()

0 голосов
/ 08 мая 2020

Так как для меня нет воспроизводимого кода, настройте его и покажите вам. Мое предложение немного подправить ваш код. Chatbot требует постоянной потоковой передачи данных при поступлении нового сообщения, чтобы вычислить высоту элемента div, созданного для сообщения. Если элемент div больше, чем высота виджета, прокрутите вверх, иначе вы можете оставить все как есть.

...