Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(electron): enhance app #87

Merged
merged 3 commits into from
Dec 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions packages/client/src/components/WaitForConnection.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,21 @@
<script setup lang="ts">
import { VueInput } from '@vue-devtools-next/ui'
import AppConnecting from '~/components/AppConnecting.vue'

const props = defineProps<{
local?: string
network?: string
}>()

function scriptWrapper(str: string) {
return `\<script src="${str}"\>\</script\>`
}

const _local = scriptWrapper(props.local!)
const _network = scriptWrapper(props.network!)

const local = ref(_local)
const network = ref(_network)
</script>

<template>
Expand All @@ -8,6 +24,17 @@ import AppConnecting from '~/components/AppConnecting.vue'
<p class="pt-5 font-bold text-base">
Waiting for connection...
</p>
<div v-if="props.local && props.network" class="mt-5">
<p class="text-center text-sm op80 text-base">
Add one of the following to the top of your page 👇:
</p>
<div class="mt-3 $ui-fcc flex-row">
<VueInput v-model="local" left-icon="i-carbon-copy" class="w-400px!" />
</div>
<div class="mt-3 $ui-fcc flex-row">
<VueInput v-model="network" left-icon="i-carbon-copy" class="w-400px!" />
</div>
</div>
</AppConnecting>
</div>
</template>
Expand Down
6 changes: 5 additions & 1 deletion packages/client/src/composables/state-tab.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { useDevToolsBridgeRpc, useDevToolsState } from '@vue-devtools-next/core'
import type { MaybeRef } from 'vue'
import type { CustomTab } from '@vue-devtools-next/kit'
import { isInElectron } from '@vue-devtools-next/shared'

import type { ModuleBuiltinTab } from '~/types/tab'

export interface TabSettings {
Expand Down Expand Up @@ -31,7 +33,9 @@ export function useAllTabs() {
if (currentTab) {
if (currentTab[1].some(t => t.name === tab.name))
return
if (!vitePluginDetected && viteOnlyTabs.includes(tab.name))

// @TODO: electron app support vite only tabs
if ((!vitePluginDetected || isInElectron) && viteOnlyTabs.includes(tab.name))
return

currentTab[1].push({
Expand Down
6 changes: 4 additions & 2 deletions packages/client/src/constants/tab.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { DevtoolsBridgeAppRecord } from '@vue-devtools-next/core'
import { deepClone } from '@vue-devtools-next/shared'
import { deepClone, isInElectron } from '@vue-devtools-next/shared'
import type { ModuleBuiltinTab } from '~/types'

// @unocss-include
Expand Down Expand Up @@ -93,7 +93,9 @@ export function getBuiltinTab(viteDetected: boolean, moduleDetectives?: Devtools
if (item[0] === 'modules')
item[1] = item[1].filter(t => moduleDetectives ? isDetected(moduleDetectives, t) : true)
})
return viteDetected

// @TODO: electron app support vite only tabs
return (viteDetected && !isInElectron)
? tab
: tab.map(([_, tabs]) => [_, tabs.filter(t => !viteOnlyTabs.includes(t.name))])
}
2 changes: 2 additions & 0 deletions packages/client/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import { VIEW_MODE_STORAGE_KEY, isBrowser, isInChromePanel, target } from '@vue-

import { initDevTools as _initDevTools } from './main'

export { createConnectionApp } from './main'

export function initDevTools(shell) {
if (!isBrowser)
return
Expand Down
18 changes: 10 additions & 8 deletions packages/client/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import '@unocss/reset/tailwind.css'
import 'floating-vue/dist/style.css'

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

import type { App as AppType } from 'vue'
Expand Down Expand Up @@ -105,6 +105,14 @@ export async function initDevTools(shell, options: { viewMode?: 'overlay' | 'pan
})
}

export function createConnectionApp(container: string = '#app', props?: Record<string, string>) {
const app = createApp(WaitForConnection, {
...props,
})
app.mount(container)
return app
}

window.addEventListener('message', (event) => {
if (event.data === '__VUE_DEVTOOLS_CREATE_CLIENT__') {
initDevTools({
Expand Down Expand Up @@ -133,7 +141,7 @@ window.addEventListener('message', (event) => {
})

// @TODO: refactor separate window channel
if (!isInIframe) {
if (!isInIframe && !isInChromePanel && !isInElectron) {
function initSeparateWindowChannel() {
const connectionInfo: {
connected: boolean
Expand All @@ -147,12 +155,6 @@ if (!isInIframe) {

const channel = new BroadcastChannel(BROADCAST_CHANNEL_NAME)

function createConnectionApp() {
const app = createApp(WaitForConnection)
app.mount('#app')
return app
}

function connect() {
connectionInfo.timer = setInterval(() => {
channel.postMessage({
Expand Down
11 changes: 9 additions & 2 deletions packages/electron/app.html
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,14 @@
display: flex;
height: 100%;
}
.loading {
width: 100vw;
height: 100vh;
font-weight: bold;
display: flex;
align-items: center;
justify-content: center;
}
</style>
<link rel="stylesheet" type="text/css" href="./client/devtools-panel.css" />
<script>
Expand All @@ -20,8 +28,7 @@
<body>
<div id="container">
<div id="app">
<!-- @TODO: connection style and host/port input -->
Waiting for connection...
<p class="loading">Loading DevTools Client...</p>
</div>
</div>
<script src="./dist/devtools.js"></script>
Expand Down
1 change: 1 addition & 0 deletions packages/electron/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
"electron": "^28.0.0",
"execa": "^8.0.1",
"h3": "^1.9.0",
"ip": "^1.1.8",
"socket.io": "^4.7.2",
"socket.io-client": "^4.7.2"
},
Expand Down
3 changes: 2 additions & 1 deletion packages/electron/src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ function createWindow() {
webSecurity: false,
nodeIntegration: true,
contextIsolation: false,
devTools: true,
// @TODO: enabled in dev mode
devTools: false,
},
})
const appEntryPath = path.join(__dirname, '../app.html')
Expand Down
80 changes: 50 additions & 30 deletions packages/electron/src/devtools.ts
Original file line number Diff line number Diff line change
@@ -1,34 +1,54 @@
import io from 'socket.io-client'
import { initDevTools } from '../client/devtools-panel'
import io from 'socket.io-client/dist/socket.io.js'
import ip from 'ip'
import { createConnectionApp, initDevTools } from '../client/devtools-panel'
import { Bridge } from '../../core/src/bridge'

const port = window.process.env.PORT || 8098
const socket = io(`http://localhost:${port}`)

let reload: Function | null = null

socket.on('vue-devtools:init', () => {
// If new page is opened reload devtools
if (reload)
return reload()

initDevTools({
connect(cb) {
const bridge = new Bridge({
tracker(fn) {
socket.on('vue-devtools:message', (data) => {
fn(data)
})
},
trigger(data) {
socket.emit('vue-devtools:message', data)
},
})

cb(bridge)
},
reload(fn) {
reload = fn
},

function init() {
const localhost = `http://localhost:${port}`
const socket = io(localhost)
let reload: Function | null = null

const app = createConnectionApp('#app', {
local: localhost,
network: `http://${ip.address()}:${port}`,
})

socket.on('vue-devtools:init', () => {
app.unmount()

// If new page is opened reload devtools
if (reload)
return reload()

initDevTools({
connect(cb) {
const bridge = new Bridge({
tracker(fn) {
socket.on('vue-devtools:message', (data) => {
fn(data)
})
},
trigger(data) {
socket.emit('vue-devtools:message', data)
},
})

cb(bridge)
},
reload(fn) {
reload = fn
},
})
})
})

socket.on('vue-devtools:disconnect', () => {
app.unmount()
reload = null
socket.close()
init()
})
}

init()
7 changes: 6 additions & 1 deletion packages/electron/src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ export function init() {
'/',
eventHandler(() => {
const userAppContent = fs.readFileSync(path.join(__dirname, './user-app.js'), 'utf-8')
return userAppContent
const processSyntaxPolyfill = `if(!window.process){window.process={env:{}}};`
return processSyntaxPolyfill + userAppContent
}),
)

Expand All @@ -30,6 +31,10 @@ export function init() {
socket.broadcast.emit('vue-devtools:init')
})

socket.on('vue-devtools:disconnect', () => {
socket.broadcast.emit('vue-devtools:disconnect')
})

socket.on('disconnect', (reason) => {
if (reason.indexOf('client'))
socket.broadcast.emit('vue-devtools-disconnect-devtools')
Expand Down
4 changes: 3 additions & 1 deletion packages/electron/src/user-app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,6 @@ socket.on('vue-devtools:disconnect-user-app', () => {
socket.disconnect()
})

// @TODO: disconnect logic
window.addEventListener('beforeunload', () => {
socket.emit('vue-devtools:disconnect')
})
5 changes: 4 additions & 1 deletion packages/playground/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vue DevTools Playground</title>
<!-- <script src="http://localhost:8098"></script> -->
<!-- <script>
window.__VUE_DEVTOOLS_PORT__ = 8080
</script>
<script src="http://localhost:8080"></script> -->
</head>
<body>
<div id="app2"></div>
Expand Down
2 changes: 1 addition & 1 deletion packages/playground/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import Hey from './pages/Hey.vue'
import './style.css'

// connect to remote devtools
// devtools.connect('http://localhost', 8098)
// devtools.connect('http://localhost', 8080)

const pinia = createPinia()
const pinia2 = createPinia()
Expand Down
1 change: 1 addition & 0 deletions packages/shared/src/env.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ export const target = (typeof globalThis !== 'undefined'

export const isInChromePanel = typeof target.chrome !== 'undefined' && !!target.chrome.devtools
export const isInIframe = isBrowser && target.self !== target.top
export const isInElectron = typeof navigator !== 'undefined' && navigator.userAgent.toLowerCase().includes('electron')
7 changes: 7 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.