Skip to content

Commit

Permalink
feat: 新增数字组合键快速粘贴前九项 (#528)
Browse files Browse the repository at this point in the history
  • Loading branch information
ayangweb authored Sep 16, 2024
1 parent 8a5718a commit 90dfbfb
Show file tree
Hide file tree
Showing 15 changed files with 172 additions and 38 deletions.
9 changes: 4 additions & 5 deletions src-tauri/src/core/setup/mac.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
use tauri::{App, Window};
use cocoa::appkit::{NSMainMenuWindowLevel, NSWindow};
use cocoa::base::id;
use tauri::{ActivationPolicy, App, Window};

pub fn platform(app: &mut App, main_window: Window, _preference_window: Window) {
// 隐藏 mac 的程序坞图标:https://github.com/tauri-apps/tauri/issues/4852#issuecomment-1312716378
app.set_activation_policy(tauri::ActivationPolicy::Accessory);
app.set_activation_policy(ActivationPolicy::Accessory);

unsafe {
use cocoa::appkit::{NSMainMenuWindowLevel, NSWindow};
use cocoa::base::id;

let ns_window = main_window.ns_window().unwrap() as id;

// 让窗口在程序坞和菜单栏之上
Expand Down
4 changes: 3 additions & 1 deletion src/components/ProShortcut/keys.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { defaults } from "lodash-es";

export type ModifierKey = "Shift" | "Control" | "Alt" | "Command";

export interface Key {
key: string;
key: ModifierKey | (string & {});
symbol?: string;
shortcut?: string;
macosSymbol?: string;
Expand Down
6 changes: 5 additions & 1 deletion src/locales/en-US.json
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,11 @@
"title": "Shortcuts",
"label": {
"open_clipboard": "Open Clipboard Window",
"open_settings": "Open Preferences Window"
"open_settings": "Open Preferences Window",
"quick_paste": "Quick Paste"
},
"hints": {
"quick_paste": "Use number key combos to quickly paste top 9 items when window is hidden"
}
}
},
Expand Down
6 changes: 5 additions & 1 deletion src/locales/ja-JP.json
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,11 @@
"title": "ショートカットキー",
"label": {
"open_clipboard": "クリップボードを開く",
"open_settings": "クリップボード設定を開く"
"open_settings": "クリップボード設定を開く",
"quick_paste": "クイックペースト"
},
"hints": {
"quick_paste": "ウィンドウを隠す際、数字キーの組み合わせで最初の9項目を素早く貼り付ける"
}
}
},
Expand Down
6 changes: 5 additions & 1 deletion src/locales/zh-CN.json
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,11 @@
"title": "快捷键",
"label": {
"open_clipboard": "打开剪贴板窗口",
"open_settings": "打开偏好设置窗口"
"open_settings": "打开偏好设置窗口",
"quick_paste": "快速粘贴"
},
"hints": {
"quick_paste": "在隐藏窗口时,使用数字组合键快速粘贴前九项"
}
}
},
Expand Down
6 changes: 5 additions & 1 deletion src/locales/zh-TW.json
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,11 @@
"title": "快捷鍵",
"label": {
"open_clipboard": "打開剪貼簿視窗",
"open_settings": "打開偏好設定視窗"
"open_settings": "打開偏好設定視窗",
"quick_paste": "快速粘貼"
},
"hints": {
"quick_paste": "在隱藏視窗時,使用數位複合鍵快速粘貼前九項"
}
}
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,24 +43,11 @@ const Item: FC<ItemProps> = (props) => {
});

const copy = () => {
switch (type) {
case "text":
return writeText(value);
case "rtf":
return writeRTF(search, value);
case "html":
return writeHTML(search, value);
case "image":
return writeImage(value);
case "files":
return writeFiles(JSON.parse(value));
}
return writeClipboard(data);
};

const pastePlainText = async () => {
await writeText(search);

paste();
const pastePlainText = () => {
pasteClipboard(data, true);
};

const toggleFavorite = async () => {
Expand Down Expand Up @@ -121,9 +108,7 @@ const Item: FC<ItemProps> = (props) => {
const pasteValue = async () => {
if (state.activeId !== id) return;

await copy();

paste();
pasteClipboard(data);
};

const handleContextMenu = async (event: MouseEvent) => {
Expand Down
6 changes: 4 additions & 2 deletions src/pages/Clipboard/Panel/components/List/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,12 @@ const List = () => {

const isFocusWithin = useFocusWithin(document.body);

useEffect(() => {
useAsyncEffect(async () => {
rowVirtualizer.scrollToIndex(0);

getClipboardList?.();
await getClipboardList?.();

state.activeId = state.data.list[0].id;
}, [state.search, state.group, state.favorite]);

useOSKeyPress(
Expand Down
39 changes: 34 additions & 5 deletions src/pages/Clipboard/Panel/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@ import type { AudioRef } from "@/components/Audio";
import Audio from "@/components/Audio";
import type { ClipboardItem, TablePayload } from "@/types/database";
import { listen } from "@tauri-apps/api/event";
import { registerAll, unregister } from "@tauri-apps/api/globalShortcut";
import type { EventEmitter } from "ahooks/lib/useEventEmitter";
import { isEqual, merge } from "lodash-es";
import { isEqual, last, merge, range } from "lodash-es";
import { createContext } from "react";
import { useSnapshot } from "valtio";
import { subscribeKey } from "valtio/utils";
import Dock from "./components/Dock";
import Float from "./components/Float";

Expand All @@ -20,6 +22,7 @@ interface State extends TablePayload {
loading: boolean;
};
$eventBus?: EventEmitter<string>;
quickPasteShortcuts: string[];
}

const INITIAL_STATE: State = {
Expand All @@ -31,6 +34,7 @@ const INITIAL_STATE: State = {
size: 20,
loading: false,
},
quickPasteShortcuts: [],
};

interface ClipboardPanelContextValue {
Expand Down Expand Up @@ -113,6 +117,12 @@ const ClipboardPanel = () => {

// 监听主窗口显示/隐藏
listen(LISTEN_KEY.TOGGLE_MAIN_WINDOW_VISIBLE, toggleWindowVisible);

// 监听快速粘贴的启用状态变更
watchKey(globalStore.shortcut.quickPaste, "enable", registerQuickPaste);

// 监听快速粘贴的快捷键变更
subscribeKey(globalStore.shortcut.quickPaste, "value", registerQuickPaste);
});

// 监听窗口焦点
Expand All @@ -131,17 +141,36 @@ const ClipboardPanel = () => {
const getClipboardList = async () => {
const { search, group, favorite } = state;

const list = await selectSQL<ClipboardItem[]>("history", {
state.data.list = await selectSQL<ClipboardItem[]>("history", {
search,
group,
favorite,
});
};

state.data.list = list;
// 注册数字组合键快速粘贴的快捷键
const registerQuickPaste = async () => {
const { enable, value } = globalStore.shortcut.quickPaste;

if (state.data.page === 1) {
state.activeId ||= list[0]?.id;
for await (const shortcut of state.quickPasteShortcuts) {
await unregister(shortcut);
}

if (!enable) return;

const shortcuts = range(1, 10).map((item) => `${value}+${item}`);

await registerAll(shortcuts, async (shortcut) => {
if (!globalStore.shortcut.quickPaste.enable) return;

const index = Number(last(shortcut));

const data = state.data.list[index - 1];

pasteClipboard(data);
});

state.quickPasteShortcuts = shortcuts;
};

return (
Expand Down
49 changes: 49 additions & 0 deletions src/pages/Shortcut/components/QuickPaste/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import EcoSelect from "@/components/EcoSelect";
import ProListItem from "@/components/ProListItem";
import { modifierKeys } from "@/components/ProShortcut/keys";
import { Space, Switch } from "antd";
import type { DefaultOptionType } from "antd/es/select";
import { useSnapshot } from "valtio";

const QuickPaste = () => {
const { shortcut } = useSnapshot(globalStore);
const { t } = useTranslation();

const options: DefaultOptionType[] = modifierKeys.map((item) => {
const { key, symbol, macosSymbol } = item;

return {
label: isMac() ? macosSymbol : symbol,
value: key,
};
});

return (
<ProListItem
title={t("preference.shortcut.shortcut.label.quick_paste")}
description={t("preference.shortcut.shortcut.hints.quick_paste")}
>
<Switch
value={shortcut.quickPaste.enable}
onChange={(value) => {
globalStore.shortcut.quickPaste.enable = value;
}}
/>

<Space>
<EcoSelect
options={options}
value={shortcut.quickPaste.value}
disabled={!shortcut.quickPaste.enable}
onChange={(value) => {
globalStore.shortcut.quickPaste.value = value;
}}
/>

<span>1~9</span>
</Space>
</ProListItem>
);
};

export default QuickPaste;
3 changes: 3 additions & 0 deletions src/pages/Shortcut/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import ProList from "@/components/ProList";
import ProShortcut from "@/components/ProShortcut";
import { useSnapshot } from "valtio";
import QuickPaste from "./components/QuickPaste";

const Shortcut = () => {
const { shortcut } = useSnapshot(globalStore);
Expand All @@ -23,6 +24,8 @@ const Shortcut = () => {
globalStore.shortcut.preference = value;
}}
/>

<QuickPaste />
</ProList>
);
};
Expand Down
37 changes: 37 additions & 0 deletions src/plugins/clipboard.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import type { ClipboardItem } from "@/types/database";
import type { ClipboardPayload, ReadImage, WinOCR } from "@/types/plugin";
import { invoke } from "@tauri-apps/api";
import { listen } from "@tauri-apps/api/event";
Expand Down Expand Up @@ -289,3 +290,39 @@ export const onClipboardUpdate = (
oldPayload = payload;
});
};

/**
* 将数据写入剪切板
* @param data 数据
*/
export const writeClipboard = async (data: ClipboardItem) => {
const { type, value, search } = data;

switch (type) {
case "text":
return writeText(value);
case "rtf":
return writeRTF(search, value);
case "html":
return writeHTML(search, value);
case "image":
return writeImage(getSaveImagePath(value));
case "files":
return writeFiles(JSON.parse(value));
}
};

/**
* 粘贴剪切板数据
* @param data 数据
* @param plain 是否纯文本粘贴
*/
export const pasteClipboard = async (data: ClipboardItem, plain = false) => {
if (plain) {
await writeText(data.search);
} else {
await writeClipboard(data);
}

paste();
};
4 changes: 4 additions & 0 deletions src/stores/global.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ export const GLOBAL_STORE_INITIAL_STATE: GlobalStore = {
shortcut: {
clipboard: "Alt+C",
preference: "Alt+X",
quickPaste: {
enable: false,
value: "Alt",
},
},

env: {},
Expand Down
6 changes: 6 additions & 0 deletions src/types/store.d.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import type { ModifierKey } from "@/components/ProShortcut/keys";

export type Theme = "auto" | "light" | "dark";

export type Language = (typeof LANGUAGE)[keyof typeof LANGUAGE];
Expand Down Expand Up @@ -30,6 +32,10 @@ export interface GlobalStore {
shortcut: {
clipboard: string;
preference?: string;
quickPaste: {
enable: boolean;
value: ModifierKey;
};
};

// 只在当前系统环境使用
Expand Down
6 changes: 4 additions & 2 deletions src/utils/path.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,10 @@ export const getSaveImageDir = () => {
* 获取图片内容的存储路径
* @param file 文件名
*/
export const getSaveImagePath = (fileName: string) => {
return joinPath(getSaveImageDir(), fileName);
export const getSaveImagePath = (file: string) => {
if (file.startsWith(getSaveImageDir())) return file;

return joinPath(getSaveImageDir(), file);
};

/**
Expand Down

0 comments on commit 90dfbfb

Please sign in to comment.