diff --git a/src/main/services/bootstrap-cache.ts b/src/main/services/bootstrap-cache.ts index 0087d85..5375379 100644 --- a/src/main/services/bootstrap-cache.ts +++ b/src/main/services/bootstrap-cache.ts @@ -124,6 +124,16 @@ export function getBootstrapCache(accountRoot?: string): { } } +function isRawContactName(contact: Contact): boolean { + const name = String(contact.m_nsNickName || '').trim() + const username = String(contact.m_nsUsrName || '').trim() + if (!name) return true + if (name === username) return true + if (name.endsWith('@chatroom')) return true + if (name.startsWith('Group_') || name.startsWith('Unknown_')) return true + return false +} + export function mergeCachedContactAvatars(accountRoot: string, contacts: Contact[]): Contact[] { const cache = readCacheFile(accountRoot) if (!cache?.contacts?.length) return contacts @@ -132,12 +142,23 @@ export function mergeCachedContactAvatars(accountRoot: string, contacts: Contact .filter((contact) => contact.m_nsUsrName && contact.avatar) .map((contact) => [contact.m_nsUsrName, contact.avatar as string]) ) - if (avatarByUsername.size === 0) return contacts - return contacts.map((contact) => - contact.avatar || !avatarByUsername.has(contact.m_nsUsrName) - ? contact - : { ...contact, avatar: avatarByUsername.get(contact.m_nsUsrName) } + const nameByUsername = new Map( + cache.contacts + .filter((contact) => contact.m_nsUsrName && contact.m_nsNickName && !isRawContactName(contact)) + .map((contact) => [contact.m_nsUsrName, contact.m_nsNickName]) ) + if (avatarByUsername.size === 0 && nameByUsername.size === 0) return contacts + return contacts.map((contact) => ({ + ...contact, + avatar: + contact.avatar || !avatarByUsername.has(contact.m_nsUsrName) + ? contact.avatar + : avatarByUsername.get(contact.m_nsUsrName), + m_nsNickName: + !isRawContactName(contact) || !nameByUsername.has(contact.m_nsUsrName) + ? contact.m_nsNickName + : nameByUsername.get(contact.m_nsUsrName) || contact.m_nsNickName + })) } export function saveBootstrapSelf(accountRoot: string, self: CachedSelfInfo): void { @@ -156,11 +177,22 @@ export function saveBootstrapContacts(accountRoot: string, contacts: Contact[]): .filter((contact) => contact.m_nsUsrName && contact.avatar) .map((contact) => [contact.m_nsUsrName, contact.avatar as string]) ) - cache.contacts = contacts.map((contact) => - contact.avatar || !avatarByUsername.has(contact.m_nsUsrName) - ? contact - : { ...contact, avatar: avatarByUsername.get(contact.m_nsUsrName) } + const nameByUsername = new Map( + (cache.contacts || []) + .filter((contact) => contact.m_nsUsrName && contact.m_nsNickName && !isRawContactName(contact)) + .map((contact) => [contact.m_nsUsrName, contact.m_nsNickName]) ) + cache.contacts = contacts.map((contact) => ({ + ...contact, + avatar: + contact.avatar || !avatarByUsername.has(contact.m_nsUsrName) + ? contact.avatar + : avatarByUsername.get(contact.m_nsUsrName), + m_nsNickName: + !isRawContactName(contact) || !nameByUsername.has(contact.m_nsUsrName) + ? contact.m_nsNickName + : nameByUsername.get(contact.m_nsUsrName) || contact.m_nsNickName + })) cache.updatedAt = Date.now() writeCacheFile(cache) } diff --git a/src/main/wcdb4-client.ts b/src/main/wcdb4-client.ts index 1d1dc74..cc21c30 100644 --- a/src/main/wcdb4-client.ts +++ b/src/main/wcdb4-client.ts @@ -601,6 +601,11 @@ export class Wcdb4Client { .map((row) => this.normalizeSession(row)) .filter((session) => session.username) + this.hydrateDisplayNames( + sessions + .filter((session) => this.shouldHydrateSessionDisplayName(session)) + .map((session) => session.username) + ) this.cachedSessions = sessions.map((session) => ({ ...session, nickname: this.displayNameCache.get(session.username) || session.nickname || session.username @@ -1541,6 +1546,17 @@ export class Wcdb4Client { } } + private shouldHydrateSessionDisplayName(session: Wcdb4Session): boolean { + const username = String(session.username || '').trim() + const nickname = String(session.nickname || '').trim() + if (!username) return false + if (!nickname) return true + if (nickname === username) return true + if (nickname.endsWith('@chatroom')) return true + if (nickname.startsWith('Group_') || nickname.startsWith('Unknown_')) return true + return false + } + private hydrateDisplayNames(usernames: string[]): void { if (!this.wcdbGetDisplayNames) return const missing = this.uniq(usernames).filter((username) => !this.displayNameCache.has(username)) diff --git a/src/renderer/src/App.tsx b/src/renderer/src/App.tsx index 4d436d0..1faec1d 100644 --- a/src/renderer/src/App.tsx +++ b/src/renderer/src/App.tsx @@ -4,6 +4,38 @@ import ChatWindow from './components/ChatWindow' import { SettingsPanel } from './components/SettingsPanel' import { Contact, Message } from '../../shared/types' +function EyeIcon({ hidden }: { hidden: boolean }): React.ReactElement { + return ( + + ) +} + interface SelfInfo { wxid: string nickname: string @@ -760,7 +792,7 @@ function App(): React.ReactElement { onClick={() => setShowDbKey(!showDbKey)} title={showDbKey ? '隐藏密钥' : '显示密钥'} > - {showDbKey ? '隐藏' : '显示'} +