fix: inconsistent applied profile when rapidly switching profiles (#1268)

This commit is contained in:
Leon Wang 2025-10-11 07:01:51 +08:00 committed by GitHub
parent d8fdbebc4b
commit 6429e93adf
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -1,12 +1,12 @@
import React, { createContext, useContext, ReactNode } from 'react' import React, { createContext, ReactNode, useContext } from 'react'
import useSWR from 'swr' import useSWR from 'swr'
import { import {
getProfileConfig,
setProfileConfig as set,
addProfileItem as add, addProfileItem as add,
changeCurrentProfile as change,
getProfileConfig,
removeProfileItem as remove, removeProfileItem as remove,
updateProfileItem as update, setProfileConfig as set,
changeCurrentProfile as change updateProfileItem as update
} from '@renderer/utils/ipc' } from '@renderer/utils/ipc'
interface ProfileConfigContextType { interface ProfileConfigContextType {
@ -25,7 +25,8 @@ export const ProfileConfigProvider: React.FC<{ children: ReactNode }> = ({ child
const { data: profileConfig, mutate: mutateProfileConfig } = useSWR('getProfileConfig', () => const { data: profileConfig, mutate: mutateProfileConfig } = useSWR('getProfileConfig', () =>
getProfileConfig() getProfileConfig()
) )
const [targetProfileId, setTargetProfileId] = React.useState<string | null>(null) const targetProfileId = React.useRef<string | null>(null)
const pendingTask = React.useRef<Promise<void> | null>(null)
const setProfileConfig = async (config: IProfileConfig): Promise<void> => { const setProfileConfig = async (config: IProfileConfig): Promise<void> => {
try { try {
@ -72,12 +73,10 @@ export const ProfileConfigProvider: React.FC<{ children: ReactNode }> = ({ child
} }
const changeCurrentProfile = async (id: string): Promise<void> => { const changeCurrentProfile = async (id: string): Promise<void> => {
if (targetProfileId === id) { if (targetProfileId.current === id) {
return return
} }
setTargetProfileId(id)
// 立即更新 UI 状态和托盘菜单,提供即时反馈 // 立即更新 UI 状态和托盘菜单,提供即时反馈
if (profileConfig) { if (profileConfig) {
const optimisticUpdate = { ...profileConfig, current: id } const optimisticUpdate = { ...profileConfig, current: id }
@ -85,17 +84,24 @@ export const ProfileConfigProvider: React.FC<{ children: ReactNode }> = ({ child
window.electron.ipcRenderer.send('updateTrayMenu') window.electron.ipcRenderer.send('updateTrayMenu')
} }
// 异步执行后台切换,不阻塞 UI targetProfileId.current = id
try { await processChange()
await change(id) }
if (targetProfileId === id) { const processChange = async () => {
mutateProfileConfig() if (pendingTask.current) {
setTargetProfileId(null) return
} else { }
}
} catch (e) { while (targetProfileId.current) {
if (targetProfileId === id) { const targetId = targetProfileId.current
targetProfileId.current = null
pendingTask.current = change(targetId)
try {
// 异步执行后台切换,不阻塞 UI
await pendingTask.current
} catch (e) {
const errorMsg = (e as any)?.message || String(e) const errorMsg = (e as any)?.message || String(e)
// 处理 IPC 超时错误 // 处理 IPC 超时错误
if (errorMsg.includes('reply was never sent')) { if (errorMsg.includes('reply was never sent')) {
@ -104,7 +110,8 @@ export const ProfileConfigProvider: React.FC<{ children: ReactNode }> = ({ child
alert(`切换 Profile 失败: ${errorMsg}`) alert(`切换 Profile 失败: ${errorMsg}`)
mutateProfileConfig() mutateProfileConfig()
} }
setTargetProfileId(null) } finally {
pendingTask.current = null
} }
} }
} }