SnowCat 雪猫底层全源码:NapCat 4.18.28 底座 + SnowLuma 能力移植 + V8 通道适配 9.9.37

26 包 monorepo(TS 全源码):
- snowcat-core: NT 内核 API 封装 + listener(含 9.9.37 六回调适配)+ Packet 发包
- snowcat-onebot: OneBot v11 全动作 + MCP Streamable HTTP 适配器 + 稳定线
- snowcat-webui-frontend/backend: 雪猫控制台(React+HeroUI)
- snowcat-shell: 单文件 bundle 出口(vite inlineDynamicImports)
- snowcat-native: napi2native / MoeHoo / ffmpeg / pty 运行时
- 56 项 SnowLuma 独门动作移植(qzone 全家桶/群相册/装扮/闪照/收藏)
- 工具件: 解包器/启动器/便携制作器/doctor

GitHub 关联已全量指向 DandanLLab/SnowCatQQ
This commit is contained in:
天天的鸟蛋蛋 committed 2026-11-12 06:27:36 +08:00
commit b9655a5ab1
1048 files changed
+130851

No files matched your search

@@ -0,0 +1,283 @@
import { useState, useEffect } from 'react';
import { Modal, ModalContent, ModalHeader, ModalBody, ModalFooter } from '@heroui/modal';
import { Button } from '@heroui/button';
import { Chip } from '@heroui/chip';
import { Tooltip } from '@heroui/tooltip';
import { IoMdFlash, IoMdCheckmark, IoMdClose } from 'react-icons/io';
import clsx from 'clsx';
import MirrorManager, { MirrorTestResult } from '@/controllers/mirror_manager';
interface MirrorSelectorModalProps {
isOpen: boolean;
onClose: () => void;
onSelect: (mirror: string | undefined) => void;
currentMirror?: string;
type?: 'file' | 'raw';
}
export default function MirrorSelectorModal ({
isOpen,
onClose,
onSelect,
currentMirror,
type = 'file',
}: MirrorSelectorModalProps) {
const [mirrors, setMirrors] = useState<string[]>([]);
const [selectedMirror, setSelectedMirror] = useState<string>(currentMirror || 'auto');
const [testResults, setTestResults] = useState<Map<string, MirrorTestResult>>(new Map());
const [isTesting, setIsTesting] = useState(false);
const [testProgress, setTestProgress] = useState(0);
const [testMessage, setTestMessage] = useState('');
const [fastestMirror, setFastestMirror] = useState<string | null>(null);
// 加载镜像列表
useEffect(() => {
if (isOpen) {
loadMirrors();
}
}, [isOpen]);
const loadMirrors = async () => {
try {
const data = await MirrorManager.getMirrorList();
const mirrorList = type === 'raw' ? data.rawMirrors : data.fileMirrors;
setMirrors(mirrorList);
if (data.customMirror) {
setSelectedMirror(data.customMirror);
}
} catch (e) {
console.error('Failed to load mirrors:', e);
}
};
const startSpeedTest = () => {
setIsTesting(true);
setTestProgress(0);
setTestResults(new Map());
setFastestMirror(null);
setTestMessage('准备测速...');
MirrorManager.testMirrorsSSE(type, {
onStart: (data) => {
setTestMessage(data.message);
},
onTesting: (data) => {
setTestProgress((data.index / data.total) * 100);
setTestMessage(data.message);
},
onResult: (data) => {
setTestResults((prev) => {
const newMap = new Map(prev);
newMap.set(data.result.mirror, data.result);
return newMap;
});
setTestProgress(((data.index + 1) / data.total) * 100);
},
onComplete: (data) => {
setIsTesting(false);
setTestProgress(100);
setTestMessage(data.message);
if (data.fastest) {
setFastestMirror(data.fastest.mirror);
}
},
onError: (error) => {
setIsTesting(false);
setTestMessage(`测速失败: ${error}`);
},
});
};
const handleConfirm = () => {
const mirror = selectedMirror === 'auto' ? undefined : selectedMirror;
onSelect(mirror);
onClose();
};
return (
<Modal
isOpen={isOpen}
onClose={onClose}
size='2xl'
scrollBehavior='inside'
classNames={{
backdrop: 'z-[200]',
wrapper: 'z-[200]',
}}
>
<ModalContent className='rounded-3xl border border-white/70 dark:border-white/10 bg-white/92 dark:bg-zinc-900/92 backdrop-blur-2xl shadow-2xl shadow-primary-900/15'>
<ModalHeader className='flex flex-col gap-1'>
<div className='flex items-center justify-between pr-8'>
<span>选择镜像源</span>
<Button
size='sm'
color='primary'
variant='flat'
startContent={!isTesting && <IoMdFlash />}
onPress={startSpeedTest}
isLoading={isTesting}
>
{isTesting ? '测速中...' : '一键测速'}
</Button>
</div>
{isTesting && (
<div className='mt-2'>
<div className='w-full bg-default-200 rounded-full h-2'>
<div
className='bg-primary h-2 rounded-full transition-all duration-300'
style={{ width: `${testProgress}%` }}
/>
</div>
<p className='text-xs text-default-500 mt-1'>{testMessage}</p>
</div>
)}
</ModalHeader>
<ModalBody>
<div className='flex flex-col gap-2'>
{/* 自动选择选项 */}
<MirrorOption
value='auto'
label='自动选择'
description='系统自动选择最快的镜像源'
isSelected={selectedMirror === 'auto'}
onSelect={() => setSelectedMirror('auto')}
badge={<Chip size='sm' color='primary' variant='flat'>推荐</Chip>}
/>
{/* 原始 GitHub */}
<MirrorOption
value='https://github.com'
label='GitHub 原始'
description='直连 GitHub(可能较慢)'
isSelected={selectedMirror === 'https://github.com'}
onSelect={() => setSelectedMirror('https://github.com')}
testResult={testResults.get('https://github.com (原始)')}
isFastest={fastestMirror === 'https://github.com (原始)'}
/>
{/* 镜像列表 */}
{mirrors.map((mirror) => {
if (!mirror) return null;
const result = testResults.get(mirror);
const isFastest = fastestMirror === mirror;
let hostname = mirror;
try {
hostname = new URL(mirror).hostname;
} catch { }
return (
<MirrorOption
key={mirror}
value={mirror}
label={hostname}
description={mirror}
isSelected={selectedMirror === mirror}
onSelect={() => setSelectedMirror(mirror)}
testResult={result}
isFastest={isFastest}
/>
);
})}
</div>
</ModalBody>
<ModalFooter>
<Button variant='light' onPress={onClose}>
取消
</Button>
<Button color='primary' onPress={handleConfirm}>
确认选择
</Button>
</ModalFooter>
</ModalContent>
</Modal>
);
}
// 镜像选项组件
interface MirrorOptionProps {
value: string;
label: string;
description: string;
isSelected: boolean;
onSelect: () => void;
testResult?: MirrorTestResult;
isFastest?: boolean;
badge?: React.ReactNode;
}
function MirrorOption ({
label,
description,
isSelected,
onSelect,
testResult,
isFastest,
badge,
}: MirrorOptionProps) {
return (
<div
className={clsx(
'flex items-center justify-between p-3 rounded-lg cursor-pointer transition-all',
'bg-content1 hover:bg-content2 border-2',
isSelected ? 'border-primary' : 'border-transparent',
isFastest && 'ring-2 ring-success'
)}
onClick={onSelect}
>
<div className='flex-1 min-w-0'>
<p className='font-medium'>{label}</p>
<p className='text-xs text-default-500 truncate'>{description}</p>
</div>
<div className='flex items-center gap-2 ml-2'>
{badge}
{isFastest && !badge && (
<Chip size='sm' color='success' variant='flat'>最快</Chip>
)}
{testResult && <MirrorStatus result={testResult} />}
</div>
</div>
);
}
// 镜像状态显示组件
function MirrorStatus ({ result }: { result: MirrorTestResult; }) {
const formatLatency = (latency: number) => {
if (latency >= 5000) return '>5s';
if (latency >= 1000) return `${(latency / 1000).toFixed(1)}s`;
return `${latency}ms`;
};
if (!result.success) {
return (
<Tooltip content={result.error || '连接失败'}>
<Chip
size='sm'
color='danger'
variant='flat'
startContent={<IoMdClose size={14} />}
>
失败
</Chip>
</Tooltip>
);
}
const getColor = (): 'success' | 'warning' | 'danger' => {
if (result.latency < 300) return 'success';
if (result.latency < 1000) return 'warning';
return 'danger';
};
return (
<Chip
size='sm'
color={getColor()}
variant='flat'
startContent={<IoMdCheckmark size={14} />}
>
{formatLatency(result.latency)}
</Chip>
);
}