soiz1's picture
Upload folder using huggingface_hub
4d70170 verified
import type { AppRecord, BackendContext } from '@vue-devtools/app-backend-api'
import { BridgeEvents, HookEvents, SharedData, isBrowser, stringify } from '@vue-devtools/shared-utils'
import type { App, ID, TimelineEventOptions, WithId } from '@vue/devtools-api'
import { isPerformanceSupported, now } from '@vue/devtools-api'
import { hook } from './global-hook'
import { getAppRecord, getAppRecordId } from './app'
import { builtinLayers } from './timeline-builtins'
export function setupTimeline(ctx: BackendContext) {
setupBuiltinLayers(ctx)
}
export function addBuiltinLayers(appRecord: AppRecord, ctx: BackendContext) {
for (const layerDef of builtinLayers) {
ctx.timelineLayers.push({
...layerDef,
appRecord,
plugin: null,
events: [],
})
}
}
function setupBuiltinLayers(ctx: BackendContext) {
if (isBrowser) {
(['mousedown', 'mouseup', 'click', 'dblclick'] as const).forEach((eventType) => {
window.addEventListener(eventType, async (event: MouseEvent) => {
await addTimelineEvent({
layerId: 'mouse',
event: {
time: now(),
data: {
type: eventType,
x: event.clientX,
y: event.clientY,
},
title: eventType,
},
}, null, ctx)
}, {
capture: true,
passive: true,
})
})
;(['keyup', 'keydown', 'keypress'] as const).forEach((eventType) => {
window.addEventListener(eventType, async (event: KeyboardEvent) => {
await addTimelineEvent({
layerId: 'keyboard',
event: {
time: now(),
data: {
type: eventType,
key: event.key,
ctrlKey: event.ctrlKey,
shiftKey: event.shiftKey,
altKey: event.altKey,
metaKey: event.metaKey,
},
title: event.key,
},
}, null, ctx)
}, {
capture: true,
passive: true,
})
})
}
hook.on(HookEvents.COMPONENT_EMIT, async (app, instance, event, params) => {
try {
if (!SharedData.componentEventsEnabled) {
return
}
const appRecord = await getAppRecord(app, ctx)
if (!appRecord) {
return
}
const componentId = `${appRecord.id}:${instance.uid}`
const componentDisplay = (await appRecord.backend.api.getComponentName(instance)) || '<i>Unknown Component</i>'
await addTimelineEvent({
layerId: 'component-event',
event: {
time: now(),
data: {
component: {
_custom: {
type: 'component-definition',
display: componentDisplay,
},
},
event,
params,
},
title: event,
subtitle: `by ${componentDisplay}`,
meta: {
componentId,
bounds: await appRecord.backend.api.getComponentBounds(instance),
},
},
}, app, ctx)
}
catch (e) {
if (SharedData.debugInfo) {
console.error(e)
}
}
})
}
export async function sendTimelineLayers(ctx: BackendContext) {
const layers = []
for (const layer of ctx.timelineLayers) {
try {
layers.push({
id: layer.id,
label: layer.label,
color: layer.color,
appId: layer.appRecord?.id,
pluginId: layer.plugin?.descriptor.id,
groupsOnly: layer.groupsOnly,
skipScreenshots: layer.skipScreenshots,
ignoreNoDurationGroups: layer.ignoreNoDurationGroups,
})
}
catch (e) {
if (SharedData.debugInfo) {
console.error(e)
}
}
}
ctx.bridge.send(BridgeEvents.TO_FRONT_TIMELINE_LAYER_LIST, {
layers,
})
}
export async function addTimelineEvent(options: TimelineEventOptions, app: App, ctx: BackendContext) {
if (!SharedData.timelineRecording) {
return
}
const appId = app ? getAppRecordId(app) : null
const isAllApps = options.all || !app || appId == null
const id = ctx.nextTimelineEventId++
const eventData: TimelineEventOptions & WithId = {
id,
...options,
all: isAllApps,
}
ctx.timelineEventMap.set(eventData.id, eventData)
ctx.bridge.send(BridgeEvents.TO_FRONT_TIMELINE_EVENT, {
appId: eventData.all ? 'all' : appId,
layerId: eventData.layerId,
event: mapTimelineEvent(eventData),
})
const layer = ctx.timelineLayers.find(l => (isAllApps || l.appRecord?.options.app === app) && l.id === options.layerId)
if (layer) {
layer.events.push(eventData)
}
else if (SharedData.debugInfo) {
console.warn(`Timeline layer ${options.layerId} not found`)
}
}
const initialTime = Date.now()
export const dateThreshold = initialTime - 1_000_000
export const perfTimeDiff = initialTime - now()
function mapTimelineEvent(eventData: TimelineEventOptions & WithId) {
let time = eventData.event.time
if (isPerformanceSupported() && time < dateThreshold) {
time += perfTimeDiff
}
return {
id: eventData.id,
time: Math.round(time * 1000),
logType: eventData.event.logType,
groupId: eventData.event.groupId,
title: eventData.event.title,
subtitle: eventData.event.subtitle,
}
}
export async function clearTimeline(ctx: BackendContext) {
ctx.timelineEventMap.clear()
for (const layer of ctx.timelineLayers) {
layer.events = []
}
for (const backend of ctx.backends) {
await backend.api.clearTimeline()
}
}
export async function sendTimelineEventData(id: ID, ctx: BackendContext) {
if (!SharedData.timelineRecording) {
return
}
let data = null
const eventData = ctx.timelineEventMap.get(id)
if (eventData) {
data = await ctx.currentAppRecord.backend.api.inspectTimelineEvent(eventData, ctx.currentAppRecord.options.app)
data = stringify(data)
}
else if (SharedData.debugInfo) {
console.warn(`Event ${id} not found`, ctx.timelineEventMap.keys())
}
ctx.bridge.send(BridgeEvents.TO_FRONT_TIMELINE_EVENT_DATA, {
eventId: id,
data,
})
}
export function removeLayersForApp(app: App, ctx: BackendContext) {
const layers = ctx.timelineLayers.filter(l => l.appRecord?.options.app === app)
for (const layer of layers) {
const index = ctx.timelineLayers.indexOf(layer)
if (index !== -1) {
ctx.timelineLayers.splice(index, 1)
}
for (const e of layer.events) {
ctx.timelineEventMap.delete(e.id)
}
}
}
export function sendTimelineLayerEvents(appId: string, layerId: string, ctx: BackendContext) {
if (!SharedData.timelineRecording) {
return
}
const app = ctx.appRecords.find(ar => ar.id === appId)?.options.app
if (!app) {
return
}
const layer = ctx.timelineLayers.find(l => l.appRecord?.options.app === app && l.id === layerId)
if (!layer) {
return
}
ctx.bridge.send(BridgeEvents.TO_FRONT_TIMELINE_LAYER_LOAD_EVENTS, {
appId,
layerId,
events: layer.events.map(e => mapTimelineEvent(e)),
})
}