mirror of
https://github.com/clash-verge-rev/clash-verge-rev.git
synced 2026-10-14 21:20:48 +08:00
chore(deps): bump tauri-plugin-mihomo to 0.6.0 and move home card to count stream
Locks both sides to upstream main 17c7757: the WS channel now uses a single Json transport (connections wire shrinks ~3.4x) and count-stream error frames are forwarded unchanged; JS/Rust API surfaces stay identical, so upper-layer code is untouched except the card below. The home Active Connections card now subscribes to the count-only ws_connections_count stream instead of parsing the full connections snapshot every second; the full stream runs only while the Connections page is mounted.
This commit is contained in:
Generated
+21
-21
@@ -1387,7 +1387,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "117725a109d387c937a1533ce01b450cbde6b88abceea8473c4d7a85853cda3c"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"windows-sys 0.59.0",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2073,7 +2073,7 @@ dependencies = [
|
||||
"libc",
|
||||
"option-ext",
|
||||
"redox_users 0.5.2",
|
||||
"windows-sys 0.61.2",
|
||||
"windows-sys 0.60.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2347,7 +2347,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys 0.61.2",
|
||||
"windows-sys 0.60.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2865,7 +2865,7 @@ dependencies = [
|
||||
"gobject-sys 0.21.5",
|
||||
"libc",
|
||||
"system-deps 7.0.8",
|
||||
"windows-sys 0.61.2",
|
||||
"windows-sys 0.60.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3488,7 +3488,7 @@ dependencies = [
|
||||
"libc",
|
||||
"percent-encoding",
|
||||
"pin-project-lite",
|
||||
"socket2 0.6.5",
|
||||
"socket2 0.5.10",
|
||||
"system-configuration",
|
||||
"tokio",
|
||||
"tower-service",
|
||||
@@ -4316,7 +4316,7 @@ dependencies = [
|
||||
"png 0.18.1",
|
||||
"serde",
|
||||
"thiserror 2.0.20",
|
||||
"windows-sys 0.61.2",
|
||||
"windows-sys 0.60.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4485,7 +4485,7 @@ version = "0.50.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5"
|
||||
dependencies = [
|
||||
"windows-sys 0.61.2",
|
||||
"windows-sys 0.60.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4928,7 +4928,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7d8fae84b431384b68627d0f9b3b1245fcf9f46f6c0e3dc902e9dce64edd1967"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys 0.61.2",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -5602,7 +5602,7 @@ dependencies = [
|
||||
"quinn-udp",
|
||||
"rustc-hash",
|
||||
"rustls",
|
||||
"socket2 0.6.5",
|
||||
"socket2 0.5.10",
|
||||
"thiserror 2.0.20",
|
||||
"tokio",
|
||||
"tracing",
|
||||
@@ -5641,9 +5641,9 @@ dependencies = [
|
||||
"cfg_aliases",
|
||||
"libc",
|
||||
"once_cell",
|
||||
"socket2 0.6.5",
|
||||
"socket2 0.5.10",
|
||||
"tracing",
|
||||
"windows-sys 0.61.2",
|
||||
"windows-sys 0.60.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -6198,7 +6198,7 @@ dependencies = [
|
||||
"errno",
|
||||
"libc",
|
||||
"linux-raw-sys 0.12.1",
|
||||
"windows-sys 0.61.2",
|
||||
"windows-sys 0.60.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -6257,7 +6257,7 @@ dependencies = [
|
||||
"security-framework",
|
||||
"security-framework-sys",
|
||||
"webpki-root-certs",
|
||||
"windows-sys 0.61.2",
|
||||
"windows-sys 0.60.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -6899,7 +6899,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c3d1e2c7f27f8d4cb10542a02c49005dbd6e93095799d6f3be745fae9f8fedd4"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys 0.61.2",
|
||||
"windows-sys 0.60.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -7565,8 +7565,8 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tauri-plugin-mihomo"
|
||||
version = "0.5.6"
|
||||
source = "git+https://github.com/clash-verge-rev/tauri-plugin-mihomo?branch=main#8bf567b9e2230cdd02f9b8c9774fb8eb0d71af1e"
|
||||
version = "0.6.0"
|
||||
source = "git+https://github.com/clash-verge-rev/tauri-plugin-mihomo?branch=main#17c7757389ca73d29882753ecf7a160de29aabbe"
|
||||
dependencies = [
|
||||
"arc-swap",
|
||||
"clashmap",
|
||||
@@ -7863,7 +7863,7 @@ dependencies = [
|
||||
"getrandom 0.4.3",
|
||||
"once_cell",
|
||||
"rustix 1.1.4",
|
||||
"windows-sys 0.61.2",
|
||||
"windows-sys 0.60.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -8582,7 +8582,7 @@ dependencies = [
|
||||
"png 0.18.1",
|
||||
"serde",
|
||||
"thiserror 2.0.20",
|
||||
"windows-sys 0.61.2",
|
||||
"windows-sys 0.60.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -8685,7 +8685,7 @@ checksum = "f2f6fb2847f6742cd76af783a2a2c49e9375d0a111c7bef6f71cd9e738c72d6e"
|
||||
dependencies = [
|
||||
"memoffset",
|
||||
"tempfile",
|
||||
"windows-sys 0.61.2",
|
||||
"windows-sys 0.60.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -9270,7 +9270,7 @@ version = "0.1.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22"
|
||||
dependencies = [
|
||||
"windows-sys 0.61.2",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -9874,7 +9874,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7d6f32a0ff4a9f6f01231eb2059cc85479330739333e0e58cadf03b6af2cca10"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"windows-sys 0.61.2",
|
||||
"windows-sys 0.60.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
||||
Generated
+5
-5
@@ -234,7 +234,7 @@ importers:
|
||||
version: 2.5.1(react@19.2.8)
|
||||
tauri-plugin-mihomo-api:
|
||||
specifier: github:clash-verge-rev/tauri-plugin-mihomo#main
|
||||
version: https://codeload.github.com/clash-verge-rev/tauri-plugin-mihomo/tar.gz/8bf567b9e2230cdd02f9b8c9774fb8eb0d71af1e
|
||||
version: https://codeload.github.com/clash-verge-rev/tauri-plugin-mihomo/tar.gz/17c7757389ca73d29882753ecf7a160de29aabbe
|
||||
types-pac:
|
||||
specifier: ^1.0.3
|
||||
version: 1.0.3
|
||||
@@ -4838,9 +4838,9 @@ packages:
|
||||
resolution: {integrity: sha512-MFO/QzvtAOmJbkhOaCTvbGcFN9L9b+JunIsDwaKljSOdcLMea3NJ1k9Usz/rjdfSXTq4dfzfeS7W4p4YOAAHeA==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
tauri-plugin-mihomo-api@https://codeload.github.com/clash-verge-rev/tauri-plugin-mihomo/tar.gz/8bf567b9e2230cdd02f9b8c9774fb8eb0d71af1e:
|
||||
resolution: {gitHosted: true, integrity: sha512-ZUNzoqUI/328gbYuFUw9oKe0BVi/reurZZ2ut1+B8ZgEtZ6dtNgKMea7Kp8UvKTnF543WvI/8RwetH1Fzkflzw==, tarball: https://codeload.github.com/clash-verge-rev/tauri-plugin-mihomo/tar.gz/8bf567b9e2230cdd02f9b8c9774fb8eb0d71af1e}
|
||||
version: 0.5.6
|
||||
tauri-plugin-mihomo-api@https://codeload.github.com/clash-verge-rev/tauri-plugin-mihomo/tar.gz/17c7757389ca73d29882753ecf7a160de29aabbe:
|
||||
resolution: {gitHosted: true, integrity: sha512-DoJmecNZhwYzj8Gy0tpRoJDaWBLXIM6zwOBu2ITLKgFm+TUaMyqHmJ/tWzRfeqHX8izkgMi/TFNw9BO/JWkTyQ==, tarball: https://codeload.github.com/clash-verge-rev/tauri-plugin-mihomo/tar.gz/17c7757389ca73d29882753ecf7a160de29aabbe}
|
||||
version: 0.6.0
|
||||
|
||||
teex@1.0.1:
|
||||
resolution: {integrity: sha512-eYE6iEI62Ni1H8oIa7KlDU6uQBtqr4Eajni3wX7rpfXD8ysFx8z0+dri+KWEPWpBsxXfxu58x/0jvTVT1ekOSg==}
|
||||
@@ -10220,7 +10220,7 @@ snapshots:
|
||||
minizlib: 3.1.0
|
||||
yallist: 5.0.0
|
||||
|
||||
tauri-plugin-mihomo-api@https://codeload.github.com/clash-verge-rev/tauri-plugin-mihomo/tar.gz/8bf567b9e2230cdd02f9b8c9774fb8eb0d71af1e:
|
||||
tauri-plugin-mihomo-api@https://codeload.github.com/clash-verge-rev/tauri-plugin-mihomo/tar.gz/17c7757389ca73d29882753ecf7a160de29aabbe:
|
||||
dependencies:
|
||||
'@tauri-apps/api': 2.11.1
|
||||
|
||||
|
||||
@@ -24,6 +24,10 @@ interface ConnectionMonitorData {
|
||||
closedConnections: IConnectionsItem[]
|
||||
}
|
||||
|
||||
interface ConnectionSummaryPayload {
|
||||
count?: number
|
||||
}
|
||||
|
||||
interface ConnectionSummaryData {
|
||||
activeConnectionCount: number
|
||||
}
|
||||
@@ -34,9 +38,6 @@ const initConnSummaryData: ConnectionSummaryData = {
|
||||
|
||||
let connectionData: ConnectionMonitorData = initConnData
|
||||
let connectionSummary: ConnectionSummaryData = initConnSummaryData
|
||||
let connectionSocket: MihomoWebSocket | null = null
|
||||
let connectionConnecting = false
|
||||
let reconnectTimer: ReturnType<typeof setTimeout> | null = null
|
||||
let flushTimer: ReturnType<typeof setTimeout> | null = null
|
||||
let pendingMessageData: string | null = null
|
||||
let lastFlushAt = 0
|
||||
@@ -52,9 +53,6 @@ const notifySummaryListeners = () => {
|
||||
summaryListeners.forEach((listener) => listener())
|
||||
}
|
||||
|
||||
const hasConnectionSubscribers = () =>
|
||||
connectionListeners.size > 0 || summaryListeners.size > 0
|
||||
|
||||
const sameMetadata = (left: ConnectionMetadata, right: ConnectionMetadata) =>
|
||||
metadataValue(left.network) === metadataValue(right.network) &&
|
||||
metadataValue(left.type) === metadataValue(right.type) &&
|
||||
@@ -208,16 +206,16 @@ const mergeConnectionSnapshot = (
|
||||
}
|
||||
|
||||
const mergeConnectionSummary = (
|
||||
payload: IConnections,
|
||||
payload: ConnectionSummaryPayload,
|
||||
): ConnectionSummaryData => ({
|
||||
activeConnectionCount: payload.connections?.length ?? 0,
|
||||
activeConnectionCount: payload.count ?? 0,
|
||||
})
|
||||
|
||||
const flushPendingMessage = () => {
|
||||
flushTimer = null
|
||||
const messageData = pendingMessageData
|
||||
pendingMessageData = null
|
||||
if (!messageData || !hasConnectionSubscribers()) return
|
||||
if (!messageData || connectionListeners.size === 0) return
|
||||
|
||||
let payload: IConnections
|
||||
try {
|
||||
@@ -228,10 +226,6 @@ const flushPendingMessage = () => {
|
||||
}
|
||||
|
||||
lastFlushAt = Date.now()
|
||||
connectionSummary = mergeConnectionSummary(payload)
|
||||
notifySummaryListeners()
|
||||
|
||||
if (connectionListeners.size === 0) return
|
||||
|
||||
connectionData = mergeConnectionSnapshot(payload, connectionData)
|
||||
notifyConnectionListeners()
|
||||
@@ -253,115 +247,171 @@ const enqueueConnectionMessage = (messageData: string) => {
|
||||
)
|
||||
}
|
||||
|
||||
const clearReconnectTimer = () => {
|
||||
if (!reconnectTimer) return
|
||||
window.clearTimeout(reconnectTimer)
|
||||
reconnectTimer = null
|
||||
}
|
||||
|
||||
const closeConnectionSocket = async () => {
|
||||
const socket = connectionSocket
|
||||
connectionSocket = null
|
||||
if (!socket) return
|
||||
|
||||
try {
|
||||
await socket.close()
|
||||
} catch (err) {
|
||||
console.warn('Failed to close connection websocket', err)
|
||||
}
|
||||
}
|
||||
|
||||
const scheduleReconnect = () => {
|
||||
if (!hasConnectionSubscribers()) return
|
||||
if (reconnectTimer) return
|
||||
reconnectTimer = window.setTimeout(() => {
|
||||
reconnectTimer = null
|
||||
void connectConnectionSocket()
|
||||
}, CONNECTION_RECONNECT_DELAY_MS)
|
||||
}
|
||||
|
||||
async function reconnectConnectionSocket() {
|
||||
if (!hasConnectionSubscribers()) return
|
||||
await closeConnectionSocket()
|
||||
scheduleReconnect()
|
||||
}
|
||||
|
||||
async function connectConnectionSocket() {
|
||||
if (connectionSocket || connectionConnecting) return
|
||||
if (!hasConnectionSubscribers()) return
|
||||
|
||||
clearReconnectTimer()
|
||||
connectionConnecting = true
|
||||
|
||||
try {
|
||||
const socket = await MihomoWebSocket.connect_connections()
|
||||
if (!hasConnectionSubscribers()) {
|
||||
await socket.close()
|
||||
return
|
||||
}
|
||||
connectionSocket = socket
|
||||
socket.addListener((message) => {
|
||||
if (connectionSocket !== socket) return
|
||||
if (message.type !== 'Text') return
|
||||
if (message.data.startsWith('Websocket error')) {
|
||||
void reconnectConnectionSocket()
|
||||
return
|
||||
}
|
||||
|
||||
enqueueConnectionMessage(message.data)
|
||||
})
|
||||
} catch {
|
||||
scheduleReconnect()
|
||||
} finally {
|
||||
connectionConnecting = false
|
||||
}
|
||||
}
|
||||
|
||||
const startConnectionMonitor = () => {
|
||||
void connectConnectionSocket()
|
||||
}
|
||||
|
||||
const stopConnectionMonitorIfIdle = () => {
|
||||
if (hasConnectionSubscribers()) return
|
||||
|
||||
clearReconnectTimer()
|
||||
const clearPendingMessage = () => {
|
||||
pendingMessageData = null
|
||||
if (flushTimer) {
|
||||
window.clearTimeout(flushTimer)
|
||||
flushTimer = null
|
||||
}
|
||||
void closeConnectionSocket()
|
||||
}
|
||||
|
||||
interface SocketSupervisor {
|
||||
start: () => void
|
||||
stopIfIdle: () => void
|
||||
reconnect: () => Promise<void>
|
||||
}
|
||||
|
||||
const createSocketSupervisor = (options: {
|
||||
listeners: Set<ConnectionListener>
|
||||
connectSocket: () => Promise<MihomoWebSocket>
|
||||
onText: (data: string) => void
|
||||
closeLogLabel: string
|
||||
onIdle?: () => void
|
||||
}): SocketSupervisor => {
|
||||
const { listeners, connectSocket, onText, closeLogLabel, onIdle } = options
|
||||
const hasSubscribers = () => listeners.size > 0
|
||||
let socket: MihomoWebSocket | null = null
|
||||
let connecting = false
|
||||
let reconnectTimer: ReturnType<typeof setTimeout> | null = null
|
||||
|
||||
const clearReconnectTimer = () => {
|
||||
if (!reconnectTimer) return
|
||||
window.clearTimeout(reconnectTimer)
|
||||
reconnectTimer = null
|
||||
}
|
||||
|
||||
const closeSocket = async () => {
|
||||
const current = socket
|
||||
socket = null
|
||||
if (!current) return
|
||||
|
||||
try {
|
||||
await current.close()
|
||||
} catch (err) {
|
||||
console.warn(`Failed to close ${closeLogLabel} websocket`, err)
|
||||
}
|
||||
}
|
||||
|
||||
const scheduleReconnect = () => {
|
||||
if (!hasSubscribers()) return
|
||||
if (reconnectTimer) return
|
||||
reconnectTimer = window.setTimeout(() => {
|
||||
reconnectTimer = null
|
||||
void connect()
|
||||
}, CONNECTION_RECONNECT_DELAY_MS)
|
||||
}
|
||||
|
||||
const reconnect = async () => {
|
||||
if (!hasSubscribers()) return
|
||||
await closeSocket()
|
||||
scheduleReconnect()
|
||||
}
|
||||
|
||||
const connect = async () => {
|
||||
if (socket || connecting) return
|
||||
if (!hasSubscribers()) return
|
||||
|
||||
clearReconnectTimer()
|
||||
connecting = true
|
||||
|
||||
try {
|
||||
const connected = await connectSocket()
|
||||
if (!hasSubscribers()) {
|
||||
await connected.close()
|
||||
return
|
||||
}
|
||||
socket = connected
|
||||
connected.addListener((message) => {
|
||||
if (socket !== connected) return
|
||||
if (message.type !== 'Text') return
|
||||
if (message.data.startsWith('Websocket error')) {
|
||||
void reconnect()
|
||||
return
|
||||
}
|
||||
|
||||
onText(message.data)
|
||||
})
|
||||
} catch {
|
||||
scheduleReconnect()
|
||||
} finally {
|
||||
connecting = false
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
start: () => {
|
||||
void connect()
|
||||
},
|
||||
stopIfIdle: () => {
|
||||
if (hasSubscribers()) return
|
||||
|
||||
onIdle?.()
|
||||
clearReconnectTimer()
|
||||
void closeSocket()
|
||||
},
|
||||
reconnect,
|
||||
}
|
||||
}
|
||||
|
||||
const handleSummaryText = (messageData: string) => {
|
||||
let payload: ConnectionSummaryPayload
|
||||
try {
|
||||
payload = JSON.parse(messageData) as ConnectionSummaryPayload
|
||||
} catch (err) {
|
||||
console.error(
|
||||
'[Connections] Failed to parse connections count payload',
|
||||
err,
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
connectionSummary = mergeConnectionSummary(payload)
|
||||
notifySummaryListeners()
|
||||
}
|
||||
|
||||
const connectionSupervisor = createSocketSupervisor({
|
||||
listeners: connectionListeners,
|
||||
connectSocket: () => MihomoWebSocket.connect_connections(),
|
||||
onText: enqueueConnectionMessage,
|
||||
closeLogLabel: 'connection',
|
||||
onIdle: clearPendingMessage,
|
||||
})
|
||||
|
||||
const summarySupervisor = createSocketSupervisor({
|
||||
listeners: summaryListeners,
|
||||
connectSocket: () => MihomoWebSocket.connect_connections_count(),
|
||||
onText: handleSummaryText,
|
||||
closeLogLabel: 'connections count',
|
||||
})
|
||||
|
||||
const getConnectionSnapshot = () => connectionData
|
||||
const getConnectionSummarySnapshot = () => connectionSummary
|
||||
|
||||
const subscribeConnectionData = (listener: ConnectionListener) => {
|
||||
connectionListeners.add(listener)
|
||||
startConnectionMonitor()
|
||||
connectionSupervisor.start()
|
||||
return () => {
|
||||
connectionListeners.delete(listener)
|
||||
stopConnectionMonitorIfIdle()
|
||||
connectionSupervisor.stopIfIdle()
|
||||
}
|
||||
}
|
||||
|
||||
const subscribeConnectionSummary = (listener: ConnectionListener) => {
|
||||
summaryListeners.add(listener)
|
||||
startConnectionMonitor()
|
||||
summarySupervisor.start()
|
||||
return () => {
|
||||
summaryListeners.delete(listener)
|
||||
stopConnectionMonitorIfIdle()
|
||||
summarySupervisor.stopIfIdle()
|
||||
}
|
||||
}
|
||||
|
||||
const refreshConnectionData = () => {
|
||||
pendingMessageData = null
|
||||
if (flushTimer) {
|
||||
window.clearTimeout(flushTimer)
|
||||
flushTimer = null
|
||||
}
|
||||
clearPendingMessage()
|
||||
void connectionSupervisor.reconnect()
|
||||
}
|
||||
|
||||
void reconnectConnectionSocket()
|
||||
const refreshConnectionSummary = () => {
|
||||
void summarySupervisor.reconnect()
|
||||
}
|
||||
|
||||
const clearClosedConnectionData = () => {
|
||||
@@ -414,7 +464,7 @@ export const useConnectionSummaryData = (options?: { enabled?: boolean }) => {
|
||||
)
|
||||
const response = useMemo(() => ({ data }), [data])
|
||||
const refreshGetClashConnectionSummary = useCallback(() => {
|
||||
refreshConnectionData()
|
||||
refreshConnectionSummary()
|
||||
}, [])
|
||||
|
||||
return {
|
||||
|
||||
Reference in New Issue
Block a user