diff --git a/package.json b/package.json index 2596144..8d48462 100644 --- a/package.json +++ b/package.json @@ -9,19 +9,19 @@ "lint": "eslint" }, "dependencies": { + "next": "15.5.3", "react": "19.1.0", - "react-dom": "19.1.0", - "next": "15.5.3" + "react-dom": "19.1.0" }, "devDependencies": { - "typescript": "^5", + "@eslint/eslintrc": "^3", + "@tailwindcss/postcss": "^4", "@types/node": "^20", "@types/react": "^19", "@types/react-dom": "^19", - "@tailwindcss/postcss": "^4", - "tailwindcss": "^4", "eslint": "^9", "eslint-config-next": "15.5.3", - "@eslint/eslintrc": "^3" + "tailwindcss": "^4", + "typescript": "^5" } } diff --git a/src/app/page.tsx b/src/app/page.tsx index f09a532..36e928d 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,19 +1,24 @@ -function Link( - {href, label}: {href: string, label: string} +import Link from "next/link"; + +function MyLink( + { href, label }: { href: string, label: string } ) { return ( - {label} + {label} ) } export default function Home() { return ( -
-

学外语

- - -

srt-player: 一个基于srt字幕文件的逐句视频播放器,需要上传视频文件与字幕文件使用。

-

word-board: 一个板式单词记忆工具。

+
+
+ Learn Languages +
+ + + +
+
); } diff --git a/src/app/srt-player/components/VideoPlayer/SubtitleDisplay.tsx b/src/app/srt-player/components/VideoPlayer/SubtitleDisplay.tsx index f7f34e6..4becc9d 100644 --- a/src/app/srt-player/components/VideoPlayer/SubtitleDisplay.tsx +++ b/src/app/srt-player/components/VideoPlayer/SubtitleDisplay.tsx @@ -1,4 +1,4 @@ -import inspect from "@/utilities"; +import { inspect } from "@/utilities"; export default function SubtitleDisplay({ subtitle }: { subtitle: string }) { const words = subtitle.match(/\b[\w']+(?:-[\w']+)*\b/g) || []; diff --git a/src/app/word-board/WordBoard.tsx b/src/app/word-board/WordBoard.tsx index bfb4819..e4e62e0 100644 --- a/src/app/word-board/WordBoard.tsx +++ b/src/app/word-board/WordBoard.tsx @@ -1,21 +1,11 @@ 'use client'; +import { BOARD_WIDTH, TEXT_WIDTH, BOARD_HEIGHT, TEXT_SIZE } from "@/constants"; import Word from "@/interfaces/Word"; -import inspect from "@/utilities"; -import { Dispatch, SetStateAction } from "react"; - -function DraggableWord({ word }: { word: Word }) { - return (({word.word})) -} +import { Dispatch, SetStateAction, useEffect } from "react"; export default function WordBoard( - { words, setWords }: { + { words, setWords, selectWord }: { words: [ { word: string, @@ -23,20 +13,26 @@ export default function WordBoard( y: number } ], - setWords: Dispatch> + setWords: Dispatch>, + selectWord: (word: string) => void } ) { - const inspect = (word: string) => { - const goto = (url: string) => { - window.open(url, '_blank'); - } - return () => { - word = word.toLowerCase(); - goto(`https://www.youdao.com/result?word=${word}&lang=en`); - } + function DraggableWord({ word }: { word: Word }) { + return ({word.word})) + onClick={() => { selectWord(word.word); }}>{word.word}); } return ( -
+
{words.map( (v: { word: string, diff --git a/src/app/word-board/layout.tsx b/src/app/word-board/layout.tsx index 76225f4..e824878 100644 --- a/src/app/word-board/layout.tsx +++ b/src/app/word-board/layout.tsx @@ -25,6 +25,9 @@ export default function RootLayout({ return ( {children} diff --git a/src/app/word-board/page.tsx b/src/app/word-board/page.tsx index 95caeaa..2d89fe1 100644 --- a/src/app/word-board/page.tsx +++ b/src/app/word-board/page.tsx @@ -1,8 +1,10 @@ 'use client'; import WordBoard from "@/app/word-board/WordBoard"; import Button from "../../components/Button"; -import { useRef, useState } from "react"; +import { KeyboardEvent, useRef, useState } from "react"; import Word from "@/interfaces/Word"; +import { BOARD_WIDTH, TEXT_WIDTH, BOARD_HEIGHT, TEXT_SIZE } from "@/constants"; +import { inspect } from "@/utilities"; export default function Home() { const inputRef = useRef(null); @@ -26,17 +28,52 @@ export default function Home() { })) ); const generateNewWord = (word: string) => { - return { - word: word, - x: Math.random(), - y: Math.random() - } as Word; + const isOK = (w: Word) => { + if (words.length === 0) return true; + const tf = (ww: Word) => ({ + word: ww.word, + x: Math.floor(ww.x * (BOARD_WIDTH - TEXT_WIDTH * ww.word.length)), + y: Math.floor(ww.y * (BOARD_HEIGHT - TEXT_SIZE)) + } as Word); + const tfd_words = words.map(tf); + const tfd_w = tf(w); + for (const www of tfd_words) { + const p1 = { + x: (www.x + www.x + TEXT_WIDTH * www.word.length) / 2, + y: (www.y + www.y + TEXT_SIZE) / 2 + } + const p2 = { + x: (tfd_w.x + tfd_w.x + TEXT_WIDTH * tfd_w.word.length) / 2, + y: (tfd_w.y + tfd_w.y + TEXT_SIZE) / 2 + } + if ( + Math.abs(p1.x - p2.x) < (TEXT_WIDTH * (www.word.length + tfd_w.word.length)) / 2 && + Math.abs(p1.y - p2.y) < TEXT_SIZE + ) { + return false; + } + } + return true; + } + let new_word; + let count = 0; + do { + new_word = { + word: word, + x: Math.random(), + y: Math.random() + }; + if (++count > 1000) return null; + } while (!isOK(new_word)); + return new_word as Word; } const insertWord = () => { if (!inputRef.current) return; const word = inputRef.current.value.trim(); if (word === '') return; - setWords([...words, generateNewWord(word)]); + const new_word = generateNewWord(word); + if (!new_word) return; + setWords([...words, new_word]); inputRef.current.value = ''; } const deleteWord = () => { @@ -72,16 +109,47 @@ export default function Home() { reader.readAsText(files[0]); } } + const deleteAll = () => { + setWords([] as Array); + } + const handleKeyDown = (e: KeyboardEvent) => { + // e.preventDefault(); + if (e.key === 'Enter') { + insertWord(); + } + } + const selectWord = (word: string) => { + if (!inputRef.current) return; + inputRef.current.value = word; + } + const searchWord = () => { + if (!inputRef.current) return; + const word = inputRef.current.value.trim(); + if (word === '') return; + inspect(word)(); + inputRef.current.value = ''; + } + // const readWordAloud = () => { + // playFromUrl('https://fanyi.baidu.com/gettts?lan=uk&text=disclose&spd=3') + // return; + // if (!inputRef.current) return; + // const word = inputRef.current.value.trim(); + // if (word === '') return; + // inspect(word)(); + // inputRef.current.value = ''; + // } return ( -
- +
+
- + + - + + {/* */}
diff --git a/src/utilities.ts b/src/utilities.ts index 1110b76..8cef614 100644 --- a/src/utilities.ts +++ b/src/utilities.ts @@ -1,4 +1,4 @@ -export default function inspect(word: string) { +export function inspect(word: string) { const goto = (url: string) => { window.open(url, '_blank'); }