import { Avatar, Button, Divider, Listbox, ListboxItem, ListboxSection, Modal, ModalBody, ModalContent, ModalFooter, ModalHeader, Switch, Textarea, Tooltip, useDisclosure, Link, } from '@nextui-org/react'; import { PlusIcon } from '@web/components/PlusIcon'; import { trpc } from '@web/utils/trpc'; import { useMemo, useState } from 'react'; import { useNavigate, useParams } from 'react-router-dom'; import { toast } from 'sonner'; import dayjs from 'dayjs'; import { serverOriginUrl } from '@web/utils/env'; import ArticleList from './list'; const Feeds = () => { const { id } = useParams(); const { isOpen, onOpen, onOpenChange, onClose } = useDisclosure(); const { refetch: refetchFeedList, data: feedData } = trpc.feed.list.useQuery( {}, { refetchOnWindowFocus: true, }, ); const navigate = useNavigate(); const queryUtils = trpc.useUtils(); const { mutateAsync: getMpInfo, isLoading: isGetMpInfoLoading } = trpc.platform.getMpInfo.useMutation({}); const { mutateAsync: updateMpInfo } = trpc.feed.edit.useMutation({}); const { mutateAsync: addFeed, isLoading: isAddFeedLoading } = trpc.feed.add.useMutation({}); const { mutateAsync: refreshMpArticles, isLoading: isGetArticlesLoading } = trpc.feed.refreshArticles.useMutation(); const { mutateAsync: getHistoryArticles, isLoading: isGetHistoryArticlesLoading, } = trpc.feed.getHistoryArticles.useMutation(); const { data: inProgressHistoryMp, refetch: refetchInProgressHistoryMp } = trpc.feed.getInProgressHistoryMp.useQuery(undefined, { refetchOnWindowFocus: true, refetchInterval: 10 * 1e3, refetchOnMount: true, refetchOnReconnect: true, }); const { data: isRefreshAllMpArticlesRunning } = trpc.feed.isRefreshAllMpArticlesRunning.useQuery(); const { mutateAsync: deleteFeed, isLoading: isDeleteFeedLoading } = trpc.feed.delete.useMutation({}); const [wxsLink, setWxsLink] = useState(''); const [currentMpId, setCurrentMpId] = useState(id || ''); const handleConfirm = async () => { console.log('wxsLink', wxsLink); // TODO show operation in progress const wxsLinks = wxsLink.split('\n').filter((link) => link.trim() !== ''); for (const link of wxsLinks) { console.log('add wxsLink', link); const res = await getMpInfo({ wxsLink: link }); if (res[0]) { const item = res[0]; await addFeed({ id: item.id, mpName: item.name, mpCover: item.cover, mpIntro: item.intro, updateTime: item.updateTime, status: 1, }); await refreshMpArticles({ mpId: item.id }); toast.success('添加成功', { description: `公众号 ${item.name}`, }); await queryUtils.article.list.reset(); } else { toast.error('添加失败', { description: '请检查链接是否正确' }); } } refetchFeedList(); setWxsLink(''); onClose(); }; const isActive = (key: string) => { return currentMpId === key; }; const currentMpInfo = useMemo(() => { return feedData?.items.find((item) => item.id === currentMpId); }, [currentMpId, feedData?.items]); const handleExportOpml = async (ev) => { ev.preventDefault(); ev.stopPropagation(); if (!feedData?.items?.length) { console.warn('没有订阅源'); return; } let opmlContent = ` WeWeRSS 所有订阅源 `; feedData?.items.forEach((sub) => { opmlContent += ` \n`; }); opmlContent += ` `; const blob = new Blob([opmlContent], { type: 'text/xml;charset=utf-8;' }); const link = document.createElement('a'); link.href = URL.createObjectURL(blob); link.download = 'WeWeRSS-All.opml'; document.body.appendChild(link); link.click(); document.body.removeChild(link); }; return ( <>
共{feedData?.items.length || 0}个订阅
{feedData?.items ? ( setCurrentMpId(key as string)} > } > 全部 {feedData?.items.map((item) => { return ( } > {item.mpName} ); }) || []} ) : ( '' )}

{currentMpInfo?.mpName || '全部'}

{currentMpInfo ? (
最后更新时间: {dayjs(currentMpInfo.syncTime * 1e3).format( 'YYYY-MM-DD HH:mm:ss', )}
{ ev.preventDefault(); ev.stopPropagation(); await refreshMpArticles({ mpId: currentMpInfo.id }); await refetchFeedList(); await queryUtils.article.list.reset(); }} > {isGetArticlesLoading ? '更新中...' : '立即更新'} {currentMpInfo.hasHistory === 1 && ( <> { ev.preventDefault(); ev.stopPropagation(); if (inProgressHistoryMp?.id === currentMpInfo.id) { await getHistoryArticles({ mpId: '', }); } else { await getHistoryArticles({ mpId: currentMpInfo.id, }); } await refetchInProgressHistoryMp(); }} > {inProgressHistoryMp?.id === currentMpInfo.id ? `停止获取历史文章` : `获取历史文章`} )}
{ await updateMpInfo({ id: currentMpInfo.id, data: { status: value ? 1 : 0, }, }); await refetchFeedList(); }} isSelected={currentMpInfo?.status === 1} >
{ ev.preventDefault(); ev.stopPropagation(); if (window.confirm('确定删除吗?')) { await deleteFeed(currentMpInfo.id); navigate('/feeds'); await refetchFeedList(); } }} > 删除 可添加.atom/.rss/.json格式输出, limit=20&page=1控制分页
} > RSS
) : (
{ ev.preventDefault(); ev.stopPropagation(); await refreshMpArticles({}); await refetchFeedList(); await queryUtils.article.list.reset(); }} > {isRefreshAllMpArticlesRunning || isGetArticlesLoading ? '更新中...' : '更新全部'} 导出OPML RSS
)}
{(onClose) => ( <> 添加公众号源