mirror of
https://github.com/fofolee/uTools-quickcommand.git
synced 2025-07-05 07:32:45 +08:00
添加pin的雏形
This commit is contained in:
parent
0d4f49fcf4
commit
6f1c98fb4a
30
plugin/lib/pin/controller.js
Normal file
30
plugin/lib/pin/controller.js
Normal file
@ -0,0 +1,30 @@
|
||||
const { ipcRenderer } = require("electron");
|
||||
|
||||
// 等待 DOM 加载完成
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
let parentId = null;
|
||||
let windowId = null;
|
||||
let commandCode = null;
|
||||
|
||||
// 监听父窗口发来的配置
|
||||
ipcRenderer.on("window-config", (event, config) => {
|
||||
parentId = event.senderId;
|
||||
windowId = config.windowId;
|
||||
commandCode = config.commandCode;
|
||||
|
||||
// 设置主题
|
||||
document.documentElement.setAttribute(
|
||||
"data-theme",
|
||||
config.isDark ? "dark" : "light"
|
||||
);
|
||||
|
||||
// 设置图标
|
||||
document.getElementById("command-icon").src = config.icon;
|
||||
});
|
||||
|
||||
// 点击图标执行命令
|
||||
document.querySelector(".pin-container").addEventListener("click", () => {
|
||||
console.log("click", parentId, `pin-execute-${windowId}`);
|
||||
ipcRenderer.sendTo(parentId, `pin-execute-${windowId}`, commandCode);
|
||||
});
|
||||
});
|
108
plugin/lib/pin/service.js
Normal file
108
plugin/lib/pin/service.js
Normal file
@ -0,0 +1,108 @@
|
||||
const { ipcRenderer } = require("electron");
|
||||
const { createBrowserWindow } = utools;
|
||||
|
||||
const pinPath = "lib/pin/view.html";
|
||||
const preloadPath = "lib/pin/controller.js";
|
||||
|
||||
// 存储所有pin窗口的信息
|
||||
const pinWindows = new Map();
|
||||
|
||||
/**
|
||||
* 创建pin窗口
|
||||
* @param {object} commandInfo - 命令信息
|
||||
* @param {object} position - 窗口位置 {x, y}
|
||||
* @returns {Promise} 返回窗口对象
|
||||
*/
|
||||
const createPinWindow = (commandInfo, position = null) => {
|
||||
return new Promise((resolve) => {
|
||||
const windowOptions = {
|
||||
width: 52,
|
||||
height: 52,
|
||||
transparent: true,
|
||||
frame: false,
|
||||
resizable: false,
|
||||
skipTaskbar: true,
|
||||
alwaysOnTop: true,
|
||||
focusable: false,
|
||||
movable: true,
|
||||
webPreferences: {
|
||||
preload: preloadPath,
|
||||
devTools: utools.isDev(),
|
||||
},
|
||||
};
|
||||
|
||||
// 如果指定了位置,添加到选项中
|
||||
if (position) {
|
||||
windowOptions.x = position.x;
|
||||
windowOptions.y = position.y;
|
||||
}
|
||||
|
||||
// 创建窗口
|
||||
const UBrowser = createBrowserWindow(pinPath, windowOptions, () => {
|
||||
const windowId = UBrowser.webContents.id;
|
||||
UBrowser.webContents.openDevTools({
|
||||
mode: "undocked",
|
||||
});
|
||||
|
||||
// 监听命令执行请求
|
||||
ipcRenderer.once(`pin-execute-${windowId}`, (event, code) => {
|
||||
// 执行命令
|
||||
console.log("execute command", event, code, commandInfo);
|
||||
});
|
||||
|
||||
// 保存窗口信息
|
||||
pinWindows.set(commandInfo.features.code, {
|
||||
window: UBrowser,
|
||||
windowId,
|
||||
position: UBrowser.getPosition(),
|
||||
});
|
||||
|
||||
// 发送配置到子窗口
|
||||
ipcRenderer.sendTo(windowId, "window-config", {
|
||||
isDark: utools.isDarkColors(),
|
||||
icon: commandInfo.features.icon,
|
||||
commandCode: commandInfo.features.code,
|
||||
windowId,
|
||||
});
|
||||
|
||||
resolve(UBrowser);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 移除pin窗口
|
||||
* @param {string} commandCode - 命令代码
|
||||
*/
|
||||
const removePinWindow = (commandCode) => {
|
||||
const pinInfo = pinWindows.get(commandCode);
|
||||
if (pinInfo) {
|
||||
pinInfo.window.destroy();
|
||||
pinWindows.delete(commandCode);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 获取所有pin窗口信息
|
||||
* @returns {Map} pin窗口信息Map
|
||||
*/
|
||||
const getPinWindows = () => {
|
||||
return pinWindows;
|
||||
};
|
||||
|
||||
/**
|
||||
* 恢复所有pin窗口
|
||||
* @param {Array} pinnedCommands - pin命令列表
|
||||
*/
|
||||
const restorePinWindows = async (pinnedCommands) => {
|
||||
for (const command of pinnedCommands) {
|
||||
await createPinWindow(command.info, command.position);
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
createPinWindow,
|
||||
removePinWindow,
|
||||
getPinWindows,
|
||||
restorePinWindows,
|
||||
};
|
40
plugin/lib/pin/style.css
Normal file
40
plugin/lib/pin/style.css
Normal file
@ -0,0 +1,40 @@
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background: transparent;
|
||||
overflow: hidden;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.pin-container {
|
||||
width: 52px;
|
||||
height: 52px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
.pin-container:hover {
|
||||
transform: scale(1.1);
|
||||
}
|
||||
|
||||
.pin-icon {
|
||||
width: 45px;
|
||||
height: 45px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.pin-icon img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
body[data-theme="dark"] .pin-icon {
|
||||
background: rgba(57, 57, 57, 0.09);
|
||||
border: 1px solid rgb(59 58 58 / 5%);
|
||||
box-shadow: 0 1px 5px rgb(0 0 0 / 20%), 0 2px 2px rgb(0 0 0 / 14%),
|
||||
0 3px 1px -2px rgb(69 67 67 / 12%);
|
||||
}
|
15
plugin/lib/pin/view.html
Normal file
15
plugin/lib/pin/view.html
Normal file
@ -0,0 +1,15 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>Pin</title>
|
||||
<link rel="stylesheet" href="style.css" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="pin-container">
|
||||
<div class="pin-icon">
|
||||
<img id="command-icon" src="" alt="command icon" />
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -20,6 +20,7 @@ const md5 = (input) => {
|
||||
|
||||
window.lodashM = require("./lib/lodashMini");
|
||||
window.pinyinMatch = require("pinyin-match");
|
||||
window.pinService = require("./lib/pin/service");
|
||||
window.DOMPurify = DOMPurify;
|
||||
|
||||
const createTerminalCommand = require("./lib/createTerminalCommand");
|
||||
|
@ -122,6 +122,10 @@ export default defineComponent({
|
||||
window.quickcommandHttpServer().run(this.nativeProfile.serverPort);
|
||||
console.log("Server Start...");
|
||||
}
|
||||
// 恢复固定到桌面的命令
|
||||
if (this.nativeProfile.pinnedCommands) {
|
||||
window.pinService.restorePinWindows(this.nativeProfile.pinnedCommands);
|
||||
}
|
||||
},
|
||||
enterPlugin(enter) {
|
||||
this.updateExp();
|
||||
|
@ -4,6 +4,20 @@
|
||||
v-ripple
|
||||
:class="{ [`text-${disabledColor}`]: !isActivated, command: 1 }"
|
||||
>
|
||||
<q-badge floating transparent style="z-index: 1000" v-if="isActivated">
|
||||
<q-btn
|
||||
flat
|
||||
round
|
||||
dense
|
||||
:color="isPinned ? 'amber' : 'grey'"
|
||||
icon="push_pin"
|
||||
@click.stop="togglePin"
|
||||
size="12px"
|
||||
>
|
||||
<q-tooltip>{{ isPinned ? "取消固定到桌面" : "固定到桌面" }}</q-tooltip>
|
||||
</q-btn>
|
||||
</q-badge>
|
||||
|
||||
<component
|
||||
:is="currentLayout"
|
||||
:commandInfo="commandInfo"
|
||||
@ -56,6 +70,33 @@ export default {
|
||||
"--icon-url": `url(${this.commandInfo.features.icon})`,
|
||||
};
|
||||
},
|
||||
isPinned() {
|
||||
return (
|
||||
this.$root.nativeProfile.pinnedCommands?.some(
|
||||
(cmd) => cmd.info.features.code === this.commandInfo.features.code
|
||||
) || false
|
||||
);
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
async togglePin() {
|
||||
if (this.isPinned) {
|
||||
window.pinService.removePinWindow(this.commandInfo.features.code);
|
||||
this.$root.nativeProfile.pinnedCommands =
|
||||
this.$root.nativeProfile.pinnedCommands.filter(
|
||||
(cmd) => cmd.info.features.code !== this.commandInfo.features.code
|
||||
);
|
||||
} else {
|
||||
await window.pinService.createPinWindow(this.commandInfo);
|
||||
if (!this.$root.nativeProfile.pinnedCommands) {
|
||||
this.$root.nativeProfile.pinnedCommands = [];
|
||||
}
|
||||
this.$root.nativeProfile.pinnedCommands.push({
|
||||
info: this.commandInfo,
|
||||
position: utools.getCursorScreenPoint(),
|
||||
});
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
@ -80,4 +121,28 @@ export default {
|
||||
box-shadow: 0 1px 5px rgb(0 0 0 / 20%), 0 2px 2px rgb(0 0 0 / 14%),
|
||||
0 3px 1px -2px rgb(69 67 67 / 12%);
|
||||
}
|
||||
|
||||
.pin-icon {
|
||||
opacity: 0;
|
||||
transform: translateY(-5px);
|
||||
visibility: hidden;
|
||||
transition: all 0.35s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
will-change: transform, opacity, visibility;
|
||||
}
|
||||
|
||||
.q-card:hover .pin-icon {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
visibility: visible;
|
||||
backdrop-filter: blur(1px);
|
||||
}
|
||||
|
||||
.pin-icon .q-btn {
|
||||
transition: transform 0.35s cubic-bezier(0.68, -0.6, 0.32, 1.6);
|
||||
will-change: transform;
|
||||
}
|
||||
|
||||
.pin-icon .q-btn:hover {
|
||||
transform: scale(1.15);
|
||||
}
|
||||
</style>
|
||||
|
Loading…
x
Reference in New Issue
Block a user