Files
altbin.dev/app/[id]/page.tsx
T

105 lines
3.1 KiB
TypeScript
Raw Normal View History

2025-08-20 14:14:33 +02:00
'use client';
import Prism from 'prismjs';
2025-08-20 16:41:27 +02:00
import { use, useCallback, useEffect, useState } from 'react';
2025-08-20 15:16:00 +02:00
2025-08-20 14:14:33 +02:00
import 'prismjs/plugins/line-numbers/prism-line-numbers.css';
import 'prismjs/plugins/line-numbers/prism-line-numbers.js';
2025-08-20 15:16:00 +02:00
import 'prismjs/themes/prism-tomorrow.css';
2025-08-20 14:14:33 +02:00
2025-08-20 16:41:27 +02:00
import AuthSection from '@/components/paste-form/AuthSection';
2025-08-20 15:16:00 +02:00
import CodeViewer from '@/components/paste/CodeViewer';
import LoadingPaste from '@/components/paste/LoadingPaste';
2025-08-20 17:42:45 +02:00
import PasswordForm from '@/components/paste/Password';
import PasteSidebar from '@/components/paste/Sidebar';
2025-08-20 16:41:27 +02:00
import { Paste } from '@/types/paste';
2025-08-20 16:05:24 +02:00
async function loadLanguage(lang: string) {
try {
await import(`prismjs/components/prism-${lang}.js`);
2025-08-20 16:41:27 +02:00
} catch {
2025-08-20 16:05:24 +02:00
console.warn(`[Prism] Language '${lang}' introuvable. Fallback -> plaintext`);
}
}
2025-08-20 15:16:00 +02:00
export default function PastePage({
params,
}: {
params: Promise<{ id: string }>;
}) {
const { id } = use(params);
2025-08-20 14:14:33 +02:00
2025-08-20 16:41:27 +02:00
const [paste, setPaste] = useState<Paste | null>(null);
2025-08-20 14:14:33 +02:00
const [error, setError] = useState('');
const [loading, setLoading] = useState(true);
const [language, setLanguage] = useState<string>('language-javascript');
2025-08-20 16:41:27 +02:00
const fetchPaste = useCallback(async (pwd?: string) => {
2025-08-20 14:14:33 +02:00
setLoading(true);
2025-08-20 15:16:00 +02:00
const res = await fetch(`/api/paste/${id}`, {
2025-08-20 14:14:33 +02:00
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ password: pwd || '' }),
});
if (res.status === 403) {
setError('Invalid password.');
setLoading(false);
return;
}
if (res.status === 404) {
setError('Paste not found or expired.');
setLoading(false);
return;
}
2025-08-20 16:41:27 +02:00
const data: Paste = await res.json();
2025-08-20 14:14:33 +02:00
setPaste(data);
2025-08-20 16:05:24 +02:00
const content = data.content.toLowerCase();
let detected = 'javascript';
if (content.includes('select ') || content.includes('insert into')) {
detected = 'sql';
} else if (content.includes('function') || content.includes('const')) {
detected = 'javascript';
} else if (content.includes('import ') || content.includes('export ')) {
detected = 'typescript';
} else if (content.includes('{') && content.includes('}')) {
detected = 'json';
} else if (content.includes('#include') || content.includes('int main')) {
detected = 'cpp';
} else if (content.includes('arduino')) {
detected = 'arduino';
2025-08-20 14:14:33 +02:00
} else {
2025-08-20 16:05:24 +02:00
detected = 'bash';
2025-08-20 14:14:33 +02:00
}
2025-08-20 16:05:24 +02:00
await loadLanguage(detected);
setLanguage(`language-${detected}`);
2025-08-20 14:14:33 +02:00
setLoading(false);
2025-08-20 16:41:27 +02:00
}, [id]);
2025-08-20 14:14:33 +02:00
useEffect(() => {
fetchPaste();
2025-08-20 16:41:27 +02:00
}, [fetchPaste]);
2025-08-20 14:14:33 +02:00
useEffect(() => {
2025-08-20 16:05:24 +02:00
if (paste?.content) Prism.highlightAll();
}, [paste, language]);
2025-08-20 14:14:33 +02:00
if (loading) return <LoadingPaste />;
if (error || (paste?.protected && !paste?.content)) {
2025-08-20 15:16:00 +02:00
return <PasswordForm error={error} onSubmit={(pwd) => fetchPaste(pwd)} />;
2025-08-20 14:14:33 +02:00
}
return (
<div className="relative w-screen h-screen bg-[#0e0f13] text-white flex overflow-hidden">
2025-08-20 16:41:27 +02:00
<CodeViewer paste={paste!} language={language} />
<PasteSidebar paste={paste!} id={id} />
2025-08-20 15:16:00 +02:00
<AuthSection />
2025-08-20 14:14:33 +02:00
</div>
);
2025-08-20 16:41:27 +02:00
}