mirror of
https://github.com/rubickCenter/rubick
synced 2025-06-29 17:22:44 +08:00
feat: 增加系统app搜索功能
This commit is contained in:
parent
56bf86286c
commit
74f7f3ebdf
@ -16,7 +16,7 @@
|
|||||||
id="search"
|
id="search"
|
||||||
:placeholder="subPlaceHolder && selected && selected.key === 'plugin-container' ? subPlaceHolder : 'Hi, Rubick'"
|
:placeholder="subPlaceHolder && selected && selected.key === 'plugin-container' ? subPlaceHolder : 'Hi, Rubick'"
|
||||||
class="main-input"
|
class="main-input"
|
||||||
@change="e => onSearch({value: e.target.value})"
|
@change="e => search({value: e.target.value})"
|
||||||
:value="searchValue"
|
:value="searchValue"
|
||||||
:maxLength="selected && selected.key !== 'plugin-container' ? 0 : 1000"
|
:maxLength="selected && selected.key !== 'plugin-container' ? 0 : 1000"
|
||||||
>
|
>
|
||||||
@ -33,7 +33,7 @@
|
|||||||
<a-list-item-meta
|
<a-list-item-meta
|
||||||
:description="item.desc"
|
:description="item.desc"
|
||||||
>
|
>
|
||||||
<span slot="title" >{{ item.name }}</span>
|
<span slot="title" v-html="renderTitle(item.name)" ></span>
|
||||||
<a-avatar
|
<a-avatar
|
||||||
slot="avatar"
|
slot="avatar"
|
||||||
:src="item.icon"
|
:src="item.icon"
|
||||||
@ -67,7 +67,7 @@
|
|||||||
<script>
|
<script>
|
||||||
import {mapActions, mapMutations, mapState} from "vuex";
|
import {mapActions, mapMutations, mapState} from "vuex";
|
||||||
import {ipcRenderer, remote} from "electron";
|
import {ipcRenderer, remote} from "electron";
|
||||||
import {getWindowHeight} from "./assets/common/utils";
|
import {getWindowHeight, debounce} from "./assets/common/utils";
|
||||||
|
|
||||||
const {Menu, MenuItem} = remote;
|
const {Menu, MenuItem} = remote;
|
||||||
|
|
||||||
@ -75,7 +75,8 @@ export default {
|
|||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
searchType: this.$route.query.searchType ? 'subWindow' : '',
|
searchType: this.$route.query.searchType ? 'subWindow' : '',
|
||||||
query: this.$route.query
|
query: this.$route.query,
|
||||||
|
searchFn: null,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
@ -89,6 +90,16 @@ export default {
|
|||||||
methods: {
|
methods: {
|
||||||
...mapActions('main', ['onSearch', 'showMainUI']),
|
...mapActions('main', ['onSearch', 'showMainUI']),
|
||||||
...mapMutations('main', ['commonUpdate']),
|
...mapMutations('main', ['commonUpdate']),
|
||||||
|
search(v) {
|
||||||
|
if (!this.searchFn) {
|
||||||
|
this.searchFn = debounce(this.onSearch, 200);
|
||||||
|
}
|
||||||
|
this.searchFn(v);
|
||||||
|
},
|
||||||
|
renderTitle(title) {
|
||||||
|
const result = title.split(this.searchValue);
|
||||||
|
return `<div>${result[0]}<span style="color: red">${this.searchValue}</span>${result[1]}</div>`
|
||||||
|
},
|
||||||
checkNeedInit(e) {
|
checkNeedInit(e) {
|
||||||
// 如果搜索栏无内容,且按了删除键,则清空 tag
|
// 如果搜索栏无内容,且按了删除键,则清空 tag
|
||||||
if (this.searchValue === '' && e.keyCode === 8) {
|
if (this.searchValue === '' && e.keyCode === 8) {
|
||||||
@ -178,6 +189,9 @@ export default {
|
|||||||
padding-top: 60px;
|
padding-top: 60px;
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
|
::-webkit-scrollbar {
|
||||||
|
width: 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.rubick-select, .rubick-select-subMenu {
|
.rubick-select, .rubick-select-subMenu {
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -211,6 +225,8 @@ export default {
|
|||||||
left: 0;
|
left: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
z-index: 99;
|
z-index: 99;
|
||||||
|
max-height: calc(~'100vh - 60px');
|
||||||
|
overflow: auto;
|
||||||
.op-item {
|
.op-item {
|
||||||
padding: 0 10px;
|
padding: 0 10px;
|
||||||
height: 60px;
|
height: 60px;
|
||||||
|
@ -39,11 +39,18 @@ const SYSTEM_PLUGINS = [
|
|||||||
],
|
],
|
||||||
"tag": 'rubick-screen-short-cut',
|
"tag": 'rubick-screen-short-cut',
|
||||||
}
|
}
|
||||||
]
|
];
|
||||||
|
|
||||||
|
const APP_FINDER_PATH = [
|
||||||
|
'/System/Applications',
|
||||||
|
'/Applications',
|
||||||
|
'/System/Library/PreferencePanes',
|
||||||
|
];
|
||||||
|
|
||||||
export {
|
export {
|
||||||
WINDOW_MAX_HEIGHT,
|
WINDOW_MAX_HEIGHT,
|
||||||
WINDOW_MIN_HEIGHT,
|
WINDOW_MIN_HEIGHT,
|
||||||
PRE_ITEM_HEIGHT,
|
PRE_ITEM_HEIGHT,
|
||||||
SYSTEM_PLUGINS,
|
SYSTEM_PLUGINS,
|
||||||
|
APP_FINDER_PATH,
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,8 @@ import fs from 'fs';
|
|||||||
import process from 'child_process';
|
import process from 'child_process';
|
||||||
import Store from 'electron-store';
|
import Store from 'electron-store';
|
||||||
import downloadFile from 'download';
|
import downloadFile from 'download';
|
||||||
|
import {nativeImage} from 'electron';
|
||||||
|
import {APP_FINDER_PATH} from './constans';
|
||||||
|
|
||||||
const store = new Store();
|
const store = new Store();
|
||||||
|
|
||||||
@ -148,6 +150,70 @@ function find(p, target = 'plugin.json') {
|
|||||||
console.log(e);
|
console.log(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
const fileLists = [];
|
||||||
|
// 默认搜索目录
|
||||||
|
APP_FINDER_PATH.forEach((searchPath) => {
|
||||||
|
fs.readdir(searchPath, (err, files) => {
|
||||||
|
try {
|
||||||
|
for (let i = 0; i < files.length; i++) {
|
||||||
|
const appName = files[i];
|
||||||
|
const extname = path.extname(appName);
|
||||||
|
const appSubStr = appName.split(extname)[0];
|
||||||
|
if ((extname === '.app' || extname === '.prefPane') >= 0 ) {
|
||||||
|
try {
|
||||||
|
const path1 = path.join(searchPath, `${appName}/Contents/Resources/App.icns`);
|
||||||
|
const path2 = path.join(searchPath, `${appName}/Contents/Resources/AppIcon.icns`);
|
||||||
|
const path3 = path.join(searchPath, `${appName}/Contents/Resources/${appSubStr}.icns`);
|
||||||
|
const path4 = path.join(searchPath, `${appName}/Contents/Resources/${appSubStr.replace(' ', '')}.icns`);
|
||||||
|
let iconPath = path1;
|
||||||
|
if (fs.existsSync(path1)) {
|
||||||
|
iconPath = path1;
|
||||||
|
} else if (fs.existsSync(path2)) {
|
||||||
|
iconPath = path2;
|
||||||
|
} else if (fs.existsSync(path3)) {
|
||||||
|
iconPath = path3;
|
||||||
|
} else if (fs.existsSync(path4)) {
|
||||||
|
iconPath = path4;
|
||||||
|
} else {
|
||||||
|
// 性能最低的方式
|
||||||
|
const resourceList = fs.readdirSync(path.join(searchPath, `${appName}/Contents/Resources`));
|
||||||
|
const iconName = resourceList.filter(file => path.extname(file) === '.icns')[0];
|
||||||
|
iconPath = path.join(searchPath, `${appName}/Contents/Resources/${iconName}`);
|
||||||
|
}
|
||||||
|
nativeImage.createThumbnailFromPath(iconPath, {width: 64, height: 64}).then(img => {
|
||||||
|
fileLists.push({
|
||||||
|
name: appSubStr,
|
||||||
|
value: 'plugin',
|
||||||
|
icon: img.toDataURL(),
|
||||||
|
desc: path.join(searchPath, appName),
|
||||||
|
type: 'app',
|
||||||
|
action: `open ${path.join(searchPath, appName).replace(' ', '\\ ')}`
|
||||||
|
})
|
||||||
|
})
|
||||||
|
} catch (e) {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
function debounce(fn, delay) {
|
||||||
|
let timer
|
||||||
|
return function () {
|
||||||
|
const context = this
|
||||||
|
const args = arguments
|
||||||
|
|
||||||
|
clearTimeout(timer)
|
||||||
|
timer = setTimeout(function () {
|
||||||
|
fn.apply(context, args)
|
||||||
|
}, delay)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export {
|
export {
|
||||||
getWindowHeight,
|
getWindowHeight,
|
||||||
@ -157,4 +223,6 @@ export {
|
|||||||
mergePlugins,
|
mergePlugins,
|
||||||
find,
|
find,
|
||||||
downloadZip,
|
downloadZip,
|
||||||
|
fileLists,
|
||||||
|
debounce,
|
||||||
}
|
}
|
||||||
|
@ -8,10 +8,12 @@ import {
|
|||||||
mergePlugins,
|
mergePlugins,
|
||||||
find,
|
find,
|
||||||
downloadZip,
|
downloadZip,
|
||||||
|
fileLists,
|
||||||
} from '../../assets/common/utils';
|
} from '../../assets/common/utils';
|
||||||
import systemMethod from '../../assets/common/system';
|
import systemMethod from '../../assets/common/system';
|
||||||
import fs from "fs";
|
import fs from "fs";
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
|
import {execSync} from 'child_process';
|
||||||
|
|
||||||
const state = {
|
const state = {
|
||||||
selected: null,
|
selected: null,
|
||||||
@ -89,7 +91,7 @@ const actions = {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
onSearch ({ commit }, paylpad) {
|
async onSearch ({ commit }, paylpad) {
|
||||||
if (state.selected && state.selected.key !== 'plugin-container') {
|
if (state.selected && state.selected.key !== 'plugin-container') {
|
||||||
commit('commonUpdate', {searchValue: ''});
|
commit('commonUpdate', {searchValue: ''});
|
||||||
return;
|
return;
|
||||||
@ -199,6 +201,16 @@ const actions = {
|
|||||||
]
|
]
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
options = [
|
||||||
|
...options,
|
||||||
|
...(fileLists.filter(plugin => plugin.name.indexOf(value) >= 0)).map(plugin => {
|
||||||
|
plugin.click = () => {
|
||||||
|
console.log(plugin)
|
||||||
|
actions.openPlugin({commit}, {plugin});
|
||||||
|
}
|
||||||
|
return plugin
|
||||||
|
}),
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
commit('commonUpdate', {
|
commit('commonUpdate', {
|
||||||
@ -224,6 +236,19 @@ const actions = {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
openPlugin({commit}, {cmd, plugin, feature, router}) {
|
openPlugin({commit}, {cmd, plugin, feature, router}) {
|
||||||
|
if (plugin.type === 'app') {
|
||||||
|
execSync(plugin.action);
|
||||||
|
commit('commonUpdate', {
|
||||||
|
selected: null,
|
||||||
|
showMain: false,
|
||||||
|
options: [],
|
||||||
|
searchValue: '',
|
||||||
|
});
|
||||||
|
ipcRenderer.send('changeWindowSize-rubick', {
|
||||||
|
height: getWindowHeight([]),
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
commit('commonUpdate', {
|
commit('commonUpdate', {
|
||||||
selected: {
|
selected: {
|
||||||
key: 'plugin-container',
|
key: 'plugin-container',
|
||||||
|
Loading…
x
Reference in New Issue
Block a user