From 8826032546ea6a80268bd4729736f139d68b6273 Mon Sep 17 00:00:00 2001 From: Michael DeMarco Date: Sun, 31 Mar 2024 14:58:22 -0700 Subject: [PATCH] feat: enable rhyme copy-paste; jsonify errors --- client/src/components/Footer.tsx | 4 +- client/src/components/PoetryVisualizer.tsx | 50 +++++++++++++++++++++- client/src/components/RhymeVisualizer.tsx | 50 +++++++++++++++++++++- client/src/util/generateWords.ts | 34 ++++++++------- client/src/util/rhymes.tsx | 2 +- client/src/util/rtf.ts | 44 +++++++++++++++++++ server/main.py | 21 +++++++++ 7 files changed, 184 insertions(+), 21 deletions(-) create mode 100644 client/src/util/rtf.ts diff --git a/client/src/components/Footer.tsx b/client/src/components/Footer.tsx index 2879ba9..ea824fd 100644 --- a/client/src/components/Footer.tsx +++ b/client/src/components/Footer.tsx @@ -1,8 +1,10 @@ const Footer = () => { + const year = new Date().getFullYear(); + return (

Deployed on Railway. 🚂

-

© 2023 RapViz

+

© {year} RapViz

); }; diff --git a/client/src/components/PoetryVisualizer.tsx b/client/src/components/PoetryVisualizer.tsx index 99398a9..64b0acf 100644 --- a/client/src/components/PoetryVisualizer.tsx +++ b/client/src/components/PoetryVisualizer.tsx @@ -1,13 +1,16 @@ -import { useState, useMemo } from "react"; +import { useState, useMemo, useRef } from "react"; import { serverEndpoint } from "../config"; import { buildRhymeOutput } from "../util/rhymes"; +import { convertHtmlToRtf } from "../util/rtf"; const PoetryVisualizer = ({ onBack }: any) => { const [lyrics, setLyrics] = useState(""); const [rhymes, setRhymes] = useState([]); const [isLoading, setIsLoading] = useState(false); + const contentRef = useRef(null); + const handleLyrics = (event: any) => { setLyrics(event.target.value); }; @@ -42,6 +45,43 @@ const PoetryVisualizer = ({ onBack }: any) => { } }; + const handleRichCopy = async () => { + if (!contentRef.current) { + return; + } + + const htmlContent = contentRef.current.innerHTML; + + // Use the Clipboard API if available; else, download an RTF file + if (navigator.clipboard && navigator.clipboard.write) { + const blob = new Blob([htmlContent], { type: 'text/html' }); + const item = new ClipboardItem({ 'text/html': blob }); + + try { + await navigator.clipboard.write([item]); + console.log("Rich text copied to clipboard.") + } catch (error) { + console.error("Failed to copy rich text: ", error); + } + } else { + const rtfContent = convertHtmlToRtf(htmlContent); + + const blob = new Blob([rtfContent], { type: 'application/rtf' }); + + const filename = "lyrics.rtf"; + + const anchor = document.createElement('a'); + anchor.href = URL.createObjectURL(blob); + anchor.download = filename; + + document.body.appendChild(anchor); + anchor.click(); + document.body.removeChild(anchor); + + URL.revokeObjectURL(anchor.href); + } + } + const rhymeOutput = useMemo( () => buildRhymeOutput(lyrics, rhymes), [lyrics, rhymes] @@ -60,13 +100,19 @@ const PoetryVisualizer = ({ onBack }: any) => { > ANALYZE + {isLoading &&

(one sec...)

}