mirror of
https://github.com/hicccc77/WeFlow.git
synced 2026-03-25 15:25:50 +00:00
perf(sidebar): show cached user profile before async refresh
This commit is contained in:
@@ -12,6 +12,42 @@ interface SidebarUserProfile {
|
|||||||
avatarUrl?: string
|
avatarUrl?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const SIDEBAR_USER_PROFILE_CACHE_KEY = 'sidebar_user_profile_cache_v1'
|
||||||
|
|
||||||
|
interface SidebarUserProfileCache extends SidebarUserProfile {
|
||||||
|
updatedAt: number
|
||||||
|
}
|
||||||
|
|
||||||
|
const readSidebarUserProfileCache = (): SidebarUserProfile | null => {
|
||||||
|
try {
|
||||||
|
const raw = window.localStorage.getItem(SIDEBAR_USER_PROFILE_CACHE_KEY)
|
||||||
|
if (!raw) return null
|
||||||
|
const parsed = JSON.parse(raw) as SidebarUserProfileCache
|
||||||
|
if (!parsed || typeof parsed !== 'object') return null
|
||||||
|
if (!parsed.wxid || !parsed.displayName) return null
|
||||||
|
return {
|
||||||
|
wxid: parsed.wxid,
|
||||||
|
displayName: parsed.displayName,
|
||||||
|
avatarUrl: parsed.avatarUrl
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const writeSidebarUserProfileCache = (profile: SidebarUserProfile): void => {
|
||||||
|
if (!profile.wxid || !profile.displayName) return
|
||||||
|
try {
|
||||||
|
const payload: SidebarUserProfileCache = {
|
||||||
|
...profile,
|
||||||
|
updatedAt: Date.now()
|
||||||
|
}
|
||||||
|
window.localStorage.setItem(SIDEBAR_USER_PROFILE_CACHE_KEY, JSON.stringify(payload))
|
||||||
|
} catch {
|
||||||
|
// 忽略本地缓存失败,不影响主流程
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function Sidebar() {
|
function Sidebar() {
|
||||||
const location = useLocation()
|
const location = useLocation()
|
||||||
const [collapsed, setCollapsed] = useState(false)
|
const [collapsed, setCollapsed] = useState(false)
|
||||||
@@ -28,10 +64,6 @@ function Sidebar() {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const loadCurrentUser = async () => {
|
const loadCurrentUser = async () => {
|
||||||
try {
|
|
||||||
const wxid = await configService.getMyWxid()
|
|
||||||
let displayName = wxid || '未识别用户'
|
|
||||||
|
|
||||||
const normalizeName = (value?: string | null): string | undefined => {
|
const normalizeName = (value?: string | null): string | undefined => {
|
||||||
if (!value) return undefined
|
if (!value) return undefined
|
||||||
const trimmed = value.trim()
|
const trimmed = value.trim()
|
||||||
@@ -39,48 +71,86 @@ function Sidebar() {
|
|||||||
return trimmed
|
return trimmed
|
||||||
}
|
}
|
||||||
|
|
||||||
let enrichedDisplayName: string | undefined
|
const patchUserProfile = (patch: Partial<SidebarUserProfile>, expectedWxid?: string) => {
|
||||||
let fallbackSelfName: string | undefined
|
setUserProfile(prev => {
|
||||||
|
if (expectedWxid && prev.wxid && prev.wxid !== expectedWxid) {
|
||||||
|
return prev
|
||||||
|
}
|
||||||
|
const next: SidebarUserProfile = {
|
||||||
|
...prev,
|
||||||
|
...patch
|
||||||
|
}
|
||||||
|
if (!next.displayName) {
|
||||||
|
next.displayName = next.wxid || '未识别用户'
|
||||||
|
}
|
||||||
|
writeSidebarUserProfileCache(next)
|
||||||
|
return next
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
if (wxid) {
|
try {
|
||||||
const [myContact, enrichedResult] = await Promise.all([
|
const wxid = await configService.getMyWxid()
|
||||||
window.electronAPI.chat.getContact(wxid),
|
const resolvedWxid = wxid || ''
|
||||||
window.electronAPI.chat.enrichSessionsContactInfo([wxid, 'self'])
|
const fallbackDisplayName = resolvedWxid || '未识别用户'
|
||||||
])
|
|
||||||
|
|
||||||
enrichedDisplayName = normalizeName(enrichedResult.contacts?.[wxid]?.displayName)
|
// 第一阶段:先把 wxid/名称打上,保证侧边栏第一时间可见。
|
||||||
fallbackSelfName = normalizeName(enrichedResult.contacts?.self?.displayName)
|
patchUserProfile({
|
||||||
|
wxid: resolvedWxid,
|
||||||
|
displayName: fallbackDisplayName
|
||||||
|
})
|
||||||
|
|
||||||
const bestName =
|
if (!resolvedWxid) return
|
||||||
|
|
||||||
|
// 第二阶段:后台补齐名称(不会阻塞首屏)。
|
||||||
|
void (async () => {
|
||||||
|
try {
|
||||||
|
const myContact = await window.electronAPI.chat.getContact(resolvedWxid)
|
||||||
|
const fromContact =
|
||||||
normalizeName(myContact?.remark) ||
|
normalizeName(myContact?.remark) ||
|
||||||
normalizeName(myContact?.nickName) ||
|
normalizeName(myContact?.nickName) ||
|
||||||
normalizeName(myContact?.alias) ||
|
normalizeName(myContact?.alias)
|
||||||
enrichedDisplayName ||
|
|
||||||
fallbackSelfName
|
|
||||||
|
|
||||||
|
if (fromContact) {
|
||||||
|
patchUserProfile({ displayName: fromContact }, resolvedWxid)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const enrichedResult = await window.electronAPI.chat.enrichSessionsContactInfo([resolvedWxid, 'self'])
|
||||||
|
const enrichedDisplayName = normalizeName(enrichedResult.contacts?.[resolvedWxid]?.displayName)
|
||||||
|
const fallbackSelfName = normalizeName(enrichedResult.contacts?.self?.displayName)
|
||||||
|
const bestName = enrichedDisplayName || fallbackSelfName
|
||||||
if (bestName) {
|
if (bestName) {
|
||||||
displayName = bestName
|
patchUserProfile({ displayName: bestName }, resolvedWxid)
|
||||||
} else if (fallbackSelfName && fallbackSelfName !== wxid) {
|
|
||||||
displayName = fallbackSelfName
|
|
||||||
}
|
}
|
||||||
|
} catch (nameError) {
|
||||||
|
console.error('加载侧边栏用户昵称失败:', nameError)
|
||||||
}
|
}
|
||||||
|
})()
|
||||||
|
|
||||||
let avatarUrl: string | undefined
|
// 第二阶段:后台补齐头像(不会阻塞首屏)。
|
||||||
|
void (async () => {
|
||||||
|
try {
|
||||||
const avatarResult = await window.electronAPI.chat.getMyAvatarUrl()
|
const avatarResult = await window.electronAPI.chat.getMyAvatarUrl()
|
||||||
if (avatarResult.success && avatarResult.avatarUrl) {
|
if (avatarResult.success && avatarResult.avatarUrl) {
|
||||||
avatarUrl = avatarResult.avatarUrl
|
patchUserProfile({ avatarUrl: avatarResult.avatarUrl }, resolvedWxid)
|
||||||
}
|
}
|
||||||
|
} catch (avatarError) {
|
||||||
setUserProfile({
|
console.error('加载侧边栏用户头像失败:', avatarError)
|
||||||
wxid: wxid || '',
|
}
|
||||||
displayName,
|
})()
|
||||||
avatarUrl
|
|
||||||
})
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('加载侧边栏用户信息失败:', error)
|
console.error('加载侧边栏用户信息失败:', error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const cachedProfile = readSidebarUserProfileCache()
|
||||||
|
if (cachedProfile) {
|
||||||
|
setUserProfile(prev => ({
|
||||||
|
...prev,
|
||||||
|
...cachedProfile
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
void loadCurrentUser()
|
void loadCurrentUser()
|
||||||
const onWxidChanged = () => { void loadCurrentUser() }
|
const onWxidChanged = () => { void loadCurrentUser() }
|
||||||
window.addEventListener('wxid-changed', onWxidChanged as EventListener)
|
window.addEventListener('wxid-changed', onWxidChanged as EventListener)
|
||||||
|
|||||||
Reference in New Issue
Block a user