improve chat scrolling #82
This commit is contained in:
@@ -241,7 +241,6 @@ export function Hints({ hints, conclusion, counter=undefined } : {
|
||||
export function ChatPanel ({visible = true}) {
|
||||
|
||||
let { t } = useTranslation()
|
||||
const chatRef = useRef<HTMLDivElement>(null)
|
||||
|
||||
const { mobile } = useContext(PreferencesContext)
|
||||
const { gameId, worldId, levelId } = useContext(GameIdContext)
|
||||
@@ -255,7 +254,7 @@ export function ChatPanel ({visible = true}) {
|
||||
|
||||
const [introText, setIntroText] = useState<Array<GameHintWithStep>>([])
|
||||
const [chatMessages, setChatMessages] = useState<Array<GameHintWithStep>>([])
|
||||
const { deletedChat, showHelp, selectedStep } = useContext(ChatContext)
|
||||
const { chatRef, deletedChat, showHelp, selectedStep } = useContext(ChatContext)
|
||||
const { proof } = useContext(ProofContext)
|
||||
|
||||
const readIntro = useSelector(selectReadIntro(gameId, worldId))
|
||||
@@ -316,26 +315,32 @@ export function ChatPanel ({visible = true}) {
|
||||
setChatMessages(messages)
|
||||
}, [gameInfo, levelInfo, gameId, worldId, levelId, proof])
|
||||
|
||||
// Scroll to the top when loading a new page
|
||||
// Scroll the chat
|
||||
useEffect(() => {
|
||||
console.debug(`scroll chat: top`)
|
||||
chatRef.current!.scrollTo(0,0)
|
||||
}, [completed, gameId, worldId, levelId])
|
||||
if (levelId > 0) {
|
||||
|
||||
// Scroll to first message of the last step.
|
||||
// If the proof is currently completed, scroll to the conclusion
|
||||
useEffect(() => {
|
||||
if (levelId > 0 && proof) {
|
||||
if (proof?.completed) {
|
||||
console.debug('scroll chat: down to conclusion')
|
||||
chatRef.current!.lastElementChild?.scrollIntoView({block: "center"})
|
||||
if (proof) {
|
||||
if (proof?.completed) {
|
||||
// proof currently completed: scroll down
|
||||
console.debug('scroll chat: down to conclusion')
|
||||
chatRef.current!.lastElementChild?.scrollIntoView({block: "center"})
|
||||
} else {
|
||||
// proof currently not completed: first message of last step
|
||||
let lastStep = proof?.steps.length - (lastStepHasErrors(proof) ? 2 : 1)
|
||||
console.debug(`scroll chat: first message of step ${lastStep}`)
|
||||
chatRef.current?.getElementsByClassName(`step-${lastStep}`)[0]?.scrollIntoView({block: "center"})
|
||||
}
|
||||
} else {
|
||||
let lastStep = proof?.steps.length - (lastStepHasErrors(proof) ? 2 : 1)
|
||||
console.debug(`scroll chat: first message of step ${lastStep}`)
|
||||
chatRef.current?.getElementsByClassName(`step-${lastStep}`)[0]?.scrollIntoView({block: "center"})
|
||||
// no proof available: scroll to top.
|
||||
console.debug(`scroll chat: top`)
|
||||
chatRef.current!.scrollTo(0,0)
|
||||
}
|
||||
} else {
|
||||
// introduction: scroll to last message
|
||||
console.debug('scroll chat: down')
|
||||
chatRef.current!.lastElementChild?.scrollIntoView({block: "center"})
|
||||
}
|
||||
}, [chatMessages, gameId, worldId, levelId])
|
||||
}, [counter, introText, chatMessages, gameId, worldId, levelId])
|
||||
|
||||
// Scroll down when new hidden hints are triggered
|
||||
useEffect(() => {
|
||||
@@ -343,6 +348,7 @@ export function ChatPanel ({visible = true}) {
|
||||
let lastStep = proof?.steps.length - (lastStepHasErrors(proof) ? 2 : 1)
|
||||
if (showHelp.has(lastStep)) {
|
||||
console.debug('scroll chat: down to hidden hints')
|
||||
// TODO: last element of hidden hints?
|
||||
chatRef.current!.lastElementChild?.scrollIntoView({block: "center"})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,6 +54,7 @@ function Game() {
|
||||
|
||||
// const [pageNumber, setPageNumber] = React.useState(readIntro ? 1 : 0)
|
||||
|
||||
const chatRef = useRef<HTMLDivElement>(null)
|
||||
// When deleting the proof, we want to keep to old messages around until
|
||||
// a new proof has been entered. e.g. to consult messages coming from dead ends
|
||||
const [deletedChat, setDeletedChat] = useState<Array<GameHint>>([])
|
||||
@@ -93,7 +94,7 @@ function Game() {
|
||||
setShowHelp(new Set())
|
||||
}, [gameId, worldId, levelId])
|
||||
|
||||
return <ChatContext.Provider value={{selectedStep, setSelectedStep, deletedChat, setDeletedChat, showHelp, setShowHelp}}>
|
||||
return <ChatContext.Provider value={{selectedStep, setSelectedStep, deletedChat, setDeletedChat, showHelp, setShowHelp, chatRef}}>
|
||||
<ProofContext.Provider value={{proof, setProof, interimDiags, setInterimDiags, crashed: isCrashed, setCrashed: setIsCrashed}}>
|
||||
{ mobile ?
|
||||
<div className="app-content mobile">
|
||||
|
||||
@@ -95,19 +95,21 @@ export const PreferencesContext = React.createContext<IPreferencesContext>({
|
||||
|
||||
|
||||
export const ChatContext = React.createContext<{
|
||||
selectedStep : number,
|
||||
selectedStep : number
|
||||
setSelectedStep: React.Dispatch<React.SetStateAction<number>>
|
||||
deletedChat : GameHint[],
|
||||
deletedChat : GameHint[]
|
||||
setDeletedChat: React.Dispatch<React.SetStateAction<Array<GameHint>>>
|
||||
showHelp : Set<number>,
|
||||
showHelp : Set<number>
|
||||
setShowHelp: React.Dispatch<React.SetStateAction<Set<number>>>
|
||||
chatRef: React.MutableRefObject<HTMLDivElement>
|
||||
}>({
|
||||
selectedStep : undefined,
|
||||
setSelectedStep: () => {},
|
||||
deletedChat: undefined,
|
||||
setDeletedChat: () => {},
|
||||
showHelp: undefined,
|
||||
setShowHelp: () => {}
|
||||
setShowHelp: () => {},
|
||||
chatRef: null
|
||||
})
|
||||
|
||||
export const PageContext = React.createContext<{
|
||||
|
||||
Reference in New Issue
Block a user