render svg using webview

This commit is contained in:
pompurin404 2024-08-27 19:28:26 +08:00
parent 8af1495df5
commit 38849a8739
No known key found for this signature in database
10 changed files with 79 additions and 950 deletions

View File

@ -38,7 +38,6 @@ jobs:
run: | run: |
pnpm install pnpm install
pnpm add @mihomo-party/sysproxy-win32-${{ matrix.arch }}-msvc pnpm add @mihomo-party/sysproxy-win32-${{ matrix.arch }}-msvc
pnpm add @resvg/resvg-js-win32-${{ matrix.arch }}-msvc
pnpm prepare --${{ matrix.arch }} pnpm prepare --${{ matrix.arch }}
- name: Build - name: Build
env: env:
@ -96,7 +95,6 @@ jobs:
run: | run: |
pnpm install pnpm install
pnpm add @mihomo-party/sysproxy-linux-${{ matrix.arch }}-gnu pnpm add @mihomo-party/sysproxy-linux-${{ matrix.arch }}-gnu
pnpm add @resvg/resvg-js-linux-${{ matrix.arch }}-gnu
pnpm prepare --${{ matrix.arch }} pnpm prepare --${{ matrix.arch }}
- name: Build - name: Build
env: env:
@ -154,7 +152,6 @@ jobs:
run: | run: |
pnpm install pnpm install
pnpm add @mihomo-party/sysproxy-darwin-${{ matrix.arch }} pnpm add @mihomo-party/sysproxy-darwin-${{ matrix.arch }}
pnpm add @resvg/resvg-js-darwin-${{ matrix.arch }}
pnpm prepare --${{ matrix.arch }} pnpm prepare --${{ matrix.arch }}
- name: Build - name: Build
env: env:

View File

@ -27,7 +27,6 @@
"adm-zip": "^0.5.15", "adm-zip": "^0.5.15",
"axios": "^1.7.5", "axios": "^1.7.5",
"dayjs": "^1.11.13", "dayjs": "^1.11.13",
"svg2img": "1.0.0-beta.2",
"webdav": "^5.7.1", "webdav": "^5.7.1",
"ws": "^8.18.0", "ws": "^8.18.0",
"yaml": "^2.5.0" "yaml": "^2.5.0"

File diff suppressed because it is too large Load Diff

View File

@ -1,20 +1,11 @@
import axios, { AxiosInstance } from 'axios' import axios, { AxiosInstance } from 'axios'
import { getAppConfig, getControledMihomoConfig } from '../config' import { getAppConfig, getControledMihomoConfig } from '../config'
import templateIcon from '../../../resources/iconTemplate.png?asset'
import svgIcon from '../../../resources/iconTemplate@2x.png?asset'
import { mainWindow } from '..' import { mainWindow } from '..'
import WebSocket from 'ws' import WebSocket from 'ws'
import { tray } from '../resolve/tray' import { tray } from '../resolve/tray'
import { calcTraffic } from '../utils/calc' import { calcTraffic } from '../utils/calc'
import { getRuntimeConfig } from './factory' import { getRuntimeConfig } from './factory'
import { nativeImage } from 'electron'
import parseSvg from '../utils/parseSvg'
const icon = nativeImage.createFromPath(svgIcon)
icon.setTemplateImage(true)
const base64 = icon.toPNG().toString('base64')
let hasShowTraffic = false
let drawing = false
let axiosIns: AxiosInstance = null! let axiosIns: AxiosInstance = null!
let mihomoTrafficWs: WebSocket | null = null let mihomoTrafficWs: WebSocket | null = null
let trafficRetry = 10 let trafficRetry = 10
@ -180,7 +171,6 @@ export const stopMihomoTraffic = (): void => {
} }
const mihomoTraffic = async (): Promise<void> => { const mihomoTraffic = async (): Promise<void> => {
const { showTraffic = true } = await getAppConfig()
const controledMihomoConfig = await getControledMihomoConfig() const controledMihomoConfig = await getControledMihomoConfig()
let server = controledMihomoConfig['external-controller'] let server = controledMihomoConfig['external-controller']
const secret = controledMihomoConfig.secret ?? '' const secret = controledMihomoConfig.secret ?? ''
@ -194,38 +184,6 @@ const mihomoTraffic = async (): Promise<void> => {
const json = JSON.parse(data) as IMihomoTrafficInfo const json = JSON.parse(data) as IMihomoTrafficInfo
trafficRetry = 10 trafficRetry = 10
mainWindow?.webContents.send('mihomoTraffic', json) mainWindow?.webContents.send('mihomoTraffic', json)
if (process.platform === 'darwin') {
if (showTraffic) {
if (drawing) return
drawing = true
const svgContent = `
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 156 36">
<image height='36' width='36' href='data:image/png;base64,${base64}'/>
<text x='40' y='15' font-size='18' font-family="PingFang SC" font-weight='bold' text-anchor='start'></text>
<text x='40' y='34' font-size='18' font-family="PingFang SC" font-weight='bold' text-anchor='start'></text>
<text x='156' y='15' font-size='18' font-family="PingFang SC" font-weight='bold' text-anchor='end'>${calcTraffic(json.up)}/s</text>
<text x='156' y='34' font-size='18' font-family="PingFang SC" font-weight='bold' text-anchor='end'>${calcTraffic(json.down)}/s</text>
</svg>`
try {
const buffer = await parseSvg(svgContent)
const image = nativeImage.createFromBuffer(buffer).resize({ height: 16 })
image.setTemplateImage(true)
tray?.setImage(image)
hasShowTraffic = true
} catch (e) {
// ignore
} finally {
drawing = false
}
} else {
if (hasShowTraffic) {
const icon = nativeImage.createFromPath(templateIcon)
icon.setTemplateImage(true)
tray?.setImage(icon)
hasShowTraffic = false
}
}
}
if (process.platform !== 'linux') { if (process.platform !== 'linux') {
tray?.setToolTip( tray?.setToolTip(
'↑' + '↑' +

View File

@ -237,6 +237,11 @@ export async function createTray(): Promise<void> {
if (!useDockIcon) { if (!useDockIcon) {
app.dock.hide() app.dock.hide()
} }
ipcMain.on('trayIconUpdate', async (_, png: string) => {
const image = nativeImage.createFromDataURL(png).resize({ height: 16 })
image.setTemplateImage(true)
tray?.setImage(image)
})
tray?.addListener('right-click', async () => { tray?.addListener('right-click', async () => {
if (mainWindow?.isVisible()) { if (mainWindow?.isVisible()) {
mainWindow?.close() mainWindow?.close()

View File

@ -1,32 +0,0 @@
import { Worker } from 'worker_threads'
export default function parseSvg(svgStr: string): Promise<Buffer> {
return new Promise((resolve, reject) => {
const worker = new Worker(workerString, {
eval: true,
env: {
__dirname
},
workerData: svgStr
})
worker.on('message', resolve)
worker.on('error', reject)
worker.on('exit', (code) => {
if (code !== 0) reject(new Error(`Worker stopped with exit code ${code}`))
})
})
}
const workerString = `
const { parentPort, workerData } = require('worker_threads')
const path = require('path')
const svg2img = require(path.resolve(process.env.__dirname, '../../node_modules/svg2img'))
const svgStr = workerData
svg2img(svgStr, (err, buffer) => {
if (err) {
throw err
}
parentPort?.postMessage(buffer)
})
`

View File

@ -6,7 +6,7 @@
<!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP --> <!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP -->
<meta <meta
http-equiv="Content-Security-Policy" http-equiv="Content-Security-Policy"
content="default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src *" content="default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src * data:;"
/> />
</head> </head>

File diff suppressed because one or more lines are too long

View File

@ -122,6 +122,7 @@ const Connections: React.FC = () => {
<TableCell>{item.metadata.process || item.metadata.sourceIP}</TableCell> <TableCell>{item.metadata.process || item.metadata.sourceIP}</TableCell>
<TableCell className="max-w-[100px] text-ellipsis whitespace-nowrap overflow-hidden"> <TableCell className="max-w-[100px] text-ellipsis whitespace-nowrap overflow-hidden">
{item.metadata.host || {item.metadata.host ||
item.metadata.sniffHost ||
item.metadata.remoteDestination || item.metadata.remoteDestination ||
item.metadata.destinationIP} item.metadata.destinationIP}
</TableCell> </TableCell>

View File

@ -1,21 +1,33 @@
export function calcTraffic(byte: number): string { export function calcTraffic(byte: number): string {
if (byte < 1024) return `${byte} B` if (byte < 1024) return `${byte} B`
byte /= 1024 byte /= 1024
if (byte < 1024) return `${byte.toFixed(2)} KB` if (byte < 1024) return `${formatNumString(byte)} KB`
byte /= 1024 byte /= 1024
if (byte < 1024) return `${byte.toFixed(2)} MB` if (byte < 1024) return `${formatNumString(byte)} MB`
byte /= 1024 byte /= 1024
if (byte < 1024) return `${byte.toFixed(2)} GB` if (byte < 1024) return `${formatNumString(byte)} GB`
byte /= 1024 byte /= 1024
if (byte < 1024) return `${byte.toFixed(2)} TB` if (byte < 1024) return `${formatNumString(byte)} TB`
byte /= 1024 byte /= 1024
if (byte < 1024) return `${byte.toFixed(2)} PB` if (byte < 1024) return `${formatNumString(byte)} PB`
byte /= 1024 byte /= 1024
if (byte < 1024) return `${byte.toFixed(2)} EB` if (byte < 1024) return `${formatNumString(byte)} EB`
byte /= 1024 byte /= 1024
if (byte < 1024) return `${byte.toFixed(2)} ZB` if (byte < 1024) return `${formatNumString(byte)} ZB`
byte /= 1024 byte /= 1024
return `${byte.toFixed(2)} YB` return `${formatNumString(byte)} YB`
}
function formatNumString(num: number): string {
let str = num.toFixed(2)
if (str.length <= 5) return str
if (str.length == 6) {
str = num.toFixed(1)
return str
} else {
str = Math.round(num).toString()
return str
}
} }
export function calcPercent( export function calcPercent(