Compare commits

...

2 Commits

Author SHA1 Message Date
ezequielnick
84c89105b4 chore(workflow): update dev 2025-08-29 12:42:06 +08:00
ezequielnick
f7716ae448 feat: add option to disable HardwareAcceleration 2025-08-29 11:09:46 +08:00
12 changed files with 196 additions and 46 deletions

View File

@ -20,26 +20,48 @@ jobs:
continue-on-error: true continue-on-error: true
run: | run: |
# Get release ID for dev tag # Get release ID for dev tag
echo "🔍 Looking for existing dev release..."
RELEASE_ID=$(curl -s -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \ RELEASE_ID=$(curl -s -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
"https://api.github.com/repos/${{ github.repository }}/releases/tags/dev" | \ "https://api.github.com/repos/${{ github.repository }}/releases/tags/dev" | \
jq -r '.id // empty') jq -r '.id // empty')
if [ ! -z "$RELEASE_ID" ]; then if [ ! -z "$RELEASE_ID" ] && [ "$RELEASE_ID" != "empty" ]; then
echo "Found dev release with ID: $RELEASE_ID" echo "✅ Found dev release with ID: $RELEASE_ID"
# Get all assets and delete them # Get all assets
curl -s -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \ echo "📋 Getting list of assets..."
"https://api.github.com/repos/${{ github.repository }}/releases/$RELEASE_ID/assets" | \ ASSETS=$(curl -s -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
jq -r '.[].id' | \ "https://api.github.com/repos/${{ github.repository }}/releases/$RELEASE_ID/assets")
while read asset_id; do
echo "Deleting asset: $asset_id" ASSET_COUNT=$(echo "$ASSETS" | jq '. | length')
curl -X DELETE -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \ echo "📦 Found $ASSET_COUNT assets to delete"
"https://api.github.com/repos/${{ github.repository }}/releases/assets/$asset_id"
if [ "$ASSET_COUNT" -gt 0 ]; then
# Delete each asset with detailed logging
echo "$ASSETS" | jq -r '.[].id' | while read asset_id; do
if [ ! -z "$asset_id" ]; then
echo "🗑️ Deleting asset ID: $asset_id"
RESPONSE=$(curl -s -w "HTTPSTATUS:%{http_code}" -X DELETE \
-H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
"https://api.github.com/repos/${{ github.repository }}/releases/assets/$asset_id")
HTTP_CODE=$(echo $RESPONSE | tr -d '\n' | sed -e 's/.*HTTPSTATUS://')
if [ "$HTTP_CODE" = "204" ]; then
echo "✅ Successfully deleted asset $asset_id"
else
echo "❌ Failed to delete asset $asset_id (HTTP: $HTTP_CODE)"
echo "Response: $(echo $RESPONSE | sed -e 's/HTTPSTATUS:.*//')"
fi
# Add small delay to avoid rate limiting
sleep 0.5
fi
done done
echo "🎉 Finished deleting assets"
echo "All dev release assets deleted" else
echo " No assets found to delete"
fi
else else
echo "No existing dev release found" echo " No existing dev release found"
fi fi
- name: Skip for Tag Release - name: Skip for Tag Release
if: startsWith(github.ref, 'refs/tags/v') if: startsWith(github.ref, 'refs/tags/v')
@ -109,7 +131,6 @@ jobs:
dist/*.sha256 dist/*.sha256
dist/*setup.exe dist/*setup.exe
dist/*portable.7z dist/*portable.7z
body: "Development build from ${{ github.sha }}"
prerelease: true prerelease: true
draft: false draft: false
token: ${{ secrets.GITHUB_TOKEN }} token: ${{ secrets.GITHUB_TOKEN }}
@ -180,7 +201,6 @@ jobs:
dist/*.sha256 dist/*.sha256
dist/*setup.exe dist/*setup.exe
dist/*portable.7z dist/*portable.7z
body: "Development build from ${{ github.sha }}"
prerelease: true prerelease: true
draft: false draft: false
token: ${{ secrets.GITHUB_TOKEN }} token: ${{ secrets.GITHUB_TOKEN }}
@ -244,7 +264,6 @@ jobs:
dist/*.sha256 dist/*.sha256
dist/*.deb dist/*.deb
dist/*.rpm dist/*.rpm
body: "Development build from ${{ github.sha }}"
prerelease: true prerelease: true
draft: false draft: false
token: ${{ secrets.GITHUB_TOKEN }} token: ${{ secrets.GITHUB_TOKEN }}
@ -330,7 +349,6 @@ jobs:
files: | files: |
dist/*.sha256 dist/*.sha256
dist/*.pkg dist/*.pkg
body: "Development build from ${{ github.sha }}"
prerelease: true prerelease: true
draft: false draft: false
token: ${{ secrets.GITHUB_TOKEN }} token: ${{ secrets.GITHUB_TOKEN }}
@ -418,7 +436,6 @@ jobs:
files: | files: |
dist/*.sha256 dist/*.sha256
dist/*.pkg dist/*.pkg
body: "Development build from ${{ github.sha }}"
prerelease: true prerelease: true
draft: false draft: false
token: ${{ secrets.GITHUB_TOKEN }} token: ${{ secrets.GITHUB_TOKEN }}
@ -438,7 +455,15 @@ jobs:
if: startsWith(github.ref, 'refs/tags/v') if: startsWith(github.ref, 'refs/tags/v')
env: env:
TELEGRAM_BOT_TOKEN: ${{ secrets.TELEGRAM_BOT_TOKEN }} TELEGRAM_BOT_TOKEN: ${{ secrets.TELEGRAM_BOT_TOKEN }}
RELEASE_TYPE: release
run: pnpm telegram run: pnpm telegram
- name: Telegram Dev Notification
if: github.event_name == 'workflow_dispatch'
env:
TELEGRAM_BOT_TOKEN: ${{ secrets.TELEGRAM_BOT_TOKEN }}
GITHUB_SHA: ${{ github.sha }}
RELEASE_TYPE: dev
run: pnpm telegram:dev
- name: Generate latest.yml - name: Generate latest.yml
run: pnpm updater run: pnpm updater
- name: Publish Release - name: Publish Release
@ -454,7 +479,7 @@ jobs:
with: with:
tag_name: dev tag_name: dev
files: latest.yml files: latest.yml
body: "Development build updater from ${{ github.sha }}" body_path: changelog.md
prerelease: true prerelease: true
draft: false draft: false
token: ${{ secrets.GITHUB_TOKEN }} token: ${{ secrets.GITHUB_TOKEN }}

View File

@ -1,3 +1,11 @@
## 1.8.6-dev
### 新功能 (Feat)
- 增加硬件加速开关,解决某些显卡驱动问题导致的渲染异常或崩溃
### 修复 (Fix)
- 修复windows 下以非管理员模式启动后,无法自动更新的权限问题
## 1.8.5 ## 1.8.5
**🎉 本次更新增加了大家期待已久的托盘图标根据代理状态变化颜色,系统代理为蓝色,虚拟网卡为绿色,双开为红色 **🎉 本次更新增加了大家期待已久的托盘图标根据代理状态变化颜色,系统代理为蓝色,虚拟网卡为绿色,双开为红色
@ -34,17 +42,4 @@
### 修复 (Fix) ### 修复 (Fix)
- 修复某些系统下的悬浮窗开启崩溃的问题(开启兼容模式=关闭硬件加速) - 修复某些系统下的悬浮窗开启崩溃的问题(开启兼容模式=关闭硬件加速)
- 开机自启在非管理员模式下报错的问题 - 开机自启在非管理员模式下报错的问题
- 解决某些 macos 系统下无法开启虚拟网卡的问题(tun device名称冲突) - 解决某些 macos 系统下无法开启虚拟网卡的问题(tun device名称冲突)
## 1.8.3
**本次更新移除了 Windows 下启动必须管理员模式的机制,改为只在启用虚拟网卡模式的时候,申请 UAC 权限重启软件,安全性更好,更灵活,给无法使用管理员模式运行软件的企业用户提供了更大的便利**
### 新功能 (Feat)
- 移除 Windows 下启动必须管理员模式的机制,改为只在启用虚拟网卡模式的时候,申请 UAC 权限重启软件
### 重构 (Refactor)
- Geodata 文件只有在源文件更新的时候才会在启动时覆盖更新
### 修复 (Fix)
- 修复 DNS/嗅探覆写开关逻辑,修改设置不再会直接写入运行时配置,增加了“仅保存”按钮
- 悬浮窗改为纯矩形,修复 windows 下兼容性问题带来的白边

View File

@ -1,6 +1,6 @@
{ {
"name": "mihomo-party", "name": "mihomo-party",
"version": "1.8.5", "version": "1.8.6-dev",
"description": "Mihomo Party", "description": "Mihomo Party",
"main": "./out/main/index.js", "main": "./out/main/index.js",
"author": "mihomo-party-org", "author": "mihomo-party-org",
@ -14,7 +14,8 @@
"prepare": "node scripts/prepare.mjs", "prepare": "node scripts/prepare.mjs",
"updater": "node scripts/updater.mjs", "updater": "node scripts/updater.mjs",
"checksum": "node scripts/checksum.mjs", "checksum": "node scripts/checksum.mjs",
"telegram": "node scripts/telegram.mjs", "telegram": "node scripts/telegram.mjs release",
"telegram:dev": "node scripts/telegram.mjs dev",
"artifact": "node scripts/artifact.mjs", "artifact": "node scripts/artifact.mjs",
"dev": "electron-vite dev", "dev": "electron-vite dev",
"postinstall": "electron-builder install-app-deps", "postinstall": "electron-builder install-app-deps",

View File

@ -5,18 +5,64 @@ const chat_id = '@MihomoPartyChannel'
const pkg = readFileSync('package.json', 'utf-8') const pkg = readFileSync('package.json', 'utf-8')
const changelog = readFileSync('changelog.md', 'utf-8') const changelog = readFileSync('changelog.md', 'utf-8')
const { version } = JSON.parse(pkg) const { version } = JSON.parse(pkg)
const downloadUrl = `https://github.com/mihomo-party-org/mihomo-party/releases/download/v${version}`
let content = `<b>🌟 <a href="https://github.com/mihomo-party-org/mihomo-party/releases/tag/v${version}">Mihomo Party v${version}</a> 正式发布</b>\n\n` const releaseType = process.env.RELEASE_TYPE || process.argv[2] || 'release'
for (const line of changelog.split('\n')) { const isDevRelease = releaseType === 'dev'
if (line.length === 0) {
content += '\n' function convertMarkdownToTelegramHTML(content) {
} else if (line.startsWith('### ')) { return content
content += `<b>${line.replace('### ', '')}</b>\n` .split("\n")
} else { .map((line) => {
content += `${line}\n` if (line.trim().length === 0) {
} return "";
} else if (line.startsWith("## ")) {
return `<b>${line.replace("## ", "")}</b>`;
} else if (line.startsWith("### ")) {
return `<b>${line.replace("### ", "")}</b>`;
} else if (line.startsWith("#### ")) {
return `<b>${line.replace("#### ", "")}</b>`;
} else {
let processedLine = line.replace(
/\[([^\]]+)\]\(([^)]+)\)/g,
(match, text, url) => {
const encodedUrl = encodeURI(url);
return `<a href="${encodedUrl}">${text}</a>`;
},
);
processedLine = processedLine.replace(
/\*\*([^*]+)\*\*/g,
"<b>$1</b>",
);
return processedLine;
}
})
.join("\n");
} }
let content = '';
if (isDevRelease) {
const commitSha = process.env.GITHUB_SHA || 'unknown'
const shortCommitSha = commitSha.substring(0, 7)
content = `<b>🚧 <a href="https://github.com/mihomo-party-org/mihomo-party/releases/tag/dev">Mihomo Party Dev Build</a> 开发版本发布</b>\n\n`
content += `<b>基于版本:</b> ${version}\n`
content += `<b>提交哈希:</b> <a href="https://github.com/mihomo-party-org/mihomo-party/commit/${commitSha}">${shortCommitSha}</a>\n\n`
content += `<b>更新日志:</b>\n`
content += convertMarkdownToTelegramHTML(changelog)
content += '\n\n<b>⚠️ 注意:这是开发版本,可能存在不稳定性,仅供测试使用</b>\n'
} else {
// 正式版本通知
content = `<b>🌟 <a href="https://github.com/mihomo-party-org/mihomo-party/releases/tag/v${version}">Mihomo Party v${version}</a> 正式发布</b>\n\n`
content += convertMarkdownToTelegramHTML(changelog)
}
// 构建下载链接
const downloadUrl = isDevRelease
? `https://github.com/mihomo-party-org/mihomo-party/releases/download/dev`
: `https://github.com/mihomo-party-org/mihomo-party/releases/download/v${version}`
content += '\n<b>下载地址:</b>\n<b>Windows10/11</b>\n' content += '\n<b>下载地址:</b>\n<b>Windows10/11</b>\n'
content += `安装版:<a href="${downloadUrl}/mihomo-party-windows-${version}-x64-setup.exe">64位</a> | <a href="${downloadUrl}/mihomo-party-windows-${version}-ia32-setup.exe">32位</a> | <a href="${downloadUrl}/mihomo-party-windows-${version}-arm64-setup.exe">ARM64</a>\n` content += `安装版:<a href="${downloadUrl}/mihomo-party-windows-${version}-x64-setup.exe">64位</a> | <a href="${downloadUrl}/mihomo-party-windows-${version}-ia32-setup.exe">32位</a> | <a href="${downloadUrl}/mihomo-party-windows-${version}-arm64-setup.exe">ARM64</a>\n`
content += `便携版:<a href="${downloadUrl}/mihomo-party-windows-${version}-x64-portable.7z">64位</a> | <a href="${downloadUrl}/mihomo-party-windows-${version}-ia32-portable.7z">32位</a> | <a href="${downloadUrl}/mihomo-party-windows-${version}-arm64-portable.7z">ARM64</a>\n` content += `便携版:<a href="${downloadUrl}/mihomo-party-windows-${version}-x64-portable.7z">64位</a> | <a href="${downloadUrl}/mihomo-party-windows-${version}-ia32-portable.7z">32位</a> | <a href="${downloadUrl}/mihomo-party-windows-${version}-arm64-portable.7z">ARM64</a>\n`
@ -44,3 +90,5 @@ await axios.post(`https://api.telegram.org/bot${process.env.TELEGRAM_BOT_TOKEN}/
}, },
parse_mode: 'HTML' parse_mode: 'HTML'
}) })
console.log(`${isDevRelease ? '开发版本' : '正式版本'}Telegram 通知发送成功`)

View File

@ -199,6 +199,21 @@ function getSystemLanguage(): 'zh-CN' | 'en-US' {
return locale.startsWith('zh') ? 'zh-CN' : 'en-US' return locale.startsWith('zh') ? 'zh-CN' : 'en-US'
} }
// 硬件加速设置
async function initHardwareAcceleration(): Promise<void> {
try {
await initBasic()
const { disableHardwareAcceleration = false } = await getAppConfig()
if (disableHardwareAcceleration) {
app.disableHardwareAcceleration()
}
} catch (e) {
console.warn('Failed to read hardware acceleration config:', e)
}
}
initHardwareAcceleration()
// This method will be called when Electron has finished // This method will be called when Electron has finished
// initialization and is ready to create browser windows. // initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs. // Some APIs can only be used after this event occurs.

View File

@ -22,6 +22,7 @@ export const defaultConfig: IAppConfig = {
controlDns: true, controlDns: true,
controlSniff: true, controlSniff: true,
floatingWindowCompatMode: true, floatingWindowCompatMode: true,
disableHardwareAcceleration: false,
disableLoopbackDetector: false, disableLoopbackDetector: false,
disableEmbedCA: false, disableEmbedCA: false,
disableSystemCA: false, disableSystemCA: false,

View File

@ -30,6 +30,7 @@ import { IoIosHelpCircle, IoMdCloudDownload } from 'react-icons/io'
import { MdEditDocument } from 'react-icons/md' import { MdEditDocument } from 'react-icons/md'
import CSSEditorModal from './css-editor-modal' import CSSEditorModal from './css-editor-modal'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import BaseConfirmModal from '../base/base-confirm-modal'
const GeneralConfig: React.FC = () => { const GeneralConfig: React.FC = () => {
const { t, i18n } = useTranslation() const { t, i18n } = useTranslation()
@ -39,6 +40,8 @@ const GeneralConfig: React.FC = () => {
const [openCSSEditor, setOpenCSSEditor] = useState(false) const [openCSSEditor, setOpenCSSEditor] = useState(false)
const [fetching, setFetching] = useState(false) const [fetching, setFetching] = useState(false)
const [isRelaunching, setIsRelaunching] = useState(false) const [isRelaunching, setIsRelaunching] = useState(false)
const [showHardwareAccelConfirm, setShowHardwareAccelConfirm] = useState(false)
const [pendingHardwareAccelValue, setPendingHardwareAccelValue] = useState(false)
const { setTheme } = useTheme() const { setTheme } = useTheme()
const { const {
silentStart = false, silentStart = false,
@ -49,6 +52,7 @@ const GeneralConfig: React.FC = () => {
showFloatingWindow: showFloating = false, showFloatingWindow: showFloating = false,
spinFloatingIcon = true, spinFloatingIcon = true,
floatingWindowCompatMode = true, floatingWindowCompatMode = true,
disableHardwareAcceleration = false,
useWindowFrame = false, useWindowFrame = false,
autoQuitWithoutCore = false, autoQuitWithoutCore = false,
autoQuitWithoutCoreDelay = 60, autoQuitWithoutCoreDelay = 60,
@ -78,6 +82,28 @@ const GeneralConfig: React.FC = () => {
}} }}
/> />
)} )}
{showHardwareAccelConfirm && (
<BaseConfirmModal
isOpen={showHardwareAccelConfirm}
title={t('settings.hardwareAcceleration.confirm.title')}
content={t('settings.hardwareAcceleration.confirm.content')}
onCancel={() => {
setShowHardwareAccelConfirm(false)
setPendingHardwareAccelValue(false)
}}
onConfirm={async () => {
setShowHardwareAccelConfirm(false)
setIsRelaunching(true)
try {
await patchAppConfig({ disableHardwareAcceleration: pendingHardwareAccelValue })
await relaunchApp()
} catch (e) {
alert(e)
setIsRelaunching(false)
}
}}
/>
)}
<SettingCard> <SettingCard>
<SettingItem title={t('settings.language')} divider> <SettingItem title={t('settings.language')} divider>
<Select <Select
@ -348,6 +374,28 @@ const GeneralConfig: React.FC = () => {
}, 1000)} }, 1000)}
/> />
</SettingItem> </SettingItem>
<SettingItem
title={t('settings.disableHardwareAcceleration')}
actions={
<Tooltip content={t('settings.disableHardwareAccelerationTooltip')}>
<Button isIconOnly size="sm" variant="light">
<IoIosHelpCircle className="text-lg" />
</Button>
</Tooltip>
}
divider
>
<Switch
size="sm"
isSelected={disableHardwareAcceleration}
isDisabled={isRelaunching}
onValueChange={(v) => {
if (isRelaunching) return
setPendingHardwareAccelValue(v)
setShowHardwareAccelConfirm(true)
}}
/>
</SettingItem>
<SettingItem title={t('settings.backgroundColor')} divider> <SettingItem title={t('settings.backgroundColor')} divider>
<Tabs <Tabs
size="sm" size="sm"

View File

@ -65,6 +65,10 @@
"settings.showTraffic_mac": "Show Network Speed in Status Bar", "settings.showTraffic_mac": "Show Network Speed in Status Bar",
"settings.showDockIcon": "Show Dock Icon", "settings.showDockIcon": "Show Dock Icon",
"settings.useWindowFrame": "Use System Title Bar", "settings.useWindowFrame": "Use System Title Bar",
"settings.disableHardwareAcceleration": "Disable Hardware Acceleration",
"settings.disableHardwareAccelerationTooltip": "Disabling hardware acceleration can resolve rendering issues or crashes caused by graphics driver problems, but may reduce performance. Requires app restart to take effect",
"settings.hardwareAcceleration.confirm.title": "Confirm App Restart",
"settings.hardwareAcceleration.confirm.content": "Changing hardware acceleration settings requires an app restart to take effect. Restart now?",
"settings.backgroundColor": "Background Color", "settings.backgroundColor": "Background Color",
"settings.backgroundAuto": "Auto", "settings.backgroundAuto": "Auto",
"settings.backgroundDark": "Dark", "settings.backgroundDark": "Dark",

View File

@ -62,6 +62,10 @@
"settings.showTraffic_mac": "نمایش سرعت شبکه در نوار وضعیت", "settings.showTraffic_mac": "نمایش سرعت شبکه در نوار وضعیت",
"settings.showDockIcon": "نمایش آیکون Dock", "settings.showDockIcon": "نمایش آیکون Dock",
"settings.useWindowFrame": "استفاده از نوار عنوان سیستم", "settings.useWindowFrame": "استفاده از نوار عنوان سیستم",
"settings.disableHardwareAcceleration": "غیرفعال کردن شتاب سخت‌افزاری",
"settings.disableHardwareAccelerationTooltip": "غیرفعال کردن شتاب سخت‌افزاری می‌تواند مشکلات رندرینگ یا کرش ناشی از مشکلات درایور گرافیک را حل کند، اما ممکن است عملکرد را کاهش دهد. نیاز به راه‌اندازی مجدد برنامه دارد",
"settings.hardwareAcceleration.confirm.title": "تایید راه‌اندازی مجدد برنامه",
"settings.hardwareAcceleration.confirm.content": "تغییر تنظیمات شتاب سخت‌افزاری نیاز به راه‌اندازی مجدد برنامه دارد. اکنون راه‌اندازی مجدد شود؟",
"settings.backgroundColor": "رنگ پس‌زمینه", "settings.backgroundColor": "رنگ پس‌زمینه",
"settings.backgroundAuto": "خودکار", "settings.backgroundAuto": "خودکار",
"settings.backgroundDark": "تیره", "settings.backgroundDark": "تیره",

View File

@ -62,6 +62,10 @@
"settings.showTraffic_mac": "Показывать скорость в строке состояния", "settings.showTraffic_mac": "Показывать скорость в строке состояния",
"settings.showDockIcon": "Показывать значок в доке", "settings.showDockIcon": "Показывать значок в доке",
"settings.useWindowFrame": "Использовать системную рамку окна", "settings.useWindowFrame": "Использовать системную рамку окна",
"settings.disableHardwareAcceleration": "Отключить аппаратное ускорение",
"settings.disableHardwareAccelerationTooltip": "Отключение аппаратного ускорения может решить проблемы с рендерингом или сбоями, вызванными проблемами драйверов графики, но может снизить производительность. Требует перезапуска приложения",
"settings.hardwareAcceleration.confirm.title": "Подтверждение перезапуска приложения",
"settings.hardwareAcceleration.confirm.content": "Изменение настроек аппаратного ускорения требует перезапуска приложения. Перезапустить сейчас?",
"settings.backgroundColor": "Цвет фона", "settings.backgroundColor": "Цвет фона",
"settings.backgroundAuto": "Авто", "settings.backgroundAuto": "Авто",
"settings.backgroundDark": "Тёмный", "settings.backgroundDark": "Тёмный",

View File

@ -65,6 +65,10 @@
"settings.showTraffic_mac": "在状态栏显示网速", "settings.showTraffic_mac": "在状态栏显示网速",
"settings.showDockIcon": "显示 Dock 图标", "settings.showDockIcon": "显示 Dock 图标",
"settings.useWindowFrame": "使用系统标题栏", "settings.useWindowFrame": "使用系统标题栏",
"settings.disableHardwareAcceleration": "禁用硬件加速",
"settings.disableHardwareAccelerationTooltip": "禁用硬件加速可以解决某些显卡驱动问题导致的渲染异常或崩溃,但可能会降低性能。修改后需要重启应用生效",
"settings.hardwareAcceleration.confirm.title": "确认重启应用",
"settings.hardwareAcceleration.confirm.content": "修改硬件加速设置需要重启应用才能生效。是否立即重启?",
"settings.backgroundColor": "背景颜色", "settings.backgroundColor": "背景颜色",
"settings.backgroundAuto": "自动", "settings.backgroundAuto": "自动",
"settings.backgroundDark": "深色", "settings.backgroundDark": "深色",

View File

@ -237,6 +237,7 @@ interface IAppConfig {
disableTray?: boolean disableTray?: boolean
showFloatingWindow?: boolean showFloatingWindow?: boolean
floatingWindowCompatMode?: boolean floatingWindowCompatMode?: boolean
disableHardwareAcceleration?: boolean
connectionCardStatus?: CardStatus connectionCardStatus?: CardStatus
dnsCardStatus?: CardStatus dnsCardStatus?: CardStatus
logCardStatus?: CardStatus logCardStatus?: CardStatus