Skip to content

Commit a9cb5df

Browse files
committed
feat: layer & custom inspector plugin source
1 parent cb6398f commit a9cb5df

File tree

12 files changed

+171
-24
lines changed

12 files changed

+171
-24
lines changed

packages/app-backend-api/src/api.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -222,23 +222,23 @@ export class DevtoolsPluginApiInstance implements DevtoolsPluginApi {
222222
}
223223

224224
addTimelineLayer (options: TimelineLayerOptions) {
225-
this.ctx.hook.emit(HookEvents.TIMELINE_LAYER_ADDED, options, this.plugin.descriptor.app)
225+
this.ctx.hook.emit(HookEvents.TIMELINE_LAYER_ADDED, options, this.plugin)
226226
}
227227

228228
addTimelineEvent (options: TimelineEventOptions) {
229-
this.ctx.hook.emit(HookEvents.TIMELINE_EVENT_ADDED, options, this.plugin.descriptor.app)
229+
this.ctx.hook.emit(HookEvents.TIMELINE_EVENT_ADDED, options, this.plugin)
230230
}
231231

232232
addInspector (options: CustomInspectorOptions) {
233-
this.ctx.hook.emit(HookEvents.CUSTOM_INSPECTOR_ADD, options, this.plugin.descriptor.app)
233+
this.ctx.hook.emit(HookEvents.CUSTOM_INSPECTOR_ADD, options, this.plugin)
234234
}
235235

236236
sendInspectorTree (inspectorId: string) {
237-
this.ctx.hook.emit(HookEvents.CUSTOM_INSPECTOR_SEND_TREE, inspectorId, this.plugin.descriptor.app)
237+
this.ctx.hook.emit(HookEvents.CUSTOM_INSPECTOR_SEND_TREE, inspectorId, this.plugin)
238238
}
239239

240240
sendInspectorState (inspectorId: string) {
241-
this.ctx.hook.emit(HookEvents.CUSTOM_INSPECTOR_SEND_STATE, inspectorId, this.plugin.descriptor.app)
241+
this.ctx.hook.emit(HookEvents.CUSTOM_INSPECTOR_SEND_STATE, inspectorId, this.plugin)
242242
}
243243

244244
getComponentBounds (instance: ComponentInstance) {

packages/app-backend-api/src/backend-context.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,12 @@ export interface BackendContext {
2121

2222
export interface TimelineLayer extends TimelineLayerOptions {
2323
app: App
24+
plugin: Plugin
2425
}
2526

2627
export interface CustomInspector extends CustomInspectorOptions {
2728
app: App
29+
plugin: Plugin
2830
treeFilter: string
2931
selectedNodeId: string
3032
}

packages/app-backend-core/src/index.ts

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import {
22
createBackendContext,
3-
BackendContext
3+
BackendContext,
4+
Plugin
45
} from '@vue-devtools/app-backend-api'
56
import {
67
Bridge,
@@ -221,16 +222,17 @@ async function connect () {
221222
sendTimelineLayers(ctx)
222223
})
223224

224-
hook.on(HookEvents.TIMELINE_LAYER_ADDED, (options: TimelineLayerOptions, app: App) => {
225+
hook.on(HookEvents.TIMELINE_LAYER_ADDED, (options: TimelineLayerOptions, plugin: Plugin) => {
225226
ctx.timelineLayers.push({
226227
...options,
227-
app
228+
app: plugin.descriptor.app,
229+
plugin
228230
})
229231
ctx.bridge.send(BridgeEvents.TO_FRONT_TIMELINE_LAYER_ADD, {})
230232
})
231233

232-
hook.on(HookEvents.TIMELINE_EVENT_ADDED, (options: TimelineEventOptions, app: App) => {
233-
addTimelineEvent(options, app, ctx)
234+
hook.on(HookEvents.TIMELINE_EVENT_ADDED, (options: TimelineEventOptions, plugin: Plugin) => {
235+
addTimelineEvent(options, plugin.descriptor.app, ctx)
234236
})
235237

236238
ctx.bridge.on(BridgeEvents.TO_BACK_TIMELINE_SHOW_SCREENSHOT, ({ screenshot }) => {
@@ -252,6 +254,7 @@ async function connect () {
252254
inspectors: ctx.customInspectors.map(i => ({
253255
id: i.id,
254256
appId: getAppRecordId(i.app),
257+
pluginId: i.plugin.descriptor.id,
255258
label: i.label,
256259
icon: i.icon,
257260
treeFilterPlaceholder: i.treeFilterPlaceholder,
@@ -280,27 +283,28 @@ async function connect () {
280283
}
281284
})
282285

283-
hook.on(HookEvents.CUSTOM_INSPECTOR_ADD, (options: CustomInspectorOptions, app: App) => {
286+
hook.on(HookEvents.CUSTOM_INSPECTOR_ADD, (options: CustomInspectorOptions, plugin: Plugin) => {
284287
ctx.customInspectors.push({
285288
...options,
286-
app,
289+
app: plugin.descriptor.app,
290+
plugin,
287291
treeFilter: '',
288292
selectedNodeId: null
289293
})
290294
ctx.bridge.send(BridgeEvents.TO_FRONT_CUSTOM_INSPECTOR_ADD, {})
291295
})
292296

293-
hook.on(HookEvents.CUSTOM_INSPECTOR_SEND_TREE, (inspectorId: string, app: App) => {
294-
const inspector = getInspector(inspectorId, app, ctx)
297+
hook.on(HookEvents.CUSTOM_INSPECTOR_SEND_TREE, (inspectorId: string, plugin: Plugin) => {
298+
const inspector = getInspector(inspectorId, plugin.descriptor.app, ctx)
295299
if (inspector) {
296300
sendInspectorTree(inspector, ctx)
297301
} else {
298302
console.error(`Inspector ${inspectorId} not found`)
299303
}
300304
})
301305

302-
hook.on(HookEvents.CUSTOM_INSPECTOR_SEND_STATE, (inspectorId: string, app: App) => {
303-
const inspector = getInspector(inspectorId, app, ctx)
306+
hook.on(HookEvents.CUSTOM_INSPECTOR_SEND_STATE, (inspectorId: string, plugin: Plugin) => {
307+
const inspector = getInspector(inspectorId, plugin.descriptor.app, ctx)
304308
if (inspector) {
305309
sendInspectorState(inspector, ctx)
306310
} else {

packages/app-backend-core/src/timeline.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,8 @@ export function sendTimelineLayers (ctx: BackendContext) {
9090
id: layer.id,
9191
label: layer.label,
9292
color: layer.color,
93-
appId: getAppRecord(layer.app, ctx)?.id
93+
appId: getAppRecord(layer.app, ctx)?.id,
94+
pluginId: layer.plugin.descriptor.id
9495
}))
9596
})
9697
}

packages/app-frontend/src/app.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { setupAppsBridgeEvents } from './features/apps'
1010
import { setupComponentsBridgeEvents } from './features/components'
1111
import { setupTimelineBridgeEvents } from './features/timeline'
1212
import { setupCustomInspectorBridgeEvents } from './features/inspector/custom'
13+
import { setupPluginsBridgeEvents } from './features/plugin'
1314

1415
setupPlugins()
1516

@@ -84,6 +85,7 @@ export function connectApp (app, shell) {
8485
setupComponentsBridgeEvents(bridge)
8586
setupTimelineBridgeEvents(bridge)
8687
setupCustomInspectorBridgeEvents(bridge)
88+
setupPluginsBridgeEvents(bridge)
8789

8890
// @TODO bridge listeners
8991

packages/app-frontend/src/features/header/AppHeader.vue

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,15 @@ import AppHeaderSelect from './AppHeaderSelect.vue'
99
import { useBridge } from '../bridge'
1010
import { useTabs } from './tabs'
1111
import { useInspectors } from '../inspector/custom'
12+
import PluginSourceIcon from '../plugin/PluginSourceIcon.vue'
1213
1314
export default {
1415
components: {
1516
AppMainMenu,
1617
AppHistoryNav,
1718
AppSelect,
18-
AppHeaderSelect
19+
AppHeaderSelect,
20+
PluginSourceIcon
1921
},
2022
2123
setup () {
@@ -63,6 +65,7 @@ export default {
6365
].concat(customInspectors.value.map(i => ({
6466
icon: i.icon || 'tab',
6567
label: i.label,
68+
pluginId: i.pluginId,
6669
targetRoute: { name: 'custom-inspector', params: { inspectorId: i.id } },
6770
matchRoute: route => route.params.inspectorId === i.id
6871
}))))
@@ -119,7 +122,17 @@ export default {
119122
:items="inspectorRoutes"
120123
:selected-item="currentInspectorRoute"
121124
@select="route => $router.push(route.targetRoute)"
122-
/>
125+
>
126+
<template #default="{ item }">
127+
<div class="flex items-center space-x-2">
128+
<span class="flex-1">{{ item.label }}</span>
129+
<PluginSourceIcon
130+
v-if="item.pluginId"
131+
:plugin-id="item.pluginId"
132+
/>
133+
</div>
134+
</template>
135+
</AppHeaderSelect>
123136
</template>
124137

125138
<div class="flex-1" />

packages/app-frontend/src/features/header/AppHeaderSelect.vue

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,4 +247,10 @@ export default {
247247
fill: currentColor !important;
248248
}
249249
}
250+
251+
.vue-ui-dropdown-button /deep/ {
252+
.default-slot {
253+
flex: 1;
254+
}
255+
}
250256
</style>
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
<script>
2+
import { usePlugins } from '.'
3+
import { computed } from '@vue/composition-api'
4+
5+
export default {
6+
props: {
7+
pluginId: {
8+
type: String,
9+
required: true
10+
}
11+
},
12+
13+
setup (props) {
14+
const {
15+
plugins
16+
} = usePlugins()
17+
18+
const plugin = computed(() => plugins.value.find(p => p.id === props.pluginId))
19+
20+
return {
21+
plugin
22+
}
23+
}
24+
}
25+
</script>
26+
27+
<template>
28+
<VTooltip>
29+
<VueIcon
30+
icon="extension"
31+
class="opacity-25 hover:opacity-100"
32+
/>
33+
34+
<template #popper>
35+
<div class="flex space-x-3 items-center">
36+
<div class="flex items-center justify-center w-8 h-8 bg-gray-700 dark:bg-gray-200 rounded-full">
37+
<VueIcon
38+
icon="extension"
39+
/>
40+
</div>
41+
<div>
42+
<div>Provided by <b>{{ plugin ? plugin.label : pluginId }}</b></div>
43+
<div
44+
v-if="plugin"
45+
class="opacity-50"
46+
>
47+
<div>ID: {{ plugin.id }}</div>
48+
</div>
49+
</div>
50+
</div>
51+
</template>
52+
</VTooltip>
53+
</template>
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import Vue from 'vue'
2+
import { computed, ref } from '@vue/composition-api'
3+
import { BridgeEvents } from '@vue-devtools/shared-utils'
4+
import { getBridge } from '../bridge'
5+
import { useApps } from '../apps'
6+
7+
const pluginsPerApp = ref({})
8+
9+
function getPlugins (appId) {
10+
let plugins = pluginsPerApp.value[appId]
11+
if (!plugins) {
12+
plugins = []
13+
Vue.set(pluginsPerApp.value, appId, plugins)
14+
// Read the property again to make it reactive
15+
plugins = pluginsPerApp.value[appId]
16+
}
17+
return plugins
18+
}
19+
20+
function fetchPlugins () {
21+
getBridge().send(BridgeEvents.TO_BACK_DEVTOOLS_PLUGIN_LIST, {})
22+
}
23+
24+
export function usePlugins () {
25+
const { currentAppId } = useApps()
26+
27+
const plugins = computed(() => getPlugins(currentAppId.value))
28+
29+
return {
30+
plugins
31+
}
32+
}
33+
34+
export function setupPluginsBridgeEvents (bridge) {
35+
bridge.on(BridgeEvents.TO_FRONT_DEVTOOLS_PLUGIN_ADD, ({ plugin }) => {
36+
getPlugins(plugin.appId).push(plugin)
37+
})
38+
39+
bridge.on(BridgeEvents.TO_FRONT_DEVTOOLS_PLUGIN_LIST, ({ plugins }) => {
40+
for (const plugin of plugins) {
41+
getPlugins(plugin.appId).push(plugin)
42+
}
43+
})
44+
45+
fetchPlugins()
46+
}

packages/app-frontend/src/features/timeline/LayerItem.vue

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
<script>
2+
import PluginSourceIcon from '../plugin/PluginSourceIcon.vue'
3+
24
export default {
5+
components: {
6+
PluginSourceIcon
7+
},
8+
39
props: {
410
layer: {
511
type: Object,
@@ -27,7 +33,7 @@ export default {
2733
height: `${(layer.height + 1) * 16}px`
2834
}"
2935
>
30-
<div class="flex items-center space-x-4 px-4 py-1">
36+
<div class="flex items-center space-x-2 px-2 py-1">
3137
<div
3238
class="flex-none w-3 h-3 rounded-full"
3339
:style="{
@@ -37,6 +43,11 @@ export default {
3743
<div class="flex-1 truncate text-sm">
3844
{{ layer.label }}
3945
</div>
46+
47+
<PluginSourceIcon
48+
v-if="layer.pluginId"
49+
:plugin-id="layer.pluginId"
50+
/>
4051
</div>
4152
</div>
4253

0 commit comments

Comments
 (0)