"use client"; import { useEffect, useRef, useState } from "react"; export default function Terminal() { const [isReady, setIsReady] = useState(false); const [currentIndex, setCurrentLineIndex] = useState(0); const element = useRef(null); useEffect(() => { if (!element.current) { return; } const observer = new IntersectionObserver( (entries) => { entries.forEach((entry) => { if (entry.isIntersecting) { setIsReady(true); observer.disconnect(); } }); }, { threshold: 1 }, ); observer.observe(element.current); return () => observer.disconnect(); }, [currentIndex]); function onLineCompleted() { if (currentIndex < lines.length - 1) { setCurrentLineIndex((prev) => prev + 1); } } return (
{lines.slice(0, currentIndex).map((line, index) => ( ))} {isReady ? : null}
); } function NormalLine(props: { text: string }) { return (
{props.text}
); } function LastLine(props: { text: string; onCompleted?: () => void }) { const [timeText, setTimeText] = useState(""); const [textToShow, setTextToShow] = useState(""); useEffect(() => { let interval: NodeJS.Timeout | undefined = undefined; setTimeout(() => { interval = setInterval(() => { setTextToShow((prev) => { if (prev.length < props.text.length) { return prev + props.text[prev.length]; } else { clearInterval(interval); return prev; } }); }, 50); }, 300); return () => clearInterval(interval); }, [props.text]); useEffect(() => { if (textToShow.length === props.text.length) { setTimeout(() => { props.onCompleted?.(); }, 300); } }, [props, textToShow]); useEffect(() => { setTimeText(dateToString(new Date())); const interval = setInterval(() => { setTimeText(dateToString(new Date())); }, 1000); return () => clearInterval(interval); }, []); return (
╭─  squid{" "} ~/Documents/blog
 {timeText}
╰─ {textToShow}
); } function Cursor() { const [isVisible, setIsVisible] = useState(true); useEffect(() => { const interval = setInterval(() => { setIsVisible((prev) => !prev); setTimeout(() => { setIsVisible((prev) => !prev); }, 500); }, 1000); return () => clearInterval(interval); }, []); return ; } function dateToString(date: Date) { return date.toLocaleString("en-US", { hour: "2-digit", minute: "2-digit", second: "2-digit", hour12: false }); } const lines = [ "大家好,我是 Squid 魷魚", "身為一位軟體工程師", "平常最喜歡埋首於程式碼的世界", "鑽研各種新奇有趣的技術", "在這裡", "我會分享我的技術筆記、開發心得", "還有各式各樣實用工具的評測與介紹", "一起探索數位世界的無限可能吧!", ];