修复 Windows 会话名称和密钥显示图标

This commit is contained in:
电摇小子
2026-07-14 11:07:35 +08:00
committed by 电摇小子
parent 8bb9576f10
commit 995a95e8dc
4 changed files with 106 additions and 12 deletions
+41 -9
View File
@@ -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[] { export function mergeCachedContactAvatars(accountRoot: string, contacts: Contact[]): Contact[] {
const cache = readCacheFile(accountRoot) const cache = readCacheFile(accountRoot)
if (!cache?.contacts?.length) return contacts if (!cache?.contacts?.length) return contacts
@@ -132,12 +142,23 @@ export function mergeCachedContactAvatars(accountRoot: string, contacts: Contact
.filter((contact) => contact.m_nsUsrName && contact.avatar) .filter((contact) => contact.m_nsUsrName && contact.avatar)
.map((contact) => [contact.m_nsUsrName, contact.avatar as string]) .map((contact) => [contact.m_nsUsrName, contact.avatar as string])
) )
if (avatarByUsername.size === 0) return contacts const nameByUsername = new Map(
return contacts.map((contact) => cache.contacts
contact.avatar || !avatarByUsername.has(contact.m_nsUsrName) .filter((contact) => contact.m_nsUsrName && contact.m_nsNickName && !isRawContactName(contact))
? contact .map((contact) => [contact.m_nsUsrName, contact.m_nsNickName])
: { ...contact, avatar: avatarByUsername.get(contact.m_nsUsrName) }
) )
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 { 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) .filter((contact) => contact.m_nsUsrName && contact.avatar)
.map((contact) => [contact.m_nsUsrName, contact.avatar as string]) .map((contact) => [contact.m_nsUsrName, contact.avatar as string])
) )
cache.contacts = contacts.map((contact) => const nameByUsername = new Map(
contact.avatar || !avatarByUsername.has(contact.m_nsUsrName) (cache.contacts || [])
? contact .filter((contact) => contact.m_nsUsrName && contact.m_nsNickName && !isRawContactName(contact))
: { ...contact, avatar: avatarByUsername.get(contact.m_nsUsrName) } .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() cache.updatedAt = Date.now()
writeCacheFile(cache) writeCacheFile(cache)
} }
+16
View File
@@ -601,6 +601,11 @@ export class Wcdb4Client {
.map((row) => this.normalizeSession(row)) .map((row) => this.normalizeSession(row))
.filter((session) => session.username) .filter((session) => session.username)
this.hydrateDisplayNames(
sessions
.filter((session) => this.shouldHydrateSessionDisplayName(session))
.map((session) => session.username)
)
this.cachedSessions = sessions.map((session) => ({ this.cachedSessions = sessions.map((session) => ({
...session, ...session,
nickname: this.displayNameCache.get(session.username) || session.nickname || session.username 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 { private hydrateDisplayNames(usernames: string[]): void {
if (!this.wcdbGetDisplayNames) return if (!this.wcdbGetDisplayNames) return
const missing = this.uniq(usernames).filter((username) => !this.displayNameCache.has(username)) const missing = this.uniq(usernames).filter((username) => !this.displayNameCache.has(username))
+33 -1
View File
@@ -4,6 +4,38 @@ import ChatWindow from './components/ChatWindow'
import { SettingsPanel } from './components/SettingsPanel' import { SettingsPanel } from './components/SettingsPanel'
import { Contact, Message } from '../../shared/types' import { Contact, Message } from '../../shared/types'
function EyeIcon({ hidden }: { hidden: boolean }): React.ReactElement {
return (
<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false">
<path
d="M2.5 12s3.5-6 9.5-6 9.5 6 9.5 6-3.5 6-9.5 6-9.5-6-9.5-6Z"
fill="none"
stroke="currentColor"
strokeWidth="1.8"
strokeLinecap="round"
strokeLinejoin="round"
/>
<circle
cx="12"
cy="12"
r="3"
fill="none"
stroke="currentColor"
strokeWidth="1.8"
/>
{hidden && (
<path
d="M4 4l16 16"
fill="none"
stroke="currentColor"
strokeWidth="1.8"
strokeLinecap="round"
/>
)}
</svg>
)
}
interface SelfInfo { interface SelfInfo {
wxid: string wxid: string
nickname: string nickname: string
@@ -760,7 +792,7 @@ function App(): React.ReactElement {
onClick={() => setShowDbKey(!showDbKey)} onClick={() => setShowDbKey(!showDbKey)}
title={showDbKey ? '隐藏密钥' : '显示密钥'} title={showDbKey ? '隐藏密钥' : '显示密钥'}
> >
{showDbKey ? '隐藏' : '显示'} <EyeIcon hidden={showDbKey} />
</button> </button>
</div> </div>
<button <button
+16 -2
View File
@@ -740,11 +740,25 @@ body {
.login-input-toggle { .login-input-toggle {
position: absolute; position: absolute;
right: 8px; right: 8px;
width: 28px;
height: 28px;
display: inline-flex;
align-items: center;
justify-content: center;
background: none; background: none;
border: none; border: none;
cursor: pointer; cursor: pointer;
padding: 4px 8px; padding: 0;
font-size: 18px; color: #111827;
}
.login-input-toggle svg {
width: 20px;
height: 20px;
}
.login-input-toggle:hover {
color: #07c160;
} }
.login-btn { .login-btn {