Skip to content

Commit a00432f

Browse files
committed
✨ Added clipboard search shortcut configuration
1 parent 238821d commit a00432f

11 files changed

+164
-115
lines changed

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
"@vueuse/motion": "2.0.0-beta.12",
2424
"@vueuse/router": "^9.9.0",
2525
"@widget-js/core": "^0.11.22-beta.1",
26-
"@widget-js/vue3": "^0.11.21-rc.2",
26+
"@widget-js/vue3": "^0.11.21-rc.5",
2727
"animate.css": "^4.1.1",
2828
"axios": "^1.6.0",
2929
"color": "^4.2.3",
File renamed without changes.
File renamed without changes.
File renamed without changes.

public/widget.json

+32-32
Original file line numberDiff line numberDiff line change
@@ -366,38 +366,6 @@
366366
"configPagePath": "/widget/config/countdown2",
367367
"routes": []
368368
},
369-
{
370-
"name": "cn.widgetjs.widgets.countdown",
371-
"title": {
372-
"zh-CN": "倒计时"
373-
},
374-
"description": {
375-
"zh-CN": "简单的倒计时组件,支持农历"
376-
},
377-
"keywords": [
378-
"recommend"
379-
],
380-
"security": false,
381-
"permissions": [],
382-
"lang": "zh-CN",
383-
"width": 2,
384-
"height": 2,
385-
"maxWidth": 4,
386-
"webviewTag": false,
387-
"maxHeight": 4,
388-
"minWidth": 2,
389-
"minHeight": 2,
390-
"movable": true,
391-
"singleton": false,
392-
"resizable": true,
393-
"path": "/widget/countdown",
394-
"meta": {},
395-
"backgroundThrottling": true,
396-
"previewImage": "/images/preview_countdown.png",
397-
"supportDeployMode": 17,
398-
"configPagePath": "/widget/config/countdown",
399-
"routes": []
400-
},
401369
{
402370
"name": "cn.widgetjs.widgets.clipboard",
403371
"title": {
@@ -432,6 +400,38 @@
432400
"configPagePath": "/widget/config/clipboard",
433401
"routes": []
434402
},
403+
{
404+
"name": "cn.widgetjs.widgets.countdown",
405+
"title": {
406+
"zh-CN": "倒计时"
407+
},
408+
"description": {
409+
"zh-CN": "简单的倒计时组件,支持农历"
410+
},
411+
"keywords": [
412+
"recommend"
413+
],
414+
"security": false,
415+
"permissions": [],
416+
"lang": "zh-CN",
417+
"width": 2,
418+
"height": 2,
419+
"maxWidth": 4,
420+
"webviewTag": false,
421+
"maxHeight": 4,
422+
"minWidth": 2,
423+
"minHeight": 2,
424+
"movable": true,
425+
"singleton": false,
426+
"resizable": true,
427+
"path": "/widget/countdown",
428+
"meta": {},
429+
"backgroundThrottling": true,
430+
"previewImage": "/images/preview_countdown.png",
431+
"supportDeployMode": 17,
432+
"configPagePath": "/widget/config/countdown",
433+
"routes": []
434+
},
435435
{
436436
"name": "cn.widgetjs.widgets.birthday_list",
437437
"title": {

src/widgets/clipboard/ClipboardConfigView.vue

+52-43
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,64 @@
1-
<script lang="ts">
2-
import {
3-
WidgetConfigOption,
4-
WidgetEditDialog,
5-
useWidget,
6-
} from '@widget-js/vue3'
7-
import {
8-
WidgetData,
9-
WidgetDataApi,
10-
} from '@widget-js/core'
11-
12-
export default {
13-
name: '',
14-
components: { WidgetEditDialog },
15-
setup() {
16-
const {
17-
widgetData,
18-
widgetParams,
19-
} = useWidget(WidgetData)
20-
21-
// 修改成需要设置组件参数配置
22-
const widgetConfigOption = new WidgetConfigOption({
23-
custom: true,
24-
theme: {
25-
backgroundColor: true,
26-
borderRadius: true,
27-
},
28-
})
29-
30-
return {
31-
widgetData,
32-
widgetParams,
33-
widgetConfigOption,
34-
}
35-
},
36-
methods: {
37-
async onSaveClick() {
38-
await WidgetDataApi.save(this.widgetData)
39-
window.close()
40-
},
41-
},
1+
<script lang="ts" setup>
2+
import { WidgetConfigOption, WidgetEditDialog, useWidget } from '@widget-js/vue3'
3+
import { BroadcastApi, BroadcastEvent, BrowserWindowApi, WidgetApiEvent, WidgetData } from '@widget-js/core'
4+
import { useLocalStorage } from '@vueuse/core'
5+
import ClipboardWidget from '@/widgets/clipboard/Clipboard.widget'
6+
import { searchPlatformList } from '@/widgets/clipboard/model/SearchPlatform'
7+
8+
const shortcut = useLocalStorage(`${ClipboardWidget.name}.shortcut`, 'Meta+Alt+S')
9+
const searchPlatform = useLocalStorage(`${ClipboardWidget.name}.platform`, 'google')
10+
const {
11+
widgetData,
12+
widgetParams,
13+
} = useWidget(WidgetData)
14+
15+
const widgetConfigOption = new WidgetConfigOption({
16+
custom: true,
17+
})
18+
19+
async function apply() {
20+
const event = new BroadcastEvent({
21+
event: WidgetApiEvent.DATA_CHANGED,
22+
payload: { name: ClipboardWidget.name },
23+
})
24+
await BroadcastApi.send(event)
4225
}
26+
27+
async function save() {
28+
await apply()
29+
window.close()
30+
}
31+
32+
BrowserWindowApi.setup({
33+
width: 500,
34+
height: 400,
35+
center: true,
36+
})
4337
</script>
4438

4539
<template>
4640
<WidgetEditDialog
4741
v-model="widgetData" :widget-params="widgetParams"
4842
:option="widgetConfigOption"
49-
@confirm="onSaveClick()"
43+
@apply="apply"
44+
@confirm="save"
5045
>
5146
<template #custom>
52-
<!-- TODO 这里写自定义表单内容 -->
47+
<el-alert type="info" :closable="false">
48+
按下快捷键搜索剪贴板内容,不用鼠标点击搜索框
49+
</el-alert>
50+
<el-form class="mt-4" label-width="100">
51+
<el-form-item label="搜索快捷键">
52+
<BindShortcutField v-model="shortcut" />
53+
</el-form-item>
54+
<el-form-item label="搜索平台">
55+
<el-radio-group v-model="searchPlatform">
56+
<el-radio v-for="platform in searchPlatformList" :key="platform.value" :label="platform.value">
57+
{{ platform.title }}
58+
</el-radio>
59+
</el-radio-group>
60+
</el-form-item>
61+
</el-form>
5362
</template>
5463
</WidgetEditDialog>
5564
</template>
+10-10
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,22 @@
11
import type { RouteRecordRaw } from 'vue-router'
2-
import ClipboardWidgetDefine from './Clipboard.widget'
2+
import ClipboardWidget from './Clipboard.widget'
33

4-
const path = ClipboardWidgetDefine.path
5-
const name = ClipboardWidgetDefine.name
4+
const path = ClipboardWidget.path
5+
const name = ClipboardWidget.name
66

7-
// const configUrl = ClipboardWidgetDefine.getConfigRoute()!.path;
7+
const configUrl = ClipboardWidget.configPagePath!
88

99
const ClipboardWidgetRoutes: RouteRecordRaw[] = [
1010
{
1111
path,
1212
name: `${name}`,
13-
component: () => import(/* webpackChunkName: "com.wisdom.widgets.clipboard" */ './ClipboardWidget.vue'),
13+
component: () => import(/* webpackChunkName: "com.wisdom.widgets.clipboard" */ './ClipboardWidgetView.vue'),
14+
},
15+
{
16+
path: configUrl,
17+
name: `${name}.config`,
18+
component: () => import(/* webpackChunkName: "com.wisdom.widgets.clipboard.config" */ './ClipboardConfigView.vue'),
1419
},
15-
// {
16-
// path: configUrl,
17-
// name: `${name}.config`,
18-
// component: () => import(/* webpackChunkName: "com.wisdom.widgets.clipboard.config" */ './ClipboardConfigView.vue')
19-
// }
2020
]
2121

2222
export default ClipboardWidgetRoutes

src/widgets/clipboard/ClipboardWidget.vue src/widgets/clipboard/ClipboardWidgetView.vue

+24-27
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
<script lang="ts" setup>
2-
import { useAppBroadcast } from '@widget-js/vue3'
2+
import { useAppBroadcast, useShortcutListener } from '@widget-js/vue3'
33
import {
44
BrowserWindowApi,
55
BrowserWindowApiEvent,
66
ClipboardApiEvent,
7+
ShortcutApi,
78
} from '@widget-js/core'
89
import {
910
ref,
@@ -12,12 +13,12 @@ import {
1213
import type { Transition } from '@vueuse/motion'
1314
import { useMotion } from '@vueuse/motion'
1415
import delay from 'lodash-es/delay'
16+
import { useLocalStorage } from '@vueuse/core'
1517
import { ClipboardData } from '@/widgets/clipboard/model/ClipboardData'
18+
import type { SearchEngine } from '@/widgets/clipboard/model/SearchPlatform'
19+
import { search, searchPlatformList } from '@/widgets/clipboard/model/SearchPlatform'
20+
import ClipboardWidget from '@/widgets/clipboard/Clipboard.widget'
1621
17-
type SearchEngine = 'bing' | 'google' | 'baidu'
18-
// const { widgetData } = useWidget(ClipboardListData, {
19-
// loadDataByWidgetName: true
20-
// })
2122
const showing = ref(false)
2223
const data = ref<ClipboardData | undefined>()
2324
@@ -76,20 +77,6 @@ function startHideTimer() {
7677
}, 3000)
7778
}
7879
79-
function search(se: SearchEngine) {
80-
switch (se) {
81-
case 'bing':
82-
BrowserWindowApi.openUrl(`https://cn.bing.com/search?q=${data.value?.content}`, { external: true })
83-
break
84-
case 'google':
85-
BrowserWindowApi.openUrl(`https://www.google.com/search?q=${data.value?.content}`, { external: true })
86-
break
87-
case 'baidu':
88-
BrowserWindowApi.openUrl(`https://www.baidu.com/s?wd=${data.value?.content}`, { external: true })
89-
break
90-
}
91-
}
92-
9380
watch(
9481
() => motionProperties.y,
9582
(newY) => {
@@ -111,6 +98,7 @@ async function initWindow() {
11198
}
11299
113100
initWindow()
101+
114102
useAppBroadcast([ClipboardApiEvent.CHANGED, BrowserWindowApiEvent.FOCUS], async (broadcast) => {
115103
if (broadcast.event == ClipboardApiEvent.CHANGED) {
116104
const text = broadcast.payload.content as string
@@ -122,6 +110,21 @@ useAppBroadcast([ClipboardApiEvent.CHANGED, BrowserWindowApiEvent.FOCUS], async
122110
startHideTimer()
123111
}
124112
})
113+
114+
const shortcut = useLocalStorage(`${ClipboardWidget.name}.shortcut`, 'Meta+Alt+S', { listenToStorageChanges: true })
115+
const searchPlatform = useLocalStorage<SearchEngine>(`${ClipboardWidget.name}.platform`, 'google', { listenToStorageChanges: true })
116+
watch(shortcut, (newShortcut, oldValue) => {
117+
ShortcutApi.unregister(oldValue)
118+
ShortcutApi.register(newShortcut)
119+
})
120+
121+
ShortcutApi.register(shortcut.value)
122+
123+
useShortcutListener(() => {
124+
if (data.value) {
125+
search(searchPlatform.value, data.value!.content)
126+
}
127+
})
125128
</script>
126129

127130
<template>
@@ -130,14 +133,8 @@ useAppBroadcast([ClipboardApiEvent.CHANGED, BrowserWindowApiEvent.FOCUS], async
130133
{{ data?.content }}
131134
</div>
132135
<div class="actions">
133-
<div class="search-engine" @click="search('bing')">
134-
<img src="./assets/bing.png" alt="Bing" @click="search('bing')">
135-
</div>
136-
<div class="search-engine">
137-
<img src="./assets/google.png" alt="Google" @click="search('google')">
138-
</div>
139-
<div class="search-engine">
140-
<img src="./assets/baidu.png" alt="BaiDu" @click="search('baidu')">
136+
<div v-for="platform in searchPlatformList" :key="platform.value" class="search-engine" @click="search(platform.value)">
137+
<img :src="platform.icon" :alt="platform.title">
141138
</div>
142139
</div>
143140
</div>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import { BrowserWindowApi } from '@widget-js/core'
2+
3+
export type SearchEngine = 'bing' | 'google' | 'baidu'
4+
5+
export interface SearchPlatform {
6+
title: string
7+
url: string
8+
value: SearchEngine
9+
icon: string
10+
}
11+
12+
export const searchPlatformList: SearchPlatform[] = [
13+
{
14+
title: 'Google',
15+
url: 'https://www.google.com/search?q=%s',
16+
value: 'google',
17+
icon: '/images/logo/google.png',
18+
},
19+
{
20+
title: 'Bing',
21+
url: 'https://cn.bing.com/search?q=%s',
22+
value: 'bing',
23+
icon: '/images/logo/bing.png',
24+
},
25+
{
26+
title: '百度',
27+
url: 'https://www.baidu.com/s?wd=%s',
28+
value: 'baidu',
29+
icon: '/images/logo/baidu.png',
30+
},
31+
]
32+
33+
export function search(se: SearchEngine, keyword: string) {
34+
const platform = searchPlatformList.find(item => item.value === se)
35+
if (platform) {
36+
const url = platform.url.replaceAll('%s', keyword)
37+
BrowserWindowApi.openUrl(url, { external: true })
38+
}
39+
}

uno.config.ts

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import { defineConfig } from 'unocss'
2+
3+
export default defineConfig({
4+
})

vite.config.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import vue from '@vitejs/plugin-vue'
44
import AutoImport from 'unplugin-auto-import/vite'
55
import Components from 'unplugin-vue-components/vite'
66
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
7-
import ViteWidget from '@widget-js/vite-plugin-widget'
7+
import widget from '@widget-js/vite-plugin-widget'
88
import checker from 'vite-plugin-checker'
99
import UnoCSS from 'unocss/vite'
1010

@@ -20,7 +20,7 @@ export default defineConfig({
2020
},
2121
},
2222
},
23-
plugins: [vue(), UnoCSS(), ViteWidget(), checker({ typescript: true }), AutoImport({ resolvers: [ElementPlusResolver()] }), Components({ resolvers: [ElementPlusResolver()] })],
23+
plugins: [vue(), UnoCSS(), widget(), checker({ typescript: true }), AutoImport({ resolvers: [ElementPlusResolver()] }), Components({ resolvers: [ElementPlusResolver()] })],
2424
resolve: {
2525
alias: [{
2626
find: '@',

0 commit comments

Comments
 (0)