Merge pull request #876 from ManishMadan2882/main

Pause Auto-scroll on user interrupt
This commit is contained in:
Alex
2024-03-14 11:33:07 +00:00
committed by GitHub
9 changed files with 170 additions and 525 deletions

View File

@@ -5,7 +5,7 @@ import About from './About';
import PageNotFound from './PageNotFound';
import { inject } from '@vercel/analytics';
import { useMediaQuery } from './hooks';
import { useState,useEffect } from 'react';
import { useState} from 'react';
import Setting from './Setting';
inject();
@@ -32,4 +32,4 @@ export default function App() {
</div>
</div>
);
}
}

View File

@@ -6,14 +6,15 @@ export default function Hero({ className = '' }: { className?: string }) {
const { isMobile } = useMediaQuery();
const [isDarkTheme] = useDarkTheme()
return (
<div className={`mt-14 ${isMobile ? 'mb-2' : 'mb-12'}flex flex-col text-black-1000 dark:text-bright-gray`}>
<div className={`mt-14 ${isMobile ? 'mb-2' : 'mb-12'} flex flex-col text-black-1000 dark:text-bright-gray`}>
<div className=" mb-2 flex items-center justify-center sm:mb-10">
<p className="mr-2 text-4xl font-semibold">DocsGPT</p>
<img className="mb-2 h-14" src={DocsGPT3} alt="DocsGPT" />
</div>
{isMobile ? (
<p className="mb-3 text-center leading-6">
Welcome to <span className="font-bold ">DocsGPT</span>, your technical
Welcome to <span className="font-bold">DocsGPT</span>, your technical
documentation assistant! Start by entering your query in the input
field below, and we&apos;ll provide you with the most relevant
answers.

View File

@@ -1,12 +1,12 @@
import { useEffect, useRef, useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { NavLink, useNavigate } from 'react-router-dom';
import PropTypes from 'prop-types';
import DocsGPT3 from './assets/cute_docsgpt3.svg';
import Documentation from './assets/documentation.svg';
import DocumentationDark from './assets/documentation-dark.svg';
import Discord from './assets/discord.svg';
import DiscordDark from './assets/discord-dark.svg';
import Expand from './assets/expand.svg';
import Github from './assets/github.svg';
import GithubDark from './assets/github-dark.svg';
@@ -46,10 +46,10 @@ interface NavigationProps {
navOpen: boolean;
setNavOpen: React.Dispatch<React.SetStateAction<boolean>>;
}
const NavImage: React.FC<{ Light: string; Dark: string }> = ({
Light,
Dark,
}) => {
const NavImage: React.FC<{
Light: string | undefined;
Dark: string | undefined;
}> = ({ Light, Dark }) => {
return (
<>
<img src={Dark} alt="icon" className="ml-2 hidden w-5 dark:block " />
@@ -57,6 +57,10 @@ const NavImage: React.FC<{ Light: string; Dark: string }> = ({
</>
);
};
NavImage.propTypes = {
Light: PropTypes.string,
Dark: PropTypes.string,
};
export default function Navigation({ navOpen, setNavOpen }: NavigationProps) {
const dispatch = useDispatch();
const docs = useSelector(selectSourceDocs);

View File

@@ -4,7 +4,7 @@ import { useDarkTheme } from '../hooks';
import Hero from '../Hero';
import { AppDispatch } from '../store';
import ConversationBubble from './ConversationBubble';
import conversationSlice, {
import {
addQuery,
fetchAnswer,
selectQueries,
@@ -17,19 +17,23 @@ import Spinner from './../assets/spinner.svg';
import { FEEDBACK, Query } from './conversationModels';
import { sendFeedback } from './conversationApi';
import ArrowDown from './../assets/arrow-down.svg';
import { selectConversationId } from '../preferences/preferenceSlice';
export default function Conversation() {
const queries = useSelector(selectQueries);
const status = useSelector(selectStatus);
const conversationId = useSelector(selectConversationId)
const dispatch = useDispatch<AppDispatch>();
const endMessageRef = useRef<HTMLDivElement>(null);
const inputRef = useRef<HTMLDivElement>(null);
const [isDarkTheme] = useDarkTheme();
const [hasScrolledToLast, setHasScrolledToLast] = useState(true);
const fetchStream = useRef<any>(null)
const fetchStream = useRef<any>(null);
const [eventInterrupt, setEventInterrupt] = useState(false);
const handleUserInterruption = () => {
if (!eventInterrupt && status === "loading")
setEventInterrupt(true)
}
useEffect(() => {
scrollIntoView();
!eventInterrupt && scrollIntoView();
}, [queries.length, queries[queries.length - 1]]);
useEffect(() => {
@@ -46,6 +50,7 @@ export default function Conversation() {
}
}
}, [status])
useEffect(() => {
const observerCallback: IntersectionObserverCallback = (entries) => {
entries.forEach((entry) => {
@@ -71,14 +76,14 @@ export default function Conversation() {
behavior: 'smooth',
block: 'start',
});
};
}
const handleQuestion = (question: string) => {
question = question.trim();
if (question === '') return;
setEventInterrupt(false)
dispatch(addQuery({ prompt: question }));
fetchStream.current = dispatch(fetchAnswer({ question }));
};
const handleFeedback = (query: Query, feedback: FEEDBACK, index: number) => {
const prevFeedback = query.feedback;
@@ -126,7 +131,10 @@ export default function Conversation() {
};
return (
<div className="flex flex-col justify-center p-4 md:flex-row">
<div
onWheel={handleUserInterruption}
onTouchMove={handleUserInterruption}
className="flex flex-col justify-center w-full p-4 md:flex-row">
{queries.length > 0 && !hasScrolledToLast && (
<button
onClick={scrollIntoView}
@@ -142,7 +150,7 @@ export default function Conversation() {
)}
{queries.length > 0 && (
<div className="mt-20 mb-9 flex flex-col transition-all md:w-3/4">
<div className="mt-20 mb-9 flex flex-col transition-all md:w-3/4">
{queries.map((query, index) => {
return (
<Fragment key={index}>
@@ -160,7 +168,7 @@ export default function Conversation() {
</div>
)}
{queries.length === 0 && (
<Hero className="mt-24 h-[100vh] md:mt-52"></Hero>
<Hero className="mt-24 md:mt-52"></Hero>
)}
<div className="absolute bottom-0 flex w-11/12 md:w-[65%] flex-col items-end self-center bg-white dark:bg-raisin-black pt-4 md:fixed">
<div className="flex h-full w-full">