aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShin'ya Ueoka <ueokande@i-beam.org>2022-05-05 07:01:55 +0000
committerShin'ya Ueoka <ueokande@i-beam.org>2022-05-05 07:27:44 +0000
commit0d17912972de6b9e8b08aedf141260413c60d7fd (patch)
treef0a56bfea9204dd3067c43e2667e3d70e581d183
parentbc890c55bfbd6d1aa4ece5b0ef96a9ab6d358ad7 (diff)
Use useDebounce
-rw-r--r--src/console/completion/hooks.ts135
-rw-r--r--src/console/components/CommandPrompt.tsx6
-rw-r--r--src/console/hooks/useDebounce.ts19
3 files changed, 71 insertions, 89 deletions
diff --git a/src/console/completion/hooks.ts b/src/console/completion/hooks.ts
index 62baab4..3a2ec33 100644
--- a/src/console/completion/hooks.ts
+++ b/src/console/completion/hooks.ts
@@ -36,41 +36,6 @@ const propertyDocs: { [key: string]: string } = {
const completionClient = new CompletionClient();
-const useDelayedCallback = <T extends unknown, U extends unknown>(
- callback: (arg1: T, arg2: U) => void,
- timeout: number
-) => {
- const [timer, setTimer] = React.useState<
- ReturnType<typeof setTimeout> | undefined
- >();
- const [enabled, setEnabled] = React.useState(false);
-
- const enableDelay = React.useCallback(() => {
- setEnabled(true);
- }, [setEnabled]);
-
- const delayedCallback = React.useCallback(
- (arg1: T, arg2: U) => {
- if (enabled) {
- if (typeof timer !== "undefined") {
- clearTimeout(timer);
- }
- const id = setTimeout(() => {
- callback(arg1, arg2);
- clearTimeout(timer!);
- setTimer(undefined);
- }, timeout);
- setTimer(id);
- } else {
- callback(arg1, arg2);
- }
- },
- [enabled, timer]
- );
-
- return { enableDelay, delayedCallback };
-};
-
const getCommandCompletions = async (query: string): Promise<Completions> => {
const items = Object.entries(commandDocs)
.filter(([name]) => name.startsWith(query))
@@ -215,60 +180,56 @@ export const useCompletions = () => {
dispatch(actions.setCompletionSource(source));
}, []);
- const { delayedCallback: queryCompletions, enableDelay } = useDelayedCallback(
- React.useCallback(
- (text: string, completionTypes: CompletionType[]) => {
- const phase = commandLineParser.inputPhase(text);
- if (phase === InputPhase.OnCommand) {
- getCommandCompletions(text).then((completions) =>
- dispatch(actions.setCompletions(completions))
- );
- } else {
- let cmd: CommandLine | null = null;
- try {
- cmd = commandLineParser.parse(text);
- } catch (e) {
- if (e instanceof UnknownCommandError) {
- return;
- }
- }
- switch (cmd?.command) {
- case Command.Open:
- case Command.TabOpen:
- case Command.WindowOpen:
- getOpenCompletions(cmd.command, cmd.args, completionTypes).then(
- (completions) => dispatch(actions.setCompletions(completions))
- );
- break;
- case Command.Buffer:
- getTabCompletions(cmd.command, cmd.args, false).then(
- (completions) => dispatch(actions.setCompletions(completions))
- );
- break;
- case Command.BufferDelete:
- case Command.BuffersDelete:
- getTabCompletions(cmd.command, cmd.args, true).then(
- (completions) => dispatch(actions.setCompletions(completions))
- );
- break;
- case Command.BufferDeleteForce:
- case Command.BuffersDeleteForce:
- getTabCompletions(cmd.command, cmd.args, false).then(
- (completions) => dispatch(actions.setCompletions(completions))
- );
- break;
- case Command.Set:
- getPropertyCompletions(cmd.command, cmd.args).then(
- (completions) => dispatch(actions.setCompletions(completions))
- );
- break;
+ const queryCompletions = React.useCallback(
+ (text: string, completionTypes: CompletionType[]) => {
+ const phase = commandLineParser.inputPhase(text);
+ if (phase === InputPhase.OnCommand) {
+ getCommandCompletions(text).then((completions) =>
+ dispatch(actions.setCompletions(completions))
+ );
+ } else {
+ let cmd: CommandLine | null = null;
+ try {
+ cmd = commandLineParser.parse(text);
+ } catch (e) {
+ if (e instanceof UnknownCommandError) {
+ return;
}
- enableDelay();
}
- },
- [dispatch]
- ),
- 100
+ switch (cmd?.command) {
+ case Command.Open:
+ case Command.TabOpen:
+ case Command.WindowOpen:
+ getOpenCompletions(cmd.command, cmd.args, completionTypes).then(
+ (completions) => dispatch(actions.setCompletions(completions))
+ );
+ break;
+ case Command.Buffer:
+ getTabCompletions(cmd.command, cmd.args, false).then(
+ (completions) => dispatch(actions.setCompletions(completions))
+ );
+ break;
+ case Command.BufferDelete:
+ case Command.BuffersDelete:
+ getTabCompletions(cmd.command, cmd.args, true).then((completions) =>
+ dispatch(actions.setCompletions(completions))
+ );
+ break;
+ case Command.BufferDeleteForce:
+ case Command.BuffersDeleteForce:
+ getTabCompletions(cmd.command, cmd.args, false).then(
+ (completions) => dispatch(actions.setCompletions(completions))
+ );
+ break;
+ case Command.Set:
+ getPropertyCompletions(cmd.command, cmd.args).then((completions) =>
+ dispatch(actions.setCompletions(completions))
+ );
+ break;
+ }
+ }
+ },
+ [dispatch]
);
React.useEffect(() => {
diff --git a/src/console/components/CommandPrompt.tsx b/src/console/components/CommandPrompt.tsx
index 0e2506c..0312fe4 100644
--- a/src/console/components/CommandPrompt.tsx
+++ b/src/console/components/CommandPrompt.tsx
@@ -3,6 +3,7 @@ import Completion from "./console/Completion";
import Input from "./console//Input";
import styled from "styled-components";
import { useCompletions, useSelectCompletion } from "../completion/hooks";
+import useDebounce from "../hooks/useDebounce";
import useAutoResize from "../hooks/useAutoResize";
import { CompletionProvider } from "../completion/provider";
import { useExecCommand, useHide } from "../app/hooks";
@@ -20,6 +21,7 @@ interface Props {
const CommandPromptInner: React.FC<Props> = ({ initialInputValue }) => {
const hide = useHide();
const [inputValue, setInputValue] = React.useState(initialInputValue);
+ const debouncedValue = useDebounce(inputValue, 100);
const { completions, updateCompletions } = useCompletions();
const { select, currentValue, selectNext, selectPrev } =
useSelectCompletion();
@@ -82,8 +84,8 @@ const CommandPromptInner: React.FC<Props> = ({ initialInputValue }) => {
};
React.useEffect(() => {
- updateCompletions(inputValue);
- }, [inputValue]);
+ updateCompletions(debouncedValue);
+ }, [debouncedValue]);
return (
<ConsoleWrapper>
diff --git a/src/console/hooks/useDebounce.ts b/src/console/hooks/useDebounce.ts
new file mode 100644
index 0000000..838ff34
--- /dev/null
+++ b/src/console/hooks/useDebounce.ts
@@ -0,0 +1,19 @@
+import React from "react";
+
+const useDebounce = <T extends unknown>(value: T, delay: number) => {
+ const [debouncedValue, setDebouncedValue] = React.useState(value);
+
+ React.useEffect(() => {
+ const timer = setTimeout(() => {
+ setDebouncedValue(value);
+ }, delay);
+
+ return () => {
+ clearTimeout(timer);
+ };
+ }, [value, delay]);
+
+ return debouncedValue;
+};
+
+export default useDebounce;