From 3444bdd89c49092a37715f2706caca3e695591a5 Mon Sep 17 00:00:00 2001 From: Guillaume Chau Date: Tue, 10 Oct 2023 11:49:47 +0200 Subject: [PATCH 01/68] fix: disable screenshots by default --- packages/shared-utils/src/shared-data.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/shared-utils/src/shared-data.ts b/packages/shared-utils/src/shared-data.ts index 03ae7809f..4c0011453 100644 --- a/packages/shared-utils/src/shared-data.ts +++ b/packages/shared-utils/src/shared-data.ts @@ -22,7 +22,7 @@ const internalSharedData = { vuexGroupGettersByModule: true, showMenuScrollTip: true, timelineTimeGrid: true, - timelineScreenshots: true, + timelineScreenshots: false, menuStepScrolling: isMac, pluginPermissions: {} as any, pluginSettings: {} as any, From 56af8da13239dd5f68d67cb865e6dbc9cbb4323f Mon Sep 17 00:00:00 2001 From: Guillaume Chau Date: Tue, 10 Oct 2023 11:53:59 +0200 Subject: [PATCH 02/68] v6.5.1 --- package.json | 2 +- packages/api/package.json | 2 +- packages/shell-chrome/manifest.json | 4 ++-- packages/shell-electron/package.json | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index d71ab8597..6ee2b0bc4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "vue-devtools", - "version": "6.5.0", + "version": "6.5.1", "description": "devtools for Vue.js!", "private": true, "workspaces": [ diff --git a/packages/api/package.json b/packages/api/package.json index 0fe878b42..9fa5e8c75 100644 --- a/packages/api/package.json +++ b/packages/api/package.json @@ -1,6 +1,6 @@ { "name": "@vue/devtools-api", - "version": "6.5.0", + "version": "6.5.1", "description": "Interact with the Vue devtools from the page", "main": "lib/cjs/index.js", "browser": "lib/esm/index.js", diff --git a/packages/shell-chrome/manifest.json b/packages/shell-chrome/manifest.json index 6e85dd5c1..f5c6b08cb 100644 --- a/packages/shell-chrome/manifest.json +++ b/packages/shell-chrome/manifest.json @@ -1,7 +1,7 @@ { "name": "Vue.js devtools", - "version": "6.5.0", - "version_name": "6.5.0", + "version": "6.5.1", + "version_name": "6.5.1", "description": "Browser DevTools extension for debugging Vue.js applications.", "manifest_version": 2, "icons": { diff --git a/packages/shell-electron/package.json b/packages/shell-electron/package.json index f2adcd541..ca5729498 100644 --- a/packages/shell-electron/package.json +++ b/packages/shell-electron/package.json @@ -1,6 +1,6 @@ { "name": "@vue/devtools", - "version": "6.5.0", + "version": "6.5.1", "description": "StandAlone vue-devtools", "repository": { "url": "https://github.com/vuejs/vue-devtools.git", From bc09ebf720bdb8216b6231d0f27400ada098cd39 Mon Sep 17 00:00:00 2001 From: Guillaume Chau Date: Tue, 10 Oct 2023 11:57:13 +0200 Subject: [PATCH 03/68] ci: fix release action --- .github/workflows/create-release.yml | 53 ++-------------------------- 1 file changed, 2 insertions(+), 51 deletions(-) diff --git a/.github/workflows/create-release.yml b/.github/workflows/create-release.yml index 8c642148d..c93564f57 100644 --- a/.github/workflows/create-release.yml +++ b/.github/workflows/create-release.yml @@ -1,57 +1,10 @@ -name: Create Release +name: Create release on: push: tags: - "v*" -# jobs: -# build: -# runs-on: ubuntu-latest -# steps: -# - name: Checkout -# uses: actions/checkout@v2 -# with: -# fetch-depth: 0 - -# - name: Set up Node.js -# uses: actions/setup-node@v2 -# with: -# node-version: 14.x - -# - name: Set up lerna yarn cache -# uses: actions/cache@v2 -# with: -# path: | -# node_modules -# */*/node_modules -# ~/.cache/yarn -# ~/.cache/Cypress -# key: ${{ runner.os }}-${{ hashFiles('**/yarn.lock') }} - -# - name: Install yarn dependencies -# if: steps.cache.outputs.cache-hit != 'true' -# run: yarn install --pure-lockfile - -# - name: Build the extension -# run: yarn run build && node release.js && yarn run test && yarn run zip - -# - name: Create Release for Tag -# id: release_tag -# uses: Akryum/release-tag@conventional -# env: -# GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} -# with: -# tag_name: ${{ github.ref }} -# preset: angular - -# - name: Upload artifacts -# uses: softprops/action-gh-release@v1 -# if: startsWith(github.ref, 'refs/tags/') -# with: -# files: | -# dist/devtools-* - jobs: build: name: Create Release @@ -64,10 +17,8 @@ jobs: - name: Create Release for Tag id: release_tag - uses: Akryum/release-tag@conventional + uses: Akryum/release-tag@v4.0.7 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: tag_name: ${{ github.ref }} - preset: angular # Use conventional-changelog preset - From 6ccd5083c0be6222007f12be36af8d9ed9a9900e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrg=20Lehni?= Date: Fri, 15 Dec 2023 09:36:45 +0100 Subject: [PATCH 04/68] fix(vue3): prevent mixin leakage caused by inspection, fix #2037 (#2038) Co-authored-by: Himself65 --- packages/app-backend-vue3/src/components/data.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/app-backend-vue3/src/components/data.ts b/packages/app-backend-vue3/src/components/data.ts index 958f8b551..30718c760 100644 --- a/packages/app-backend-vue3/src/components/data.ts +++ b/packages/app-backend-vue3/src/components/data.ts @@ -485,7 +485,7 @@ function mergeOptions ( if (!to[key]) { to[key] = from[key] } else { - Object.assign(to[key], from[key]) + to[key] = Object.assign(Object.create(null), to[key], from[key]) } } } From aac74c0a4d3575692ef33bcf8b9f1a7161447150 Mon Sep 17 00:00:00 2001 From: Clay Levering Date: Fri, 15 Dec 2023 00:38:28 -0800 Subject: [PATCH 05/68] fix: add null checks for appRecord and appRecord.instanceMap, fix #1892 (#2122) --- packages/app-backend-core/src/index.ts | 55 ++++++++++++++--------- packages/app-backend-core/src/perf.ts | 2 + packages/app-backend-core/src/plugin.ts | 1 + packages/app-backend-core/src/timeline.ts | 1 + 4 files changed, 38 insertions(+), 21 deletions(-) diff --git a/packages/app-backend-core/src/index.ts b/packages/app-backend-core/src/index.ts index 66ea11d69..2a527200f 100644 --- a/packages/app-backend-core/src/index.ts +++ b/packages/app-backend-core/src/index.ts @@ -174,12 +174,14 @@ async function connect () { if (component.__VUE_DEVTOOLS_UID__ == null) { component.__VUE_DEVTOOLS_UID__ = id } - if (!appRecord.instanceMap.has(id)) { - appRecord.instanceMap.set(id, component) + if (appRecord?.instanceMap) { + if (!appRecord.instanceMap.has(id)) { + appRecord.instanceMap.set(id, component) + } } } - if (parentUid != null) { + if (parentUid != null && appRecord?.instanceMap) { const parentInstances = await appRecord.backend.api.walkComponentParents(component) if (parentInstances.length) { // Check two parents level to update `hasChildren @@ -222,14 +224,18 @@ async function connect () { try { if (!app || (typeof uid !== 'number' && !uid) || !component) return const appRecord = await getAppRecord(app, ctx) - if (parentUid != null) { + if (parentUid != null && appRecord) { const parentInstances = await appRecord.backend.api.walkComponentParents(component) if (parentInstances.length) { const parentId = await getComponentId(app, parentUid, parentInstances[0], ctx) if (isSubscribed(BridgeSubscriptions.COMPONENT_TREE, sub => sub.payload.instanceId === parentId)) { raf(async () => { try { - sendComponentTreeData(await getAppRecord(app, ctx), parentId, appRecord.componentFilter, null, false, ctx) + const appRecord = await getAppRecord(app, ctx) + + if (appRecord) { + sendComponentTreeData(appRecord, parentId, appRecord.componentFilter, null, false, ctx) + } } catch (e) { if (SharedData.debugInfo) { console.error(e) @@ -244,7 +250,10 @@ async function connect () { if (isSubscribed(BridgeSubscriptions.SELECTED_COMPONENT_DATA, sub => sub.payload.instanceId === id)) { await sendEmptyComponentData(id, ctx) } - appRecord.instanceMap.delete(id) + + if (appRecord) { + appRecord.instanceMap.delete(id) + } await refreshComponentTreeSearch(ctx) } catch (e) { @@ -288,13 +297,15 @@ async function connect () { hook.on(HookEvents.TIMELINE_LAYER_ADDED, async (options: TimelineLayerOptions, plugin: Plugin) => { const appRecord = await getAppRecord(plugin.descriptor.app, ctx) - ctx.timelineLayers.push({ - ...options, - appRecord, - plugin, - events: [], - }) - ctx.bridge.send(BridgeEvents.TO_FRONT_TIMELINE_LAYER_ADD, {}) + if (appRecord) { + ctx.timelineLayers.push({ + ...options, + appRecord, + plugin, + events: [], + }) + ctx.bridge.send(BridgeEvents.TO_FRONT_TIMELINE_LAYER_ADD, {}) + } }) hook.on(HookEvents.TIMELINE_EVENT_ADDED, async (options: TimelineEventOptions, plugin: Plugin) => { @@ -305,14 +316,16 @@ async function connect () { hook.on(HookEvents.CUSTOM_INSPECTOR_ADD, async (options: CustomInspectorOptions, plugin: Plugin) => { const appRecord = await getAppRecord(plugin.descriptor.app, ctx) - ctx.customInspectors.push({ - ...options, - appRecord, - plugin, - treeFilter: '', - selectedNodeId: null, - }) - ctx.bridge.send(BridgeEvents.TO_FRONT_CUSTOM_INSPECTOR_ADD, {}) + if (appRecord) { + ctx.customInspectors.push({ + ...options, + appRecord, + plugin, + treeFilter: '', + selectedNodeId: null, + }) + ctx.bridge.send(BridgeEvents.TO_FRONT_CUSTOM_INSPECTOR_ADD, {}) + } }) hook.on(HookEvents.CUSTOM_INSPECTOR_SEND_TREE, async (inspectorId: string, plugin: Plugin) => { diff --git a/packages/app-backend-core/src/perf.ts b/packages/app-backend-core/src/perf.ts index 0cfa6193d..1328ed1d3 100644 --- a/packages/app-backend-core/src/perf.ts +++ b/packages/app-backend-core/src/perf.ts @@ -17,6 +17,7 @@ export async function performanceMarkStart ( try { if (!SharedData.performanceMonitoringEnabled) return const appRecord = await getAppRecord(app, ctx) + if (!appRecord) return const componentName = await appRecord.backend.api.getComponentName(instance) const groupId = ctx.perfUniqueGroupId++ const groupKey = `${uid}-${type}` @@ -80,6 +81,7 @@ export async function performanceMarkEnd ( try { if (!SharedData.performanceMonitoringEnabled) return const appRecord = await getAppRecord(app, ctx) + if (!appRecord) return const componentName = await appRecord.backend.api.getComponentName(instance) const groupKey = `${uid}-${type}` const groupInfo = appRecord.perfGroupIds.get(groupKey) diff --git a/packages/app-backend-core/src/plugin.ts b/packages/app-backend-core/src/plugin.ts index e8eec5d6b..20abbb81f 100644 --- a/packages/app-backend-core/src/plugin.ts +++ b/packages/app-backend-core/src/plugin.ts @@ -14,6 +14,7 @@ export async function addPlugin (pluginQueueItem: PluginQueueItem, ctx: BackendC ctx.currentPlugin = plugin try { const appRecord = await getAppRecord(plugin.descriptor.app, ctx) + if (!appRecord) return const api = new DevtoolsPluginApiInstance(plugin, appRecord, ctx) if (pluginQueueItem.proxy) { await pluginQueueItem.proxy.setRealTarget(api) diff --git a/packages/app-backend-core/src/timeline.ts b/packages/app-backend-core/src/timeline.ts index 1eff348c8..b7cda33be 100644 --- a/packages/app-backend-core/src/timeline.ts +++ b/packages/app-backend-core/src/timeline.ts @@ -73,6 +73,7 @@ function setupBuiltinLayers (ctx: BackendContext) { 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)) || 'Unknown Component' From 92386388a9492a3a40acedc64561d9d79e885327 Mon Sep 17 00:00:00 2001 From: Fan Pei Date: Sun, 4 Feb 2024 20:21:29 +0900 Subject: [PATCH 06/68] refactor(frontend): Migrate the frontend application from Vue.js 2 to 3 (#2119) Co-authored-by: Guillaume Chau --- .eslintrc.js | 12 + package.json | 7 +- packages/app-backend-vue2/package.json | 2 + packages/app-frontend/package.json | 13 +- packages/app-frontend/src/app.ts | 56 +-- .../app-frontend/src/assets/style/index.styl | 4 + packages/app-frontend/src/features/App.vue | 2 +- .../src/features/apps/AppSelect.vue | 2 +- .../src/features/apps/AppSelectPane.vue | 2 +- .../src/features/apps/AppSelectPaneItem.vue | 3 +- .../app-frontend/src/features/apps/index.ts | 6 +- .../src/features/chrome/pane-visibility.ts | 2 +- .../src/features/code/CodeEditor.vue | 29 +- .../components/ComponentsInspector.vue | 26 +- .../src/features/components/RenderCode.vue | 6 +- .../components/SelectedComponentPane.vue | 4 +- .../components/composable/components.ts | 32 +- .../components/ui/components/VueButton.vue | 119 +++++ .../components/ui/components/VueDisable.vue | 48 ++ .../components/ui/components/VueDropdown.vue | 201 ++++++++ .../ui/components/VueDropdownButton.vue | 16 + .../components/ui/components/VueFormField.vue | 94 ++++ .../components/ui/components/VueGroup.vue | 131 ++++++ .../ui/components/VueGroupButton.vue | 55 +++ .../components/ui/components/VueIcon.vue | 20 + .../components/ui/components/VueInput.vue | 443 ++++++++++++++++++ .../ui/components/VueLoadingBar.vue | 29 ++ .../ui/components/VueLoadingIndicator.vue | 6 + .../components/ui/components/VueModal.vue | 96 ++++ .../components/ui/components/VueSelect.vue | 83 ++++ .../ui/components/VueSelectButton.vue | 52 ++ .../components/ui/components/VueSwitch.vue | 86 ++++ .../components/ui/components/icons.ts | 34 ++ .../ui/composables/useDisableScroll.ts | 29 ++ .../components/ui/composables/useDisabled.ts | 34 ++ .../src/features/components/ui/index.ts | 59 +++ .../src/features/header/AppHeader.vue | 23 +- .../src/features/header/AppHeaderSelect.vue | 13 +- .../app-frontend/src/features/header/tabs.ts | 8 +- .../src/features/inspector/DataField.vue | 45 +- .../src/features/inspector/StateFields.vue | 8 +- .../src/features/inspector/StateInspector.vue | 6 +- .../inspector/custom/CustomInspector.vue | 22 +- .../inspector/custom/CustomInspectorNode.vue | 4 +- .../features/inspector/custom/composable.ts | 10 +- .../src/features/layout/SplitPane.vue | 2 +- .../src/features/layout/orientation.ts | 4 +- .../src/features/plugin/PluginListItem.vue | 2 +- .../features/plugin/PluginSettingsItem.vue | 6 +- .../plugin/PluginSourceDescription.vue | 2 +- .../src/features/plugin/PluginSourceIcon.vue | 2 +- .../src/features/plugin/Plugins.vue | 6 +- .../app-frontend/src/features/plugin/index.ts | 4 +- .../src/features/settings/GlobalSettings.vue | 4 +- .../timeline/AskScreenshotPermission.vue | 33 +- .../src/features/timeline/LayerItem.vue | 4 +- .../src/features/timeline/Timeline.vue | 45 +- .../features/timeline/TimelineEventList.vue | 10 +- .../features/timeline/TimelineScrollbar.vue | 4 +- .../src/features/timeline/TimelineView.vue | 8 +- .../features/timeline/composable/layers.ts | 14 +- .../src/features/timeline/composable/setup.ts | 5 +- packages/app-frontend/src/index.ts | 2 +- packages/app-frontend/src/mixins/keyboard.ts | 4 +- .../app-frontend/src/plugins/global-refs.ts | 5 +- packages/app-frontend/src/plugins/i18n.ts | 7 +- packages/app-frontend/src/plugins/index.ts | 36 +- .../app-frontend/src/plugins/responsive.ts | 62 +-- packages/app-frontend/src/router.ts | 28 +- packages/app-frontend/src/types/vue.d.ts | 22 + packages/app-frontend/src/util/router.ts | 10 - packages/build-tools/package.json | 4 +- packages/build-tools/src/createConfig.js | 16 +- packages/shared-utils/src/env.ts | 8 +- packages/shared-utils/src/shared-data.ts | 10 +- packages/shell-dev-vue2/package.json | 3 + packages/shell-dev-vue2/src/index.js | 2 +- packages/shell-dev-vue2/webpack.config.js | 22 +- packages/shell-dev-vue3/package.json | 7 +- .../shell-dev-vue3/src/SetupTSScriptProps.vue | 2 - packages/shell-dev-vue3/webpack.config.js | 16 - packages/shell-host/package.json | 3 +- packages/shell-host/public/index.html | 2 +- packages/shell-host/src/DevIframe.vue | 201 ++++---- packages/shell-host/src/devtools.js | 8 +- yarn.lock | 384 ++++++++++++--- 86 files changed, 2457 insertions(+), 544 deletions(-) create mode 100644 packages/app-frontend/src/features/components/ui/components/VueButton.vue create mode 100644 packages/app-frontend/src/features/components/ui/components/VueDisable.vue create mode 100644 packages/app-frontend/src/features/components/ui/components/VueDropdown.vue create mode 100644 packages/app-frontend/src/features/components/ui/components/VueDropdownButton.vue create mode 100644 packages/app-frontend/src/features/components/ui/components/VueFormField.vue create mode 100644 packages/app-frontend/src/features/components/ui/components/VueGroup.vue create mode 100644 packages/app-frontend/src/features/components/ui/components/VueGroupButton.vue create mode 100644 packages/app-frontend/src/features/components/ui/components/VueIcon.vue create mode 100644 packages/app-frontend/src/features/components/ui/components/VueInput.vue create mode 100644 packages/app-frontend/src/features/components/ui/components/VueLoadingBar.vue create mode 100644 packages/app-frontend/src/features/components/ui/components/VueLoadingIndicator.vue create mode 100644 packages/app-frontend/src/features/components/ui/components/VueModal.vue create mode 100644 packages/app-frontend/src/features/components/ui/components/VueSelect.vue create mode 100644 packages/app-frontend/src/features/components/ui/components/VueSelectButton.vue create mode 100644 packages/app-frontend/src/features/components/ui/components/VueSwitch.vue create mode 100644 packages/app-frontend/src/features/components/ui/components/icons.ts create mode 100644 packages/app-frontend/src/features/components/ui/composables/useDisableScroll.ts create mode 100644 packages/app-frontend/src/features/components/ui/composables/useDisabled.ts create mode 100644 packages/app-frontend/src/features/components/ui/index.ts create mode 100644 packages/app-frontend/src/types/vue.d.ts delete mode 100644 packages/app-frontend/src/util/router.ts diff --git a/.eslintrc.js b/.eslintrc.js index b78fc6d2e..e3f3e76a6 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -39,6 +39,9 @@ module.exports = { }, }, ], + 'func-call-spacing': 'off', + 'vue/component-definition-name-casing': 'off', + 'vue/multi-word-component-names': 'off', '@typescript-eslint/ban-ts-comment': 'warn', '@typescript-eslint/no-use-before-define': 'off', '@typescript-eslint/explicit-module-boundary-types': 'off', @@ -76,6 +79,14 @@ module.exports = { files: ['packages/shell-dev-vue3/**'], rules: { 'vue/valid-template-root': 'off', + 'vue/one-component-per-file': 'off', + 'vue/no-v-model-argument': 'off', + }, + }, + { + files: ['packages/app-frontend/**'], + rules: { + 'vue/no-v-model-argument': 'off', }, }, { @@ -99,6 +110,7 @@ module.exports = { }, rules: { 'no-console': 'off', + 'vue/no-multiple-template-root': 'off', }, }, { diff --git a/package.json b/package.json index 6ee2b0bc4..3a1437c71 100644 --- a/package.json +++ b/package.json @@ -61,7 +61,7 @@ "eslint-plugin-node": "^11.1.0", "eslint-plugin-promise": "^5.1.0", "eslint-plugin-standard": "^5.0.0", - "eslint-plugin-vue": "^6.0.0", + "eslint-plugin-vue": "^9.17.0", "execa": "^4.0.3", "inquirer": "^6.2.0", "lerna": "^4.0.0", @@ -70,8 +70,9 @@ "semver": "^5.5.1", "start-server-and-test": "^1.7.1", "tailwindcss": "npm:@tailwindcss/postcss7-compat", - "vue-loader": "^15.9.0", - "webpack-dev-server": "^4.0.0-beta.0" + "vue-loader": "^17.2.2", + "webpack-dev-server": "^4.0.0-beta.0", + "svg-inline-loader": "^0.8.2" }, "resolutions": { "cypress": "=3.4.1", diff --git a/packages/app-backend-vue2/package.json b/packages/app-backend-vue2/package.json index cacbebf25..654595d71 100644 --- a/packages/app-backend-vue2/package.json +++ b/packages/app-backend-vue2/package.json @@ -17,6 +17,8 @@ "lodash": "^4.17.21" }, "devDependencies": { + "vue": "^2.7.10", + "vue-loader": "^15.7.1", "@types/node": "^13.9.1", "@types/webpack-env": "^1.15.1", "core-js": "^3.20.2", diff --git a/packages/app-frontend/package.json b/packages/app-frontend/package.json index e39d7eec0..fa7445054 100644 --- a/packages/app-frontend/package.json +++ b/packages/app-frontend/package.json @@ -10,18 +10,23 @@ "@vue/ui": "^0.12.5", "circular-json-es6": "^2.0.2", "d3": "^5.16.0", + "floating-vue": "^5.2.2", "lodash": "^4.17.15", "lru-cache": "^5.1.1", "monaco-editor": "^0.24.0", "pixi.js-legacy": "^6.2.0", - "portal-vue": "^2.1.7", "scroll-into-view-if-needed": "^2.2.28", "semver": "^7.3.5", "stylus": "^0.54.7", "stylus-loader": "^3.0.2", "tinycolor2": "^1.4.2", - "vue": "^2.7.10", - "vue-router": "^3.6.5", - "vue-virtual-scroller": "^1.0.10" + "vue": "^3.3.4", + "vue-resize": "^2.0.0-alpha.1", + "vue-router": "^4.2.5", + "vue-safe-teleport": "^0.1.2", + "vue-virtual-scroller": "^2.0.0-alpha.1" + }, + "devDependencies": { + "@akryum/md-icons-svg": "^1.0.1" } } diff --git a/packages/app-frontend/src/app.ts b/packages/app-frontend/src/app.ts index 621b182ab..20fe47514 100644 --- a/packages/app-frontend/src/app.ts +++ b/packages/app-frontend/src/app.ts @@ -1,8 +1,7 @@ import App from './features/App.vue' - -import Vue from 'vue' +import { App as VueApp, createApp as createVueApp } from 'vue' import { isChrome, initEnv, SharedData, initSharedData, destroySharedData, BridgeEvents } from '@vue-devtools/shared-utils' -import { createRouter } from './router' +import { createRouterInstance } from './router' import { getBridge, setBridge } from './features/bridge' import { setAppConnected, setAppInitializing } from './features/connection' import { setupAppsBridgeEvents } from './features/apps' @@ -12,37 +11,25 @@ import { setupCustomInspectorBridgeEvents } from './features/inspector/custom/co import { setupPluginsBridgeEvents } from './features/plugin' import { setupPlugins } from './plugins' -setupPlugins() - // Capture and log devtool errors when running as actual extension // so that we can debug it by inspecting the background page. // We do want the errors to be thrown in the dev shell though. -if (isChrome) { - Vue.config.errorHandler = (e, vm) => { - getBridge()?.send('ERROR', { - message: e.message, - stack: e.stack, - component: vm.$options.name || (vm.$options as any)._componentTag || 'anonymous', - }) - } -} - -// @ts-ignore -Vue.options.renderError = (h, e) => { - return h('pre', { - class: 'text-white bg-red-500 p-2 rounded text-xs overflow-auto', - }, e.stack) -} - export function createApp () { - const router = createRouter() - - const app = new Vue({ - router, - render: h => h(App as any), - }) - - // @TODO [Vue 3] Setup plugins + const router = createRouterInstance() + + const app = createVueApp(App) + app.use(router) + setupPlugins(app) + + if (isChrome) { + app.config.errorHandler = (e, vm) => { + getBridge()?.send('ERROR', { + message: (e as Error).message, + stack: (e as Error).stack, + component: vm?.$options.name || (vm?.$options as any)._componentTag || 'anonymous', + }) + } + } return app } @@ -51,22 +38,22 @@ export function createApp () { * Connect then init the app. We need to reconnect on every reload, because a * new backend will be injected. */ -export function connectApp (app, shell) { +export function connectApp (app: VueApp, shell) { shell.connect(async bridge => { setBridge(bridge) // @TODO remove // @ts-ignore window.bridge = bridge - if (Object.prototype.hasOwnProperty.call(Vue.prototype, '$shared')) { + if (app.config.globalProperties.$shared) { destroySharedData() } else { - Object.defineProperty(Vue.prototype, '$shared', { + Object.defineProperty(app.config.globalProperties, '$shared', { get: () => SharedData, }) } - initEnv(Vue) + initEnv(app) bridge.on(BridgeEvents.TO_FRONT_TITLE, ({ title }: { title: string }) => { document.title = `${title} - Vue devtools` @@ -75,7 +62,6 @@ export function connectApp (app, shell) { await initSharedData({ bridge, persist: true, - Vue, }) if (SharedData.logDetected) { diff --git a/packages/app-frontend/src/assets/style/index.styl b/packages/app-frontend/src/assets/style/index.styl index 1a3dafe53..f3a677c7b 100644 --- a/packages/app-frontend/src/assets/style/index.styl +++ b/packages/app-frontend/src/assets/style/index.styl @@ -30,6 +30,10 @@ html, body body overflow hidden +#app + width: 100% + height: 100% + button:focus outline none diff --git a/packages/app-frontend/src/features/App.vue b/packages/app-frontend/src/features/App.vue index 1b3c2a9a1..cc42dd156 100644 --- a/packages/app-frontend/src/features/App.vue +++ b/packages/app-frontend/src/features/App.vue @@ -122,7 +122,7 @@ export default defineComponent({ - + diff --git a/packages/app-frontend/src/features/apps/AppSelect.vue b/packages/app-frontend/src/features/apps/AppSelect.vue index 72b255dfe..5b6ff267f 100644 --- a/packages/app-frontend/src/features/apps/AppSelect.vue +++ b/packages/app-frontend/src/features/apps/AppSelect.vue @@ -6,7 +6,7 @@ import { watch, defineComponent, computed } from 'vue' import { BridgeEvents, SharedData } from '@vue-devtools/shared-utils' import { useApps, pendingSelectAppId, scanLegacyApps } from '@front/features/apps' import { useOrientation } from '@front/features/layout/orientation' -import { useRouter } from '@front/util/router' +import { useRouter } from 'vue-router' import { useBridge } from '../bridge' import { useVueVersionCheck } from './vue-version-check' diff --git a/packages/app-frontend/src/features/apps/AppSelectPane.vue b/packages/app-frontend/src/features/apps/AppSelectPane.vue index 1326329fe..9581de477 100644 --- a/packages/app-frontend/src/features/apps/AppSelectPane.vue +++ b/packages/app-frontend/src/features/apps/AppSelectPane.vue @@ -4,7 +4,7 @@ import AppSelectPaneItem from './AppSelectPaneItem.vue' import { watch, defineComponent, ref, computed } from 'vue' import { BridgeEvents, SharedData } from '@vue-devtools/shared-utils' import { useApps, pendingSelectAppId, scanLegacyApps } from '@front/features/apps' -import { useRouter } from '@front/util/router' +import { useRouter } from 'vue-router' import { useBridge } from '../bridge' export default defineComponent({ diff --git a/packages/app-frontend/src/features/apps/AppSelectPaneItem.vue b/packages/app-frontend/src/features/apps/AppSelectPaneItem.vue index 07a18a3e9..170f8d88c 100644 --- a/packages/app-frontend/src/features/apps/AppSelectPaneItem.vue +++ b/packages/app-frontend/src/features/apps/AppSelectPaneItem.vue @@ -14,6 +14,7 @@ export default defineComponent({ default: false, }, }, + emits: ['select'], setup (props) { const { getLatestVersion } = useVueVersionCheck() @@ -89,7 +90,7 @@ export default defineComponent({ .app-button { @apply rounded-none text-left h-auto py-1.5; - > >>> .content { + > :deep(.content) { @apply min-w-full justify-start; > .default-slot { diff --git a/packages/app-frontend/src/features/apps/index.ts b/packages/app-frontend/src/features/apps/index.ts index 32ae6eeab..f3a201848 100644 --- a/packages/app-frontend/src/features/apps/index.ts +++ b/packages/app-frontend/src/features/apps/index.ts @@ -1,7 +1,7 @@ import { ref, computed } from 'vue' import { BridgeEvents, Bridge } from '@vue-devtools/shared-utils' import { getBridge } from '@front/features/bridge' -import { useRoute, useRouter } from '@front/util/router' +import { useRoute, useRouter } from 'vue-router' import { fetchLayers } from '../timeline/composable' export interface AppRecord { @@ -15,7 +15,7 @@ const apps = ref([]) export function useCurrentApp () { const route = useRoute() - const currentAppId = computed(() => route.value.params.appId) + const currentAppId = computed(() => route.params.appId as string) const currentApp = computed(() => apps.value.find(a => currentAppId.value === a.id)) return { @@ -71,7 +71,7 @@ function fetchApps () { getBridge().send(BridgeEvents.TO_BACK_APP_LIST, {}) } -export const pendingSelectAppId = ref(null) +export const pendingSelectAppId = ref(null) const pendingSelectPromises: (() => void)[] = [] diff --git a/packages/app-frontend/src/features/chrome/pane-visibility.ts b/packages/app-frontend/src/features/chrome/pane-visibility.ts index e162b2d07..e0c40578b 100644 --- a/packages/app-frontend/src/features/chrome/pane-visibility.ts +++ b/packages/app-frontend/src/features/chrome/pane-visibility.ts @@ -1,7 +1,7 @@ import { isChrome } from '@vue-devtools/shared-utils' let panelShown = !isChrome -let pendingAction = null +let pendingAction: (() => void | Promise) | null = null if (isChrome) { chrome.runtime.onMessage.addListener(request => { diff --git a/packages/app-frontend/src/features/code/CodeEditor.vue b/packages/app-frontend/src/features/code/CodeEditor.vue index 68aa1c4fd..04a2a80d0 100644 --- a/packages/app-frontend/src/features/code/CodeEditor.vue +++ b/packages/app-frontend/src/features/code/CodeEditor.vue @@ -1,6 +1,5 @@ diff --git a/packages/app-frontend/src/features/components/ComponentsInspector.vue b/packages/app-frontend/src/features/components/ComponentsInspector.vue index af45ccfdf..f9b2d5178 100644 --- a/packages/app-frontend/src/features/components/ComponentsInspector.vue +++ b/packages/app-frontend/src/features/components/ComponentsInspector.vue @@ -135,7 +135,7 @@ export default defineComponent({ - +
Component names:
@@ -184,9 +184,9 @@ export default defineComponent({
- + - + - + - +
-
+ diff --git a/packages/app-frontend/src/features/components/ui/components/VueLoadingBar.vue b/packages/app-frontend/src/features/components/ui/components/VueLoadingBar.vue new file mode 100644 index 000000000..20c92f3a6 --- /dev/null +++ b/packages/app-frontend/src/features/components/ui/components/VueLoadingBar.vue @@ -0,0 +1,29 @@ + + + diff --git a/packages/app-frontend/src/features/components/ui/components/VueLoadingIndicator.vue b/packages/app-frontend/src/features/components/ui/components/VueLoadingIndicator.vue new file mode 100644 index 000000000..751b25232 --- /dev/null +++ b/packages/app-frontend/src/features/components/ui/components/VueLoadingIndicator.vue @@ -0,0 +1,6 @@ + diff --git a/packages/app-frontend/src/features/components/ui/components/VueModal.vue b/packages/app-frontend/src/features/components/ui/components/VueModal.vue new file mode 100644 index 000000000..2f6cdc732 --- /dev/null +++ b/packages/app-frontend/src/features/components/ui/components/VueModal.vue @@ -0,0 +1,96 @@ + + + diff --git a/packages/app-frontend/src/features/components/ui/components/VueSelect.vue b/packages/app-frontend/src/features/components/ui/components/VueSelect.vue new file mode 100644 index 000000000..3dd6de5c0 --- /dev/null +++ b/packages/app-frontend/src/features/components/ui/components/VueSelect.vue @@ -0,0 +1,83 @@ + + + diff --git a/packages/app-frontend/src/features/components/ui/components/VueSelectButton.vue b/packages/app-frontend/src/features/components/ui/components/VueSelectButton.vue new file mode 100644 index 000000000..4ab71f864 --- /dev/null +++ b/packages/app-frontend/src/features/components/ui/components/VueSelectButton.vue @@ -0,0 +1,52 @@ + + + diff --git a/packages/app-frontend/src/features/components/ui/components/VueSwitch.vue b/packages/app-frontend/src/features/components/ui/components/VueSwitch.vue new file mode 100644 index 000000000..d7bc45194 --- /dev/null +++ b/packages/app-frontend/src/features/components/ui/components/VueSwitch.vue @@ -0,0 +1,86 @@ + + + diff --git a/packages/app-frontend/src/features/components/ui/components/icons.ts b/packages/app-frontend/src/features/components/ui/components/icons.ts new file mode 100644 index 000000000..cef330919 --- /dev/null +++ b/packages/app-frontend/src/features/components/ui/components/icons.ts @@ -0,0 +1,34 @@ +const icons = require.context( + '@akryum/md-icons-svg/svg/', + true, + /materialicons\/24px\.svg$/, +) + +export default { + install () { + const sprites = [''] + let spriteIndex = 0 + // Load all the SVG symbols + icons.keys().forEach((key, index) => { + let result = icons(key) + const [, iconName] = /(\w+)\/materialicons/.exec(key) + const [, content] = /(.*)<\/svg>/.exec(result) + result = `${content}` + sprites[spriteIndex] += result + if ((index + 1) % 40 === 0) { + sprites.push('') + spriteIndex++ + } + }) + for (const html of sprites) { + const iconsWrapper = document.createElement('div') + iconsWrapper.style.display = 'none' + iconsWrapper.innerHTML = html + document.body.insertBefore(iconsWrapper, document.body.firstChild) + } + }, +} + +export function generateHtmlIcon (icon: string) { + return `
` +} diff --git a/packages/app-frontend/src/features/components/ui/composables/useDisableScroll.ts b/packages/app-frontend/src/features/components/ui/composables/useDisableScroll.ts new file mode 100644 index 000000000..56c1c21e2 --- /dev/null +++ b/packages/app-frontend/src/features/components/ui/composables/useDisableScroll.ts @@ -0,0 +1,29 @@ +import { onBeforeUnmount, onMounted } from 'vue' + +let count = 0 + +function getScrollingElements () { + return document.querySelectorAll('.vue-ui-disable-scroll, body') +} + +function updateScroll () { + if (count === 0) { + getScrollingElements().forEach((el) => + el.classList.remove('vue-ui-no-scroll'), + ) + } else if (count === 1) { + getScrollingElements().forEach((el) => el.classList.add('vue-ui-no-scroll')) + } +} + +export function useDisableScroll () { + onMounted(() => { + count++ + updateScroll() + }) + + onBeforeUnmount(() => { + count-- + updateScroll() + }) +} diff --git a/packages/app-frontend/src/features/components/ui/composables/useDisabled.ts b/packages/app-frontend/src/features/components/ui/composables/useDisabled.ts new file mode 100644 index 000000000..81132f843 --- /dev/null +++ b/packages/app-frontend/src/features/components/ui/composables/useDisabled.ts @@ -0,0 +1,34 @@ +/** + * (Use with the DisabledChild mixin) + * Allow disabling an entire tree of components implementing the DisabledChild mixin. + */ + +import { provide, reactive, watch, inject, computed } from 'vue' + +export const useDisabledParent = (props: { disabled?: boolean }) => { + const injectedDisableData = reactive({ + value: props.disabled || false, + }) + + provide('VueDisableMixin', { + data: injectedDisableData, + }) + + watch( + () => props.disabled, + (value, oldValue) => { + if (value !== oldValue) injectedDisableData.value = value + }, + ) +} + +export const useDisabledChild = (props: { disabled?: boolean }) => { + const injectDisable = inject<{ data: { value: boolean } } | undefined>( + 'VueDisableMixin', + null, + ) + + return { + finalDisabled: computed(() => props.disabled || (injectDisable && injectDisable.data.value)), + } +} diff --git a/packages/app-frontend/src/features/components/ui/index.ts b/packages/app-frontend/src/features/components/ui/index.ts new file mode 100644 index 000000000..fca5eea88 --- /dev/null +++ b/packages/app-frontend/src/features/components/ui/index.ts @@ -0,0 +1,59 @@ +import { Plugin } from 'vue' +import VueIcons from './components/icons' +import VueDisable from './components/VueDisable.vue' +import VueButton from './components/VueButton.vue' +import VueDropdown from './components/VueDropdown.vue' +import VueDropdownButton from './components/VueDropdownButton.vue' +import VueFormField from './components/VueFormField.vue' +import VueLoadingIndicator from './components/VueLoadingIndicator.vue' +import VueGroup from './components/VueGroup.vue' +import VueGroupButton from './components/VueGroupButton.vue' +import VueIcon from './components/VueIcon.vue' +import VueInput from './components/VueInput.vue' +import VueLoadingBar from './components/VueLoadingBar.vue' +import VueSwitch from './components/VueSwitch.vue' +import VueSelect from './components/VueSelect.vue' +import VueSelectButton from './components/VueSelectButton.vue' +import VueModal from './components/VueModal.vue' +import FloatingVue from 'floating-vue' +import 'floating-vue/dist/style.css' +export { generateHtmlIcon } from './components/icons' + +const ui: Plugin = { + install (app) { + app.use(VueIcons) + app.component('VueButton', VueButton) + app.component('VueDisable', VueDisable) + app.component('VueDropdown', VueDropdown) + app.component('VueFormField', VueFormField) + app.component('VueDropdownButton', VueDropdownButton) + app.component('VueLoadingIndicator', VueLoadingIndicator) + app.component('VueGroup', VueGroup) + app.component('VueGroupButton', VueGroupButton) + app.component('VueIcon', VueIcon) + app.component('VueInput', VueInput) + app.component('VueLoadingBar', VueLoadingBar) + app.component('VueSwitch', VueSwitch) + app.component('VueSelect', VueSelect) + app.component('VueSelectButton', VueSelectButton) + app.component('VueModal', VueModal) + + app.use(FloatingVue, { + container: 'body', + instantMove: true, + themes: { + tooltip: { + delay: { + show: 1000, + hide: 800, + }, + }, + dropdown: { + handleResize: false, + }, + }, + }) + }, +} + +export default ui diff --git a/packages/app-frontend/src/features/header/AppHeader.vue b/packages/app-frontend/src/features/header/AppHeader.vue index e50f4d0f3..3a00a882c 100644 --- a/packages/app-frontend/src/features/header/AppHeader.vue +++ b/packages/app-frontend/src/features/header/AppHeader.vue @@ -6,9 +6,9 @@ import PluginSourceIcon from '@front/features/plugin/PluginSourceIcon.vue' import PluginSourceDescription from '../plugin/PluginSourceDescription.vue' import { computed, ref, watch, defineComponent } from 'vue' -import type { RawLocation, Route } from 'vue-router' +import type { RouteLocationRaw, RouteLocation } from 'vue-router' import { BridgeEvents } from '@vue-devtools/shared-utils' -import { useRoute } from '@front/util/router' +import { useRoute } from 'vue-router' import { useBridge } from '@front/features/bridge' import { useInspectors } from '@front/features/inspector/custom/composable' import { useTabs } from './tabs' @@ -18,8 +18,8 @@ import { useOrientation } from '../layout/orientation' interface HeaderRoute { icon: string label: string - targetRoute: RawLocation - matchRoute: (route: Route) => boolean + targetRoute: RouteLocationRaw + matchRoute: (route: RouteLocation) => boolean pluginId?: string } @@ -60,7 +60,7 @@ export default defineComponent({ matchRoute: route => route.params.inspectorId === i.id, })))) - const currentHeaderRoute = computed(() => headerRoutes.value.find(r => r.matchRoute(route.value))) + const currentHeaderRoute = computed(() => headerRoutes.value.find(r => r.matchRoute(route))) const lastHeaderRoute = ref(null) watch(currentHeaderRoute, value => { @@ -104,7 +104,7 @@ export default defineComponent({ -