mirror of
https://github.com/clash-verge-rev/clash-verge-rev.git
synced 2026-10-31 03:02:08 +08:00
* refactor(ipc): generate bindings with Specta * fix(profile): project IPC inputs to consumed fields * fix(events): remove unused refresh payloads * fix(webdav): return only consumed backup metadata * fix(network): trim unused interface metadata * fix(sysinfo): return only displayed system fields * chore(knip): check generated runtime exports * fix(proxy): confirm runtime chain updates before UI changes * fix(clipboard): propagate proxy environment copy failures * refactor(dns): remove ignored runtime patch * refactor(core): trim unused upgrade response fields * refactor(ipc): avoid redundant response copies * refactor(proxy): clarify automatic proxy query naming * chore(tests): remove added IPC regression tests * refactor(ipc): enforce typed command boundaries * chore(contract): check generated bindings before push * refactor(ipc): remove unused proxy liveness payloads
102 lines
2.8 KiB
TypeScript
102 lines
2.8 KiB
TypeScript
import {
|
|
getProfiles,
|
|
patchProfile,
|
|
syncTrayProxySelection,
|
|
} from '@/services/cmds'
|
|
import { mutate } from '@/services/mutate'
|
|
|
|
function readLegacyTestUrls(uid: string): Record<string, string> {
|
|
try {
|
|
const states = JSON.parse(localStorage.getItem('proxy-head-state') || '{}')[
|
|
uid
|
|
]
|
|
return Object.fromEntries(
|
|
Object.entries(states || {}).flatMap(([name, state]) => {
|
|
const url = (state as { testUrl?: string }).testUrl
|
|
return typeof url === 'string' && url.trim() ? [[name, url.trim()]] : []
|
|
}),
|
|
)
|
|
} catch {
|
|
return {}
|
|
}
|
|
}
|
|
|
|
export async function saveProfileTestUrls(
|
|
uid: string,
|
|
urls: Record<string, string>,
|
|
migrateOnly = false,
|
|
) {
|
|
return mutate(
|
|
async () => {
|
|
const profiles = await getProfiles()
|
|
const profile = profiles.items?.find((item) => item.uid === uid)
|
|
if (!profile || (migrateOnly && profile.latency_test_urls !== undefined))
|
|
return
|
|
await patchProfile(uid, {
|
|
latency_test_urls: {
|
|
...(profile.latency_test_urls ?? readLegacyTestUrls(uid)),
|
|
...urls,
|
|
},
|
|
})
|
|
await syncTrayProxySelection().catch((error) => {
|
|
console.error(
|
|
'Failed to refresh tray after saving latency test URL:',
|
|
error,
|
|
)
|
|
})
|
|
},
|
|
{ id: `patch-profile:${uid}`, revalidate: [['getProfiles']] },
|
|
)
|
|
}
|
|
|
|
const migrating = new Set<string>()
|
|
|
|
export function migrateProfileTestUrls(profiles: IProfilesConfig) {
|
|
for (const profile of profiles.items || []) {
|
|
const uid = profile.uid
|
|
if (!uid) continue
|
|
if (profile.latency_test_urls !== undefined || migrating.has(uid)) continue
|
|
const urls = readLegacyTestUrls(uid)
|
|
if (!Object.keys(urls).length) continue
|
|
migrating.add(uid)
|
|
void saveProfileTestUrls(uid, urls, true)
|
|
.catch((error) => {
|
|
console.error('Failed to migrate latency test URLs:', error)
|
|
})
|
|
.finally(() => migrating.delete(uid))
|
|
}
|
|
}
|
|
|
|
const pending = new Map<string, Record<string, { url: string }>>()
|
|
|
|
export async function commitProfileTestUrl(
|
|
uid: string,
|
|
group: string,
|
|
url: string,
|
|
) {
|
|
const edit = { url: url.trim() }
|
|
const urls = { ...pending.get(uid), [group]: edit }
|
|
pending.set(uid, urls)
|
|
try {
|
|
await saveProfileTestUrls(uid, { [group]: edit.url })
|
|
const current = pending.get(uid)
|
|
if (current?.[group] === edit) {
|
|
delete current[group]
|
|
if (!Object.keys(current).length) pending.delete(uid)
|
|
}
|
|
} catch (error) {
|
|
console.error('Failed to save latency test URL:', error)
|
|
}
|
|
}
|
|
|
|
export function profileTestUrls(profile: IProfileItem): Record<string, string> {
|
|
return {
|
|
...profile.latency_test_urls,
|
|
...Object.fromEntries(
|
|
Object.entries(
|
|
(profile.uid ? pending.get(profile.uid) : undefined) ?? {},
|
|
).map(([group, edit]) => [group, edit.url]),
|
|
),
|
|
}
|
|
}
|