UNPKG

lrc-maker

Version:

歌词滚动姬|可能是你所能见到的最好用的歌词制作工具

121 lines 6.42 kB
import { stringify } from "../lrc-parser.js"; import { createFile } from "../utils/gistapi.js"; import { lrcFileName } from "../utils/lrc-file-name.js"; import { appContext } from "./app.context.js"; import { CloudUploadSVG, CopySVG, DownloadSVG, OpenFileSVG, UtilitySVG } from "./svg.js"; import { toastPubSub } from "./toast.js"; const { useCallback, useContext, useEffect, useMemo, useRef, useState } = React; const disableCheck = { autoCapitalize: "none", autoComplete: "off", autoCorrect: "off", spellCheck: false, }; const useDefaultValue = (defaultValue, ref) => { const or = (a, b) => a !== null && a !== void 0 ? a : b; const $ref = or(ref, useRef(null)); useEffect(() => { if ($ref.current) { $ref.current.value = defaultValue; } }, [defaultValue, $ref]); return { ref: $ref, defaultValue }; }; export const Eidtor = ({ lrcState, lrcDispatch }) => { const { prefState, lang, trimOptions } = useContext(appContext); const parse = useCallback((ev) => { lrcDispatch({ type: 0, payload: { text: ev.target.value, options: trimOptions }, }); }, [lrcDispatch, trimOptions]); const setInfo = useCallback((ev) => { const { name, value } = ev.target; lrcDispatch({ type: 4, payload: { name, value }, }); }, [lrcDispatch]); const text = stringify(lrcState, prefState); const details = useRef(null); const onDetailsToggle = useCallback(() => { sessionStorage.setItem("editor-details-open", details.current.open.toString()); }, []); const detailsOpened = useMemo(() => { return sessionStorage.getItem("editor-details-open") !== "false"; }, []); const textarea = useRef(null); const [href, setHref] = useState(undefined); const onDownloadClick = useCallback(() => { setHref((url) => { if (url) { URL.revokeObjectURL(url); } return URL.createObjectURL(new Blob([textarea.current.value], { type: "text/plain;charset=UTF-8", })); }); }, []); const onTextFileUpload = useCallback((ev) => { if (ev.target.files === null || ev.target.files.length === 0) { return; } const fileReader = new FileReader(); fileReader.addEventListener("load", () => { lrcDispatch({ type: 0, payload: { text: fileReader.result, options: trimOptions }, }); }); fileReader.readAsText(ev.target.files[0], "UTF-8"); }, [lrcDispatch, trimOptions]); const onCopyClick = useCallback(() => { var _a; (_a = textarea.current) === null || _a === void 0 ? void 0 : _a.select(); document.execCommand("copy"); }, []); const downloadName = useMemo(() => lrcFileName(lrcState.info), [lrcState.info]); const canSaveToGist = useMemo(() => { return localStorage.getItem("lrc-maker-oauth-token") !== null && localStorage.getItem("lrc-maker-gist-id") !== null; }, []); const onGistSave = useCallback(() => { setTimeout(() => { const name = prompt(lang.editor.saveFileName, downloadName); if (name) { createFile(name, textarea.current.value).catch((error) => { toastPubSub.pub({ type: "warning", text: error.message, }); }); } }, 500); }, [downloadName, lang]); return (React.createElement("div", { className: "app-editor" }, React.createElement("details", { ref: details, open: detailsOpened, onToggle: onDetailsToggle }, React.createElement("summary", null, lang.editor.metaInfo), React.createElement("section", { className: "app-editor-infobox", onBlur: setInfo }, React.createElement("label", { htmlFor: "info-ti" }, "[ti:"), React.createElement("input", Object.assign({ id: "info-ti", name: "ti", placeholder: lang.editor.title }, disableCheck, useDefaultValue(lrcState.info.get("ti") || ""))), React.createElement("label", { htmlFor: "info-ti" }, "]"), React.createElement("label", { htmlFor: "info-ar" }, "[ar:"), React.createElement("input", Object.assign({ id: "info-ar", name: "ar", placeholder: lang.editor.artist }, disableCheck, useDefaultValue(lrcState.info.get("ar") || ""))), React.createElement("label", { htmlFor: "info-ar" }, "]"), React.createElement("label", { htmlFor: "info-al" }, "[al:"), React.createElement("input", Object.assign({ id: "info-al", name: "al", placeholder: lang.editor.album }, disableCheck, useDefaultValue(lrcState.info.get("al") || ""))), React.createElement("label", { htmlFor: "info-al" }, "]"))), React.createElement("section", { className: "editor-tools" }, React.createElement("label", { className: "editor-tools-item ripple", title: lang.editor.uploadText }, React.createElement("input", { hidden: true, type: "file", accept: "text/*, .txt, .lrc", onChange: onTextFileUpload }), React.createElement(OpenFileSVG, null)), React.createElement("button", { className: "editor-tools-item ripple", title: lang.editor.copyText, onClick: onCopyClick }, React.createElement(CopySVG, null)), React.createElement("a", { className: "editor-tools-item ripple", title: lang.editor.downloadText, href: href, onClick: onDownloadClick, download: downloadName }, React.createElement(DownloadSVG, null)), React.createElement("a", { title: lang.editor.saveToGist, href: canSaveToGist ? undefined : "#/gist/", className: "editor-tools-item ripple", onClick: canSaveToGist ? onGistSave : undefined }, React.createElement(CloudUploadSVG, null)), React.createElement("a", { title: lang.editor.utils, href: "/lrc-utils/", className: "editor-tools-item ripple" }, React.createElement(UtilitySVG, null))), React.createElement("textarea", Object.assign({ className: "app-textarea", "aria-label": "lrc input here", onBlur: parse }, disableCheck, useDefaultValue(text, textarea))))); }; //# sourceMappingURL=editor.js.map