From 0599de372a66f54e89f5b78b3f58faaa9d4fa123 Mon Sep 17 00:00:00 2001 From: aits2026 Date: Fri, 6 Mar 2026 15:44:24 +0800 Subject: [PATCH] refactor(sns): move jump calendar to header --- src/components/Sns/SnsFilterPanel.tsx | 169 +------------------------- src/pages/SnsPage.scss | 53 -------- src/pages/SnsPage.tsx | 135 +++++++++++++++++++- 3 files changed, 136 insertions(+), 221 deletions(-) diff --git a/src/components/Sns/SnsFilterPanel.tsx b/src/components/Sns/SnsFilterPanel.tsx index d769360..b07e596 100644 --- a/src/components/Sns/SnsFilterPanel.tsx +++ b/src/components/Sns/SnsFilterPanel.tsx @@ -1,7 +1,6 @@ -import React, { useEffect, useRef, useState, useCallback } from 'react' -import { Search, Calendar, User, X, Loader2 } from 'lucide-react' +import React from 'react' +import { Search, User, X, Loader2 } from 'lucide-react' import { Avatar } from '../Avatar' -import JumpToDatePopover from '../JumpToDatePopover' interface Contact { username: string @@ -20,8 +19,6 @@ interface ContactsCountProgress { interface SnsFilterPanelProps { searchKeyword: string setSearchKeyword: (val: string) => void - jumpTargetDate?: Date - setJumpTargetDate: (date?: Date) => void totalFriendsLabel?: string selectedUsernames: string[] setSelectedUsernames: (val: string[]) => void @@ -35,8 +32,6 @@ interface SnsFilterPanelProps { export const SnsFilterPanel: React.FC = ({ searchKeyword, setSearchKeyword, - jumpTargetDate, - setJumpTargetDate, totalFriendsLabel, selectedUsernames, setSelectedUsernames, @@ -46,104 +41,6 @@ export const SnsFilterPanel: React.FC = ({ loading, contactsCountProgress }) => { - const [showJumpPopover, setShowJumpPopover] = useState(false) - const [jumpPopoverDate, setJumpPopoverDate] = useState(jumpTargetDate || new Date()) - const [jumpDateCounts, setJumpDateCounts] = useState>({}) - const [jumpDateMessageDates, setJumpDateMessageDates] = useState>(new Set()) - const [hasLoadedJumpDateCounts, setHasLoadedJumpDateCounts] = useState(false) - const [loadingJumpDateCounts, setLoadingJumpDateCounts] = useState(false) - const jumpCalendarWrapRef = useRef(null) - const jumpDateCountsCacheRef = useRef>>(new Map()) - const jumpDateRequestSeqRef = useRef(0) - - useEffect(() => { - if (!showJumpPopover) return - const handleClickOutside = (event: MouseEvent) => { - if (!jumpCalendarWrapRef.current) return - if (jumpCalendarWrapRef.current.contains(event.target as Node)) return - setShowJumpPopover(false) - } - document.addEventListener('mousedown', handleClickOutside) - return () => document.removeEventListener('mousedown', handleClickOutside) - }, [showJumpPopover]) - - useEffect(() => { - if (showJumpPopover) return - setJumpPopoverDate(jumpTargetDate || new Date()) - }, [jumpTargetDate, showJumpPopover]) - - const toMonthKey = useCallback((date: Date) => { - return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}` - }, []) - - const toDateKey = useCallback((timestampSeconds: number) => { - const date = new Date(timestampSeconds * 1000) - const year = date.getFullYear() - const month = String(date.getMonth() + 1).padStart(2, '0') - const day = String(date.getDate()).padStart(2, '0') - return `${year}-${month}-${day}` - }, []) - - const applyJumpDateCounts = useCallback((counts: Record) => { - setJumpDateCounts(counts) - setJumpDateMessageDates(new Set(Object.keys(counts))) - setHasLoadedJumpDateCounts(true) - }, []) - - const loadJumpDateCounts = useCallback(async (monthDate: Date) => { - const monthKey = toMonthKey(monthDate) - const cached = jumpDateCountsCacheRef.current.get(monthKey) - if (cached) { - applyJumpDateCounts(cached) - setLoadingJumpDateCounts(false) - return - } - - const requestSeq = ++jumpDateRequestSeqRef.current - setLoadingJumpDateCounts(true) - setHasLoadedJumpDateCounts(false) - - const year = monthDate.getFullYear() - const month = monthDate.getMonth() - const monthStart = new Date(year, month, 1, 0, 0, 0, 0) - const monthEnd = new Date(year, month + 1, 0, 23, 59, 59, 999) - const startTime = Math.floor(monthStart.getTime() / 1000) - const endTime = Math.floor(monthEnd.getTime() / 1000) - const pageSize = 200 - let offset = 0 - const counts: Record = {} - - try { - while (true) { - const result = await window.electronAPI.sns.getTimeline(pageSize, offset, [], '', startTime, endTime) - if (!result?.success || !Array.isArray(result.timeline) || result.timeline.length === 0) { - break - } - result.timeline.forEach((post) => { - const key = toDateKey(Number(post.createTime || 0)) - if (!key) return - counts[key] = (counts[key] || 0) + 1 - }) - if (result.timeline.length < pageSize) break - offset += pageSize - } - - if (requestSeq !== jumpDateRequestSeqRef.current) return - jumpDateCountsCacheRef.current.set(monthKey, counts) - applyJumpDateCounts(counts) - } catch (error) { - console.error('加载朋友圈按日条数失败:', error) - if (requestSeq !== jumpDateRequestSeqRef.current) return - setJumpDateCounts({}) - setJumpDateMessageDates(new Set()) - setHasLoadedJumpDateCounts(true) - } finally { - if (requestSeq === jumpDateRequestSeqRef.current) { - setLoadingJumpDateCounts(false) - } - } - }, [applyJumpDateCounts, toDateKey, toMonthKey]) - const filteredContacts = contacts.filter(c => (c.displayName || '').toLowerCase().includes(contactSearch.toLowerCase()) || c.username.toLowerCase().includes(contactSearch.toLowerCase()) @@ -153,7 +50,6 @@ export const SnsFilterPanel: React.FC = ({ if (selectedUsernames.includes(username)) { setSelectedUsernames(selectedUsernames.filter(u => u !== username)) } else { - setJumpTargetDate(undefined) // Reset date jump when selecting user setSelectedUsernames([...selectedUsernames, username]) } } @@ -161,7 +57,6 @@ export const SnsFilterPanel: React.FC = ({ const clearFilters = () => { setSearchKeyword('') setSelectedUsernames([]) - setJumpTargetDate(undefined) } const getEmptyStateText = () => { @@ -178,7 +73,7 @@ export const SnsFilterPanel: React.FC = ({