Skip to content

Commit

Permalink
feat: add keyboard shortcuts, remove event-bus
Browse files Browse the repository at this point in the history
  • Loading branch information
invm committed Sep 30, 2023
1 parent 3312876 commit 0f47831
Show file tree
Hide file tree
Showing 15 changed files with 202 additions and 133 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"@codemirror/state": "^6.2.1",
"@codemirror/view": "^6.14.1",
"@replit/codemirror-vim": "^6.0.14",
"@solid-primitives/event-bus": "^1.0.8",
"@solid-primitives/keyboard": "^1.2.5",
"@tauri-apps/api": "^1.4.0",
"@uiw/codemirror-theme-dracula": "^4.21.7",
"codemirror": "^6.0.1",
Expand Down
51 changes: 38 additions & 13 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

48 changes: 9 additions & 39 deletions src/components/CommandPalette/CommandPaletteContext.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { actions, commandPaletteEmitter } from "./actions";
import { actions } from "./actions";
import { useAppSelector } from "services/Context";
import { CommandPalette, Root } from "solid-command-palette";
import { JSX } from "solid-js/jsx-runtime";
import { onMount } from "solid-js";
import { createShortcut } from "@solid-primitives/keyboard";

export interface ActionsContext {
[key: string]: any;
Expand All @@ -13,50 +13,20 @@ export const CommandPaletteContext = (props: { children: JSX.Element }) => {
connectionsService: {
addContentTab,
removeContentTab,
getContentData,
setContentIdx,
setConnectionIdx,
},
} = useAppSelector();

const actionsContext: ActionsContext = {};

onMount(() => {
document.onkeyup = function(e: KeyboardEvent) {
const number = e.code.startsWith("Digit")
? +e.code.replace("Digit", "")
: null;
const { ctrlKey, metaKey, altKey, key, preventDefault, code } = e;
if (
(ctrlKey || metaKey || altKey) &&
number &&
number > 0 &&
number <= 9
) {
preventDefault();
if (altKey) setContentIdx(number);
else setConnectionIdx(number - 1);
} else if ((ctrlKey || metaKey) && code === "KeyT") {
e.preventDefault();
if (e.shiftKey) removeContentTab();
else addContentTab();
} else if (code === "KeyE" && (ctrlKey || metaKey)) {
commandPaletteEmitter.emit("execute", undefined);
} else if (
key === "p" &&
ctrlKey &&
getContentData("Query").result_sets.length
) {
commandPaletteEmitter.emit("prev-result-set", undefined);
} else if (
key === "n" &&
ctrlKey &&
getContentData("Query").result_sets.length
) {
commandPaletteEmitter.emit("next-result-set", undefined);
}
};
});
for (let i = 0; i < 9; i++) {
createShortcut(["Alt", String(i)], () => setContentIdx(i - 1));
createShortcut(["Control", String(i)], () => setConnectionIdx(i - 1));
}

createShortcut(["Control", "T"], () => addContentTab());
createShortcut(["Control", "Shift", "T"], () => removeContentTab());

return (
<Root actions={actions} actionsContext={actionsContext}>
Expand Down
17 changes: 7 additions & 10 deletions src/components/CommandPalette/actions.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,6 @@
import { createEmitter } from "@solid-primitives/event-bus";
import { defineAction } from "solid-command-palette";
import { t } from "utils/i18n";

export const commandPaletteEmitter = createEmitter<{
"focus-query-text-area": boolean;
"next-result-set": undefined;
"prev-result-set": undefined;
execute: undefined;
}>();

const focusOn = defineAction({
id: "focus_on",
title: t("command_palette.focus_on"),
Expand All @@ -19,9 +11,14 @@ const focusQueryTextArea = defineAction({
title: t("command_palette.focus_query_text_area"),
parentActionId: focusOn.id,
/* Condition for allowing action */
shortcut: "$mod+d", // $mod = Command on Mac & Control on Windows.
shortcut: "$mod+l", // $mod = Command on Mac & Control on Windows.
run: () => {
commandPaletteEmitter.emit("focus-query-text-area", true);
// document.dispatchEvent(
// new KeyboardEvent("keydown", {
// code: "KeyL", // put everything you need in this object.
// ctrlKey: true, // if you aren't going to use them.
// })
// );
},
});

Expand Down
21 changes: 20 additions & 1 deletion src/components/Screens/Console/Content/QueryTab/QueryTab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import Split from "split.js";
import { QueryTextArea } from "./QueryTextArea";
import { createStore } from "solid-js/store";
import { Row } from "interfaces";
import { createShortcut } from "@solid-primitives/keyboard";

export const QueryTab = () => {
const {
Expand Down Expand Up @@ -34,10 +35,28 @@ export const QueryTab = () => {
setRows(getContentData("Query").result_sets[idx()]?.rows || []);
});

const onPrevClick = () => {
setIdx(
(idx() - 1 + getContentData("Query").result_sets.length) %
getContentData("Query").result_sets.length
);
};

const onNextClick = () => {
setIdx((idx() + 1) % getContentData("Query").result_sets.length);
};

createShortcut(["Control", "Shift", "N"], onNextClick);
createShortcut(["Control", "Shift", "P"], onPrevClick);

return (
<div class="flex flex-col h-full overflow-hidden">
<div id="query" class="flex flex-col">
<QueryTextArea idx={idx} setIdx={setIdx} />
<QueryTextArea
idx={idx}
onPrevClick={onPrevClick}
onNextClick={onNextClick}
/>
</div>
<div id="results">
<Show when={!getContent().error}>
Expand Down
80 changes: 19 additions & 61 deletions src/components/Screens/Console/Content/QueryTab/QueryTextArea.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,7 @@ import {
createEditorControlledValue,
createEditorFocus,
} from "solid-codemirror";
import {
Accessor,
createEffect,
createSignal,
For,
onMount,
Setter,
Show,
} from "solid-js";
import { Accessor, createEffect, createSignal, For, Show } from "solid-js";
import {
EditorView,
drawSelection,
Expand All @@ -23,17 +15,24 @@ import { dracula } from "@uiw/codemirror-theme-dracula";
import { vim } from "@replit/codemirror-vim";
import { format } from "sql-formatter";
import { invoke } from "@tauri-apps/api";
import { EditIcon, FireIcon, VimIcon } from "components/UI/Icons";
import {
ChevronLeft,
ChevronRight,
EditIcon,
FireIcon,
VimIcon,
} from "components/UI/Icons";
import { useAppSelector } from "services/Context";
import { QueryResult } from "interfaces";
import { commandPaletteEmitter } from "components/CommandPalette/actions";
import { t } from "utils/i18n";
import { Alert } from "components/UI";
import { basicSetup } from "codemirror";
import { createShortcut } from "@solid-primitives/keyboard";

export const QueryTextArea = (props: {
idx: Accessor<number>;
setIdx: Setter<number>;
onPrevClick: () => void;
onNextClick: () => void;
}) => {
const {
connectionsService: {
Expand Down Expand Up @@ -105,7 +104,6 @@ export const QueryTextArea = (props: {
updateContentTab("data", { query: code(), executed: true, result_sets });
// console.log({ result_sets });
} catch (error) {
// console.log({ error });
updateContentTab("error", String(error));
}
};
Expand All @@ -114,49 +112,9 @@ export const QueryTextArea = (props: {
setCode(getContentData("Query").query ?? "");
});

const handleKeyDown = async (e: KeyboardEvent) => {
if ((e.altKey || e.metaKey || e.ctrlKey) && e.code.startsWith("Digit")) {
e.preventDefault();
}
if (e.key === "f" && e.ctrlKey) {
onFormat();
} else if (
(e.metaKey || e.ctrlKey) &&
(e.key === "Enter" || e.key === "e")
) {
await onExecute();
}
};

onMount(() => {
commandPaletteEmitter.on("focus-query-text-area", () => {
// this is done with a timeout because when this event is emitted the active element is the command palette
// and imeediately focusing the query text area doesn't work
setTimeout(() => {
// @ts-ignore
document.activeElement?.blur();
setFocused(true);
}, 1);
});
commandPaletteEmitter.on("next-result-set", onNextClick);
commandPaletteEmitter.on("prev-result-set", onPrevClick);
commandPaletteEmitter.on("execute", async () => {
await onExecute();
});
});

const onPrevClick = () => {
props.setIdx(
(props.idx() - 1 + getContentData("Query").result_sets.length) %
getContentData("Query").result_sets.length
);
};

const onNextClick = () => {
props.setIdx(
(props.idx() + 1) % getContentData("Query").result_sets.length
);
};
createShortcut(["Control", "e"], onExecute);
createShortcut(["Control", "l"], () => setFocused(true));
createShortcut(["Control", "Shift", "F"], onFormat);

return (
<div class="flex-1 flex flex-col">
Expand Down Expand Up @@ -218,16 +176,16 @@ export const QueryTextArea = (props: {
{t("components.console.result_set")}
<button
class="btn btn-xs mx-0.5 btn-neutral h-5 min-h-0"
onClick={onPrevClick}
onClick={props.onPrevClick}
>
{"<"}
<ChevronLeft />
</button>
{"#" + (props.idx() + 1)}
<button
class="btn btn-xs mx-0.5 btn-neutral h-5 min-h-0"
onClick={onNextClick}
onClick={props.onNextClick}
>
{">"}
<ChevronRight />
</button>
{t("components.console.out_of") +
getContentData("Query").result_sets.length +
Expand All @@ -240,7 +198,7 @@ export const QueryTextArea = (props: {
</For>
</Show>
</div>
<div class="overflow-hidden w-full h-full" onKeyDown={handleKeyDown}>
<div class="overflow-hidden w-full h-full">
<div ref={ref} class="w-full h-full" />
</div>
</div>
Expand Down
Loading

0 comments on commit 0f47831

Please sign in to comment.