Compare commits

...

4 Commits

Author SHA1 Message Date
Memory2314
f959801db2 Bump to 1.9.4 2026-03-29 23:41:53 +08:00
Memory2314
d2e651e79d update changelog.md 2026-03-29 23:41:53 +08:00
Memory2314
8530cdefcc pnpm update 2026-03-29 23:41:53 +08:00
StarHeart
2a4b9f4e5b
feat: support user agent config per sub (#1712)
* feat: add user agent support in profile configuration

* Introduced a new user agent field in profile settings, allowing users to specify a custom user agent.
* Updated relevant components and localization files to support the new user agent feature.
* Added a new pnpm workspace configuration for built dependencies.

* feat: enhance profile settings with user agent input and toggle functionality

* Added a user agent input field to the advanced profile settings.
* Implemented toggle icons for showing/hiding advanced settings.
* Updated layout to accommodate the new user agent input alongside the existing auth token field.

* chore: remove pnpm workspace configuration for built dependencies
2026-03-29 18:54:56 +08:00
13 changed files with 408 additions and 416 deletions

View File

@ -1,64 +1,16 @@
# 1.9.3
# 1.9.4
## 新功能 (Feat)
- 新增网络信息页卡片
- 更新下载新增进度显示和 SHA256 完整性校验
- 新增每个订阅独立的 User-Agent 配置
- 使用 mshta 在 Electron 初始化前同步检测 PowerShell 版本
## 修复 (Fix)
- 修复更新软件时的超时问题
- 修复切换离开智能内核时未清理智能覆盖配置的问题
- 修复部分机场返回压缩包导致订阅导入失败的问题
- 修复悬浮窗无法关闭的问题
- 修复日志滚动延迟的问题
- 修复添加新订阅时只能重启生效的问题
- 修复进入代理列表页面时滚动位置未重置到顶部的问题
- 修复托盘流量图标闪烁问题
- 修复 Win7 兼容性问题
- 修复日志清理正则表达式以正确匹配带前缀的文件名
## 其他 (Chore)
- 重构 rule-item 额外字段处理逻辑并补充类型定义
- 更新依赖
# 1.9.2
## 新功能 (Feat)
- 增加 Fish 和 Nushell 环境变量支持
- 增加规则统计和禁用开关
- 连接页面显示应用图标
- 增加订阅超时设置
- 增加 Windows 7 兼容构建支持
## 修复 (Fix)
- 修复 group.all 过滤器中代理未定义导致的错误
- 修复默认延迟测试 URL 改为 HTTPS
- 修复连接图表 z-index 和缩放问题
- 修复减少动画模式下侧边栏卡片拖拽动画异常
- 修复 IME 输入法输入时字符重复问题
- 修复配置切换失败后切换队列损坏问题
- 修复取消最大化状态未保存的问题
- 优化备份配置导入处理
- 修复禁用自动滚动时日志显示未冻结的问题
- 修复订阅页面相对时间未自动刷新的问题
- 修复连接数badge遮挡下方关闭按钮点击的问题
## 优化 (Optimize)
- 虚拟化规则编辑弹窗中的规则列表,提升渲染性能
- 优化内核启动性能
- 重构外部控制器和规则编辑器
- 优化订阅更新逻辑效率
## 其他 (Chore)
- 更新依赖
# 1.9.1
## 修复 (Fix)
- 修复 Windows 下以管理员重启开启 TUN 时因单实例锁冲突导致的闪退问题
- 修复托盘菜单开启 TUN 时管理员重启后继续执行导致的竞态问题
- 修复关键资源文件复制失败时静默跳过导致内核启动异常的问题

View File

@ -1,6 +1,6 @@
{
"name": "mihomo-party",
"version": "1.9.3",
"version": "1.9.4",
"description": "Clash Party",
"type": "module",
"main": "./out/main/index.js",
@ -36,7 +36,7 @@
"@electron-toolkit/utils": "^4.0.0",
"@types/plist": "^3.0.5",
"adm-zip": "^0.5.16",
"axios": "^1.13.6",
"axios": "^1.14.0",
"chokidar": "^5.0.0",
"croner": "^9.1.0",
"crypto-js": "^4.2.0",
@ -44,7 +44,7 @@
"file-icon": "^6.0.0",
"file-icon-info": "^1.1.1",
"flag-icons": "^7.5.0",
"i18next": "^25.10.3",
"i18next": "^25.10.10",
"iconv-lite": "^0.7.2",
"js-yaml": "^4.1.1",
"plist": "^3.1.0",
@ -72,8 +72,8 @@
"@types/react-dom": "^19.2.3",
"@types/validator": "^13.15.10",
"@types/ws": "^8.18.1",
"@typescript-eslint/eslint-plugin": "^8.57.1",
"@typescript-eslint/parser": "^8.57.1",
"@typescript-eslint/eslint-plugin": "^8.57.2",
"@typescript-eslint/parser": "^8.57.2",
"@vitejs/plugin-react": "^5.2.0",
"chart.js": "^4.5.1",
"cron-validator": "^1.4.0",
@ -101,20 +101,20 @@
"react-chartjs-2": "^5.3.1",
"react-dom": "^19.2.4",
"react-error-boundary": "^6.1.1",
"react-i18next": "^16.6.0",
"react-i18next": "^16.6.6",
"react-icons": "^5.6.0",
"react-markdown": "^10.1.0",
"react-monaco-editor": "^0.59.0",
"react-router-dom": "^7.13.1",
"react-router-dom": "^7.13.2",
"react-virtuoso": "^4.18.3",
"swr": "^2.4.1",
"tailwindcss": "^4.2.2",
"tar": "^7.5.12",
"tar": "^7.5.13",
"tsx": "^4.21.0",
"types-pac": "^1.0.3",
"typescript": "^5.9.3",
"vite": "^7.3.1",
"vite-plugin-monaco-editor": "^1.1.0"
},
"packageManager": "pnpm@10.27.0"
"packageManager": "pnpm@10.33.0"
}

679
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@ -248,6 +248,7 @@ export async function createProfile(item: Partial<IProfileItem>): Promise<IProfi
allowFixedInterval: item.allowFixedInterval || false,
autoUpdate: item.autoUpdate ?? false,
authToken: item.authToken,
userAgent: item.userAgent,
updated: new Date().getTime(),
updateTimeout: item.updateTimeout || 5
}
@ -268,7 +269,7 @@ export async function createProfile(item: Partial<IProfileItem>): Promise<IProfi
const baseOptions: Omit<FetchOptions, 'useProxy' | 'timeout'> = {
url: item.url,
mixedPort,
userAgent: userAgent || `mihomo.party/v${app.getVersion()} (clash.meta)`,
userAgent: item.userAgent || userAgent || `mihomo.party/v${app.getVersion()} (clash.meta)`,
authToken: item.authToken,
substore: newItem.substore || false
}

View File

@ -108,6 +108,17 @@ const EditInfoModal: React.FC<Props> = (props) => {
placeholder={t('profiles.editInfo.authTokenPlaceholder')}
/>
</SettingItem>
<SettingItem title={t('profiles.editInfo.userAgent')}>
<Input
size="sm"
className={cn(inputWidth)}
value={values.userAgent || ''}
onValueChange={(v) => {
setValues({ ...values, userAgent: v || undefined })
}}
placeholder={t('profiles.editInfo.userAgentPlaceholder')}
/>
</SettingItem>
<SettingItem title={t('profiles.editInfo.useProxy')}>
<Switch
size="sm"

View File

@ -496,6 +496,8 @@
"profiles.editInfo.url": "Subscription URL",
"profiles.editInfo.authToken": "Authorization Token",
"profiles.editInfo.authTokenPlaceholder": "Bearer token or other auth header value",
"profiles.editInfo.userAgent": "User Agent",
"profiles.editInfo.userAgentPlaceholder": "Leave empty to use global User Agent",
"profiles.editInfo.useProxy": "Use Proxy to Update",
"profiles.editInfo.interval": "Upd. Interval",
"profiles.editInfo.intervalPlaceholder": "e.g.: 30 or '0 * * * *'",

View File

@ -471,6 +471,8 @@
"profiles.editInfo.title": "ویرایش اطلاعات",
"profiles.editInfo.name": "نام",
"profiles.editInfo.url": "آدرس اشتراک",
"profiles.editInfo.userAgent": "User Agent",
"profiles.editInfo.userAgentPlaceholder": "برای استفاده از User Agent جهانی خالی بگذارید",
"profiles.editInfo.useProxy": "استفاده از پراکسی برای به‌روزرسانی",
"profiles.editInfo.interval": "فاصله به‌روزرسانی",
"profiles.editInfo.fixedInterval": "فاصله به‌روزرسانی ثابت",

View File

@ -473,6 +473,8 @@
"profiles.editInfo.title": "Редактировать информацию",
"profiles.editInfo.name": "Имя",
"profiles.editInfo.url": "URL подписки",
"profiles.editInfo.userAgent": "User Agent",
"profiles.editInfo.userAgentPlaceholder": "Оставьте пустым для глобального User Agent",
"profiles.editInfo.useProxy": "Использовать прокси для обновления",
"profiles.editInfo.interval": "Интервал обн.",
"profiles.editInfo.fixedInterval": "Фиксированный интервал обновления",

View File

@ -501,6 +501,8 @@
"profiles.editInfo.url": "订阅地址",
"profiles.editInfo.authToken": "授权令牌",
"profiles.editInfo.authTokenPlaceholder": "Bearer token 或其他认证头值",
"profiles.editInfo.userAgent": "User Agent",
"profiles.editInfo.userAgentPlaceholder": "留空则使用全局 User Agent",
"profiles.editInfo.useProxy": "使用代理更新",
"profiles.editInfo.interval": "更新间隔",
"profiles.editInfo.intervalPlaceholder": "例如30 或 '0 * * * *'",

View File

@ -501,6 +501,8 @@
"profiles.editInfo.url": "訂閱地址",
"profiles.editInfo.authToken": "授權令牌",
"profiles.editInfo.authTokenPlaceholder": "Bearer token 或其他認證頭值",
"profiles.editInfo.userAgent": "User Agent",
"profiles.editInfo.userAgentPlaceholder": "留空則使用全局 User Agent",
"profiles.editInfo.useProxy": "使用代理更新",
"profiles.editInfo.interval": "更新間隔",
"profiles.editInfo.intervalPlaceholder": "例如30 或 '0 * * * *'",

View File

@ -18,7 +18,7 @@ import { useAppConfig } from '@renderer/hooks/use-app-config'
import { getFilePath, readTextFile, subStoreCollections, subStoreSubs } from '@renderer/utils/ipc'
import type { KeyboardEvent } from 'react'
import { ReactNode, useCallback, useEffect, useMemo, useRef, useState } from 'react'
import { MdContentPaste } from 'react-icons/md'
import { MdContentPaste, MdUnfoldMore, MdUnfoldLess } from 'react-icons/md'
import {
DndContext,
closestCenter,
@ -53,6 +53,7 @@ const Profiles: React.FC = () => {
const [sortedItems, setSortedItems] = useState(items)
const [useProxy, setUseProxy] = useState(false)
const [authToken, setAuthToken] = useState('')
const [userAgent, setUserAgent] = useState('')
const [showAdvanced, setShowAdvanced] = useState(false)
const [subStoreImporting, setSubStoreImporting] = useState(false)
const [importing, setImporting] = useState(false)
@ -135,10 +136,12 @@ const Profiles: React.FC = () => {
type: 'remote',
url,
useProxy,
authToken: authToken || undefined
authToken: authToken || undefined,
userAgent: userAgent || undefined
})
setUrl('')
setAuthToken('')
setUserAgent('')
setImporting(false)
}
const pageRef = useRef<HTMLDivElement>(null)
@ -300,7 +303,11 @@ const Profiles: React.FC = () => {
isIconOnly
onPress={() => setShowAdvanced(!showAdvanced)}
>
🔑
{showAdvanced ? (
<MdUnfoldLess className="text-lg" />
) : (
<MdUnfoldMore className="text-lg" />
)}
</Button>
</Tooltip>
<Button
@ -426,16 +433,25 @@ const Profiles: React.FC = () => {
</Dropdown>
</div>
{showAdvanced && (
<Input
size="sm"
type="password"
placeholder={t('profiles.editInfo.authTokenPlaceholder')}
value={authToken}
onValueChange={setAuthToken}
onKeyUp={handleInputKeyUp}
className="w-full"
startContent={<span className="text-default-400 text-sm">🔑</span>}
/>
<div className="flex gap-2">
<Input
size="sm"
type="password"
placeholder={t('profiles.editInfo.authTokenPlaceholder')}
value={authToken}
onValueChange={setAuthToken}
onKeyUp={handleInputKeyUp}
className="flex-1"
/>
<Input
size="sm"
placeholder={t('profiles.editInfo.userAgentPlaceholder')}
value={userAgent}
onValueChange={setUserAgent}
onKeyUp={handleInputKeyUp}
className="flex-1"
/>
</div>
)}
</div>
<Divider />

View File

@ -519,6 +519,7 @@ interface IProfileItem {
allowFixedInterval?: boolean
autoUpdate?: boolean
authToken?: string
userAgent?: string
updateTimeout?: number
}