mirror of
https://github.com/hicccc77/WeFlow.git
synced 2026-03-25 07:16:51 +00:00
refactor(export): reuse shared sns timeline dialog
This commit is contained in:
@@ -39,6 +39,7 @@ import {
|
|||||||
} from '../services/exportBridge'
|
} from '../services/exportBridge'
|
||||||
import { useContactTypeCountsStore } from '../stores/contactTypeCountsStore'
|
import { useContactTypeCountsStore } from '../stores/contactTypeCountsStore'
|
||||||
import { SnsPostItem } from '../components/Sns/SnsPostItem'
|
import { SnsPostItem } from '../components/Sns/SnsPostItem'
|
||||||
|
import { ContactSnsTimelineDialog } from '../components/Sns/ContactSnsTimelineDialog'
|
||||||
import type { SnsPost } from '../types/sns'
|
import type { SnsPost } from '../types/sns'
|
||||||
import './ExportPage.scss'
|
import './ExportPage.scss'
|
||||||
|
|
||||||
@@ -2241,6 +2242,21 @@ function ExportPage() {
|
|||||||
setSessionSnsTimelineStatsLoading(false)
|
setSessionSnsTimelineStatsLoading(false)
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
|
const sessionSnsTimelineInitialTotalPosts = useMemo(() => {
|
||||||
|
const username = String(sessionSnsTimelineTarget?.username || '').trim()
|
||||||
|
if (!username) return null
|
||||||
|
if (!Object.prototype.hasOwnProperty.call(snsUserPostCounts, username)) return null
|
||||||
|
const count = Number(snsUserPostCounts[username] || 0)
|
||||||
|
return Number.isFinite(count) ? Math.max(0, Math.floor(count)) : 0
|
||||||
|
}, [sessionSnsTimelineTarget, snsUserPostCounts])
|
||||||
|
|
||||||
|
const sessionSnsTimelineInitialTotalPostsLoading = useMemo(() => {
|
||||||
|
const username = String(sessionSnsTimelineTarget?.username || '').trim()
|
||||||
|
if (!username) return false
|
||||||
|
if (Object.prototype.hasOwnProperty.call(snsUserPostCounts, username)) return false
|
||||||
|
return snsUserPostCountsStatus === 'loading' || snsUserPostCountsStatus === 'idle'
|
||||||
|
}, [sessionSnsTimelineTarget, snsUserPostCounts, snsUserPostCountsStatus])
|
||||||
|
|
||||||
const openSessionSnsTimelineByTarget = useCallback((target: SessionSnsTimelineTarget) => {
|
const openSessionSnsTimelineByTarget = useCallback((target: SessionSnsTimelineTarget) => {
|
||||||
sessionSnsRankRequestTokenRef.current += 1
|
sessionSnsRankRequestTokenRef.current += 1
|
||||||
sessionSnsRankLoadingRef.current = false
|
sessionSnsRankLoadingRef.current = false
|
||||||
@@ -2255,22 +2271,21 @@ function ExportPage() {
|
|||||||
setSessionSnsTimelineHasMore(false)
|
setSessionSnsTimelineHasMore(false)
|
||||||
setSessionSnsTimelineLoadingMore(false)
|
setSessionSnsTimelineLoadingMore(false)
|
||||||
setSessionSnsTimelineLoading(false)
|
setSessionSnsTimelineLoading(false)
|
||||||
|
const hasKnownCount = Object.prototype.hasOwnProperty.call(snsUserPostCounts, target.username)
|
||||||
if (snsUserPostCountsStatus === 'ready') {
|
if (hasKnownCount) {
|
||||||
const count = Number(snsUserPostCounts[target.username] || 0)
|
const count = Number(snsUserPostCounts[target.username] || 0)
|
||||||
setSessionSnsTimelineTotalPosts(Number.isFinite(count) ? Math.max(0, Math.floor(count)) : 0)
|
const normalizedCount = Number.isFinite(count) ? Math.max(0, Math.floor(count)) : 0
|
||||||
|
setSessionSnsTimelineTotalPosts(normalizedCount)
|
||||||
setSessionSnsTimelineStatsLoading(false)
|
setSessionSnsTimelineStatsLoading(false)
|
||||||
setSessionSnsRankTotalPosts(Number.isFinite(count) ? Math.max(0, Math.floor(count)) : 0)
|
setSessionSnsRankTotalPosts(normalizedCount)
|
||||||
} else {
|
} else {
|
||||||
setSessionSnsTimelineTotalPosts(null)
|
setSessionSnsTimelineTotalPosts(null)
|
||||||
setSessionSnsTimelineStatsLoading(true)
|
setSessionSnsTimelineStatsLoading(snsUserPostCountsStatus === 'loading' || snsUserPostCountsStatus === 'idle')
|
||||||
setSessionSnsRankTotalPosts(null)
|
setSessionSnsRankTotalPosts(null)
|
||||||
}
|
}
|
||||||
|
|
||||||
void loadSessionSnsTimelinePosts(target, { reset: true })
|
|
||||||
void loadSnsUserPostCounts()
|
void loadSnsUserPostCounts()
|
||||||
}, [
|
}, [
|
||||||
loadSessionSnsTimelinePosts,
|
|
||||||
loadSnsUserPostCounts,
|
loadSnsUserPostCounts,
|
||||||
snsUserPostCounts,
|
snsUserPostCounts,
|
||||||
snsUserPostCountsStatus
|
snsUserPostCountsStatus
|
||||||
@@ -4973,11 +4988,7 @@ function ExportPage() {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!sessionSnsTimelineTarget) return
|
if (!sessionSnsTimelineTarget) return
|
||||||
if (snsUserPostCountsStatus === 'loading' || snsUserPostCountsStatus === 'idle') {
|
if (Object.prototype.hasOwnProperty.call(snsUserPostCounts, sessionSnsTimelineTarget.username)) {
|
||||||
setSessionSnsTimelineStatsLoading(true)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (snsUserPostCountsStatus === 'ready') {
|
|
||||||
const total = Number(snsUserPostCounts[sessionSnsTimelineTarget.username] || 0)
|
const total = Number(snsUserPostCounts[sessionSnsTimelineTarget.username] || 0)
|
||||||
const normalizedTotal = Number.isFinite(total) ? Math.max(0, Math.floor(total)) : 0
|
const normalizedTotal = Number.isFinite(total) ? Math.max(0, Math.floor(total)) : 0
|
||||||
setSessionSnsTimelineTotalPosts(normalizedTotal)
|
setSessionSnsTimelineTotalPosts(normalizedTotal)
|
||||||
@@ -4985,6 +4996,10 @@ function ExportPage() {
|
|||||||
setSessionSnsTimelineStatsLoading(false)
|
setSessionSnsTimelineStatsLoading(false)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if (snsUserPostCountsStatus === 'loading' || snsUserPostCountsStatus === 'idle') {
|
||||||
|
setSessionSnsTimelineStatsLoading(true)
|
||||||
|
return
|
||||||
|
}
|
||||||
setSessionSnsTimelineTotalPosts(null)
|
setSessionSnsTimelineTotalPosts(null)
|
||||||
setSessionSnsRankTotalPosts(null)
|
setSessionSnsRankTotalPosts(null)
|
||||||
setSessionSnsTimelineStatsLoading(false)
|
setSessionSnsTimelineStatsLoading(false)
|
||||||
@@ -6213,136 +6228,12 @@ function ExportPage() {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{sessionSnsTimelineTarget && (
|
<ContactSnsTimelineDialog
|
||||||
<div className="export-session-sns-overlay" onClick={closeSessionSnsTimeline}>
|
target={sessionSnsTimelineTarget}
|
||||||
<div
|
onClose={closeSessionSnsTimeline}
|
||||||
className="export-session-sns-dialog"
|
initialTotalPosts={sessionSnsTimelineInitialTotalPosts}
|
||||||
role="dialog"
|
initialTotalPostsLoading={sessionSnsTimelineInitialTotalPostsLoading}
|
||||||
aria-modal="true"
|
|
||||||
aria-label="联系人朋友圈"
|
|
||||||
onClick={(event) => event.stopPropagation()}
|
|
||||||
>
|
|
||||||
<div className="sns-dialog-header">
|
|
||||||
<div className="sns-dialog-header-main">
|
|
||||||
<div className="sns-dialog-avatar">
|
|
||||||
{sessionSnsTimelineTarget.avatarUrl ? (
|
|
||||||
<img src={sessionSnsTimelineTarget.avatarUrl} alt="" />
|
|
||||||
) : (
|
|
||||||
<span>{getAvatarLetter(sessionSnsTimelineTarget.displayName || sessionSnsTimelineTarget.username)}</span>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
<div className="sns-dialog-meta">
|
|
||||||
<h4>{sessionSnsTimelineTarget.displayName}</h4>
|
|
||||||
<div className="sns-dialog-username">@{sessionSnsTimelineTarget.username}</div>
|
|
||||||
<div className="sns-dialog-stats">{renderSessionSnsTimelineStats()}</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="sns-dialog-header-actions">
|
|
||||||
<div className="sns-dialog-rank-switch">
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
className={`sns-dialog-rank-btn ${sessionSnsRankMode === 'likes' ? 'active' : ''}`}
|
|
||||||
onClick={() => toggleSessionSnsRankMode('likes')}
|
|
||||||
>
|
|
||||||
点赞排行
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
className={`sns-dialog-rank-btn ${sessionSnsRankMode === 'comments' ? 'active' : ''}`}
|
|
||||||
onClick={() => toggleSessionSnsRankMode('comments')}
|
|
||||||
>
|
|
||||||
评论排行
|
|
||||||
</button>
|
|
||||||
{sessionSnsRankMode && (
|
|
||||||
<div
|
|
||||||
className="sns-dialog-rank-panel"
|
|
||||||
role="region"
|
|
||||||
aria-label={sessionSnsRankMode === 'likes' ? '点赞排行' : '评论排行'}
|
|
||||||
>
|
|
||||||
{sessionSnsRankLoading && (
|
|
||||||
<div className="sns-dialog-rank-loading">
|
|
||||||
<Loader2 size={12} className="spin" />
|
|
||||||
<span>
|
|
||||||
{sessionSnsRankTotalPosts !== null && sessionSnsRankTotalPosts > 0
|
|
||||||
? `统计中,已加载 ${sessionSnsRankLoadedPosts} / ${sessionSnsRankTotalPosts} 条`
|
|
||||||
: `统计中,已加载 ${sessionSnsRankLoadedPosts} 条`}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
{!sessionSnsRankLoading && sessionSnsRankError ? (
|
|
||||||
<div className="sns-dialog-rank-empty">{sessionSnsRankError}</div>
|
|
||||||
) : !sessionSnsRankLoading && sessionSnsActiveRankings.length === 0 ? (
|
|
||||||
<div className="sns-dialog-rank-empty">
|
|
||||||
{sessionSnsRankMode === 'likes' ? '暂无点赞数据' : '暂无评论数据'}
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
sessionSnsActiveRankings.slice(0, SNS_RANK_DISPLAY_LIMIT).map((item, index) => (
|
|
||||||
<div className="sns-dialog-rank-row" key={`${sessionSnsRankMode}-${item.name}`}>
|
|
||||||
<span className="sns-dialog-rank-index">{index + 1}</span>
|
|
||||||
<span className="sns-dialog-rank-name" title={item.name}>{item.name}</span>
|
|
||||||
<span className="sns-dialog-rank-count">
|
|
||||||
{item.count.toLocaleString('zh-CN')}
|
|
||||||
{sessionSnsRankMode === 'likes' ? '次' : '条'}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
))
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
<button className="close-btn" type="button" onClick={closeSessionSnsTimeline}>
|
|
||||||
<X size={16} />
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="sns-dialog-tip">
|
|
||||||
在微信桌面客户端中打开这个人的朋友圈浏览,可快速把其朋友圈同步到这里。若你在乎这个人,一定要试试~
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="sns-dialog-body">
|
|
||||||
{sessionSnsTimelinePosts.length > 0 && (
|
|
||||||
<div className="posts-list author-timeline-posts-list export-session-sns-posts-list">
|
|
||||||
{sessionSnsTimelinePosts.map((post) => (
|
|
||||||
<SnsPostItem
|
|
||||||
key={post.id}
|
|
||||||
post={post}
|
|
||||||
onPreview={(src, isVideo, liveVideoPath) => {
|
|
||||||
if (isVideo) {
|
|
||||||
void window.electronAPI.window.openVideoPlayerWindow(src)
|
|
||||||
} else {
|
|
||||||
void window.electronAPI.window.openImageViewerWindow(src, liveVideoPath || undefined)
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
onDebug={() => {}}
|
|
||||||
hideAuthorMeta
|
|
||||||
/>
|
/>
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{sessionSnsTimelineLoading && (
|
|
||||||
<div className="sns-dialog-status">正在加载该联系人的朋友圈...</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{!sessionSnsTimelineLoading && sessionSnsTimelinePosts.length === 0 && (
|
|
||||||
<div className="sns-dialog-status empty">该联系人暂无朋友圈</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{!sessionSnsTimelineLoading && sessionSnsTimelineHasMore && (
|
|
||||||
<button
|
|
||||||
className="sns-dialog-load-more"
|
|
||||||
type="button"
|
|
||||||
onClick={loadMoreSessionSnsTimeline}
|
|
||||||
disabled={sessionSnsTimelineLoadingMore}
|
|
||||||
>
|
|
||||||
{sessionSnsTimelineLoadingMore ? '正在加载...' : '加载更多'}
|
|
||||||
</button>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user