From cb1b56f5a0eddbf77446f415f2beda57c8305f85 Mon Sep 17 00:00:00 2001 From: polwex Date: Sun, 23 Nov 2025 01:12:53 +0700 Subject: wut --- packages/prosody-ui/src/components/Sentence.tsx | 57 +++++ packages/prosody-ui/src/components/Word.tsx | 119 +++++++++++ packages/prosody-ui/src/components/sentence.css | 272 ++++++++++++++++++++++++ packages/prosody-ui/src/components/word.css | 0 4 files changed, 448 insertions(+) create mode 100644 packages/prosody-ui/src/components/Sentence.tsx create mode 100644 packages/prosody-ui/src/components/Word.tsx create mode 100644 packages/prosody-ui/src/components/sentence.css create mode 100644 packages/prosody-ui/src/components/word.css (limited to 'packages/prosody-ui/src/components') diff --git a/packages/prosody-ui/src/components/Sentence.tsx b/packages/prosody-ui/src/components/Sentence.tsx new file mode 100644 index 0000000..33144ac --- /dev/null +++ b/packages/prosody-ui/src/components/Sentence.tsx @@ -0,0 +1,57 @@ +import React from "react"; +import { notRandomFromArray } from "sortug"; +import "./sentence.css"; + +export function ColoredText({ + frags, + fn, + lang, +}: { + frags: string[]; + fn?: (s: string) => void; + lang?: string; +}) { + return ( + <> + {frags.map((s, i) => { + const prev = frags[i - 1]; + const prevC = prev ? notRandomFromArray(prev, colors) : "lol"; + const color = notRandomFromArray(s, colors); + const opacity = prev && prevC === color ? 0.8 : 1; + const style = { color, opacity }; + console.log({ style }); + return ; + })} + + ); +} + +export function CTInner({ + s, + style, + fn, + lang, +}: { + s: string; + style: any; + fn?: (s: string) => void; + lang?: string; +}) { + function handleClick(e: React.MouseEvent) { + console.log(!!fn, "fn"); + if (fn) fn(e.currentTarget.innerText.trim()); + } + return ( + + {s} + + ); +} +export const colors = [ + "#8c2c2c", + "#000000", + "#ffd400", + "#1513a0", + "#7e7e7e", + "1eb52d", +]; diff --git a/packages/prosody-ui/src/components/Word.tsx b/packages/prosody-ui/src/components/Word.tsx new file mode 100644 index 0000000..82939ce --- /dev/null +++ b/packages/prosody-ui/src/components/Word.tsx @@ -0,0 +1,119 @@ +import React, { useCallback, useEffect, useState } from "react"; +import spinner from "../assets/icons/spinner.svg"; +import likeIcon from "../assets/icons/heart.svg"; +import commentsIcon from "../assets/icons/quote.svg"; +import shareIcon from "../assets/icons/share.svg"; +import fontIcon from "../assets/icons/font.svg"; +import bookmarkIcon from "../assets/icons/bookmark.svg"; +import speakerIcon from "../assets/icons/speaker.svg"; +import type { AnalyzeRes, Meaning } from "../logic/types"; +import { ColoredText } from "./Sentence.tsx"; +import { P, Span, useSpeechSynthesis } from "../hooks/useLang.tsx"; + +function Word({ data, lang }: { data: AnalyzeRes; lang: string }) { + async function load() { + // const wiki = await fetchWiki(data.word); + // console.log(wiki, "wiki res"); + // if ("ok" in wiki) setM(wiki.ok.meanings); + // else setError(wiki.error); + // setLoading(false); + } + useEffect(() => { + load(); + }, []); + const [error, setError] = useState(""); + const [loading, setLoading] = useState(true); + const [meanings, setM] = useState([]); + const [font, setFont] = useState(0); + + function changeFont() { + if (font === 6) setFont(0); + else setFont(font + 1); + } + const { voices, speaking, speak, stop } = useSpeechSynthesis(); + function playAudio() { + console.log({ voices, speaking }); + console.log("word", data.word); + speak(data.word); + } + + async function saveW() {} + + return ( +
+ + +
+ +
+
+

{`/${data.ipa.replace(/\s/g, "")}/`}

+ +
+
+ {loading ? ( + + ) : ( + meanings.map((m) => ( +
+
+ {m.pos} +
+
    + {m.meaning.map((t, i) => ( +
  1. +

    {t}

    +
  2. + ))} +
+
+ )) + )} + {error &&
{error}
} +
+
+ ); +} + +export default Word; + +// function FloatingButtons({ +// tweet, +// avatar, +// changeFont, +// }: { +// tweet: Tweet; +// avatar: string; +// changeFont: any; +// }) { +// const { apiKeys, prompts, setModal } = useGlobalState(); +// function openUser() {} +// function openComments() {} +// function openShare() {} +// async function doLike() { +// const key = apiKeys.openai; +// // TODO hide button if key not set +// console.log(tweet.text, "whole text"); +// console.log(tweet.media, "media"); +// if (tweet.media[0] && !tweet.media[0].isVideo) { +// const res = await vision(tweet.media[0].url, "", key); +// console.log(res, "vision res"); +// } +// // const res = await translate(tweet.text, prompts.translate,key); +// // if ("ok" in res) +// // setModal() +// } +// async function doBookmark() {} +// return ( +//
+//
+// +//
+// +// +// +// +// +//
+// ); +// } diff --git a/packages/prosody-ui/src/components/sentence.css b/packages/prosody-ui/src/components/sentence.css new file mode 100644 index 0000000..0bd0a49 --- /dev/null +++ b/packages/prosody-ui/src/components/sentence.css @@ -0,0 +1,272 @@ +#root { + max-width: 1280px; + margin: 0 auto; + padding: 2rem; + text-align: center; +} + +#root>.spinner { + width: 100px; + height: 100px; +} + +#entry>.spinner { + width: 80px; + height: 80px; +} + + + +.logo { + height: 6em; + padding: 1.5em; + will-change: filter; + transition: filter 300ms; +} + +.logo:hover { + filter: drop-shadow(0 0 2em #646cffaa); +} + +.logo.react:hover { + filter: drop-shadow(0 0 2em #61dafbaa); +} + +@keyframes logo-spin { + from { + transform: rotate(0deg); + } + + to { + transform: rotate(360deg); + } +} + +@media (prefers-reduced-motion: no-preference) { + a:nth-of-type(2) .logo { + animation: logo-spin infinite 20s linear; + } +} + +.card { + padding: 2em; +} + +.read-the-docs { + color: #888; +} + +#cookies { + & .active { + background-color: var(--huang); + } + + & input { + margin-left: 1rem; + width: 100%; + } + + & textarea { + width: 100%; + height: 500px; + resize: none; + outline: none; + } +} + +#entry { + width: 100%; + height: 100%; + position: relative; + padding: 1rem; + /* prov */ + border: 2px solid black; + + & div[lang="th"] { + + & .tw-text, + & .tw-hashtag { + font-size: 3rem; + } + } + + & .text-wrapper { + display: block; + margin: 0.5rem 0; + /* overflow: hidden; */ + } + + & .word { + display: inline-block; + transition: transform 0.3s ease; + } + + & .word:hover { + transform: scale(1.4); + background-color: white; + } + + & #tw-media { + max-width: 100%; + + & img, + & video { + max-width: 100%; + } + } +} + +#inner { + height: 100%; + max-height: 100%; + overflow-y: auto; +} + +#entry-icons { + position: absolute; + bottom: 5%; + right: 5%; + width: 50px; + display: flex; + flex-direction: column; + gap: 1rem; + + & .avatar { + border: 2px solid black; + border-radius: 50%; + width: 50px; + height: 50px; + overflow: hidden; + box-shadow: 0 0 10px rgba(0, 0, 0, 0.2); + + & img { + width: 100%; + height: 100%; + object-fit: cover; + } + } +} + +#word-modal { + position: relative; + + & .font-icon { + position: absolute; + top: 0; + left: 0; + width: 32px; + height: 32px; + } + + & .save-icon { + position: absolute; + top: 0; + right: 0; + width: 32px; + height: 32px; + } + + & .original { + font-size: 4rem; + margin-bottom: 1rem; + } + + & .syllable {} + + & .IPA { + font-size: 1.6rem; + line-height: 1.6rem; + & img{ + width: 50px; + margin-left: 1rem; + } + } + + & .meanings { + + & .spinner { + width: 80px; + height: 80px; + } + + & .meaning { + margin: 1rem auto; + } + + & .pos { + font-size: 1.2rem; + margin-bottom: 0.3rem; + text-align: left; + } + + & ol { + word-wrap: normal; + margin: auto; + text-align: left; + } + } +} + +img { + width: 100%; + height: 100%; + object-fit: cover; +} +.flex1{ + width: 100%; + display: flex; + gap: 1rem; + align-items: center; +} +.flex-center{ + justify-content: center; +} + +/* p { */ +/* position: absolute; */ +/* top: 50%; */ +/* left: 50%; */ +/* transform: translate(-50%, -50%); */ +/* color: white; */ +/* background-color: rgba(0, 0, 0, 0.5); */ +/* padding: 10px; */ +/* border-radius: 5px; */ +/* } */ +#modal-bg{ + height: 100vh; + width: 100vw; + background-color: rgb(0, 0, 0, 0.9); + position: fixed; + top: 0; + left: 0; + z-index: 100; +} + +#modal-fg { + position: fixed; + top: 50%; + left: 50%; + width: 80%; + z-index: 101; + transform: translate(-50%, -50%); + /* background-color: var(--background-color); */ + background-color: lightgrey; + font-size: 1.2rem; + padding: 1rem; + max-height: 80%; + overflow-y: scroll; +} + + +.text-ipa{ + font-size: 1.5rem; +} +.text-thai{ + font-size: 1.5rem; +} + + +/* // new */ +.word.cp{ + margin: 0 0.5ch; +} diff --git a/packages/prosody-ui/src/components/word.css b/packages/prosody-ui/src/components/word.css new file mode 100644 index 0000000..e69de29 -- cgit v1.2.3