Skip to content

Commit d102dcd

Browse files
committed
feat(plugin): timeline integration
1 parent 0b43171 commit d102dcd

File tree

13 files changed

+202
-56
lines changed

13 files changed

+202
-56
lines changed

packages/api/src/api/api.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,24 @@ import { ComponentInstance } from './component'
55
export interface DevtoolsPluginApi {
66
on: Hookable<Context>
77
notifyComponentUpdate (instance: ComponentInstance)
8+
addTimelineLayer (options: TimelineLayerOptions)
9+
addTimelineEvent (options: TimelineEventOptions)
10+
}
11+
12+
export interface TimelineLayerOptions {
13+
id: string
14+
label: string
15+
color: number
16+
}
17+
18+
export interface TimelineEventOptions {
19+
layerId: string
20+
event: TimelineEvent
21+
all?: boolean
22+
}
23+
24+
export interface TimelineEvent<TData = any, TMeta = any> {
25+
time: number
26+
data: TData
27+
meta: TMeta
828
}

packages/api/src/api/context.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import { DevtoolsPluginApi } from './api'
22

33
export interface Context {
4-
api: DevtoolsPluginApi
54
currentTab: string
65
}

packages/api/src/index.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,5 +23,3 @@ export function setupDevtoolsPlugin (pluginDescriptor: PluginDescriptor, setupFn
2323
})
2424
}
2525
}
26-
27-
export const api: DevtoolsPluginApi = target.__VUE_DEVTOOLS_API__

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

Lines changed: 39 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,35 +4,35 @@ import {
44
HookPayloads,
55
App,
66
DevtoolsPluginApi,
7-
ComponentInstance
7+
ComponentInstance,
8+
TimelineLayerOptions,
9+
TimelineEventOptions
810
} from '@vue/devtools-api'
911
import { DevtoolsHookable } from './hooks'
1012
import { BackendContext } from './backend-context'
13+
import { Plugin } from './plugin'
1114

12-
export class DevtoolsApi implements DevtoolsPluginApi {
15+
let backendOn: DevtoolsHookable
16+
let pluginOn: DevtoolsHookable
17+
18+
export class DevtoolsApi {
1319
bridge: Bridge
1420
ctx: BackendContext
15-
protected backendOn: DevtoolsHookable
16-
protected pluginOn: DevtoolsHookable
1721

1822
constructor (bridge: Bridge, ctx: BackendContext) {
1923
this.bridge = bridge
2024
this.ctx = ctx
21-
this.backendOn = new DevtoolsHookable(ctx)
22-
this.pluginOn = new DevtoolsHookable(ctx)
25+
if (!backendOn) { backendOn = new DevtoolsHookable(ctx) }
26+
if (!pluginOn) { pluginOn = new DevtoolsHookable(ctx) }
2327
}
2428

2529
get on () {
26-
if (this.ctx.currentPlugin) {
27-
return this.pluginOn
28-
} else {
29-
return this.backendOn
30-
}
30+
return backendOn
3131
}
3232

3333
async callHook<T extends Hooks> (eventType: T, payload: HookPayloads[T], ctx: BackendContext = this.ctx) {
34-
payload = await this.backendOn.callHandlers(eventType, payload, ctx)
35-
payload = await this.pluginOn.callHandlers(eventType, payload, ctx)
34+
payload = await backendOn.callHandlers(eventType, payload, ctx)
35+
payload = await pluginOn.callHandlers(eventType, payload, ctx)
3636
return payload
3737
}
3838

@@ -120,14 +120,39 @@ export class DevtoolsApi implements DevtoolsPluginApi {
120120
})
121121
return payload.componentInstance
122122
}
123+
}
124+
125+
export class DevtoolsPluginApiInstance implements DevtoolsPluginApi {
126+
bridge: Bridge
127+
ctx: BackendContext
128+
plugin: Plugin
129+
130+
constructor (plugin: Plugin, ctx: BackendContext) {
131+
this.bridge = ctx.bridge
132+
this.ctx = ctx
133+
this.plugin = plugin
134+
if (!pluginOn) { pluginOn = new DevtoolsHookable(ctx) }
135+
}
136+
137+
get on () {
138+
return pluginOn
139+
}
123140

124141
// Plugin API
125142

126143
async notifyComponentUpdate (instance: ComponentInstance = null) {
127144
if (instance) {
128-
this.ctx.hook.emit(HookEvents.COMPONENT_UPDATED, ...await this.transformCall(HookEvents.COMPONENT_UPDATED, instance))
145+
this.ctx.hook.emit(HookEvents.COMPONENT_UPDATED, ...await this.ctx.api.transformCall(HookEvents.COMPONENT_UPDATED, instance))
129146
} else {
130147
this.ctx.hook.emit(HookEvents.COMPONENT_UPDATED)
131148
}
132149
}
150+
151+
addTimelineLayer (options: TimelineLayerOptions) {
152+
this.ctx.hook.emit(HookEvents.TIMELINE_LAYER_ADDED, options, this.plugin?.descriptor.app)
153+
}
154+
155+
addTimelineEvent (options: TimelineEventOptions) {
156+
this.ctx.hook.emit(HookEvents.TIMELINE_EVENT_ADDED, options, this.plugin?.descriptor.app)
157+
}
133158
}

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

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { Bridge, target } from '@vue-devtools/shared-utils'
2+
import { TimelineLayerOptions, App } from '@vue/devtools-api'
23
import { AppRecord } from './app-record'
34
import { DevtoolsApi } from './api'
45
import { Plugin } from './plugin'
@@ -13,7 +14,11 @@ export interface BackendContext {
1314
currentAppRecord: AppRecord
1415
currentInspectedComponentId: string
1516
plugins: Plugin[]
16-
currentPlugin: Plugin
17+
timelineLayers: TimelineLayer[]
18+
}
19+
20+
export interface TimelineLayer extends TimelineLayerOptions {
21+
app: App
1722
}
1823

1924
export interface CreateBackendContextOptions {
@@ -22,7 +27,7 @@ export interface CreateBackendContextOptions {
2227
}
2328

2429
export function createBackendContext (options: CreateBackendContextOptions): BackendContext {
25-
const ctx = {
30+
const ctx: BackendContext = {
2631
bridge: options.bridge,
2732
hook: options.hook,
2833
api: null,
@@ -31,8 +36,8 @@ export function createBackendContext (options: CreateBackendContextOptions): Bac
3136
currentAppRecord: null,
3237
currentInspectedComponentId: null,
3338
plugins: [],
34-
currentPlugin: null
39+
timelineLayers: []
3540
}
36-
ctx.api = target.__VUE_DEVTOOLS_API__ = new DevtoolsApi(options.bridge, ctx)
41+
ctx.api = new DevtoolsApi(options.bridge, ctx)
3742
return ctx
3843
}

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

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,20 @@
1-
import { createBackendContext, BackendContext } from '@vue-devtools/app-backend-api'
1+
import {
2+
createBackendContext,
3+
BackendContext
4+
} from '@vue-devtools/app-backend-api'
25
import {
36
Bridge,
47
HookEvents,
58
BridgeEvents,
69
BuiltinTabs,
710
initSharedData,
8-
BridgeSubscriptions
11+
BridgeSubscriptions,
12+
stringify
913
} from '@vue-devtools/shared-utils'
1014
import { hook } from './global-hook'
1115
import { subscribe, unsubscribe, isSubscribed } from './util/subscriptions'
1216
import { highlight, unHighlight } from './highlighter'
13-
import { setupTimeline } from './timeline'
17+
import { setupTimeline, sendTimelineLayers, TimelineEventPayload } from './timeline'
1418
import ComponentPicker from './component-pick'
1519
import {
1620
sendComponentTreeData,
@@ -19,8 +23,8 @@ import {
1923
getComponentId
2024
} from './component'
2125
import { addQueuedPlugins, addPlugin, sendPluginList } from './plugin'
22-
import { PluginDescriptor, SetupFunction } from '@vue/devtools-api'
23-
import { registerApp, selectApp, mapAppRecord } from './app'
26+
import { PluginDescriptor, SetupFunction, TimelineLayerOptions, App, TimelineEventOptions } from '@vue/devtools-api'
27+
import { registerApp, selectApp, mapAppRecord, getAppRecord } from './app'
2428

2529
let ctx: BackendContext
2630

@@ -167,6 +171,30 @@ function connect () {
167171

168172
setupTimeline(ctx)
169173

174+
hook.on(HookEvents.TIMELINE_LAYER_ADDED, (options: TimelineLayerOptions, app: App) => {
175+
ctx.timelineLayers.push({
176+
...options,
177+
app
178+
})
179+
ctx.bridge.send(BridgeEvents.TO_FRONT_TIMELINE_LAYER_ADD, {})
180+
})
181+
182+
ctx.bridge.on(BridgeEvents.TO_BACK_TIMELINE_LAYER_LIST, () => {
183+
sendTimelineLayers(ctx)
184+
})
185+
186+
hook.on(HookEvents.TIMELINE_EVENT_ADDED, (options: TimelineEventOptions, app: App) => {
187+
const appId = app && getAppRecord(app, ctx)?.id
188+
ctx.bridge.send(BridgeEvents.TO_FRONT_TIMELINE_EVENT, {
189+
appId: options.all || !app || appId == null ? 'all' : appId,
190+
layerId: options.layerId,
191+
event: {
192+
time: options.event.time,
193+
data: stringify(options.event.data)
194+
}
195+
} as TimelineEventPayload)
196+
})
197+
170198
// Plugins
171199

172200
addQueuedPlugins(ctx)

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

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { PluginDescriptor, SetupFunction } from '@vue/devtools-api'
2-
import { Plugin, BackendContext } from '@vue-devtools/app-backend-api'
2+
import { Plugin, BackendContext, DevtoolsPluginApiInstance } from '@vue-devtools/app-backend-api'
33
import { BridgeEvents, target } from '@vue-devtools/shared-utils'
44

55
export function addPlugin (pluginDescriptor: PluginDescriptor, setupFn: SetupFunction, ctx: BackendContext) {
@@ -8,14 +8,13 @@ export function addPlugin (pluginDescriptor: PluginDescriptor, setupFn: SetupFun
88
setupFn,
99
error: null
1010
}
11-
ctx.currentPlugin = plugin
1211
try {
13-
setupFn(ctx.api)
12+
const api = new DevtoolsPluginApiInstance(plugin, ctx)
13+
setupFn(api)
1414
} catch (e) {
1515
plugin.error = e
1616
console.error(e)
1717
}
18-
ctx.currentPlugin = null
1918
ctx.plugins.push(plugin)
2019
ctx.bridge.send(BridgeEvents.TO_FRONT_DEVTOOLS_PLUGIN_ADD, {
2120
plugin: serializePlugin(plugin)

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

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,13 @@
11
import { BackendContext } from '@vue-devtools/app-backend-api'
22
import { BridgeEvents, HookEvents, stringify } from '@vue-devtools/shared-utils'
3+
import { TimelineEvent } from '@vue/devtools-api'
34
import { hook } from './global-hook'
45
import { getAppRecord } from './app'
56

67
export interface TimelineEventPayload<TData = any, TMeta = any> {
78
appId: number | 'all'
89
layerId: string
9-
event: Event<TData, TMeta>
10-
}
11-
12-
export interface Event<TData = any, TMeta = any> {
13-
time: number
14-
data: TData
15-
meta: TMeta
10+
event: TimelineEvent<TData, TMeta>
1611
}
1712

1813
export function setupTimeline (ctx: BackendContext) {
@@ -91,3 +86,14 @@ function setupBuiltinLayers (ctx: BackendContext) {
9186
} as TimelineEventPayload)
9287
})
9388
}
89+
90+
export function sendTimelineLayers (ctx: BackendContext) {
91+
ctx.bridge.send(BridgeEvents.TO_FRONT_TIMELINE_LAYER_LIST, {
92+
layers: ctx.timelineLayers.map(layer => ({
93+
id: layer.id,
94+
label: layer.label,
95+
color: layer.color,
96+
appId: getAppRecord(layer.app, ctx)?.id
97+
}))
98+
})
99+
}

packages/app-frontend/src/features/bridge/index.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,3 +46,7 @@ export function useBridge () {
4646
export function setBridge (b) {
4747
bridge = b
4848
}
49+
50+
export function getBridge () {
51+
return bridge
52+
}

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

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,15 +90,21 @@ export default {
9090
initLayers()
9191
})
9292
93-
onReset(() => {
93+
function resetLayers () {
9494
for (const container of layerContainers) {
9595
container.destroy()
9696
}
9797
layerContainers = []
9898
layersMap = {}
9999
initLayers()
100+
}
101+
102+
onReset(() => {
103+
resetLayers()
100104
})
101105
106+
watch(layers, () => resetLayers())
107+
102108
// Events
103109
104110
const { selectedEvent } = useSelectedEvent()

0 commit comments

Comments
 (0)