Skip to content

Commit

Permalink
refactor(core)!: bridge messaging (#250)
Browse files Browse the repository at this point in the history
  • Loading branch information
webfansplz authored Mar 1, 2024
1 parent d6b92f4 commit 3a38cfd
Show file tree
Hide file tree
Showing 53 changed files with 810 additions and 1,015 deletions.
1 change: 1 addition & 0 deletions packages/client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@
"unplugin-auto-import": "^0.17.5",
"unplugin-vue-components": "^0.26.0",
"vite": "^5.1.3",
"vite-plugin-vue-devtools": "workspace:^",
"vue": "^3.4.19"
}
}
21 changes: 15 additions & 6 deletions packages/client/src/App.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<script setup lang="ts">
import type { Ref } from 'vue'
import { useDevToolsBridge, useDevToolsBridgeRpc, useDevToolsState } from '@vue/devtools-core'
import { defineDevToolsAction, useDevToolsBridge, useDevToolsState } from '@vue/devtools-core'
import { isInChromePanel } from '@vue/devtools-shared'
import { Pane, Splitpanes } from 'splitpanes'
Expand All @@ -11,12 +11,10 @@ useColorMode()
const router = useRouter()
const route = useRoute()
const { connected, clientConnected } = useDevToolsState()
const bridgeRpc = useDevToolsBridgeRpc()
const clientState = devtoolsClientState
const viewMode = inject<Ref<'overlay' | 'panel'>>('viewMode', ref('overlay'))
const viewModeSwitchVisible = computed(() => viewMode.value === 'overlay' && isInChromePanel)
const { toggle } = useToggleViewMode()
const bridge = useDevToolsBridge()
const isUtilityView = computed(() => route.path.startsWith('/__') || route.path === '/')
Expand Down Expand Up @@ -72,8 +70,18 @@ watchEffect(() => {
const { copy } = useCopy()
const eyeDropper = useEyeDropper({})
bridgeRpc?.isVueInspectorDetected?.()?.then(({ data }) => {
if (data) {
const checkVueInspectorDetected = defineDevToolsAction<boolean>('devtools:check-vue-inspector-detected', async (devtools) => {
return !!await devtools?.api?.getVueInspector?.()
})
const enableVueInspector = defineDevToolsAction('devtools:enable-vue-inspector', async (devtools) => {
const inspector = await devtools?.api?.getVueInspector?.()
if (inspector)
await inspector.enable()
})
checkVueInspectorDetected().then((detected) => {
if (detected) {
vueInspectorDetected.value = true
registerCommands(() =>
[{
Expand All @@ -82,12 +90,13 @@ bridgeRpc?.isVueInspectorDetected?.()?.then(({ data }) => {
icon: 'i-carbon-select-window',
action: async () => {
bridge.value.emit('toggle-panel', false)
await bridgeRpc.enableVueInspector()
await enableVueInspector()
},
}],
)
}
})
registerCommands(() => [
...(eyeDropper.isSupported.value
? [{
Expand Down
12 changes: 7 additions & 5 deletions packages/client/src/components/assets/AssetDetails.vue
Original file line number Diff line number Diff line change
@@ -1,26 +1,28 @@
<script setup lang="ts">
import { useTimeAgo } from '@vueuse/core'
import type { AssetInfo, CodeSnippet } from '@vue/devtools-core'
import { useDevToolsBridgeRpc, useDevToolsState } from '@vue/devtools-core'
import { callViteServerAction, useDevToolsState } from '@vue/devtools-core'
import { VueButton, VueIcon, VTooltip as vTooltip } from '@vue/devtools-ui'
import type { ImageMeta } from 'vite-plugin-vue-devtools'
const props = defineProps<{
modelValue: AssetInfo
}>()
const emit = defineEmits<{ (...args: any): void }>()
const bridgeRpc = useDevToolsBridgeRpc()
const state = useDevToolsState()
const getImageMeta = callViteServerAction<ImageMeta>('assets:get-image-meta')
const getTextAssetContent = callViteServerAction<string>('assets:get-text-asset-content')
const asset = useVModel(props, 'modelValue', emit, { passive: true })
const _openInEditor = openInEditor
const _vueInspectorDetected = computed(() => vueInspectorDetected.value)
const imageMeta = computedAsync(() => {
if (asset.value.type !== 'image')
return undefined
return bridgeRpc.getImageMeta(asset.value.filePath)
return getImageMeta(asset.value.filePath)
})
const newTextContent = ref()
Expand All @@ -32,7 +34,7 @@ const textContent = computedAsync(async () => {
// eslint-disable-next-line no-unused-expressions
textContentCounter.value
const content = await bridgeRpc.getTextAssetContent(asset.value.filePath)
const content = await getTextAssetContent(asset.value.filePath)
newTextContent.value = content
return content
})
Expand Down
9 changes: 6 additions & 3 deletions packages/client/src/components/common/DockingPanel.vue
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
<script setup lang="ts">
import { VueButton, VueDarkToggle, VueIcon, VueSelect } from '@vue/devtools-ui'
import { isInChromePanel } from '@vue/devtools-shared'
import { useDevToolsBridgeRpc, useDevToolsState } from '@vue/devtools-core'
import { defineDevToolsAction, useDevToolsState } from '@vue/devtools-core'
// #region view mode
const viewMode = inject<Ref<'overlay' | 'panel'>>('viewMode', ref('overlay'))
const viewModeSwitchVisible = computed(() => viewMode.value === 'panel' && isInChromePanel)
const { toggle: toggleViewMode } = useToggleViewMode()
// #endregion
const bridgeRpc = useDevToolsBridgeRpc()
const router = useRouter()
const expandSidebar = computed({
Expand All @@ -36,8 +35,12 @@ const appRecords = computed(() => devtoolsState.appRecords.value.map(app => ({
const activeAppRecordId = ref(devtoolsState.activeAppRecordId.value)
const activeAppRecordName = computed(() => appRecords.value.find(app => app.value === activeAppRecordId.value)?.label ?? '')
const toggleApp = defineDevToolsAction('devtools:toggle-app', async (devtools, id: string) => {
await devtools.api.toggleApp(id)
})
watch(activeAppRecordId, (id) => {
bridgeRpc.toggleApp(`${id}`).then(() => {
toggleApp(`${id}`).then(() => {
router.push('/overview').then(() => {
refreshCurrentPageData()
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { VueButton, VueDropdown, VueDropdownButton, VueIcon, VTooltip as vToolti
import { getRaw } from '@vue/devtools-kit'
import type { InspectorState, InspectorStateEditorPayload } from '@vue/devtools-kit'
import type { ButtonProps } from '@vue/devtools-ui/dist/types/src/components/Button'
import { useDevToolsBridgeRpc } from '@vue/devtools-core'
import { defineDevToolsAction } from '@vue/devtools-core'
import type { EditorAddNewPropType, EditorInputValidType } from '../../../composables/inspector'
const props = withDefaults(defineProps<{
Expand All @@ -22,7 +22,9 @@ defineEmits<{
'addNewProp': [type: EditorAddNewPropType]
}>()
const bridgeRpc = useDevToolsBridgeRpc()
const editInspectorState = defineDevToolsAction('devtools:edit-inspector-state', (devtools, payload: InspectorStateEditorPayload) => {
devtools.api.editInspectorState(payload)
})
const state = useStateEditorContext()
Expand All @@ -45,7 +47,7 @@ const buttonClass = computed(() => ({
}))
function quickEdit(v: unknown, remove: boolean = false) {
bridgeRpc.editInspectorState({
editInspectorState({
path: props.data.key.split('.'),
inspectorId: state.value.inspectorId,
type: props.data.stateType!,
Expand Down
11 changes: 7 additions & 4 deletions packages/client/src/components/inspector/InspectorStateField.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import type { InspectorCustomState, InspectorState, InspectorStateEditorPayload } from '@vue/devtools-kit'
import { isArray, isObject, sortByKey } from '@vue/devtools-shared'
import { formatInspectorStateValue, getInspectorStateValueType, getRaw, toEdit, toSubmit } from '@vue/devtools-kit'
import { useDevToolsBridgeRpc } from '@vue/devtools-core'
import { defineDevToolsAction } from '@vue/devtools-core'
import { VueButton, VueIcon, VTooltip as vTooltip } from '@vue/devtools-ui'
import Actions from './InspectorDataField/Actions.vue'
import type { EditorAddNewPropType } from '~/composables/inspector'
Expand All @@ -19,7 +19,6 @@ const props = withDefaults(defineProps<{
const STATE_FIELDS_LIMIT_SIZE = 30
const state = useStateEditorContext()
const bridgeRpc = useDevToolsBridgeRpc()
const value = computed(() => formatInspectorStateValue(props.data.value))
const type = computed(() => getInspectorStateValueType(props.data.value))
const stateFormatClass = computed(() => {
Expand Down Expand Up @@ -116,9 +115,13 @@ watch(() => editing.value, (v) => {
}
})
const editInspectorState = defineDevToolsAction('devtools:edit-inspector-state', (devtools, payload: InspectorStateEditorPayload) => {
devtools.api.editInspectorState(payload)
})
function submit() {
const data = props.data
bridgeRpc.editInspectorState({
editInspectorState({
path: data.key.split('.'),
inspectorId: state.value.inspectorId,
type: data.stateType!,
Expand All @@ -145,7 +148,7 @@ function submitDrafting() {
const data = props.data
const path = data.key.split('.')
path.push(draftingNewProp.value.key)
bridgeRpc.editInspectorState({
editInspectorState({
path,
inspectorId: state.value.inspectorId,
type: data.stateType!,
Expand Down
11 changes: 4 additions & 7 deletions packages/client/src/composables/open-in-editor.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
import { useDevToolsBridgeRpc } from '@vue/devtools-core'
import { defineDevToolsAction } from '@vue/devtools-core'

export const vueInspectorDetected = ref(false)
export function openInEditor(file: string) {
const bridgeRpc = useDevToolsBridgeRpc()
return bridgeRpc.openInEditor({
file,
})
}
export const openInEditor = defineDevToolsAction('devtools:open-in-editor', (devtools, file: string) => {
devtools.api.openInEditor({ file })
})
13 changes: 10 additions & 3 deletions packages/client/src/composables/state-commands.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { randomStr } from '@vue/devtools-shared'
import { CustomCommand } from '@vue/devtools-kit'
import { MaybeRefOrGetter } from 'vue'
import { useDevToolsBridgeRpc, useDevToolsState } from '@vue/devtools-core'
import { defineDevToolsListener, useDevToolsState } from '@vue/devtools-core'

export interface CommandItem {
id: string
Expand All @@ -19,6 +19,13 @@ function uniqueById(items: CommandItem[]): CommandItem[] {
}

const registeredCommands = reactive(new Map<string, MaybeRefOrGetter<CommandItem[]>>())
let removeCommandsUpdatedListener: (() => void) | null = null

const onCustomCommandsUpdated = defineDevToolsListener<CustomCommand[]>((devtools, callback) => {
devtools.api.on.customCommandsUpdated((payload) => {
callback(payload)
})
})

// @unocss-include
export function useCommands() {
Expand All @@ -32,9 +39,9 @@ export function useCommands() {
customCommands.value = state.commands.value || []
})

const bridgeRpc = useDevToolsBridgeRpc()
onDevToolsClientConnected(() => {
bridgeRpc.on.customCommandsUpdated((data) => {
removeCommandsUpdatedListener?.()
removeCommandsUpdatedListener = onCustomCommandsUpdated((data) => {
customCommands.value = data
})
})
Expand Down
13 changes: 10 additions & 3 deletions packages/client/src/composables/state-tab.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useDevToolsBridgeRpc, useDevToolsState } from '@vue/devtools-core'
import { defineDevToolsListener, useDevToolsState } from '@vue/devtools-core'
import type { MaybeRef } from 'vue'
import type { CustomTab } from '@vue/devtools-kit'
import { isInElectron } from '@vue/devtools-shared'
Expand All @@ -22,6 +22,13 @@ export interface CategorizedCategory {

export type CategorizedTabs = [CategorizedCategory, CategorizedTab[]][]

const onCustomTabsUpdated = defineDevToolsListener<CustomTab[]>((devtools, callback) => {
devtools.api.on.customTabsUpdated((payload) => {
callback(payload)
})
})
let removeTabsUpdatedListener: (() => void) | null = null

export function useAllTabs() {
const state = useDevToolsState()
const customTabs = ref<CustomTab[]>(state.tabs.value || [])
Expand Down Expand Up @@ -105,9 +112,9 @@ export function useAllTabs() {
}, [] as Array<ModuleBuiltinTab | CustomTab>)
})

const bridgeRpc = useDevToolsBridgeRpc()
onDevToolsClientConnected(() => {
bridgeRpc.on.customTabsUpdated((data) => {
removeTabsUpdatedListener?.()
removeTabsUpdatedListener = onCustomTabsUpdated((data) => {
customTabs.value = data
})
})
Expand Down
26 changes: 6 additions & 20 deletions packages/client/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,11 @@ import 'floating-vue/dist/style.css'

import type { BridgeInstanceType } from '@vue/devtools-core'
import { BROADCAST_CHANNEL_NAME, isInChromePanel, isInElectron, isInIframe } from '@vue/devtools-shared'
import { Bridge, BridgeEvents, HandShakeServer, createDevToolsVuePlugin, registerBridgeRpc } from '@vue/devtools-core'
import { Bridge, HandShakeServer, createDevToolsVuePlugin, initViteClientHotContext, setupDevToolsBridge } from '@vue/devtools-core'

import type { App as AppType } from 'vue'
import { createApp } from 'vue'
import { createMemoryHistory, createRouter } from 'vue-router'
import { getViteClient } from 'vite-hot-client'
import App from './App.vue'
import Components from '~/pages/components.vue'
import Overview from '~/pages/overview.vue'
Expand All @@ -27,14 +26,6 @@ import WaitForConnection from '~/components/WaitForConnection.vue'
import 'uno.css'
import '~/assets/styles/main.css'

async function getViteHotContext() {
if (import.meta.url?.includes('chrome-extension://'))
return

const viteCLient = await getViteClient(`${location.pathname.split('/__devtools__')[0] || ''}/`.replace(/\/\//g, '/'), false)
return viteCLient?.createHotContext('/____')
}

const routes = [
{ path: '/', component: Index },
{ path: '/overview', component: Overview },
Expand All @@ -61,13 +52,10 @@ async function reload(app, shell) {
devtoolsBridge.value.removeAllListeners()
shell.connect(async (bridge) => {
devtoolsBridge.value = bridge
registerBridgeRpc('devtools', {
viteRPCContext: await getViteHotContext(),
bridge: devtoolsBridge.value,
})
setupDevToolsBridge(devtoolsBridge.value)
new HandShakeServer(devtoolsBridge.value).onnConnect().then(() => {
app.config.globalProperties.__VUE_DEVTOOLS_UPDATE__(devtoolsBridge.value)
devtoolsBridge.value.emit(BridgeEvents.CLIENT_READY)
devtoolsBridge.value.emit('devtools:client-ready')
})
})
}
Expand All @@ -87,10 +75,8 @@ async function connectApp(app, shell) {
export async function initDevTools(shell, options: { viewMode?: 'overlay' | 'panel' } = { viewMode: 'overlay' }) {
const app = createApp(App)
await connectApp(app, shell)
registerBridgeRpc('devtools', {
viteRPCContext: await getViteHotContext(),
bridge: devtoolsBridge.value,
})
await initViteClientHotContext()
setupDevToolsBridge(devtoolsBridge.value)
new HandShakeServer(devtoolsBridge.value).onnConnect().then(() => {
const router = createRouter({
history: createMemoryHistory(),
Expand All @@ -103,7 +89,7 @@ export async function initDevTools(shell, options: { viewMode?: 'overlay' | 'pan
viewMode: options.viewMode!,
}))
app.mount('#app')
devtoolsBridge.value.emit(BridgeEvents.CLIENT_READY)
devtoolsBridge.value.emit('devtools:client-ready')
})
}

Expand Down
Loading

0 comments on commit 3a38cfd

Please sign in to comment.