diff options
Diffstat (limited to 'src/console/components/Console.tsx')
-rw-r--r-- | src/console/components/Console.tsx | 288 |
1 files changed, 38 insertions, 250 deletions
diff --git a/src/console/components/Console.tsx b/src/console/components/Console.tsx index 18a6632..db18fa0 100644 --- a/src/console/components/Console.tsx +++ b/src/console/components/Console.tsx @@ -1,251 +1,39 @@ -import { connect } from "react-redux"; import React from "react"; -import Input from "./console/Input"; -import Completion from "./console/Completion"; -import Message from "./console/Message"; -import * as consoleActions from "../../console/actions/console"; -import { State as AppState } from "../reducers"; -import CommandLineParser, { - InputPhase, -} from "../commandline/CommandLineParser"; -import { Command } from "../../shared/Command"; -import ColorScheme from "../../shared/ColorScheme"; -import { LightTheme, DarkTheme } from "./Theme"; -import styled from "./Theme"; -import { ThemeProvider } from "styled-components"; -import ConsoleFrameClient from "../clients/ConsoleFrameClient"; - -const ConsoleWrapper = styled.div` - border-top: 1px solid gray; -`; - -const COMPLETION_MAX_ITEMS = 33; - -type StateProps = ReturnType<typeof mapStateToProps>; -interface DispatchProps { - dispatch: (action: any) => void; -} -type Props = StateProps & DispatchProps; - -class Console extends React.Component<Props> { - private input: React.RefObject<Input>; - - private commandLineParser: CommandLineParser = new CommandLineParser(); - private consoleFrameClient = new ConsoleFrameClient(); - - constructor(props: Props) { - super(props); - - this.input = React.createRef(); - } - - onBlur() { - if (this.props.mode === "command" || this.props.mode === "find") { - return this.props.dispatch(consoleActions.hideCommand()); - } - } - - doEnter(e: React.KeyboardEvent<HTMLInputElement>) { - e.stopPropagation(); - e.preventDefault(); - - const value = (e.target as HTMLInputElement).value; - if (this.props.mode === "command") { - return this.props.dispatch(consoleActions.enterCommand(value)); - } else if (this.props.mode === "find") { - return this.props.dispatch( - consoleActions.enterFind(value === "" ? undefined : value) - ); - } - } - - selectNext(e: React.KeyboardEvent<HTMLInputElement>) { - this.props.dispatch(consoleActions.completionNext()); - e.stopPropagation(); - e.preventDefault(); - } - - selectPrev(e: React.KeyboardEvent<HTMLInputElement>) { - this.props.dispatch(consoleActions.completionPrev()); - e.stopPropagation(); - e.preventDefault(); - } - - onKeyDown(e: React.KeyboardEvent<HTMLInputElement>) { - switch (e.key) { - case "Escape": - return this.props.dispatch(consoleActions.hideCommand()); - case "Enter": - return this.doEnter(e); - case "Tab": - if (e.shiftKey) { - this.props.dispatch(consoleActions.completionPrev()); - } else { - this.props.dispatch(consoleActions.completionNext()); - } - e.stopPropagation(); - e.preventDefault(); - break; - case "[": - if (e.ctrlKey) { - e.preventDefault(); - return this.props.dispatch(consoleActions.hideCommand()); - } - break; - case "c": - if (e.ctrlKey) { - e.preventDefault(); - return this.props.dispatch(consoleActions.hideCommand()); - } - break; - case "m": - if (e.ctrlKey) { - return this.doEnter(e); - } - break; - case "n": - if (e.ctrlKey) { - this.selectNext(e); - } - break; - case "p": - if (e.ctrlKey) { - this.selectPrev(e); - } - break; - } - } - - onChange(e: React.ChangeEvent<HTMLInputElement>) { - const text = e.target.value; - this.props.dispatch(consoleActions.setConsoleText(text)); - if (this.props.mode !== "command") { - return; - } - this.updateCompletions(text); - } - - componentDidUpdate(prevProps: Props) { - if (prevProps.mode !== "command" && this.props.mode === "command") { - this.updateCompletions(this.props.consoleText); - this.focus(); - } else if (prevProps.mode !== "find" && this.props.mode === "find") { - this.focus(); - } - - const { - scrollWidth: width, - scrollHeight: height, - } = document.getElementById("vimvixen-console")!; - this.consoleFrameClient.resize(width, height); - } - - render() { - let theme = this.props.colorscheme; - if (this.props.colorscheme === ColorScheme.System) { - if ( - window.matchMedia && - window.matchMedia("(prefers-color-scheme: dark)").matches - ) { - theme = ColorScheme.Dark; - } else { - theme = ColorScheme.Light; - } - } - - switch (this.props.mode) { - case "command": - case "find": - return ( - <ThemeProvider - theme={theme === ColorScheme.Dark ? DarkTheme : LightTheme} - > - <ConsoleWrapper> - <Completion - size={COMPLETION_MAX_ITEMS} - completions={this.props.completions} - select={this.props.select} - /> - <Input - ref={this.input} - mode={this.props.mode} - onBlur={this.onBlur.bind(this)} - onKeyDown={this.onKeyDown.bind(this)} - onChange={this.onChange.bind(this)} - value={this.props.consoleText} - /> - </ConsoleWrapper> - </ThemeProvider> - ); - case "info": - case "error": - return ( - <ThemeProvider - theme={theme === ColorScheme.Dark ? DarkTheme : LightTheme} - > - <Message mode={this.props.mode}>{this.props.messageText}</Message> - </ThemeProvider> - ); - default: - return null; - } - } - - async focus() { - this.props.dispatch(consoleActions.setColorScheme()); - - window.focus(); - if (this.input.current) { - this.input.current.focus(); - } - } - - private updateCompletions(text: string) { - const phase = this.commandLineParser.inputPhase(text); - if (phase === InputPhase.OnCommand) { - return this.props.dispatch(consoleActions.getCommandCompletions(text)); - } else { - const cmd = this.commandLineParser.parse(text); - switch (cmd.command) { - case Command.Open: - case Command.TabOpen: - case Command.WindowOpen: - this.props.dispatch( - consoleActions.getOpenCompletions( - this.props.completionTypes, - text, - cmd.command, - cmd.args - ) - ); - break; - case Command.Buffer: - this.props.dispatch( - consoleActions.getTabCompletions(text, cmd.command, cmd.args, false) - ); - break; - case Command.BufferDelete: - case Command.BuffersDelete: - this.props.dispatch( - consoleActions.getTabCompletions(text, cmd.command, cmd.args, true) - ); - break; - case Command.BufferDeleteForce: - case Command.BuffersDeleteForce: - this.props.dispatch( - consoleActions.getTabCompletions(text, cmd.command, cmd.args, false) - ); - break; - case Command.Set: - this.props.dispatch( - consoleActions.getPropertyCompletions(text, cmd.command, cmd.args) - ); - break; - } - } - } -} - -const mapStateToProps = (state: AppState) => ({ ...state }); - -export default connect(mapStateToProps)(Console); +import FindPrompt from "./FindPrompt"; +import CommandPrompt from "./CommandPrompt"; +import InfoMessage from "./InfoMessage"; +import ErrorMessage from "./ErrorMessage"; +import { useColorSchemeRefresh } from "../colorscheme/hooks"; +import { + useCommandMode, + useErrorMessage, + useFindMode, + useInfoMessage, +} from "../app/hooks"; + +const Console: React.FC = () => { + const refreshColorScheme = useColorSchemeRefresh(); + const { visible: visibleCommand, initialInputValue } = useCommandMode(); + const { visible: visibleFind } = useFindMode(); + const { visible: visibleInfo, message: infoMessage } = useInfoMessage(); + const { visible: visibleError, message: errorMessage } = useErrorMessage(); + + React.useEffect(() => { + if (visibleCommand || visibleFind || visibleInfo || visibleError) { + refreshColorScheme(); + } + }, [visibleCommand, visibleFind, visibleInfo, visibleError]); + + if (visibleCommand) { + return <CommandPrompt initialInputValue={initialInputValue} />; + } else if (visibleFind) { + return <FindPrompt />; + } else if (visibleInfo) { + return <InfoMessage>{infoMessage}</InfoMessage>; + } else if (visibleError) { + return <ErrorMessage>{errorMessage}</ErrorMessage>; + } + return null; +}; + +export default Console; |