mirror of
https://github.com/clash-verge-rev/clash-verge-rev.git
synced 2026-10-15 13:50:47 +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
74 lines
1.9 KiB
TypeScript
74 lines
1.9 KiB
TypeScript
export type ProxyEmptyStateReason =
|
|
| 'no-subscriptions'
|
|
| 'inactive-subscription'
|
|
| 'core-unavailable'
|
|
| 'no-proxy-info'
|
|
|
|
type ProfileSummary = {
|
|
current?: string | null
|
|
items?: Array<{
|
|
uid?: string | null
|
|
type?: string | null
|
|
}> | null
|
|
}
|
|
|
|
interface ProxyListStateInput {
|
|
mode: string
|
|
profiles?: ProfileSummary
|
|
isProfilesPending: boolean
|
|
isProxyViewPending: boolean
|
|
isRunningModePending: boolean
|
|
}
|
|
|
|
const isSubscriptionProfile = (item: { type?: string | null }): boolean =>
|
|
item.type === 'remote' || item.type === 'local'
|
|
|
|
/** Decides only pre-render states; the built list owns whether it has renderable content. */
|
|
export type ProxyListState =
|
|
| { kind: 'direct' }
|
|
| { kind: 'loading' }
|
|
| { kind: 'empty'; reason: ProxyEmptyStateReason }
|
|
| { kind: 'render' }
|
|
|
|
export const resolveProxyListState = ({
|
|
mode,
|
|
profiles,
|
|
isProfilesPending,
|
|
isProxyViewPending,
|
|
isRunningModePending,
|
|
}: ProxyListStateInput): ProxyListState => {
|
|
if (mode === 'direct') return { kind: 'direct' }
|
|
|
|
if (isProfilesPending || isProxyViewPending || isRunningModePending) {
|
|
return { kind: 'loading' }
|
|
}
|
|
|
|
if (profiles) {
|
|
const subscriptions = (profiles.items ?? []).filter(isSubscriptionProfile)
|
|
if (subscriptions.length === 0) {
|
|
return { kind: 'empty', reason: 'no-subscriptions' }
|
|
}
|
|
|
|
const hasActiveSubscription = subscriptions.some(
|
|
(item) => item.uid === profiles.current,
|
|
)
|
|
if (!hasActiveSubscription) {
|
|
return { kind: 'empty', reason: 'inactive-subscription' }
|
|
}
|
|
}
|
|
|
|
return { kind: 'render' }
|
|
}
|
|
|
|
/** Explains an empty list only after the renderer observes it. */
|
|
export const resolveEmptyListReason = ({
|
|
runningMode,
|
|
isProxyViewError,
|
|
}: {
|
|
runningMode?: string
|
|
isProxyViewError: boolean
|
|
}): ProxyEmptyStateReason =>
|
|
runningMode === 'NotRunning' || isProxyViewError
|
|
? 'core-unavailable'
|
|
: 'no-proxy-info'
|