Skip to content

Commit 6204a28

Browse files
committed
feat: update tracking
1 parent 32e60cf commit 6204a28

File tree

9 files changed

+124
-4
lines changed

9 files changed

+124
-4
lines changed

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

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { stringify, BridgeEvents, parse, SharedData } from '@vue-devtools/shared-utils'
22
import { AppRecord, BackendContext, BuiltinBackendFeature } from '@vue-devtools/app-backend-api'
33
import { getAppRecord } from './app'
4-
import { App, ComponentInstance, EditStatePayload } from '@vue/devtools-api'
4+
import { App, ComponentInstance, EditStatePayload, now } from '@vue/devtools-api'
55

66
const MAX_$VM = 10
77
const $vmQueue = []
@@ -130,3 +130,14 @@ export async function refreshComponentTreeSearch (ctx: BackendContext) {
130130
if (!ctx.currentAppRecord.componentFilter) return
131131
await sendComponentTreeData(ctx.currentAppRecord, '_root', ctx.currentAppRecord.componentFilter, null, ctx)
132132
}
133+
134+
export async function sendComponentUpdateTracking (appRecord: AppRecord, instanceId: string, ctx: BackendContext) {
135+
if (!instanceId) return
136+
const instance = getComponentInstance(appRecord, instanceId, ctx)
137+
if (!instance) return
138+
const payload = {
139+
instanceId,
140+
time: Date.now(), // Use normal date
141+
}
142+
ctx.bridge.send(BridgeEvents.TO_FRONT_COMPONENT_UPDATED, payload)
143+
}

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

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import {
3333
editComponentState,
3434
getComponentInstance,
3535
refreshComponentTreeSearch,
36+
sendComponentUpdateTracking,
3637
} from './component'
3738
import { addQueuedPlugins, addPlugin, sendPluginList, addPreviouslyRegisteredPlugins } from './plugin'
3839
import { PluginDescriptor, SetupFunction, TimelineLayerOptions, TimelineEventOptions, CustomInspectorOptions, Hooks, now } from '@vue/devtools-api'
@@ -131,6 +132,10 @@ async function connect () {
131132
if (isSubscribed(BridgeSubscriptions.COMPONENT_TREE, sub => sub.payload.instanceId === id)) {
132133
sendComponentTreeData(appRecord, id, appRecord.componentFilter, 0, ctx)
133134
}
135+
136+
if (SharedData.trackUpdates) {
137+
sendComponentUpdateTracking(appRecord, id, ctx)
138+
}
134139
} catch (e) {
135140
if (SharedData.debugInfo) {
136141
console.error(e)
@@ -155,13 +160,17 @@ async function connect () {
155160
const parentInstances = await appRecord.backend.api.walkComponentParents(component)
156161
if (parentInstances.length) {
157162
// Check two parents level to update `hasChildren
158-
for (let i = 0; i < 2 && i < parentInstances.length; i++) {
163+
for (let i = 0; i < parentInstances.length; i++) {
159164
const parentId = await getComponentId(app, parentUid, parentInstances[i], ctx)
160-
if (isSubscribed(BridgeSubscriptions.COMPONENT_TREE, sub => sub.payload.instanceId === parentId)) {
165+
if (i < 2 && isSubscribed(BridgeSubscriptions.COMPONENT_TREE, sub => sub.payload.instanceId === parentId)) {
161166
requestAnimationFrame(() => {
162167
sendComponentTreeData(appRecord, parentId, appRecord.componentFilter, null, ctx)
163168
})
164169
}
170+
171+
if (SharedData.trackUpdates) {
172+
sendComponentUpdateTracking(appRecord, parentId, ctx)
173+
}
165174
}
166175
}
167176
}
@@ -170,6 +179,10 @@ async function connect () {
170179
sendSelectedComponentData(appRecord, id, ctx)
171180
}
172181

182+
if (SharedData.trackUpdates) {
183+
sendComponentUpdateTracking(appRecord, id, ctx)
184+
}
185+
173186
await refreshComponentTreeSearch(ctx)
174187
} catch (e) {
175188
if (SharedData.debugInfo) {

packages/app-frontend/src/features/components/ComponentTreeNode.vue

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@ import { computed, toRefs, onMounted, ref, watch, defineComponent, PropType } fr
33
import { ComponentTreeNode } from '@vue/devtools-api'
44
import scrollIntoView from 'scroll-into-view-if-needed'
55
import { getComponentDisplayName, UNDEFINED, SharedData } from '@vue-devtools/shared-utils'
6-
import { sortChildren, useComponent, useComponentHighlight } from './composable'
6+
import { sortChildren, useComponent, useComponentHighlight, updateTrackingEvents, updateTrackingLimit } from './composable'
77
import { onKeyDown } from '@front/util/keyboard'
8+
import { reactiveNow, useTimeAgo } from '@front/util/time'
89
910
const DEFAULT_EXPAND_DEPTH = 2
1011
@@ -140,6 +141,14 @@ export default defineComponent({
140141
}
141142
}
142143
144+
// Update tracking
145+
146+
const updateTracking = computed(() => updateTrackingEvents.value[props.instance.id])
147+
const showUpdateTracking = computed(() => updateTracking.value?.time > updateTrackingLimit.value && updateTracking.value?.time > reactiveNow.value - 20_000)
148+
const updateTrackingTime = computed(() => updateTracking.value?.time)
149+
const { timeAgo: updateTrackingTimeAgo } = useTimeAgo(updateTrackingTime)
150+
const updateTrackingOpacity = computed(() => showUpdateTracking.value ? 1 - (reactiveNow.value - updateTracking.value?.time) / 20_000 : 0)
151+
143152
return {
144153
toggleEl,
145154
sortedChildren,
@@ -153,6 +162,10 @@ export default defineComponent({
153162
unhighlight,
154163
selectNextSibling,
155164
selectPreviousSibling,
165+
showUpdateTracking,
166+
updateTracking,
167+
updateTrackingTimeAgo,
168+
updateTrackingOpacity,
156169
}
157170
},
158171
})
@@ -259,6 +272,29 @@ export default defineComponent({
259272
{{ instance.domOrder }}
260273
</span>
261274
</template>
275+
276+
<VTooltip
277+
v-if="showUpdateTracking"
278+
class="h-4"
279+
>
280+
<div class="px-3 -mx-2 h-full flex items-center">
281+
<div
282+
class="w-1 h-1 rounded-full"
283+
:class="[
284+
selected ? 'bg-white' : 'bg-green-500',
285+
]"
286+
:style="{
287+
opacity: updateTrackingOpacity,
288+
}"
289+
/>
290+
</div>
291+
292+
<template #popper>
293+
<div>
294+
Updated {{ updateTrackingTimeAgo }}
295+
</div>
296+
</template>
297+
</VTooltip>
262298
</span>
263299
</div>
264300

packages/app-frontend/src/features/components/composable/components.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,8 @@ export function resetComponents () {
259259
rootInstances.value = []
260260
componentsMap.value = {}
261261
componentsParent = {}
262+
updateTrackingEvents.value = {}
263+
updateTrackingLimit.value = Date.now() + 5_000
262264
}
263265

264266
export const requestedComponentTree = new Set()
@@ -383,3 +385,26 @@ export function getAppIdFromComponentId (id: string) {
383385
const appId = id.substring(0, index)
384386
return appId
385387
}
388+
389+
export interface ComponentUpdateTrackingEvent {
390+
instanceId: string
391+
time: number
392+
count: number
393+
}
394+
395+
export const updateTrackingEvents = ref<Record<string, ComponentUpdateTrackingEvent>>({})
396+
export const updateTrackingLimit = ref(Date.now() + 5_000)
397+
398+
export function addUpdateTrackingEvent (instanceId: string, time: number) {
399+
const event = updateTrackingEvents.value[instanceId]
400+
if (event) {
401+
event.count++
402+
event.time = time
403+
} else {
404+
Vue.set(updateTrackingEvents.value, instanceId, {
405+
instanceId,
406+
time,
407+
count: 1,
408+
})
409+
}
410+
}

packages/app-frontend/src/features/components/composable/setup.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import {
1313
requestedComponentTree,
1414
getAppIdFromComponentId,
1515
lastSelectedComponentId,
16+
addUpdateTrackingEvent,
1617
} from './components'
1718

1819
export function setupComponentsBridgeEvents (bridge: Bridge) {
@@ -71,6 +72,10 @@ export function setupComponentsBridgeEvents (bridge: Bridge) {
7172
chrome.devtools.inspectedWindow.eval('inspect(window.__VUE_DEVTOOLS_INSPECT_TARGET__)')
7273
})
7374

75+
bridge.on(BridgeEvents.TO_FRONT_COMPONENT_UPDATED, ({ instanceId, time }) => {
76+
addUpdateTrackingEvent(instanceId, time)
77+
})
78+
7479
// Persistance
7580

7681
Object.assign(lastSelectedComponentId, getStorage('lastSelectedComponentId', {}))

packages/app-frontend/src/features/settings/GlobalSettings.vue

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,17 @@ export default defineComponent({})
6161
</template>
6262
</VueFormField>
6363

64+
<VueFormField
65+
title="Update tracking"
66+
>
67+
<VueSwitch v-model="$shared.trackUpdates">
68+
Enable
69+
</VueSwitch>
70+
<template #subtitle>
71+
Turn off if your app is slowed down
72+
</template>
73+
</VueFormField>
74+
6475
<VueFormField
6576
title="Debugging info"
6677
>
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { computed, Ref, ref } from '@vue/composition-api'
2+
3+
export const reactiveNow = ref(Date.now())
4+
5+
setInterval(() => {
6+
reactiveNow.value = Date.now()
7+
}, 100)
8+
9+
export function useTimeAgo (time: Ref<number>) {
10+
return {
11+
timeAgo: computed(() => {
12+
const diff = reactiveNow.value - time.value
13+
return `${Math.round(diff / 1000)}s ago`
14+
}),
15+
}
16+
}

packages/shared-utils/src/consts.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ export enum BridgeEvents {
5151
TO_FRONT_COMPONENT_INSPECT_DOM = 'f:component:inspect-dom',
5252
TO_BACK_COMPONENT_RENDER_CODE = 'b:component:render-code',
5353
TO_FRONT_COMPONENT_RENDER_CODE = 'f:component:render-code',
54+
TO_FRONT_COMPONENT_UPDATED = 'f:component:updated',
5455

5556
// Timeline
5657
TO_FRONT_TIMELINE_EVENT = 'f:timeline:event',

packages/shared-utils/src/shared-data.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ const internalSharedData = {
2828
pluginSettings: {} as any,
2929
pageConfig: {} as any,
3030
legacyApps: false,
31+
trackUpdates: true,
3132
debugInfo: false,
3233
}
3334

@@ -52,6 +53,7 @@ const persisted = [
5253
'pluginSettings',
5354
'performanceMonitoringEnabled',
5455
'componentEventsEnabled',
56+
'trackUpdates',
5557
'debugInfo',
5658
]
5759

0 commit comments

Comments
 (0)