refactor(sns): remove contact post-count stats flow

This commit is contained in:
tisonhuang
2026-03-05 09:34:57 +08:00
parent e795474917
commit 8aaad71784
7 changed files with 3 additions and 151 deletions

View File

@@ -7,8 +7,6 @@ interface Contact {
username: string
displayName: string
avatarUrl?: string
postCount?: number
postCountStatus?: 'loading' | 'ready' | 'error'
}
interface SnsFilterPanelProps {
@@ -59,22 +57,12 @@ export const SnsFilterPanel: React.FC<SnsFilterPanelProps> = ({
setJumpTargetDate(undefined)
}
const getPostCountDisplay = (contact: Contact) => {
if (contact.postCountStatus === 'error') {
return { text: '统计失败', className: 'is-error' }
}
if (contact.postCountStatus !== 'ready') {
return { text: '统计中', className: 'is-loading' }
}
return { text: `${Math.max(0, Number(contact.postCount || 0))}`, className: '' }
}
const getEmptyStateText = () => {
if (loading && contacts.length === 0) {
return '正在加载联系人...'
}
if (contacts.length === 0) {
return '有朋友圈数据的好友或曾经的好友数量为 0'
return '暂无好友或曾经的好友'
}
return '没有找到联系人'
}
@@ -166,7 +154,6 @@ export const SnsFilterPanel: React.FC<SnsFilterPanelProps> = ({
<div className="contact-list-scroll">
{filteredContacts.map(contact => {
const countDisplay = getPostCountDisplay(contact)
return (
<div
key={contact.username}
@@ -176,7 +163,6 @@ export const SnsFilterPanel: React.FC<SnsFilterPanelProps> = ({
<Avatar src={contact.avatarUrl} name={contact.displayName} size={36} shape="rounded" />
<div className="contact-meta">
<span className="contact-name">{contact.displayName}</span>
<span className={`contact-post-count ${countDisplay.className}`}>{countDisplay.text}</span>
</div>
</div>
)

View File

@@ -1083,11 +1083,6 @@
color: var(--primary);
font-weight: 600;
}
.contact-post-count {
color: var(--primary);
opacity: 0.9;
}
}
/* If the NEXT item is also selected */
@@ -1124,20 +1119,6 @@
overflow: hidden;
text-overflow: ellipsis;
}
.contact-post-count {
font-size: 12px;
color: var(--text-tertiary);
line-height: 1.2;
&.is-loading {
font-style: italic;
}
&.is-error {
color: var(--color-error, #f44336);
}
}
}
}
}

View File

@@ -10,16 +10,12 @@ import * as configService from '../services/config'
const SNS_PAGE_CACHE_TTL_MS = 24 * 60 * 60 * 1000
const SNS_PAGE_CACHE_POST_LIMIT = 200
const SNS_PAGE_CACHE_SCOPE_FALLBACK = '__default__'
const CONTACTS_PRUNE_BATCH_SIZE = 40
const CONTACTS_PRUNE_INTERVAL_MS = 80
interface Contact {
username: string
displayName: string
avatarUrl?: string
type?: 'friend' | 'former_friend' | 'sns_only'
postCount?: number
postCountStatus: 'loading' | 'ready' | 'error'
}
interface SnsOverviewStats {
@@ -93,7 +89,6 @@ export default function SnsPage() {
const cacheScopeKeyRef = useRef('')
const scrollAdjustmentRef = useRef<{ scrollHeight: number; scrollTop: number } | null>(null)
const contactsLoadTokenRef = useRef(0)
const contactsPruneTimerRef = useRef<number | null>(null)
// Sync posts ref
useEffect(() => {
@@ -114,14 +109,6 @@ export default function SnsPage() {
useEffect(() => {
jumpTargetDateRef.current = jumpTargetDate
}, [jumpTargetDate])
useEffect(() => {
return () => {
if (contactsPruneTimerRef.current !== null) {
window.clearTimeout(contactsPruneTimerRef.current)
contactsPruneTimerRef.current = null
}
}
}, [])
// 在 DOM 更新后、浏览器绘制前同步调整滚动位置,防止向上加载时页面跳动
useLayoutEffect(() => {
const snapshot = scrollAdjustmentRef.current;
@@ -403,12 +390,8 @@ export default function SnsPage() {
}
}, [jumpTargetDate, persistSnsPageCache, searchKeyword, selectedUsernames])
// Load Contacts先展示全量好友/曾经好友,再按朋友圈条数逐步剔除 0 条联系人
// Load Contacts仅加载好友/曾经好友,不再统计朋友圈条数)
const loadContacts = useCallback(async () => {
if (contactsPruneTimerRef.current !== null) {
window.clearTimeout(contactsPruneTimerRef.current)
contactsPruneTimerRef.current = null
}
const requestToken = ++contactsLoadTokenRef.current
setContactsLoading(true)
try {
@@ -422,8 +405,7 @@ export default function SnsPage() {
username: c.username,
displayName: c.displayName,
avatarUrl: c.avatarUrl,
type: c.type === 'former_friend' ? 'former_friend' : 'friend',
postCountStatus: 'loading'
type: c.type === 'former_friend' ? 'former_friend' : 'friend'
})
}
}
@@ -453,62 +435,9 @@ export default function SnsPage() {
setContacts(contactsList)
}
}
const snsCountsResult = await window.electronAPI.sns.getUserPostCounts()
if (requestToken !== contactsLoadTokenRef.current) return
if (snsCountsResult.success && snsCountsResult.data) {
const snsPostCountMap = new Map<string, number>(
Object.entries(snsCountsResult.data).map(([username, count]) => [username, Math.max(0, Number(count || 0))])
)
const contactsWithCounts: Contact[] = contactsList.map(contact => ({
...contact,
postCount: snsPostCountMap.get(contact.username) ?? 0,
postCountStatus: 'ready' as const
}))
setContacts(contactsWithCounts)
const zeroCountUsernames = contactsWithCounts
.filter(contact => (contact.postCount || 0) <= 0)
.map(contact => contact.username)
if (zeroCountUsernames.length > 0) {
let cursor = 0
const pruneNextBatch = () => {
if (requestToken !== contactsLoadTokenRef.current) {
contactsPruneTimerRef.current = null
return
}
const batch = zeroCountUsernames.slice(cursor, cursor + CONTACTS_PRUNE_BATCH_SIZE)
if (batch.length === 0) {
contactsPruneTimerRef.current = null
return
}
const batchSet = new Set(batch)
setContacts(prev => prev.filter(contact => !batchSet.has(contact.username)))
cursor += CONTACTS_PRUNE_BATCH_SIZE
if (cursor < zeroCountUsernames.length) {
contactsPruneTimerRef.current = window.setTimeout(pruneNextBatch, CONTACTS_PRUNE_INTERVAL_MS)
} else {
contactsPruneTimerRef.current = null
}
}
contactsPruneTimerRef.current = window.setTimeout(pruneNextBatch, CONTACTS_PRUNE_INTERVAL_MS)
}
} else {
console.error('Failed to load SNS contact post counts:', snsCountsResult.error)
setContacts(prev => prev.map(contact => ({
...contact,
postCountStatus: 'error'
})))
}
} catch (error) {
if (requestToken !== contactsLoadTokenRef.current) return
console.error('Failed to load contacts:', error)
setContacts(prev => prev.map(contact => ({
...contact,
postCountStatus: 'error'
})))
} finally {
if (requestToken === contactsLoadTokenRef.current) {
setContactsLoading(false)

View File

@@ -770,7 +770,6 @@ export interface ElectronAPI {
onExportProgress: (callback: (payload: { current: number; total: number; status: string }) => void) => () => void
selectExportDir: () => Promise<{ canceled: boolean; filePath?: string }>
getSnsUsernames: () => Promise<{ success: boolean; usernames?: string[]; error?: string }>
getUserPostCounts: () => Promise<{ success: boolean; data?: Record<string, number>; error?: string }>
getExportStatsFast: () => Promise<{ success: boolean; data?: { totalPosts: number; totalFriends: number; myPosts: number | null }; error?: string }>
getExportStats: () => Promise<{ success: boolean; data?: { totalPosts: number; totalFriends: number; myPosts: number | null }; error?: string }>
installBlockDeleteTrigger: () => Promise<{ success: boolean; alreadyInstalled?: boolean; error?: string }>