mirror of
https://github.com/ZiuChen/ClipboardManager.git
synced 2025-06-07 13:54:05 +08:00
Merge branch 'v1.4.3'
This commit is contained in:
commit
33306aadac
56
public/listener.js
Normal file
56
public/listener.js
Normal file
@ -0,0 +1,56 @@
|
||||
const { chmodSync, existsSync } = require('fs')
|
||||
const { EventEmitter } = require('events')
|
||||
const path = require('path')
|
||||
const { execFile } = require('child_process')
|
||||
|
||||
class ClipboardEventListener extends EventEmitter {
|
||||
constructor() {
|
||||
super()
|
||||
this.child = null
|
||||
this.listening = false
|
||||
}
|
||||
startListening(dbPath) {
|
||||
const targetMap = {
|
||||
win32: 'clipboard-event-handler-win32.exe',
|
||||
linux: 'clipboard-event-handler-linux'
|
||||
}
|
||||
const { platform } = process
|
||||
const target = path.resolve(
|
||||
dbPath.split('_utools_clipboard_manager_storage')[0],
|
||||
targetMap[platform]
|
||||
)
|
||||
if (!existsSync(target)) {
|
||||
this.emit('error', '剪贴板监听程序不存在')
|
||||
return
|
||||
}
|
||||
if (platform === 'win32') {
|
||||
this.child = execFile(target)
|
||||
} else if (platform === 'linux') {
|
||||
chmodSync(target, 0o755)
|
||||
this.child = execFile(target)
|
||||
} else {
|
||||
throw 'Not yet supported'
|
||||
}
|
||||
this.child.stdout.on('data', (data) => {
|
||||
if (data.trim() === 'CLIPBOARD_CHANGE') {
|
||||
this.emit('change')
|
||||
}
|
||||
})
|
||||
this.child.stdout.on('close', () => {
|
||||
this.emit('close')
|
||||
this.listening = false
|
||||
})
|
||||
this.child.stdout.on('exit', () => {
|
||||
this.emit('exit')
|
||||
this.listening = false
|
||||
})
|
||||
this.listening = true
|
||||
}
|
||||
stopListening() {
|
||||
const res = this.child.kill()
|
||||
this.listening = false
|
||||
return res
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = new ClipboardEventListener()
|
@ -1,5 +1,5 @@
|
||||
{
|
||||
"version": "1.4.2",
|
||||
"version": "1.4.3",
|
||||
"pluginName": "超级剪贴板",
|
||||
"description": "强大的剪贴板管理工具",
|
||||
"author": "ZiuChen",
|
||||
|
@ -1,5 +1,6 @@
|
||||
const { existsSync, readFileSync, writeFileSync, mkdirSync } = require('fs')
|
||||
const crypto = require('crypto')
|
||||
const listener = require('./listener')
|
||||
const { clipboard } = require('electron')
|
||||
const time = require('./time')
|
||||
|
||||
@ -11,5 +12,6 @@ window.exports = {
|
||||
mkdirSync,
|
||||
crypto,
|
||||
clipboard,
|
||||
time
|
||||
time,
|
||||
Buffer
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
<template>
|
||||
<div class="app">
|
||||
<Main @show-setting="settingShown = true" v-show="!settingShown"></Main>
|
||||
<Main @show-setting="settingShown = true" v-if="!settingShown"></Main>
|
||||
<transition name="el-fade-in-linear">
|
||||
<Setting v-show="settingShown" @back="settingShown = false"></Setting>
|
||||
<Setting v-if="settingShown" @back="settingShown = false"></Setting>
|
||||
</transition>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -80,9 +80,18 @@ const props = defineProps({
|
||||
currentActiveTab: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
isSearchPanelExpand: {
|
||||
type: Boolean,
|
||||
required: true
|
||||
}
|
||||
})
|
||||
const emit = defineEmits(['onDataChange', 'onDataRemove', 'onSelectItemAdd', 'onMultiCopyExecute'])
|
||||
const emit = defineEmits([
|
||||
'onDataChange',
|
||||
'onDataRemove',
|
||||
'onMultiCopyExecute',
|
||||
'toggleMultiSelect'
|
||||
])
|
||||
const isOverSizedContent = (item) => {
|
||||
const { type, data } = item
|
||||
if (type === 'text') {
|
||||
@ -111,6 +120,7 @@ const handleItemClick = (ev, item) => {
|
||||
if (props.isMultiple === true) {
|
||||
const i = selectItemList.value.indexOf(item) // 在已选中列表中的位置
|
||||
const index = props.showList.indexOf(item) // 在全部列表中的位置
|
||||
activeIndex.value = index
|
||||
if (selectItemList.value.length !== 0 && isShiftDown.value) {
|
||||
// 列表不为空 且 Shift按下 多选
|
||||
// 找到selectList的最高位与最低位
|
||||
@ -159,8 +169,6 @@ const handleItemClick = (ev, item) => {
|
||||
selectItemList.value.push(item) // 添加到已选列表中
|
||||
}
|
||||
}
|
||||
|
||||
emit('onSelectItemAdd')
|
||||
} else {
|
||||
const { button } = ev
|
||||
if (button === 0) {
|
||||
@ -178,7 +186,11 @@ const handleItemClick = (ev, item) => {
|
||||
}
|
||||
}
|
||||
const activeIndex = ref(0)
|
||||
const handleMouseOver = (index) => (activeIndex.value = index)
|
||||
const handleMouseOver = (index) => {
|
||||
if (!props.isMultiple) {
|
||||
activeIndex.value = index
|
||||
}
|
||||
}
|
||||
// 父组件中改变了引用类型的地址 故要用 getter返回
|
||||
watch(
|
||||
() => props.showList,
|
||||
@ -194,25 +206,23 @@ onMounted(() => {
|
||||
const isCopy = (ctrlKey || metaKey) && (key === 'C' || key === 'c')
|
||||
const isNumber = parseInt(key) <= 9 && parseInt(key) >= 0
|
||||
const isShift = key === 'Shift'
|
||||
const isSpace = key === ' '
|
||||
const activeNode = !props.isMultiple
|
||||
? document.querySelector('.clip-item.active' + (isArrowDown ? '+.clip-item' : ''))
|
||||
: document.querySelector('.clip-item.multi-active' + (isArrowDown ? '+.clip-item' : ''))
|
||||
if (isArrowUp) {
|
||||
if (activeIndex.value === 1) window.toTop()
|
||||
if (activeIndex.value > 0) {
|
||||
activeIndex.value--
|
||||
const activeNode = document.querySelector('.clip-item.active')
|
||||
if (activeIndex.value === 1) {
|
||||
window.toTop()
|
||||
} else {
|
||||
activeNode?.previousElementSibling?.previousElementSibling?.scrollIntoView({
|
||||
block: 'nearest',
|
||||
inline: 'nearest'
|
||||
})
|
||||
}
|
||||
activeNode.previousElementSibling.previousElementSibling.scrollIntoView({
|
||||
block: 'nearest',
|
||||
inline: 'nearest'
|
||||
})
|
||||
}
|
||||
} else if (isArrowDown) {
|
||||
if (activeIndex.value < props.showList.length - 1) {
|
||||
activeIndex.value++
|
||||
document
|
||||
.querySelector('.clip-item.active+.clip-item')
|
||||
?.scrollIntoView({ block: 'nearest', inline: 'nearest' })
|
||||
activeNode.scrollIntoView({ block: 'nearest', inline: 'nearest' })
|
||||
}
|
||||
} else if (isCopy) {
|
||||
if (!props.fullData.data) {
|
||||
@ -246,6 +256,25 @@ onMounted(() => {
|
||||
if (props.isMultiple) {
|
||||
isShiftDown.value = true
|
||||
}
|
||||
} else if (isSpace) {
|
||||
if (props.isSearchPanelExpand) {
|
||||
// 搜索栏展开状态 不进入多选
|
||||
return
|
||||
}
|
||||
if (!props.isMultiple) {
|
||||
emit('toggleMultiSelect') // 如果不是多选状态 则切换到多选状态
|
||||
}
|
||||
e.preventDefault()
|
||||
const i = selectItemList.value.findIndex((item) => item === props.showList[activeIndex.value])
|
||||
if (i !== -1) {
|
||||
selectItemList.value.splice(i, 1) // 如果已选中 则取消选中
|
||||
} else {
|
||||
selectItemList.value.push(props.showList[activeIndex.value]) // 如果未选中 则选中
|
||||
activeIndex.value++
|
||||
document
|
||||
.querySelector('.clip-item.multi-active+.clip-item')
|
||||
.scrollIntoView({ block: 'nearest', inline: 'nearest' })
|
||||
}
|
||||
}
|
||||
})
|
||||
document.addEventListener('keyup', (e) => {
|
||||
|
@ -4,7 +4,7 @@
|
||||
<template v-for="tab of tabs">
|
||||
<div
|
||||
:class="{ 'clip-switch-item': true, active: activeTab === tab.type }"
|
||||
@click="onNavClick(tab.type)"
|
||||
@click="toggleNav(tab.type)"
|
||||
>
|
||||
<component :is="tab.icon"></component>
|
||||
{{ tab.name }}
|
||||
@ -27,12 +27,7 @@ const tabs = [
|
||||
{ name: '收藏', type: 'collect', icon: Collection }
|
||||
]
|
||||
const activeTab = ref('all')
|
||||
const emit = defineEmits(['onNavClick'])
|
||||
const toggleNav = (type) => (activeTab.value = type)
|
||||
const onNavClick = (type) => {
|
||||
toggleNav(type)
|
||||
emit('onNavClick', type)
|
||||
}
|
||||
defineExpose({
|
||||
tabs,
|
||||
activeTab,
|
||||
|
@ -1,5 +1,5 @@
|
||||
{
|
||||
"title": "重要版本更新提示",
|
||||
"content": "1. 如果你是第一次使用此插件, 请务必设置跟随主程序启动选项, 否则可能导致剪贴板记录丢失</br>2. 插件使用过程中遇到任何问题, 请到论坛发布页回帖或加入QQ群反馈",
|
||||
"version": 2
|
||||
"content": "1. 如果你是第一次使用此插件, 请务必设置跟随主程序启动选项, 否则可能导致剪贴板记录丢失</br>2. 请手动安装`clipboard-event-handler`以获得最佳剪贴板监听性能</br>3. 插件使用过程中遇到任何问题, 请到论坛发布页回帖或加入QQ群反馈",
|
||||
"version": 3
|
||||
}
|
||||
|
@ -49,7 +49,7 @@
|
||||
"regex": "^(?:#?[a-f0-9]{6}|(?:(?:25[0-5]|2[0-4]\\d|1?\\d{1,2}), ?){2}(?:25[0-5]|2[0-4]\\d|1?\\d{1,2})|rgba?\\((?:(?:25[0-5]|2[0-4]\\d|1?\\d{1,2}), ?){2}(?:25[0-5]|2[0-4]\\d|1?\\d{1,2})(?:, ?(?:1|0|0\\.\\d{1,2}))?\\)|hs[liv]a?\\((?:360|(?:(?:3[0-5]\\d|[1-2]\\d{2}|\\d{1,2})(?:\\.\\d{1,15})?))(?:deg)?(?:, |,| )(?:100|\\d{1,2}(?:\\.\\d{1,15})?)%?(?:, |,| )(?:100|\\d{1,2}(?:\\.\\d{1,15})?)%?(?:, ?(?:1|0|0\\.\\d{1,2}))?\\))$"
|
||||
}
|
||||
],
|
||||
"command": "redirect:统计文本次数"
|
||||
"command": "redirect:颜色信息"
|
||||
},
|
||||
{
|
||||
"id": "custom.1663490862",
|
||||
|
@ -1,5 +1,15 @@
|
||||
const { utools, existsSync, readFileSync, writeFileSync, mkdirSync, crypto, clipboard, time } =
|
||||
window.exports
|
||||
const {
|
||||
utools,
|
||||
existsSync,
|
||||
readFileSync,
|
||||
writeFileSync,
|
||||
mkdirSync,
|
||||
crypto,
|
||||
listener,
|
||||
clipboard,
|
||||
time,
|
||||
Buffer
|
||||
} = window.exports
|
||||
import setting from './readSetting'
|
||||
|
||||
export default function initPlugin() {
|
||||
@ -205,23 +215,56 @@ export default function initPlugin() {
|
||||
db.addItem(item)
|
||||
}
|
||||
|
||||
let prev = db.dataBase.data[0] || {}
|
||||
function loop() {
|
||||
time.sleep(300).then(loop)
|
||||
const item = pbpaste()
|
||||
if (!item) return
|
||||
item.id = crypto.createHash('md5').update(item.data).digest('hex')
|
||||
if (item && prev.id != item.id) {
|
||||
// 剪切板元素 与最近一次复制内容不同
|
||||
prev = item
|
||||
handleClipboardChange(item)
|
||||
} else {
|
||||
// 剪切板元素 与上次复制内容相同
|
||||
const addCommonListener = () => {
|
||||
let prev = db.dataBase.data[0] || {}
|
||||
function loop() {
|
||||
time.sleep(300).then(loop)
|
||||
const item = pbpaste()
|
||||
if (!item) return
|
||||
item.id = crypto.createHash('md5').update(item.data).digest('hex')
|
||||
if (item && prev.id != item.id) {
|
||||
// 剪切板元素 与最近一次复制内容不同
|
||||
prev = item
|
||||
handleClipboardChange(item)
|
||||
} else {
|
||||
// 剪切板元素 与上次复制内容相同
|
||||
}
|
||||
}
|
||||
loop()
|
||||
}
|
||||
|
||||
const registerClipEvent = (listener) => {
|
||||
const exitHandler = () => {
|
||||
utools.showNotification('剪贴板监听异常退出 请重启插件以开启监听')
|
||||
utools.outPlugin()
|
||||
}
|
||||
const errorHandler = (error) => {
|
||||
const info = '请到设置页手动安装 clipboard-event-handler 剪贴板监听程序'
|
||||
utools.showNotification('启动剪贴板监听程序启动出错: ' + error + info)
|
||||
addCommonListener()
|
||||
}
|
||||
listener
|
||||
.on('change', handleClipboardChange)
|
||||
.on('close', exitHandler)
|
||||
.on('exit', exitHandler)
|
||||
.on('error', (error) => errorHandler(error))
|
||||
}
|
||||
|
||||
if (!utools.isMacOs()) {
|
||||
// 首次启动插件 即开启监听
|
||||
registerClipEvent(listener)
|
||||
listener.startListening(setting.database.path)
|
||||
} else {
|
||||
// macos 由于无法执行 clipboard-event-handler-mac 所以使用旧方法
|
||||
addCommonListener()
|
||||
}
|
||||
loop()
|
||||
|
||||
utools.onPluginEnter(() => {
|
||||
if (!listener.listening && !utools.isMacOs()) {
|
||||
// 进入插件后 如果监听已关闭 则重新开启监听
|
||||
registerClipEvent(listener)
|
||||
listener.startListening(setting.database.path)
|
||||
}
|
||||
toTop()
|
||||
resetNav()
|
||||
})
|
||||
|
@ -9,6 +9,7 @@ import 'element-plus/theme-chalk/el-input.css'
|
||||
import 'element-plus/theme-chalk/el-select.css'
|
||||
import 'element-plus/theme-chalk/el-option.css'
|
||||
import 'element-plus/theme-chalk/el-scrollbar.css'
|
||||
import 'element-plus/theme-chalk/el-tag.css'
|
||||
import {
|
||||
ElButton,
|
||||
ElMessageBox,
|
||||
@ -17,7 +18,8 @@ import {
|
||||
ElInput,
|
||||
ElSelect,
|
||||
ElOption,
|
||||
ElScrollbar
|
||||
ElScrollbar,
|
||||
ElTag
|
||||
} from 'element-plus'
|
||||
|
||||
const components = [
|
||||
@ -28,7 +30,8 @@ const components = [
|
||||
ElInput,
|
||||
ElSelect,
|
||||
ElOption,
|
||||
ElScrollbar
|
||||
ElScrollbar,
|
||||
ElTag
|
||||
]
|
||||
|
||||
document.querySelector('html').className = utools.isDarkColors() ? 'dark' : ''
|
||||
|
@ -12,12 +12,16 @@
|
||||
width: 85px;
|
||||
}
|
||||
&.operation-select {
|
||||
width: 450px;
|
||||
width: 520px;
|
||||
}
|
||||
}
|
||||
.el-textarea {
|
||||
width: 70%;
|
||||
}
|
||||
.el-tag {
|
||||
margin: 0 10px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.path {
|
||||
width: 65%;
|
||||
}
|
||||
|
@ -7,7 +7,7 @@
|
||||
@onDataRemove="handleDataRemove"
|
||||
@onOverlayClick="toggleFullData({ type: 'text', data: '' })"
|
||||
></ClipFullData>
|
||||
<ClipSwitch ref="ClipSwitchRef" @onNavClick="handleNavClick">
|
||||
<ClipSwitch ref="ClipSwitchRef">
|
||||
<template #SidePanel>
|
||||
<div class="clip-switch-btn-list" v-show="!isSearchPanelExpand">
|
||||
<span class="clip-switch-btn clip-select-count" v-show="isMultiple">
|
||||
@ -47,7 +47,9 @@
|
||||
:fullData="fullData"
|
||||
:isMultiple="isMultiple"
|
||||
:currentActiveTab="activeTab"
|
||||
:isSearchPanelExpand="isSearchPanelExpand"
|
||||
@onMultiCopyExecute="handleMultiCopyBtnClick"
|
||||
@toggleMultiSelect="() => (isMultiple = true)"
|
||||
@onDataChange="toggleFullData"
|
||||
@onDataRemove="handleDataRemove"
|
||||
>
|
||||
@ -153,7 +155,7 @@ const textFilterCallBack = (item) => {
|
||||
}
|
||||
}
|
||||
|
||||
const updateShowList = (type) => {
|
||||
const updateShowList = (type, toTop = true) => {
|
||||
// 更新显示列表
|
||||
showList.value = list.value
|
||||
.filter((item) =>
|
||||
@ -162,7 +164,7 @@ const updateShowList = (type) => {
|
||||
.filter((item) => (filterText.value ? item.type !== 'image' : item)) // 有过滤词 排除掉图片 DataURL
|
||||
.filter((item) => textFilterCallBack(item))
|
||||
.slice(0, GAP) // 重新切分懒加载列表
|
||||
window.toTop()
|
||||
toTop && window.toTop()
|
||||
}
|
||||
|
||||
const restoreDataBase = () => {
|
||||
@ -179,11 +181,6 @@ const restoreDataBase = () => {
|
||||
.catch(() => {})
|
||||
}
|
||||
|
||||
const handleNavClick = (type) => {
|
||||
updateShowList(type)
|
||||
offset.value = 0 // 重置懒加载偏移量
|
||||
}
|
||||
|
||||
const fullData = ref({ type: 'text', data: '' })
|
||||
const fullDataShow = ref(false)
|
||||
const toggleFullData = (item) => {
|
||||
@ -197,7 +194,7 @@ const ClipSwitchRef = ref()
|
||||
const handleDataRemove = () => {
|
||||
// 此函数须在挂载后执行
|
||||
list.value = window.db.dataBase.data
|
||||
updateShowList(ClipSwitchRef.value.activeTab)
|
||||
updateShowList(ClipSwitchRef.value.activeTab, false)
|
||||
}
|
||||
|
||||
const emit = defineEmits(['showSetting'])
|
||||
@ -226,17 +223,26 @@ onMounted(() => {
|
||||
updateShowList(activeTab.value)
|
||||
|
||||
// 定期检查更新
|
||||
let prev = {}
|
||||
setInterval(() => {
|
||||
const now = window.db.dataBase.data[0]
|
||||
if (prev?.id === now?.id) {
|
||||
} else {
|
||||
// 有更新
|
||||
if (!utools.isMacOs() && window.listener.listening) {
|
||||
// 非macOS系统且监听器开启时
|
||||
window.listener.on('change', () => {
|
||||
list.value = window.db.dataBase.data
|
||||
updateShowList(activeTab.value)
|
||||
prev = now
|
||||
}
|
||||
}, 800)
|
||||
})
|
||||
} else {
|
||||
// macOS且监听器启动失败时
|
||||
let prev = {}
|
||||
setInterval(() => {
|
||||
const now = window.db.dataBase.data[0]
|
||||
if (prev?.id === now?.id) {
|
||||
} else {
|
||||
// 有更新
|
||||
list.value = window.db.dataBase.data
|
||||
updateShowList(activeTab.value)
|
||||
prev = now
|
||||
}
|
||||
}, 800)
|
||||
}
|
||||
|
||||
// 监听搜索框
|
||||
watch(filterText, (val) => updateShowList(activeTab.value))
|
||||
@ -287,6 +293,7 @@ onMounted(() => {
|
||||
const isEnter = key === 'Enter'
|
||||
const isShift = key === 'Shift'
|
||||
const isAlt = key === 'Alt'
|
||||
const isSpace = key === ' '
|
||||
if (isTab) {
|
||||
const tabTypes = tabs.map((item) => item.type)
|
||||
const index = tabTypes.indexOf(activeTab.value)
|
||||
@ -308,6 +315,7 @@ onMounted(() => {
|
||||
} else if (isMultiple.value) {
|
||||
// 退出多选状态
|
||||
isMultiple.value = !isMultiple.value
|
||||
e.stopPropagation()
|
||||
} else {
|
||||
// 无上述情况 执行默认: 隐藏uTools主窗口
|
||||
}
|
||||
@ -323,6 +331,8 @@ onMounted(() => {
|
||||
} else if (ctrlKey || metaKey || isAlt) {
|
||||
// Ctrl: utools模拟执行粘贴时触发
|
||||
// Alt:
|
||||
} else if (isSpace) {
|
||||
// 空格向下多选
|
||||
} else {
|
||||
window.focus() // 其他键盘事件 直接聚焦搜索框
|
||||
}
|
||||
|
@ -2,13 +2,23 @@
|
||||
<div class="setting">
|
||||
<el-card class="setting-card">
|
||||
<template #header>
|
||||
<el-button type="primary" @click="handleLinkClick(0)">🚀 主页</el-button>
|
||||
<el-button @click="handleLinkClick(1)">⚡ 云同步教程</el-button>
|
||||
<el-button @click="handleLinkClick(1)">💡 创造自己的功能按钮</el-button>
|
||||
<el-button type="primary" @click="handleLinkClick(4)">💖 赞赏我</el-button>
|
||||
<el-button @click="handleLinkClick(0)">🚀 主页</el-button>
|
||||
<el-button @click="handleLinkClick(1)">⚡ 迁移数据 | 云同步 | 自定义功能</el-button>
|
||||
<el-button @click="handleLinkClick(2)">⭐ 开源代码</el-button>
|
||||
<el-button @click="handleLinkClick(3)">🎈 论坛发布页</el-button>
|
||||
</template>
|
||||
<div class="setting-card-content">
|
||||
<div class="setting-card-content-item">
|
||||
<span>剪贴板监听程序状态</span>
|
||||
<el-tag
|
||||
:type="listenStatus ? 'success' : 'warning'"
|
||||
@click="handleLinkClick(1)"
|
||||
title="手动安装剪贴板监听程序"
|
||||
>
|
||||
{{ listenStatus ? '已安装' : '未安装' }}
|
||||
</el-tag>
|
||||
</div>
|
||||
<div class="setting-card-content-item">
|
||||
<span>数据库路径</span>
|
||||
<el-input class="path" v-model="path" :title="path" disabled></el-input>
|
||||
@ -38,7 +48,6 @@
|
||||
multiple
|
||||
:multiple-limit="5"
|
||||
placeholder="请选择"
|
||||
:teleported="false"
|
||||
>
|
||||
<el-option
|
||||
v-for="{ id, title, icon } in [
|
||||
@ -66,7 +75,7 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import setting from '../global/readSetting'
|
||||
import restoreSetting from '../global/restoreSetting'
|
||||
@ -83,12 +92,15 @@ const shown = ref(operation.shown)
|
||||
const custom = ref(operation.custom)
|
||||
const stringCustom = ref(JSON.stringify(operation.custom))
|
||||
|
||||
const listenStatus = ref(false)
|
||||
|
||||
const handleLinkClick = (index) => {
|
||||
const links = [
|
||||
'https://ziuchen.gitee.io/project/ClipboardManager/',
|
||||
'https://ziuchen.gitee.io/project/ClipboardManager/guide/',
|
||||
'https://github.com/ZiuChen/ClipboardManager',
|
||||
'https://yuanliao.info/d/5722'
|
||||
'https://yuanliao.info/d/5722',
|
||||
'https://ziuchen.gitee.io/project/ClipboardManager/#%F0%9F%92%9D-%E6%84%9F%E8%B0%A2%E8%B5%9E%E8%B5%8F'
|
||||
]
|
||||
utools.shellOpenExternal(links[index])
|
||||
}
|
||||
@ -169,6 +181,10 @@ const handleRestoreBtnClick = () => {
|
||||
})
|
||||
.catch(() => {})
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
listenStatus.value = window.listener.listening
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
|
Loading…
x
Reference in New Issue
Block a user