Skip to content

Commit 6aec9cb

Browse files
ayangwebmedcl
andauthored
fix: resolve pinned window shortcut not working (#917)
* fix: fix pinned window shortcut not working * docs: update changelog * refactor: update * Update _index.md --------- Co-authored-by: Medcl <m@medcl.net>
1 parent 4e58bc4 commit 6aec9cb

5 files changed

Lines changed: 78 additions & 60 deletions

File tree

docs/content.en/docs/release-notes/_index.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ feat: support opening logs from about page #915
2020

2121
fix: automatic update of service list #913
2222
fix: duplicate chat content #916
23+
fix: resolve pinned window shortcut not working (#917)
2324

2425
### ✈️ Improvements
2526

src/components/Assistant/ChatHeader.tsx

Lines changed: 4 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
import { MessageSquarePlus } from "lucide-react";
2-
import clsx from "clsx";
32

43
import HistoryIcon from "@/icons/History";
5-
import PinOffIcon from "@/icons/PinOff";
6-
import PinIcon from "@/icons/Pin";
74
import WindowsFullIcon from "@/icons/WindowsFull";
85
import { useAppStore } from "@/stores/appStore";
96
import type { Chat } from "@/types/chat";
@@ -12,6 +9,7 @@ import { useShortcutsStore } from "@/stores/shortcutsStore";
129
import { HISTORY_PANEL_ID } from "@/constants";
1310
import { AssistantList } from "./AssistantList";
1411
import { ServerList } from "./ServerList";
12+
import TogglePin from "../Common/TogglePin";
1513

1614
interface ChatHeaderProps {
1715
clearChat: () => void;
@@ -34,21 +32,9 @@ export function ChatHeader({
3432
showChatHistory = true,
3533
assistantIDs,
3634
}: ChatHeaderProps) {
37-
const { isPinned, setIsPinned, isTauri } = useAppStore();
35+
const { isTauri } = useAppStore();
3836

39-
const { historicalRecords, newSession, fixedWindow, external } =
40-
useShortcutsStore();
41-
42-
const togglePin = async () => {
43-
try {
44-
const { isPinned } = useAppStore.getState();
45-
46-
setIsPinned(!isPinned);
47-
} catch (err) {
48-
console.error("Failed to toggle window pin state:", err);
49-
setIsPinned(isPinned);
50-
}
51-
};
37+
const { historicalRecords, newSession, external } = useShortcutsStore();
5238

5339
return (
5440
<header
@@ -101,16 +87,7 @@ export function ChatHeader({
10187

10288
{isTauri ? (
10389
<div className="flex items-center gap-2">
104-
<button
105-
onClick={togglePin}
106-
className={clsx("inline-flex", {
107-
"text-blue-500": isPinned,
108-
})}
109-
>
110-
<VisibleKey shortcut={fixedWindow} onKeyPress={togglePin}>
111-
{isPinned ? <PinIcon /> : <PinOffIcon />}
112-
</VisibleKey>
113-
</button>
90+
<TogglePin className="inline-flex" />
11491

11592
<ServerList clearChat={clearChat} />
11693

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import { useAppStore } from "@/stores/appStore";
2+
import { useShortcutsStore } from "@/stores/shortcutsStore";
3+
import clsx from "clsx";
4+
import VisibleKey from "./VisibleKey";
5+
import { FC, HTMLAttributes } from "react";
6+
import PinOffIcon from "@/icons/PinOff";
7+
import PinIcon from "@/icons/Pin";
8+
9+
interface TogglePinProps extends HTMLAttributes<HTMLButtonElement> {
10+
setIsPinnedWeb?: (value: boolean) => void;
11+
}
12+
13+
const TogglePin: FC<TogglePinProps> = (props) => {
14+
const { className, setIsPinnedWeb } = props;
15+
const { isPinned, setIsPinned } = useAppStore();
16+
const { fixedWindow } = useShortcutsStore();
17+
18+
const togglePin = async () => {
19+
const { isTauri, isPinned } = useAppStore.getState();
20+
21+
try {
22+
const nextPinned = !isPinned;
23+
24+
if (!isTauri) {
25+
setIsPinnedWeb?.(nextPinned);
26+
}
27+
28+
setIsPinned(nextPinned);
29+
} catch (err) {
30+
setIsPinned(isPinned);
31+
32+
console.error("Failed to toggle window pin state:", err);
33+
}
34+
};
35+
36+
return (
37+
<button
38+
onClick={togglePin}
39+
className={clsx(className, {
40+
"text-blue-500": isPinned,
41+
})}
42+
>
43+
<VisibleKey shortcut={fixedWindow} onKeyPress={togglePin}>
44+
{isPinned ? <PinIcon /> : <PinOffIcon />}
45+
</VisibleKey>
46+
</button>
47+
);
48+
};
49+
50+
export default TogglePin;

src/components/Common/UI/Footer.tsx

Lines changed: 10 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,18 @@ import clsx from "clsx";
55

66
import CommonIcon from "@/components/Common/Icons/CommonIcon";
77
import Copyright from "@/components/Common/Copyright";
8-
import PinOffIcon from "@/icons/PinOff";
9-
import PinIcon from "@/icons/Pin";
108
import logoImg from "@/assets/icon.svg";
119
import { useAppStore } from "@/stores/appStore";
1210
import { useSearchStore } from "@/stores/searchStore";
1311
import { useUpdateStore } from "@/stores/updateStore";
14-
import VisibleKey from "../VisibleKey";
1512
import { useShortcutsStore } from "@/stores/shortcutsStore";
1613
import { formatKey } from "@/utils/keyboardUtils";
1714
import source_default_img from "@/assets/images/source_default.png";
1815
import source_default_dark_img from "@/assets/images/source_default_dark.png";
1916
import { useThemeStore } from "@/stores/themeStore";
2017
import platformAdapter from "@/utils/platformAdapter";
2118
import FontIcon from "../Icons/FontIcon";
19+
import TogglePin from "../TogglePin";
2220

2321
interface FooterProps {
2422
setIsPinnedWeb?: (value: boolean) => void;
@@ -37,28 +35,11 @@ export default function Footer({ setIsPinnedWeb }: FooterProps) {
3735

3836
const isDark = useThemeStore((state) => state.isDark);
3937

40-
const { isTauri, isPinned, setIsPinned } = useAppStore();
38+
const { isTauri } = useAppStore();
4139

4240
const { setVisible, updateInfo, skipVersions } = useUpdateStore();
4341

44-
const { fixedWindow, modifierKey } = useShortcutsStore();
45-
46-
const togglePin = async () => {
47-
try {
48-
const { isTauri, isPinned } = useAppStore.getState();
49-
50-
const nextPinned = !isPinned;
51-
52-
if (!isTauri) {
53-
setIsPinnedWeb?.(nextPinned);
54-
}
55-
56-
setIsPinned(nextPinned);
57-
} catch (err) {
58-
console.error("Failed to toggle window pin state:", err);
59-
setIsPinned(isPinned);
60-
}
61-
};
42+
const { modifierKey } = useShortcutsStore();
6243

6344
const openSetting = useCallback(() => {
6445
return platformAdapter.emitEvent("open_settings", "");
@@ -88,7 +69,10 @@ export default function Footer({ setIsPinnedWeb }: FooterProps) {
8869
if (visibleExtensionDetail && selectedExtension) {
8970
return (
9071
<div className="flex items-center gap-2">
91-
<img src={selectedExtension.icon} className="size-5 dark:drop-shadow-[0_0_6px_rgb(255,255,255)]" />
72+
<img
73+
src={selectedExtension.icon}
74+
className="size-5 dark:drop-shadow-[0_0_6px_rgb(255,255,255)]"
75+
/>
9276
<span className="text-sm">{selectedExtension.name}</span>
9377
</div>
9478
);
@@ -139,17 +123,12 @@ export default function Footer({ setIsPinnedWeb }: FooterProps) {
139123
<div className="flex items-center space-x-2">
140124
{renderLeft()}
141125

142-
<button
143-
onClick={togglePin}
126+
<TogglePin
144127
className={clsx({
145-
"text-blue-500": isPinned,
146128
"pl-2": hasUpdate,
147129
})}
148-
>
149-
<VisibleKey shortcut={fixedWindow} onKeyPress={togglePin}>
150-
{isPinned ? <PinIcon /> : <PinOffIcon />}
151-
</VisibleKey>
152-
</button>
130+
setIsPinnedWeb={setIsPinnedWeb}
131+
/>
153132
</div>
154133
</div>
155134
) : (

src/components/Common/VisibleKey.tsx

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ import { last } from "lodash-es";
66
import { POPOVER_PANEL_SELECTOR } from "@/constants";
77
import { useShortcutsStore } from "@/stores/shortcutsStore";
88
import { useAppStore } from "@/stores/appStore";
9+
import { KeyType } from "ahooks/lib/useKeyPress";
10+
11+
const keyTriggerMap = new Map<KeyType, number>();
912

1013
interface VisibleKeyProps extends HTMLAttributes<HTMLDivElement> {
1114
shortcut: string;
@@ -60,8 +63,16 @@ const VisibleKey: FC<VisibleKeyProps> = (props) => {
6063
setVisibleShortcut(isChildInPopover && modifierKeyPressed);
6164
}, [openPopover, modifierKeyPressed]);
6265

63-
useKeyPress(`${modifierKey}.${shortcut}`, (event) => {
64-
if (!visibleShortcut) return;
66+
useKeyPress(`${modifierKey}.${shortcut}`, (event, key) => {
67+
if (!visibleShortcut || event.repeat) return;
68+
69+
const now = Date.now();
70+
const last = keyTriggerMap.get(key) ?? 0;
71+
const wait = 100;
72+
73+
if (now - last < wait) return;
74+
75+
keyTriggerMap.set(key, now);
6576

6677
event.stopPropagation();
6778
event.preventDefault();

0 commit comments

Comments
 (0)