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"
|
checksum = "117725a109d387c937a1533ce01b450cbde6b88abceea8473c4d7a85853cda3c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"windows-sys 0.59.0",
|
"windows-sys 0.48.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -2073,7 +2073,7 @@ dependencies = [
|
|||||||
"libc",
|
"libc",
|
||||||
"option-ext",
|
"option-ext",
|
||||||
"redox_users 0.5.2",
|
"redox_users 0.5.2",
|
||||||
"windows-sys 0.61.2",
|
"windows-sys 0.60.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -2347,7 +2347,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
|
checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"windows-sys 0.61.2",
|
"windows-sys 0.60.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -2865,7 +2865,7 @@ dependencies = [
|
|||||||
"gobject-sys 0.21.5",
|
"gobject-sys 0.21.5",
|
||||||
"libc",
|
"libc",
|
||||||
"system-deps 7.0.8",
|
"system-deps 7.0.8",
|
||||||
"windows-sys 0.61.2",
|
"windows-sys 0.60.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -3488,7 +3488,7 @@ dependencies = [
|
|||||||
"libc",
|
"libc",
|
||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
"socket2 0.6.5",
|
"socket2 0.5.10",
|
||||||
"system-configuration",
|
"system-configuration",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tower-service",
|
"tower-service",
|
||||||
@@ -4316,7 +4316,7 @@ dependencies = [
|
|||||||
"png 0.18.1",
|
"png 0.18.1",
|
||||||
"serde",
|
"serde",
|
||||||
"thiserror 2.0.20",
|
"thiserror 2.0.20",
|
||||||
"windows-sys 0.61.2",
|
"windows-sys 0.60.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -4485,7 +4485,7 @@ version = "0.50.3"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5"
|
checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"windows-sys 0.61.2",
|
"windows-sys 0.60.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -4928,7 +4928,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "7d8fae84b431384b68627d0f9b3b1245fcf9f46f6c0e3dc902e9dce64edd1967"
|
checksum = "7d8fae84b431384b68627d0f9b3b1245fcf9f46f6c0e3dc902e9dce64edd1967"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"windows-sys 0.61.2",
|
"windows-sys 0.48.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -5602,7 +5602,7 @@ dependencies = [
|
|||||||
"quinn-udp",
|
"quinn-udp",
|
||||||
"rustc-hash",
|
"rustc-hash",
|
||||||
"rustls",
|
"rustls",
|
||||||
"socket2 0.6.5",
|
"socket2 0.5.10",
|
||||||
"thiserror 2.0.20",
|
"thiserror 2.0.20",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tracing",
|
"tracing",
|
||||||
@@ -5641,9 +5641,9 @@ dependencies = [
|
|||||||
"cfg_aliases",
|
"cfg_aliases",
|
||||||
"libc",
|
"libc",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"socket2 0.6.5",
|
"socket2 0.5.10",
|
||||||
"tracing",
|
"tracing",
|
||||||
"windows-sys 0.61.2",
|
"windows-sys 0.60.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -6198,7 +6198,7 @@ dependencies = [
|
|||||||
"errno",
|
"errno",
|
||||||
"libc",
|
"libc",
|
||||||
"linux-raw-sys 0.12.1",
|
"linux-raw-sys 0.12.1",
|
||||||
"windows-sys 0.61.2",
|
"windows-sys 0.60.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -6257,7 +6257,7 @@ dependencies = [
|
|||||||
"security-framework",
|
"security-framework",
|
||||||
"security-framework-sys",
|
"security-framework-sys",
|
||||||
"webpki-root-certs",
|
"webpki-root-certs",
|
||||||
"windows-sys 0.61.2",
|
"windows-sys 0.60.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -6899,7 +6899,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "c3d1e2c7f27f8d4cb10542a02c49005dbd6e93095799d6f3be745fae9f8fedd4"
|
checksum = "c3d1e2c7f27f8d4cb10542a02c49005dbd6e93095799d6f3be745fae9f8fedd4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"windows-sys 0.61.2",
|
"windows-sys 0.60.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -7565,8 +7565,8 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tauri-plugin-mihomo"
|
name = "tauri-plugin-mihomo"
|
||||||
version = "0.5.6"
|
version = "0.6.0"
|
||||||
source = "git+https://github.com/clash-verge-rev/tauri-plugin-mihomo?branch=main#8bf567b9e2230cdd02f9b8c9774fb8eb0d71af1e"
|
source = "git+https://github.com/clash-verge-rev/tauri-plugin-mihomo?branch=main#17c7757389ca73d29882753ecf7a160de29aabbe"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"arc-swap",
|
"arc-swap",
|
||||||
"clashmap",
|
"clashmap",
|
||||||
@@ -7863,7 +7863,7 @@ dependencies = [
|
|||||||
"getrandom 0.4.3",
|
"getrandom 0.4.3",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"rustix 1.1.4",
|
"rustix 1.1.4",
|
||||||
"windows-sys 0.61.2",
|
"windows-sys 0.60.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -8582,7 +8582,7 @@ dependencies = [
|
|||||||
"png 0.18.1",
|
"png 0.18.1",
|
||||||
"serde",
|
"serde",
|
||||||
"thiserror 2.0.20",
|
"thiserror 2.0.20",
|
||||||
"windows-sys 0.61.2",
|
"windows-sys 0.60.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -8685,7 +8685,7 @@ checksum = "f2f6fb2847f6742cd76af783a2a2c49e9375d0a111c7bef6f71cd9e738c72d6e"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"memoffset",
|
"memoffset",
|
||||||
"tempfile",
|
"tempfile",
|
||||||
"windows-sys 0.61.2",
|
"windows-sys 0.60.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -9270,7 +9270,7 @@ version = "0.1.11"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22"
|
checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"windows-sys 0.61.2",
|
"windows-sys 0.48.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -9874,7 +9874,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "7d6f32a0ff4a9f6f01231eb2059cc85479330739333e0e58cadf03b6af2cca10"
|
checksum = "7d6f32a0ff4a9f6f01231eb2059cc85479330739333e0e58cadf03b6af2cca10"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"windows-sys 0.61.2",
|
"windows-sys 0.60.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|||||||
Generated
+5
-5
@@ -234,7 +234,7 @@ importers:
|
|||||||
version: 2.5.1(react@19.2.8)
|
version: 2.5.1(react@19.2.8)
|
||||||
tauri-plugin-mihomo-api:
|
tauri-plugin-mihomo-api:
|
||||||
specifier: github:clash-verge-rev/tauri-plugin-mihomo#main
|
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:
|
types-pac:
|
||||||
specifier: ^1.0.3
|
specifier: ^1.0.3
|
||||||
version: 1.0.3
|
version: 1.0.3
|
||||||
@@ -4838,9 +4838,9 @@ packages:
|
|||||||
resolution: {integrity: sha512-MFO/QzvtAOmJbkhOaCTvbGcFN9L9b+JunIsDwaKljSOdcLMea3NJ1k9Usz/rjdfSXTq4dfzfeS7W4p4YOAAHeA==}
|
resolution: {integrity: sha512-MFO/QzvtAOmJbkhOaCTvbGcFN9L9b+JunIsDwaKljSOdcLMea3NJ1k9Usz/rjdfSXTq4dfzfeS7W4p4YOAAHeA==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
|
|
||||||
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:
|
||||||
resolution: {gitHosted: true, integrity: sha512-ZUNzoqUI/328gbYuFUw9oKe0BVi/reurZZ2ut1+B8ZgEtZ6dtNgKMea7Kp8UvKTnF543WvI/8RwetH1Fzkflzw==, tarball: https://codeload.github.com/clash-verge-rev/tauri-plugin-mihomo/tar.gz/8bf567b9e2230cdd02f9b8c9774fb8eb0d71af1e}
|
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.5.6
|
version: 0.6.0
|
||||||
|
|
||||||
teex@1.0.1:
|
teex@1.0.1:
|
||||||
resolution: {integrity: sha512-eYE6iEI62Ni1H8oIa7KlDU6uQBtqr4Eajni3wX7rpfXD8ysFx8z0+dri+KWEPWpBsxXfxu58x/0jvTVT1ekOSg==}
|
resolution: {integrity: sha512-eYE6iEI62Ni1H8oIa7KlDU6uQBtqr4Eajni3wX7rpfXD8ysFx8z0+dri+KWEPWpBsxXfxu58x/0jvTVT1ekOSg==}
|
||||||
@@ -10220,7 +10220,7 @@ snapshots:
|
|||||||
minizlib: 3.1.0
|
minizlib: 3.1.0
|
||||||
yallist: 5.0.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:
|
dependencies:
|
||||||
'@tauri-apps/api': 2.11.1
|
'@tauri-apps/api': 2.11.1
|
||||||
|
|
||||||
|
|||||||
@@ -24,6 +24,10 @@ interface ConnectionMonitorData {
|
|||||||
closedConnections: IConnectionsItem[]
|
closedConnections: IConnectionsItem[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface ConnectionSummaryPayload {
|
||||||
|
count?: number
|
||||||
|
}
|
||||||
|
|
||||||
interface ConnectionSummaryData {
|
interface ConnectionSummaryData {
|
||||||
activeConnectionCount: number
|
activeConnectionCount: number
|
||||||
}
|
}
|
||||||
@@ -34,9 +38,6 @@ const initConnSummaryData: ConnectionSummaryData = {
|
|||||||
|
|
||||||
let connectionData: ConnectionMonitorData = initConnData
|
let connectionData: ConnectionMonitorData = initConnData
|
||||||
let connectionSummary: ConnectionSummaryData = initConnSummaryData
|
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 flushTimer: ReturnType<typeof setTimeout> | null = null
|
||||||
let pendingMessageData: string | null = null
|
let pendingMessageData: string | null = null
|
||||||
let lastFlushAt = 0
|
let lastFlushAt = 0
|
||||||
@@ -52,9 +53,6 @@ const notifySummaryListeners = () => {
|
|||||||
summaryListeners.forEach((listener) => listener())
|
summaryListeners.forEach((listener) => listener())
|
||||||
}
|
}
|
||||||
|
|
||||||
const hasConnectionSubscribers = () =>
|
|
||||||
connectionListeners.size > 0 || summaryListeners.size > 0
|
|
||||||
|
|
||||||
const sameMetadata = (left: ConnectionMetadata, right: ConnectionMetadata) =>
|
const sameMetadata = (left: ConnectionMetadata, right: ConnectionMetadata) =>
|
||||||
metadataValue(left.network) === metadataValue(right.network) &&
|
metadataValue(left.network) === metadataValue(right.network) &&
|
||||||
metadataValue(left.type) === metadataValue(right.type) &&
|
metadataValue(left.type) === metadataValue(right.type) &&
|
||||||
@@ -208,16 +206,16 @@ const mergeConnectionSnapshot = (
|
|||||||
}
|
}
|
||||||
|
|
||||||
const mergeConnectionSummary = (
|
const mergeConnectionSummary = (
|
||||||
payload: IConnections,
|
payload: ConnectionSummaryPayload,
|
||||||
): ConnectionSummaryData => ({
|
): ConnectionSummaryData => ({
|
||||||
activeConnectionCount: payload.connections?.length ?? 0,
|
activeConnectionCount: payload.count ?? 0,
|
||||||
})
|
})
|
||||||
|
|
||||||
const flushPendingMessage = () => {
|
const flushPendingMessage = () => {
|
||||||
flushTimer = null
|
flushTimer = null
|
||||||
const messageData = pendingMessageData
|
const messageData = pendingMessageData
|
||||||
pendingMessageData = null
|
pendingMessageData = null
|
||||||
if (!messageData || !hasConnectionSubscribers()) return
|
if (!messageData || connectionListeners.size === 0) return
|
||||||
|
|
||||||
let payload: IConnections
|
let payload: IConnections
|
||||||
try {
|
try {
|
||||||
@@ -228,10 +226,6 @@ const flushPendingMessage = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
lastFlushAt = Date.now()
|
lastFlushAt = Date.now()
|
||||||
connectionSummary = mergeConnectionSummary(payload)
|
|
||||||
notifySummaryListeners()
|
|
||||||
|
|
||||||
if (connectionListeners.size === 0) return
|
|
||||||
|
|
||||||
connectionData = mergeConnectionSnapshot(payload, connectionData)
|
connectionData = mergeConnectionSnapshot(payload, connectionData)
|
||||||
notifyConnectionListeners()
|
notifyConnectionListeners()
|
||||||
@@ -253,115 +247,171 @@ const enqueueConnectionMessage = (messageData: string) => {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const clearReconnectTimer = () => {
|
const clearPendingMessage = () => {
|
||||||
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()
|
|
||||||
pendingMessageData = null
|
pendingMessageData = null
|
||||||
if (flushTimer) {
|
if (flushTimer) {
|
||||||
window.clearTimeout(flushTimer)
|
window.clearTimeout(flushTimer)
|
||||||
flushTimer = null
|
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 getConnectionSnapshot = () => connectionData
|
||||||
const getConnectionSummarySnapshot = () => connectionSummary
|
const getConnectionSummarySnapshot = () => connectionSummary
|
||||||
|
|
||||||
const subscribeConnectionData = (listener: ConnectionListener) => {
|
const subscribeConnectionData = (listener: ConnectionListener) => {
|
||||||
connectionListeners.add(listener)
|
connectionListeners.add(listener)
|
||||||
startConnectionMonitor()
|
connectionSupervisor.start()
|
||||||
return () => {
|
return () => {
|
||||||
connectionListeners.delete(listener)
|
connectionListeners.delete(listener)
|
||||||
stopConnectionMonitorIfIdle()
|
connectionSupervisor.stopIfIdle()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const subscribeConnectionSummary = (listener: ConnectionListener) => {
|
const subscribeConnectionSummary = (listener: ConnectionListener) => {
|
||||||
summaryListeners.add(listener)
|
summaryListeners.add(listener)
|
||||||
startConnectionMonitor()
|
summarySupervisor.start()
|
||||||
return () => {
|
return () => {
|
||||||
summaryListeners.delete(listener)
|
summaryListeners.delete(listener)
|
||||||
stopConnectionMonitorIfIdle()
|
summarySupervisor.stopIfIdle()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const refreshConnectionData = () => {
|
const refreshConnectionData = () => {
|
||||||
pendingMessageData = null
|
clearPendingMessage()
|
||||||
if (flushTimer) {
|
void connectionSupervisor.reconnect()
|
||||||
window.clearTimeout(flushTimer)
|
}
|
||||||
flushTimer = null
|
|
||||||
}
|
|
||||||
|
|
||||||
void reconnectConnectionSocket()
|
const refreshConnectionSummary = () => {
|
||||||
|
void summarySupervisor.reconnect()
|
||||||
}
|
}
|
||||||
|
|
||||||
const clearClosedConnectionData = () => {
|
const clearClosedConnectionData = () => {
|
||||||
@@ -414,7 +464,7 @@ export const useConnectionSummaryData = (options?: { enabled?: boolean }) => {
|
|||||||
)
|
)
|
||||||
const response = useMemo(() => ({ data }), [data])
|
const response = useMemo(() => ({ data }), [data])
|
||||||
const refreshGetClashConnectionSummary = useCallback(() => {
|
const refreshGetClashConnectionSummary = useCallback(() => {
|
||||||
refreshConnectionData()
|
refreshConnectionSummary()
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
Reference in New Issue
Block a user