Skip to content

Commit

Permalink
Use Tooltip for evaluation result copying
Browse files Browse the repository at this point in the history
Displaying a dialog is too visually obtrusive for such a small action.
  • Loading branch information
graphemecluster committed Oct 3, 2024
1 parent 8b4111c commit d043d8d
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 51 deletions.
40 changes: 27 additions & 13 deletions src/Components/Main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { allOptions, defaultArticle } from "../consts";
import evaluate from "../evaluate";
import { listenArticle } from "../options";
import initialState, { stateStorageLocation } from "../state";
import { copy, notifyError } from "../utils";
import TooltipLabel from "./TooltipLabel";

import type { MainState, Option, ReactNode } from "../consts";

Expand Down Expand Up @@ -176,11 +176,19 @@ export default function Main({ evaluateHandlerRef }: { evaluateHandlerRef: Mutab

const [loading, setLoading] = useState(false);

const handleCopy = useCallback(() => {
const txt = ref.current.textContent?.trim();
if (txt) copy(txt);
else notifyError("請先進行操作,再匯出結果");
const [copyTooltipText, setCopyTooltipText] = useState("複製到剪貼簿");
const copyEvaluationResult = useCallback(async () => {
const content = ref.current.textContent?.trim();
if (content) {
try {
await navigator.clipboard.writeText(content);
setCopyTooltipText("成功複製到剪貼簿");
} catch {
setCopyTooltipText("無法複製到剪貼簿");
}
}
}, []);
const onHideTooltip = useCallback(() => setCopyTooltipText("複製到剪貼簿"), []);

// XXX Please Rewrite
useEffect(() => {
Expand Down Expand Up @@ -287,14 +295,20 @@ export default function Main({ evaluateHandlerRef }: { evaluateHandlerRef: Mutab
<OutputPopup>
<Title>
<span>推導結果</span>
<CopyButton title="匯出至剪貼簿" hidden={loading} onClick={handleCopy}>
<FontAwesomeIcon icon={faCopy} size="sm" />
</CopyButton>
<form method="dialog">
<CloseButton type="submit" className="swal2-close" title="關閉" hidden={loading}>
×
</CloseButton>
</form>
{!loading && (
<>
<TooltipLabel description={copyTooltipText} onHideTooltip={onHideTooltip}>
<CopyButton onClick={copyEvaluationResult}>
<FontAwesomeIcon icon={faCopy} size="sm" />
</CopyButton>
</TooltipLabel>
<form method="dialog">
<CloseButton type="submit" className="swal2-close" title="關閉">
×
</CloseButton>
</form>
</>
)}
</Title>
<OutputContent key={operation} ref={ref}>
{evaluationResult}
Expand Down
14 changes: 9 additions & 5 deletions src/Components/Tooltip.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,6 @@ const root = createRoot(div);

let tooltipTarget: symbol | null = null;

function hideTooltip() {
div.style.visibility = "hidden";
}

function TooltipAnchor({
relativeToNodeBox,
children,
Expand Down Expand Up @@ -80,10 +76,12 @@ export default function Tooltip({
element,
children,
fixedWidth = true,
onHideTooltip,
}: {
element: ReactElement;
children: ReactElement;
fixedWidth?: boolean;
onHideTooltip?: (() => void) | undefined;
}) {
const selfRef = useRef(Symbol("Tooltip"));
const boxRef = useRef<DOMRect | null>(null);
Expand All @@ -109,14 +107,20 @@ export default function Tooltip({
renderTooltip();
}
}, [renderTooltip]);

const hideTooltip = useCallback(() => {
div.style.visibility = "hidden";
onHideTooltip?.();
}, [onHideTooltip]);
useEffect(
() => () => {
if (tooltipTarget === selfRef.current) {
hideTooltip();
}
},
[],
[hideTooltip],
);

return cloneElement(children, {
onMouseEnter: showTooltip,
onTouchStart: showTooltip,
Expand Down
5 changes: 4 additions & 1 deletion src/Components/TooltipLabel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,11 @@ const Option = styled.label`
export default function TooltipLabel({
description,
children,
onHideTooltip,
}: {
description?: string | undefined;
children: ReactNode;
onHideTooltip?: (() => void) | undefined;
}) {
return typeof description === "string" && description ? (
<Tooltip
Expand All @@ -35,7 +37,8 @@ export default function TooltipLabel({
<p key={i}>{line}</p>
))}
</Wrapper>
}>
}
onHideTooltip={onHideTooltip}>
<Option>{children}</Option>
</Tooltip>
) : (
Expand Down
32 changes: 0 additions & 32 deletions src/utils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,38 +53,6 @@ export function notifyError(msg: string, err?: unknown) {
return new Error(msg, err instanceof Error ? { cause: err } : {});
}

export async function copy(txt: string) {
if (
await (async () => {
try {
await navigator.clipboard.writeText(txt);
return true;
} catch {
const textArea = document.createElement("textarea");
textArea.value = txt;
textArea.style.position = "fixed";
document.body.appendChild(textArea);
textArea.focus();
textArea.select();
try {
return document.execCommand("copy");
} catch {
return false;
} finally {
document.body.removeChild(textArea);
}
}
})()
)
Swal.fire({
icon: "success",
title: "成功",
text: "已成功匯出至剪貼簿",
confirmButtonText: "確定",
});
else notifyError("瀏覽器不支援匯出至剪貼簿,操作失敗");
}

export async function fetchFile(input: string) {
try {
const text = await (await fetch(input, { cache: "no-cache" })).text();
Expand Down

0 comments on commit d043d8d

Please sign in to comment.