Skip to content

Commit

Permalink
feat(manager): support plugin teleport
Browse files Browse the repository at this point in the history
  • Loading branch information
shigma committed Jun 6, 2022
1 parent 34f431b commit bcf3e1a
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 37 deletions.
73 changes: 41 additions & 32 deletions plugins/frontend/manager/client/settings/select.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,44 +8,26 @@
<k-tab-item class="k-tab-group-title" label="@global" v-model="model">
全局设置
</k-tab-item>
<el-tree :data="plugins.data" :expand-on-click-node="false" default-expand-all :props="{ class: getClass }"
<el-tree
:data="plugins.data"
:expand-on-click-node="false"
default-expand-all draggable
:props="{ class: getClass }"
:allow-drag="allowDrag"
:allow-drop="allowDrop"
@node-click="handleClick"
@node-drop="handleDrop"
#="{ node }">
{{ node.label }}
</el-tree>
<!-- <div class="k-tab-group-title">
运行中的插件
</div>
<k-tab-group
:data="packages" v-model="model"
:filter="data => data.id" #="data">
<span :class="{ readonly: isReadonly(data) }">{{ data.shortname }}</span>
</k-tab-group>
<div class="k-tab-group-title">
未运行的插件
<k-hint placement="right" name="filter" v-model="config.showDepsOnly">
<template v-if="config.showDepsOnly">
<b>筛选:已开启</b><br>只显示依赖的插件。
</template>
<template v-else>
<b>筛选:已关闭</b><br>显示本地的全部插件。
</template>
</k-hint>
</div>
<k-tab-group
:data="packages" v-model="model"
:filter="data => !data.id && data.name && (!config.showDepsOnly || store.dependencies[data.name])" #="data">
<span :class="{ readonly: isReadonly(data) }">{{ data.shortname }}</span>
</k-tab-group> -->
</el-scrollbar>
</template>

<script lang="ts" setup>
import { ref, computed, onActivated, nextTick } from 'vue'
import { store } from '@koishijs/client'
import { Tree, envMap, plugins } from './utils'
import { config } from '../utils'
import { store, send } from '@koishijs/client'
import { Tree, plugins } from './utils'
const props = defineProps<{
modelValue: string
Expand All @@ -58,10 +40,41 @@ const model = computed({
set: val => emits('update:modelValue', val),
})
function allowDrag(node: Tree) {
return node.path !== ''
}
interface Node {
data: Tree
parent: Node
isLeaf: boolean
childNodes: Node[]
}
function allowDrop(source: Node, target: Node, type: 'inner' | 'prev' | 'next') {
return type === 'inner' ? !target.isLeaf : target.data.path !== ''
}
function handleClick(tree: Tree) {
model.value = tree.path
}
function handleDrop(source: Node, target: Node, position: 'before' | 'after' | 'inner', event: DragEvent) {
const parent = position === 'inner' ? target : target.parent
const oldPath = source.data.path
const ctxPath = parent.data.path
const index = parent.childNodes.findIndex(node => node.data.path === oldPath)
send('manager/teleport', oldPath, ctxPath, index)
const segments1 = oldPath.split('/')
const segments2 = ctxPath ? ctxPath.split('/') : []
segments2.push(segments1.pop())
const newPath = source.data.path = segments2.join('/')
if (oldPath === newPath) return
plugins.value.map[newPath] = plugins.value.map[oldPath]
delete plugins.value.map[oldPath]
emits('update:modelValue', newPath)
}
function getClass(tree: Tree) {
const words: string[] = []
if (tree.children) words.push('is-group')
Expand All @@ -80,10 +93,6 @@ const packages = computed(() => {
const root = ref<{ $el: HTMLElement }>(null)
const keyword = ref('')
function isReadonly(data: any) {
return envMap.value[data.name].invalid
}
onActivated(async () => {
const container = root.value.$el
await nextTick()
Expand Down
47 changes: 42 additions & 5 deletions plugins/frontend/manager/src/writer.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,42 @@
import { DataService } from '@koishijs/plugin-console'
import { Adapter, App, Bot, Context } from 'koishi'
import { Adapter, App, Bot, Context, remove } from 'koishi'
import { Loader } from '@koishijs/cli'

declare module '@koishijs/plugin-console' {
interface Events {
'manager/app-reload'(config: any): void
'manager/teleport'(source: string, target: string, index: number): void
'manager/plugin-reload'(path: string, config: any): void
'manager/plugin-unload'(path: string, config: any): void
'manager/bot-update'(id: string, adapter: string, config: any): void
'manager/bot-remove'(id: string): void
}
}

function insertKey(object: {}, temp: {}, rest: string[]) {
for (const key of rest) {
temp[key] = object[key]
delete object[key]
}
Object.assign(object, temp)
}

function rename(object: any, old: string, neo: string, value: string) {
const keys = Object.keys(object)
const index = keys.indexOf(old)
const rest = index < 0 ? [] : keys.slice(index + 1)
const temp = { [neo]: value }
delete object[old]
for (const key of rest) {
temp[key] = object[key]
delete object[key]
insertKey(object, temp, rest)
}

function dropKey(plugins: {}, name: string) {
if (!(name in plugins)) {
name = '~' + name
}
Object.assign(object, temp)
const value = plugins[name]
delete plugins[name]
return { [name]: value }
}

class ConfigWriter extends DataService<App.Config> {
Expand All @@ -38,6 +52,10 @@ class ConfigWriter extends DataService<App.Config> {
this.reloadApp(config)
}, { authority: 4 })

ctx.console.addListener('manager/teleport', (source, target, index) => {
this.teleport(source, target, index)
}, { authority: 4 })

ctx.console.addListener('manager/plugin-reload', (name, config) => {
this.reloadPlugin(name, config)
}, { authority: 4 })
Expand Down Expand Up @@ -93,6 +111,25 @@ class ConfigWriter extends DataService<App.Config> {
this.loader.writeConfig()
}

teleport(source: string, target: string, index: number) {
const [runtimeS, nameS] = this.resolve(source)
const [runtimeT] = this.resolve(target ? target + '/' : '')

// teleport fork
const fork = runtimeS[Symbol.for('koishi.loader.record')][nameS]
if (fork) {
remove(fork.parent.state.disposables, fork.dispose)
fork.parent = runtimeT.context
fork.parent.state.disposables.push(fork.dispose)
}

// teleport config
const temp = dropKey(runtimeS.config, nameS)
const rest = Object.keys(runtimeT.config).slice(index)
insertKey(runtimeT.config, temp, rest)
this.loader.writeConfig()
}

updateBot(id: string, adapter: string, config: any) {
let bot: Bot
const name = 'adapter-' + adapter
Expand Down

0 comments on commit bcf3e1a

Please sign in to comment.