Skip to content

Commit 0f5a0ad

Browse files
committed
feat: update shortcut handling to use $mod for cross-platform compatibility
- Replaced instances of `Meta` with `$mod` in shortcut definitions across various components and hooks. - Introduced new shortcuts for actions like "Open in Browser" and "Mark All as Read". - Enhanced the `useCommandBinding` hook to support the new shortcut structure. - Updated UI components to reflect the changes in shortcut keys, ensuring consistency in user experience. Signed-off-by: Innei <[email protected]>
1 parent bf23120 commit 0f5a0ad

File tree

15 files changed

+132
-91
lines changed

15 files changed

+132
-91
lines changed

apps/desktop/layer/renderer/src/atoms/context-menu.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ export type FollowMenuItem = MenuItemText | MenuItemSeparator
5656
export type MenuItemInput = MenuItemText | MenuItemSeparator | NilValue
5757

5858
function sortShortcutsString(shortcut: string) {
59+
shortcut = shortcut.replace("$mod", "Meta")
5960
const order = ["Shift", "Ctrl", "Meta", "Alt"]
6061
const nextShortcut = transformShortcut(shortcut)
6162

@@ -101,7 +102,7 @@ function transformMenuItemsForNative(nextItems: FollowMenuItem[]): ElectronMenuI
101102
click: item.click,
102103
enabled:
103104
(!item.disabled && item.click !== undefined) || (!!item.submenu && item.submenu.length > 0),
104-
accelerator: item.shortcut?.replace("Meta", "CmdOrCtrl"),
105+
accelerator: item.shortcut?.replace("$mod", "CmdOrCtrl"),
105106
checked: typeof item.checked === "boolean" ? item.checked : undefined,
106107
submenu:
107108
item.submenu.length > 0

apps/desktop/layer/renderer/src/constants/shortcuts.ts

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ const shortcutConfigs = {
1111
subscriptions: {
1212
add: {
1313
name: tShortcuts("keys.subscriptions.add"),
14-
key: "Meta+T",
14+
key: "$mod+T",
1515
},
1616
switchToView: {
1717
name: tShortcuts("keys.subscriptions.switchToView"),
@@ -37,19 +37,27 @@ const shortcutConfigs = {
3737
name: tShortcuts("keys.subscriptions.toggleFolderCollapse"),
3838
key: "Z",
3939
},
40+
openInBrowser: {
41+
name: tShortcuts("keys.subscriptions.openInBrowser"),
42+
key: "O",
43+
},
44+
markAllAsRead: {
45+
name: tShortcuts("keys.entries.markAllAsRead"),
46+
key: "Shift+$mod+A",
47+
},
4048
},
4149
layout: {
4250
toggleSidebar: {
4351
name: tShortcuts("keys.layout.toggleSidebar"),
44-
key: "Meta+B, [",
52+
key: "$mod+B, [",
4553
},
4654
showShortcuts: {
4755
name: tShortcuts("keys.layout.showShortcuts"),
4856
key: "?",
4957
},
5058
toggleWideMode: {
5159
name: tShortcuts("keys.layout.toggleWideMode"),
52-
key: "Meta+[",
60+
key: "$mod+[",
5361
},
5462
zenMode: {
5563
name: tShortcuts("keys.layout.zenMode"),
@@ -69,10 +77,7 @@ const shortcutConfigs = {
6977
name: tShortcuts("keys.entries.next"),
7078
key: "J, ArrowDown",
7179
},
72-
markAllAsRead: {
73-
name: tShortcuts("keys.entries.markAllAsRead"),
74-
key: "Shift+Meta+A",
75-
},
80+
7681
toggleUnreadOnly: {
7782
name: tShortcuts("keys.entries.toggleUnreadOnly"),
7883
key: "U",
@@ -94,23 +99,23 @@ const shortcutConfigs = {
9499
},
95100
tts: {
96101
name: tShortcuts("keys.entry.tts"),
97-
key: "Shift+Meta+V",
102+
key: "Shift+$mod+V",
98103
},
99104
copyLink: {
100105
name: tShortcuts("keys.entry.copyLink"),
101-
key: "Shift+Meta+C",
106+
key: "Shift+$mod+C",
102107
},
103108
copyTitle: {
104109
name: tShortcuts("keys.entry.copyTitle"),
105-
key: "Shift+Meta+B",
110+
key: "Shift+$mod+B",
106111
},
107112
tip: {
108113
name: tShortcuts("keys.entry.tip"),
109-
key: "Shift+Meta+T",
114+
key: "Shift+$mod+T",
110115
},
111116
share: {
112117
name: tShortcuts("keys.entry.share"),
113-
key: "Meta+Alt+S",
118+
key: "$mod+Alt+S",
114119
},
115120
scrollUp: {
116121
name: tShortcuts("keys.entry.scrollUp"),
@@ -138,7 +143,7 @@ const shortcutConfigs = {
138143
misc: {
139144
quickSearch: {
140145
name: tShortcuts("keys.misc.quickSearch"),
141-
key: "Meta+K",
146+
key: "$mod+K",
142147
},
143148
},
144149
} as const

apps/desktop/layer/renderer/src/hooks/biz/useFeedActions.tsx

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import { MenuItemSeparator, MenuItemText } from "~/atoms/context-menu"
1313
import { useIsInMASReview } from "~/atoms/server-configs"
1414
import { whoami } from "~/atoms/user"
1515
import { useModalStack } from "~/components/ui/modal/stacked/hooks"
16+
import { shortcuts } from "~/constants/shortcuts"
1617
import { apiClient } from "~/lib/api-fetch"
1718
import { UrlBuilder } from "~/lib/url-builder"
1819
import { useBoostModal } from "~/modules/boost/hooks"
@@ -115,7 +116,7 @@ export const useFeedActions = ({
115116
const items: MenuItemInput[] = [
116117
new MenuItemText({
117118
label: t("sidebar.feed_actions.mark_all_as_read"),
118-
shortcut: "Meta+Shift+A",
119+
shortcut: "$mod+Shift+A",
119120
disabled: isEntryList,
120121
click: () =>
121122
subscriptionActions.markReadByFeedIds({
@@ -269,7 +270,7 @@ export const useFeedActions = ({
269270
: isEntryList
270271
? t("sidebar.feed_actions.unfollow_feed")
271272
: t("sidebar.feed_actions.unfollow"),
272-
shortcut: "Meta+Backspace",
273+
shortcut: "$mod+Backspace",
273274
disabled: isInbox,
274275
supportMultipleSelection: true,
275276
click: () => {
@@ -292,7 +293,7 @@ export const useFeedActions = ({
292293
}),
293294
new MenuItemText({
294295
label: t("sidebar.feed_actions.navigate_to_feed"),
295-
shortcut: "Meta+G",
296+
shortcut: "$mod+G",
296297
disabled: isInbox || !isEntryList || getRouteParams().feedId === feedId,
297298
click: () => {
298299
navigateEntry({ feedId })
@@ -311,7 +312,7 @@ export const useFeedActions = ({
311312
label: t("sidebar.feed_actions.open_site_in_browser", {
312313
which: t(IN_ELECTRON ? "words.browser" : "words.newTab"),
313314
}),
314-
shortcut: "Meta+O",
315+
shortcut: "$mod+O",
315316
disabled: isEntryList,
316317
click: () => {
317318
const feed = getFeedById(feedId)
@@ -324,7 +325,7 @@ export const useFeedActions = ({
324325
new MenuItemText({
325326
label: t("sidebar.feed_actions.copy_feed_url"),
326327
disabled: isEntryList,
327-
shortcut: "Meta+C",
328+
shortcut: "$mod+C",
328329
click: () => {
329330
const { url, siteUrl } = feed || {}
330331
const copied = url || siteUrl
@@ -334,7 +335,7 @@ export const useFeedActions = ({
334335
}),
335336
new MenuItemText({
336337
label: t("sidebar.feed_actions.copy_feed_id"),
337-
shortcut: "Meta+Shift+C",
338+
shortcut: "$mod+Shift+C",
338339
disabled: isEntryList,
339340
click: () => {
340341
navigator.clipboard.writeText(feedId)
@@ -419,12 +420,12 @@ export const useListActions = ({ listId, view }: { listId: string; view?: FeedVi
419420
}),
420421
new MenuItemText({
421422
label: t("sidebar.feed_actions.unfollow"),
422-
shortcut: "Meta+Backspace",
423+
shortcut: "$mod+Backspace",
423424
click: () => deleteSubscription({ subscription }),
424425
}),
425426
new MenuItemText({
426427
label: t("sidebar.feed_actions.navigate_to_list"),
427-
shortcut: "Meta+G",
428+
shortcut: "$mod+G",
428429
disabled: getRouteParams().feedId === listId,
429430
click: () => {
430431
navigateEntry({ listId })
@@ -435,20 +436,20 @@ export const useListActions = ({ listId, view }: { listId: string; view?: FeedVi
435436
label: t("sidebar.feed_actions.open_list_in_browser", {
436437
which: t(IN_ELECTRON ? "words.browser" : "words.newTab"),
437438
}),
438-
shortcut: "O",
439+
shortcut: shortcuts.subscriptions.openInBrowser.key,
439440
click: () => window.open(UrlBuilder.shareList(listId, view), "_blank"),
440441
}),
441442
MenuItemSeparator.default,
442443
new MenuItemText({
443444
label: t("sidebar.feed_actions.copy_list_url"),
444-
shortcut: "Meta+C",
445+
shortcut: "$mod+C",
445446
click: () => {
446447
navigator.clipboard.writeText(UrlBuilder.shareList(listId, view))
447448
},
448449
}),
449450
new MenuItemText({
450451
label: t("sidebar.feed_actions.copy_list_id"),
451-
shortcut: "Meta+Shift+C",
452+
shortcut: "$mod+Shift+C",
452453
click: () => {
453454
navigator.clipboard.writeText(listId)
454455
},
@@ -483,7 +484,7 @@ export const useInboxActions = ({ inboxId }: { inboxId: string }) => {
483484
MenuItemSeparator.default,
484485
new MenuItemText({
485486
label: t("sidebar.feed_actions.copy_email_address"),
486-
shortcut: "Meta+Shift+C",
487+
shortcut: "$mod+Shift+C",
487488
click: () => {
488489
navigator.clipboard.writeText(`${inboxId}${env.VITE_INBOXES_EMAIL}`)
489490
},

apps/desktop/layer/renderer/src/hooks/biz/useSubscriptionActions.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ export const useDeleteSubscription = ({ onSuccess }: { onSuccess?: () => void }
6565
<span className="flex items-center gap-1">
6666
{t("words.undo")}
6767
<Kbd className="border-border inline-flex items-center border bg-transparent text-white">
68-
Meta+Z
68+
$mod+Z
6969
</Kbd>
7070
</span>
7171
),

apps/desktop/layer/renderer/src/modules/app-layout/feed-column/mobile.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ export function FeedColumnMobile({ asWidget }: { asWidget?: boolean }) {
3737
</span>
3838
<div className="center inline-flex">
3939
<Link to="/discover" tabIndex={-1}>
40-
<ActionButton shortcut="Meta+T" tooltip={t("words.discover")}>
40+
<ActionButton shortcut="$mod+T" tooltip={t("words.discover")}>
4141
<i className="i-mgc-add-cute-re text-text-secondary size-5" />
4242
</ActionButton>
4343
</Link>

apps/desktop/layer/renderer/src/modules/command/commands/id.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,5 +76,6 @@ export const COMMAND_ID = {
7676
previousSubscription: "subscription:previous",
7777

7878
toggleFolderCollapse: "subscription:toggle-folder-collapse",
79+
markAllAsRead: "subscription:mark-all-as-read",
7980
},
8081
} as const

apps/desktop/layer/renderer/src/modules/command/commands/subscription.tsx

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
import { EventBus } from "@follow/utils/event-bus"
22

3+
import type { BizRouteParams } from "~/hooks/biz/useRouteParams"
4+
import { getRouteParams } from "~/hooks/biz/useRouteParams"
5+
36
import { useRegisterCommandEffect } from "../hooks/use-register-command"
47
import type { Command } from "../types"
58
import { COMMAND_ID } from "./id"
@@ -18,6 +21,7 @@ declare module "@follow/utils/event-bus" {
1821
"subscription:next": never
1922
"subscription:previous": never
2023
"subscription:toggle-folder-collapse": never
24+
"subscription:mark-all-as-read": BizRouteParams
2125
}
2226
}
2327
const LABEL_PREFIX = "Subscription"
@@ -100,6 +104,14 @@ export const useRegisterSubscriptionCommands = () => {
100104
EventBus.dispatch(COMMAND_ID.subscription.toggleFolderCollapse)
101105
},
102106
},
107+
{
108+
id: COMMAND_ID.subscription.markAllAsRead,
109+
label: `${LABEL_PREFIX}: Mark All as Read`,
110+
run: () => {
111+
const routeParams = getRouteParams()
112+
EventBus.dispatch(COMMAND_ID.subscription.markAllAsRead, routeParams)
113+
},
114+
},
103115
])
104116
}
105117

@@ -158,6 +170,11 @@ type ToggleFolderCollapseCommand = Command<{
158170
fn: () => void
159171
}>
160172

173+
type MarkAllAsReadCommand = Command<{
174+
id: typeof COMMAND_ID.subscription.markAllAsRead
175+
fn: () => void
176+
}>
177+
161178
export type SubscriptionCommand =
162179
| SwitchTabToNextCommand
163180
| SwitchTabToPreviousCommand
@@ -170,3 +187,4 @@ export type SubscriptionCommand =
170187
| NextSubscriptionCommand
171188
| PreviousSubscriptionCommand
172189
| ToggleFolderCollapseCommand
190+
| MarkAllAsReadCommand

apps/desktop/layer/renderer/src/modules/command/hooks/use-command-binding.ts

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,51 @@
1-
import type { BindingCommandId } from "./use-command-shortcut"
2-
import { useCommandShortcut } from "./use-command-shortcut"
1+
import { shortcuts } from "~/constants/shortcuts"
2+
3+
import { COMMAND_ID } from "../commands/id"
34
import type { RegisterHotkeyOptions } from "./use-register-hotkey"
45
import { useCommandHotkey } from "./use-register-hotkey"
56

7+
const defaultCommandShortcuts = {
8+
[COMMAND_ID.entry.read]: shortcuts.entry.toggleRead.key,
9+
[COMMAND_ID.entry.openInBrowser]: shortcuts.entry.openInBrowser.key,
10+
[COMMAND_ID.entry.star]: shortcuts.entry.toggleStarred.key,
11+
[COMMAND_ID.entry.copyLink]: shortcuts.entry.copyLink.key,
12+
[COMMAND_ID.entry.copyTitle]: shortcuts.entry.copyTitle.key,
13+
[COMMAND_ID.entry.tts]: shortcuts.entry.tts.key,
14+
[COMMAND_ID.entry.tip]: shortcuts.entry.tip.key,
15+
[COMMAND_ID.entry.share]: shortcuts.entry.share.key,
16+
17+
[COMMAND_ID.entryRender.scrollUp]: shortcuts.entry.scrollUp.key,
18+
[COMMAND_ID.entryRender.scrollDown]: shortcuts.entry.scrollDown.key,
19+
20+
[COMMAND_ID.timeline.switchToNext]: shortcuts.entries.next.key,
21+
[COMMAND_ID.timeline.switchToPrevious]: shortcuts.entries.previous.key,
22+
[COMMAND_ID.timeline.refetch]: shortcuts.entries.refetch.key,
23+
24+
[COMMAND_ID.layout.toggleTimelineColumn]: shortcuts.layout.toggleSidebar.key,
25+
26+
[COMMAND_ID.subscription.nextSubscription]: shortcuts.subscriptions.nextSubscription.key,
27+
[COMMAND_ID.subscription.previousSubscription]: shortcuts.subscriptions.previousSubscription.key,
28+
[COMMAND_ID.subscription.switchTabToNext]: shortcuts.subscriptions.switchNextView.key,
29+
[COMMAND_ID.subscription.switchTabToPrevious]: shortcuts.subscriptions.switchPreviousView.key,
30+
31+
[COMMAND_ID.global.showShortcuts]: shortcuts.layout.showShortcuts.key,
32+
33+
[COMMAND_ID.entryRender.nextEntry]: shortcuts.entry.nextEntry.key,
34+
[COMMAND_ID.entryRender.previousEntry]: shortcuts.entry.previousEntry.key,
35+
36+
[COMMAND_ID.subscription.toggleFolderCollapse]: shortcuts.subscriptions.toggleFolderCollapse.key,
37+
[COMMAND_ID.subscription.markAllAsRead]: shortcuts.subscriptions.markAllAsRead.key,
38+
} as const
39+
40+
export type BindingCommandId = keyof typeof defaultCommandShortcuts
41+
42+
// eslint-disable-next-line @eslint-react/hooks-extra/no-unnecessary-use-prefix, @eslint-react/hooks-extra/ensure-custom-hooks-using-other-hooks
43+
export const useCommandShortcut = (commandId: BindingCommandId): string => {
44+
const commandShortcut = defaultCommandShortcuts[commandId]
45+
46+
return commandShortcut
47+
}
48+
649
export const useCommandBinding = <T extends BindingCommandId>({
750
commandId,
851
when = true,

apps/desktop/layer/renderer/src/modules/command/hooks/use-command-shortcut.ts

Lines changed: 0 additions & 44 deletions
This file was deleted.

0 commit comments

Comments
 (0)