diff --git a/packages/views/locales/en/settings.json b/packages/views/locales/en/settings.json
index 856372a176..85dba20fb1 100644
--- a/packages/views/locales/en/settings.json
+++ b/packages/views/locales/en/settings.json
@@ -37,6 +37,12 @@
"description": "Customize product actions on this device. Click a shortcut, then press the new key combination.",
"search_placeholder": "Search actions...",
"reset_all": "Restore defaults",
+ "reset_confirm": {
+ "title": "Restore all shortcut defaults?",
+ "description": "This will remove every custom shortcut and restore the defaults on this device.",
+ "cancel": "Cancel",
+ "confirm": "Restore all defaults"
+ },
"reset": "Reset",
"disable": "Disable",
"reset_action": "Reset {{action}}",
diff --git a/packages/views/locales/ja/settings.json b/packages/views/locales/ja/settings.json
index a268fbec5c..4d31b2c5be 100644
--- a/packages/views/locales/ja/settings.json
+++ b/packages/views/locales/ja/settings.json
@@ -37,6 +37,12 @@
"description": "このデバイスで製品操作のショートカットをカスタマイズします。ショートカットをクリックして、新しいキーの組み合わせを押してください。",
"search_placeholder": "操作を検索...",
"reset_all": "デフォルトに戻す",
+ "reset_confirm": {
+ "title": "すべてのショートカットをデフォルトに戻しますか?",
+ "description": "このデバイスのカスタムショートカットをすべて削除し、デフォルト設定に戻します。",
+ "cancel": "キャンセル",
+ "confirm": "すべてデフォルトに戻す"
+ },
"reset": "リセット",
"disable": "無効にする",
"reset_action": "{{action}}をリセット",
diff --git a/packages/views/locales/ko/settings.json b/packages/views/locales/ko/settings.json
index 9749b37738..94b7e50f47 100644
--- a/packages/views/locales/ko/settings.json
+++ b/packages/views/locales/ko/settings.json
@@ -37,6 +37,12 @@
"description": "이 기기에서 제품 동작의 단축키를 설정합니다. 단축키를 클릭한 다음 새 키 조합을 누르세요.",
"search_placeholder": "동작 검색...",
"reset_all": "기본값 복원",
+ "reset_confirm": {
+ "title": "모든 단축키를 기본값으로 복원할까요?",
+ "description": "이 기기의 모든 사용자 지정 단축키를 삭제하고 기본 설정으로 복원합니다.",
+ "cancel": "취소",
+ "confirm": "모두 기본값으로 복원"
+ },
"reset": "재설정",
"disable": "사용 안 함",
"reset_action": "{{action}} 재설정",
diff --git a/packages/views/locales/zh-Hans/settings.json b/packages/views/locales/zh-Hans/settings.json
index 9fa864d497..cd5ee1a1ea 100644
--- a/packages/views/locales/zh-Hans/settings.json
+++ b/packages/views/locales/zh-Hans/settings.json
@@ -37,6 +37,12 @@
"description": "自定义当前设备上的产品操作。点击一个快捷键,然后按下新的组合键。",
"search_placeholder": "搜索操作...",
"reset_all": "恢复默认设置",
+ "reset_confirm": {
+ "title": "恢复所有快捷键的默认设置?",
+ "description": "这会清除当前设备上的所有自定义快捷键,并恢复默认设置。",
+ "cancel": "取消",
+ "confirm": "恢复全部默认设置"
+ },
"reset": "重置",
"disable": "停用",
"reset_action": "重置「{{action}}」",
diff --git a/packages/views/settings/components/keyboard-shortcuts-tab.test.tsx b/packages/views/settings/components/keyboard-shortcuts-tab.test.tsx
index a465baf582..9c8f3f191e 100644
--- a/packages/views/settings/components/keyboard-shortcuts-tab.test.tsx
+++ b/packages/views/settings/components/keyboard-shortcuts-tab.test.tsx
@@ -136,4 +136,35 @@ describe("KeyboardShortcutsTab", () => {
);
expect(getShortcut("createIssue")).toEqual(createShortcutChord("C"));
});
+
+ it("confirms before restoring all shortcut defaults", () => {
+ useShortcutStore.getState().setShortcut(
+ "openSearch",
+ createShortcutChord("J", { primary: true }),
+ );
+ renderWithI18n();
+
+ fireEvent.click(screen.getByRole("button", { name: "Restore defaults" }));
+ expect(screen.getByRole("alertdialog")).toHaveTextContent(
+ "This will remove every custom shortcut and restore the defaults on this device.",
+ );
+ expect(getShortcut("openSearch")).toEqual(
+ createShortcutChord("J", { primary: true }),
+ );
+
+ fireEvent.click(screen.getByRole("button", { name: "Cancel" }));
+ expect(screen.queryByRole("alertdialog")).not.toBeInTheDocument();
+ expect(getShortcut("openSearch")).toEqual(
+ createShortcutChord("J", { primary: true }),
+ );
+
+ fireEvent.click(screen.getByRole("button", { name: "Restore defaults" }));
+ fireEvent.click(
+ screen.getByRole("button", { name: "Restore all defaults" }),
+ );
+ expect(screen.queryByRole("alertdialog")).not.toBeInTheDocument();
+ expect(getShortcut("openSearch")).toEqual(
+ createShortcutChord("K", { primary: true }),
+ );
+ });
});
diff --git a/packages/views/settings/components/keyboard-shortcuts-tab.tsx b/packages/views/settings/components/keyboard-shortcuts-tab.tsx
index c6e7224508..4db3f21528 100644
--- a/packages/views/settings/components/keyboard-shortcuts-tab.tsx
+++ b/packages/views/settings/components/keyboard-shortcuts-tab.tsx
@@ -4,6 +4,16 @@ import { useMemo, useState } from "react";
import { Keyboard, RotateCcw, Search, X } from "lucide-react";
import { Button } from "@multica/ui/components/ui/button";
import { Input } from "@multica/ui/components/ui/input";
+import {
+ AlertDialog,
+ AlertDialogAction,
+ AlertDialogCancel,
+ AlertDialogContent,
+ AlertDialogDescription,
+ AlertDialogFooter,
+ AlertDialogHeader,
+ AlertDialogTitle,
+} from "@multica/ui/components/ui/alert-dialog";
import { cn } from "@multica/ui/lib/utils";
import {
findShortcutConflict,
@@ -42,6 +52,7 @@ export function KeyboardShortcutsTab() {
const [query, setQuery] = useState("");
const [recording, setRecording] = useState(null);
const [captureError, setCaptureError] = useState(null);
+ const [resetConfirmOpen, setResetConfirmOpen] = useState(false);
const overrides = useShortcutStore((state) => state.overrides);
const setShortcut = useShortcutStore((state) => state.setShortcut);
const resetShortcut = useShortcutStore((state) => state.resetShortcut);
@@ -119,11 +130,7 @@ export function KeyboardShortcutsTab() {