Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor hotkey setting UI #506

Merged
merged 4 commits into from
Apr 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 2 additions & 1 deletion enjoy/src/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -523,7 +523,8 @@
"AiTranslate": "AI translate",
"cambridgeDictionary": "Cambridge dictionary",
"customizeShortcuts": "Customize shortcuts",
"customizeShortcutsTip":"Press any sequence of keys to set a shortcut",
"customizeShortcutsTip":"Click to change",
"customizeShortcutsRecordingTip":"Recording new shortcut",
"customizeShortcutsInvalidToast": "Your shortcut should only have one modifier (Ctrl, Alt, Shift, or Meta) and one key, like 'Ctrl+C'.",
"customizeShortcutsConflictToast": "{{input}} conflicts with the existing {{otherHotkeyName}} shortcut.",
"customizeShortcutsUpdated": "Changes saved",
Expand Down
7 changes: 4 additions & 3 deletions enjoy/src/i18n/zh-CN.json
Original file line number Diff line number Diff line change
Expand Up @@ -522,9 +522,10 @@
"AiTranslate": "智能翻译",
"cambridgeDictionary": "剑桥词典",
"customizeShortcuts": "自定义快捷键",
"customizeShortcutsTip":"按任意键序列设置快捷键",
"customizeShortcutsInvalidToast":"快捷键应最多含一个修饰键(Ctrl、Alt、Shift 或 Meta)和一个键,如 'Ctrl+C'",
"customizeShortcutsConflictToast": "{{input}}和已有{{otherHotkeyName}}的键位冲突了",
"customizeShortcutsTip":"点击重新录制",
"customizeShortcutsRecordingTip":"正在录制快捷键",
"customizeShortcutsInvalidToast":"快捷键应最多含一个修饰键(Ctrl, Alt, Shift 或 Meta)和一个键,如 'Ctrl+C'",
"customizeShortcutsConflictToast": "{{input}} 和已有 {{otherHotkeyName}} 的键位冲突了",
"customizeShortcutsUpdated": "设置成功",
"following": "关注中",
"followers": "被关注",
Expand Down
103 changes: 0 additions & 103 deletions enjoy/src/renderer/components/change-hotkey-dialog.tsx

This file was deleted.

129 changes: 129 additions & 0 deletions enjoy/src/renderer/components/preferences/hotkeys-settings.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
import { t } from "i18next";
import {
AlertDialog,
AlertDialogCancel,
AlertDialogContent,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogTitle,
Button,
toast,
} from "@renderer/components/ui";
import { HotKeysSettingsProviderContext } from "@renderer/context";
import { useContext, useMemo, useEffect } from "react";

export const HotkeysSettings = ({
open,
name,
keyName,
onOpenChange,
}: {
open: boolean;
name: string;
keyName: string;
onOpenChange: (open: boolean) => void;
}) => {
const {
changeHotkey,
currentHotkeys,
recordingHotkeys,
resetRecordingHotkeys,
startRecordingHotkeys,
stopRecordingHotkeys,
isRecording,
} = useContext(HotKeysSettingsProviderContext);

const joinedKeys = useMemo(
() => [...recordingHotkeys].join("+"),
[recordingHotkeys]
);

const changeKeyMap = async () => {
const ret = (await changeHotkey(keyName, recordingHotkeys)) as unknown as {
error: "conflict" | "invalid";
data: string | string[];
input: string;
};
stopRecordingHotkeys();
const { error, data, input } = ret ?? {};

if (error === "conflict") {
toast.error(
t("customizeShortcutsConflictToast", {
input,
otherHotkeyName: (data as string[])
.map((str) => t(str.charAt(0).toLowerCase() + str.slice(1)))
.join(","),
})
);
} else if (error === "invalid") {
toast.error(t("customizeShortcutsInvalidToast"));
} else {
toast.success(t("customizeShortcutsUpdated"));
onOpenChange(false);
}
};

const reset = () => {
stopRecordingHotkeys();
resetRecordingHotkeys();
};

// ensure recording disabled when dialog close
useEffect(() => {
return () => {
stopRecordingHotkeys();
};
}, [open]);

return (
<AlertDialog open={open} onOpenChange={onOpenChange}>
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogTitle>{name}</AlertDialogTitle>
</AlertDialogHeader>
<div>
{isRecording ? (
<div className="">
<div className="flex justify-center mb-4">
<Button variant="secondary">
{joinedKeys.length > 0 ? (
<span className="text-sm">{joinedKeys}</span>
) : (
<span className="font-mono">-</span>
)}
</Button>
</div>
<div className="py-2 text-center text-sm text-muted-foreground">
{t("customizeShortcutsRecordingTip")}
</div>
</div>
) : (
<div className="">
<div className="flex justify-center mb-4">
<Button
variant="outline"
className="font-mono"
onClick={() => {
startRecordingHotkeys();
}}
>
{currentHotkeys[keyName]}
</Button>
</div>
<div className="py-2 text-center text-sm text-muted-foreground">
{t("customizeShortcutsTip")}
</div>
</div>
)}
</div>
<AlertDialogFooter>
<Button disabled={!isRecording || !joinedKeys} onClick={changeKeyMap}>
{t("save")}
</Button>
<AlertDialogCancel onClick={reset}>{t("cancel")}</AlertDialogCancel>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
);
};
46 changes: 18 additions & 28 deletions enjoy/src/renderer/components/preferences/hotkeys.tsx
Original file line number Diff line number Diff line change
@@ -1,36 +1,26 @@
import { t } from "i18next";
import { Separator } from "@renderer/components/ui";
import { HotKeysSettingsProviderContext, Hotkey } from "@/renderer/context";
import {
Separator,
} from "@renderer/components/ui";
import { HotKeysSettingsProviderContext, Hotkey } from "@renderer/context";
import { HotkeysSettings } from "@renderer/components";
import { useContext, useState } from "react";
import { ChangeHotkeyDialog } from "../change-hotkey-dialog";

export const Hotkeys = () => {
const [open, setOpen] = useState(false);
const [selectedItem, setSelectedItem] = useState<{
name: string;
keyName: string;
} | null>(null);
const {
currentHotkeys,
startRecordingHotkeys,
stopRecordingHotkeys,
} = useContext(HotKeysSettingsProviderContext);
const { currentHotkeys } = useContext(HotKeysSettingsProviderContext);

const commandOrCtrl = navigator.platform.includes("Mac") ? "Cmd" : "Ctrl";

const handleItemSelected = (item: { name: string; keyName: Hotkey }) => {
setOpen(true);
startRecordingHotkeys();
setSelectedItem(item);
};

const handleOpenChange = (open: boolean) => {
setOpen(open);
if (!open) {
stopRecordingHotkeys();
}
};

return (
<>
<div className="font-semibold mb-4 capitilized">{t("hotkeys")}</div>
Expand All @@ -39,8 +29,8 @@ export const Hotkeys = () => {

<div className="flex items-center justify-between py-4">
<div className="flex items-center space-x-2">{t("quitApp")}</div>
<kbd className="bg-muted px-2 py-1 rounded-md text-sm text-muted-foreground cursor-not-allowed">
{commandOrCtrl} + Q
<kbd className="bg-muted px-2 py-1 rounded-md text-sm text-muted-foreground cursor-not-allowed capitalize">
{commandOrCtrl}+Q
</kbd>
</div>

Expand All @@ -53,11 +43,11 @@ export const Hotkeys = () => {
<kbd
onClick={() =>
handleItemSelected({
name: "Open preferences",
name: t("openPreferences"),
keyName: "OpenPreferences",
})
}
className="bg-muted px-2 py-1 rounded-md text-sm text-muted-foreground cursor-pointer"
className="bg-muted px-2 py-1 rounded-md text-sm text-muted-foreground cursor-pointer capitalize"
>
{currentHotkeys.OpenPreferences}
</kbd>
Expand All @@ -77,7 +67,7 @@ export const Hotkeys = () => {
keyName: "PlayOrPause",
})
}
className="bg-muted px-2 py-1 rounded-md text-sm text-muted-foreground cursor-pointer"
className="bg-muted px-2 py-1 rounded-md text-sm text-muted-foreground cursor-pointer capitalize"
>
{currentHotkeys.PlayOrPause}
</kbd>
Expand All @@ -96,7 +86,7 @@ export const Hotkeys = () => {
keyName: "StartOrStopRecording",
})
}
className="bg-muted px-2 py-1 rounded-md text-sm text-muted-foreground cursor-pointer"
className="bg-muted px-2 py-1 rounded-md text-sm text-muted-foreground cursor-pointer capitalize"
>
{currentHotkeys.StartOrStopRecording}
</kbd>
Expand All @@ -115,7 +105,7 @@ export const Hotkeys = () => {
keyName: "PlayOrPauseRecording",
})
}
className="bg-muted px-2 py-1 rounded-md text-sm text-muted-foreground cursor-pointer"
className="bg-muted px-2 py-1 rounded-md text-sm text-muted-foreground cursor-pointer capitalize"
>
{currentHotkeys.PlayOrPauseRecording}
</kbd>
Expand Down Expand Up @@ -153,7 +143,7 @@ export const Hotkeys = () => {
keyName: "PlayNextSegment",
})
}
className="bg-muted px-2 py-1 rounded-md text-sm text-muted-foreground cursor-pointer"
className="bg-muted px-2 py-1 rounded-md text-sm text-muted-foreground cursor-pointer capitalize"
>
{currentHotkeys.PlayNextSegment}
</kbd>
Expand All @@ -172,7 +162,7 @@ export const Hotkeys = () => {
keyName: "Compare",
})
}
className="bg-muted px-2 py-1 rounded-md text-sm text-muted-foreground cursor-pointer"
className="bg-muted px-2 py-1 rounded-md text-sm text-muted-foreground cursor-pointer capitalize"
>
{currentHotkeys.Compare}
</kbd>
Expand All @@ -181,12 +171,12 @@ export const Hotkeys = () => {
<Separator />
</div>

<ChangeHotkeyDialog
<HotkeysSettings
open={open}
keyName={selectedItem?.keyName}
name={selectedItem?.name}
onOpenChange={handleOpenChange}
onOpenChange={setOpen}
/>
</>
);
};
};
2 changes: 2 additions & 0 deletions enjoy/src/renderer/components/preferences/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
export * from "./preferences";
export * from "./about";

export * from "./hotkeys";
export * from "./hotkeys-settings";

export * from "./default-engine-settings";
export * from "./openai-settings";
Expand Down