@@ -15,20 +15,20 @@ const DBConsoleFragment = ({ }: DBConsolePropType) => {
1515
1616 const currentTab : Tab = useContext ( TabContext ) !
1717
18- const consoleEndRef = useRef < HTMLSpanElement > ( null )
18+ const consoleRef = useRef < HTMLDivElement > ( null )
19+ const consoleEndRef = useRef < HTMLDivElement > ( null )
1920
2021 const dbConnection = useAppSelector ( selectDBConnection )
2122 const output = useAppSelector ( selectBlocks )
2223 const [ input , setInput ] = useState ( "" )
2324 const [ nfocus , setFocus ] = useState < number > ( 0 )
24- const commands = output . filter ( e => e . cmd === true )
25- const [ pointer , setPointer ] = useState < number > ( commands . length - 1 )
25+ const history = output . filter ( e => e . cmd ) . filter ( e => e . text !== "" ) . map ( e => e . text )
2626 useEffect ( ( ) => {
2727 dispatch ( initConsole ( dbConnection ! . id ) )
2828 } , [ dbConnection ] )
2929
3030 useEffect ( ( ) => {
31- consoleEndRef . current ?. scrollIntoView ( { behavior : ' smooth' } )
31+ scrollToBottom ( " smooth" )
3232 } , [ output ] )
3333
3434 const confirmInput = ( ) => {
@@ -37,21 +37,27 @@ const DBConsoleFragment = ({ }: DBConsolePropType) => {
3737 }
3838
3939 const focus = ( e : any ) => {
40- if ( e . target . id === "console" ) {
40+ if ( consoleRef . current ?. contains ( e . target ) ) {
4141 setFocus ( Math . random ( ) )
4242 }
4343 }
4444
45- return < div className = { styles . console + " " + ( currentTab . isActive ? "db-tab-active" : "db-tab" ) } id = "console" onClick = { focus } >
45+ const scrollToBottom = ( behavior : ScrollBehavior ) => {
46+ const mainContentDiv = consoleRef . current ?. parentNode as HTMLDivElement
47+ if ( mainContentDiv . scrollTop !== consoleEndRef . current ?. offsetTop )
48+ mainContentDiv . scrollTo ( { top : consoleEndRef . current ?. offsetTop , behavior } )
49+ }
50+
51+ return < div className = { styles . console + " " + ( currentTab . isActive ? "db-tab-active" : "db-tab" ) } id = "console" ref = { consoleRef } onClick = { focus } >
4652 < OutputBlock block = { {
4753 text : "Start typing command and press enter to run it.\nType 'help' for more info on console." ,
4854 cmd : false
4955 } } />
5056 { output . map ( ( block , idx ) => {
5157 return < OutputBlock block = { block } key = { idx } />
5258 } ) }
53- < PromptInputWithRef onChange = { setInput } isActive = { currentTab . isActive } nfocus = { nfocus } confirmInput = { confirmInput } commands = { commands } pointer = { pointer } setPointer = { setPointer } />
54- < span ref = { consoleEndRef } > </ span >
59+ < PromptInputWithRef onChange = { setInput } isActive = { currentTab . isActive } nfocus = { nfocus } scrollToBottom = { scrollToBottom } confirmInput = { confirmInput } history = { history } />
60+ < div id = "consoleend" className = { styles . consoleend } ref = { consoleEndRef } > </ div >
5561 </ div >
5662}
5763
@@ -66,8 +72,10 @@ const OutputBlock = ({ block }: any) => {
6672const PromptInputWithRef = ( props : any ) => {
6773 const defaultValue = useRef ( "" )
6874 const inputRef = useRef < HTMLParagraphElement > ( null )
75+ const [ pointer , setPointer ] = useState < number > ( - 1 )
6976 useEffect ( ( ) => {
7077 if ( props . isActive ) {
78+ props . scrollToBottom ( "instant" )
7179 inputRef . current ?. focus ( )
7280 }
7381 } , [ props . isActive , props . nfocus ] )
@@ -78,8 +86,8 @@ const PromptInputWithRef = (props: any) => {
7886 }
7987 }
8088
81- const setInputRef = ( cmd : string ) => {
82- if ( inputRef . current !== null ) {
89+ const setInputRef = ( cmd : string ) => {
90+ if ( inputRef . current !== null ) {
8391 inputRef . current . textContent = cmd ;
8492 }
8593 }
@@ -89,14 +97,30 @@ const PromptInputWithRef = (props: any) => {
8997 if ( inputRef . current ) {
9098 inputRef . current . innerText = ""
9199 }
100+ setPointer ( - 1 )
101+ }
102+ const updateInputFromPointer = ( newPointer : number ) => {
103+ let text = props . history . at ( props . history . length - 1 - newPointer )
104+ if ( ! text ) {
105+ text = ""
106+ }
107+ setInputRef ( text )
92108 }
93- if ( event . key . toLocaleLowerCase ( ) === 'arrowup' ) {
94- props . setPointer ( ( ) => ( ( props . pointer + props . commands . length - 1 ) % props . commands . length ) )
95- setInputRef ( props . commands . at ( props . pointer ) ?. text )
109+ if ( event . key . toLocaleLowerCase ( ) === 'arrowup' ) {
110+ if ( pointer !== props . history . length - 1 ) {
111+ setPointer ( ( ) => ( pointer + 1 ) )
112+ updateInputFromPointer ( pointer + 1 )
113+ }
96114 }
97- if ( event . key . toLocaleLowerCase ( ) === 'arrowdown' ) {
98- props . setPointer ( ( ) => ( ( props . pointer + 1 ) % props . commands . length ) )
99- setInputRef ( props . commands . at ( props . pointer ) ?. text )
115+ if ( event . key . toLocaleLowerCase ( ) === 'arrowdown' ) {
116+ let newPointer
117+ if ( pointer < 0 ) {
118+ newPointer = - 1
119+ } else {
120+ newPointer = pointer - 1
121+ }
122+ setPointer ( newPointer )
123+ updateInputFromPointer ( newPointer )
100124 }
101125 }
102126
0 commit comments