11<script setup lang="ts">
22import type { CustomInspectorState , TimelineEventOptions } from ' @vue/devtools-kit'
3- import { DevToolsMessagingEvents , rpc } from ' @vue/devtools-core'
3+ import { DevToolsMessagingEvents , rpc , useDevToolsState } from ' @vue/devtools-core'
44import { parse } from ' @vue/devtools-kit'
5+ import { vTooltip , VueIcIcon } from ' @vue/devtools-ui'
56
67import { Pane , Splitpanes } from ' splitpanes'
78import { computed , onUnmounted , ref } from ' vue'
@@ -14,6 +15,7 @@ import EventList from './EventList.vue'
1415
1516const props = withDefaults (defineProps <{
1617 layerIds: string []
18+ pluginId: string
1719 docLink: string
1820 githubRepoLink? : string
1921 headerVisible? : boolean
@@ -29,7 +31,10 @@ expandedStateNodes.value = ['0', '1']
2931const eventList = ref <TimelineEventOptions [' event' ][]>([])
3032const groupList = ref <Map <string | number | undefined , TimelineEventOptions [' event' ][]>>(new Map ())
3133const selectedEventIndex = ref (0 )
34+ const devtoolsState = useDevToolsState ()
35+ const recordingState = computed (() => devtoolsState .timelineLayersState .value ?.[props .pluginId ])
3236const selectedEventInfo = computed (() => eventList .value [selectedEventIndex .value ] ?? null )
37+ const recordingTooltip = computed (() => recordingState .value ? ' Stop recording' : ' Start recording' )
3338// event info
3439const normalizedEventInfo = computed (() => {
3540 const info: CustomInspectorState [] = []
@@ -96,19 +101,28 @@ onUnmounted(() => {
96101 rpc .functions .off (DevToolsMessagingEvents .TIMELINE_EVENT_UPDATED , onTimelineEventUpdated )
97102})
98103
104+ function clear() {
105+ eventList .value = []
106+ groupList .value .clear ()
107+ }
108+
99109defineExpose ({
100- clear() {
101- eventList .value = []
102- groupList .value .clear ()
103- },
110+ clear ,
104111})
112+
113+ function toggleRecordingState() {
114+ rpc .value .updateTimelineLayersState ({
115+ [props .pluginId ]: ! recordingState .value ,
116+ })
117+ }
105118 </script >
106119
107120<template >
108- <div class =" h-full flex flex-col" >
121+ <div class =" relative h-full flex flex-col" >
109122 <DevToolsHeader v-if =" headerVisible" :doc-link =" docLink" :github-repo-link =" githubRepoLink" >
110123 <Navbar />
111124 </DevToolsHeader >
125+
112126 <template v-if =" eventList .length " >
113127 <div class =" flex-1 overflow-hidden" >
114128 <Splitpanes class =" h-full" >
@@ -128,5 +142,36 @@ defineExpose({
128142 <Empty v-else class =" flex-1" >
129143 No events
130144 </Empty >
145+
146+ <div class =" absolute right-3 top-12 flex items-center justify-end b-1 border-base rounded-1 b-solid px2 py1" >
147+ <div class =" flex items-center gap-2 px-1" >
148+ <div v-tooltip.bottom-end =" { content: recordingTooltip }" class =" flex items-center gap1" @click =" toggleRecordingState" >
149+ <span v-if =" recordingState" class =" recording recording-btn bg-[#ef4444]" />
150+ <span v-else class =" recording-btn bg-black op70 dark:(bg-white) hover:op100" />
151+ </div >
152+ <div v-tooltip.bottom-end =" { content: 'Clear all timelines' }" class =" flex items-center gap1" @click =" clear" >
153+ <VueIcIcon name =" baseline-delete" cursor-pointer text-xl op70 hover:op100 />
154+ </div >
155+ <div v-tooltip.bottom-end =" { content: '<p style=\'width: 285px\'>Timeline events can cause significant performance overhead in large applications, so we recommend enabling it only when needed and on-demand. </p>', html: true }" class =" flex items-center gap1" >
156+ <VueIcIcon name =" baseline-tips-and-updates" cursor-pointer text-xl op70 hover:op100 />
157+ </div >
158+ </div >
159+ </div >
131160 </div >
132161</template >
162+
163+ <style scoped>
164+ @keyframes pulse {
165+ 50% {
166+ opacity : 0.5 ;
167+ }
168+ }
169+ .recording-btn {
170+ --at-apply : w-3.5 h-3.5 inline-flex cursor-pointer rounded-50%;
171+ }
172+ .recording {
173+ animation : pulse 2s cubic-bezier (0.4 , 0 , 0.6 , 1 ) infinite ;
174+ transition-duration : 1s ;
175+ box-shadow : #ef4444 0 0 8px ;
176+ }
177+ </style >
0 commit comments