Spaces:
Runtime error
Runtime error
File size: 4,197 Bytes
cd6f98e | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 | import clsx from "clsx";
import * as htmlToImage from "html-to-image";
import { useTranslation } from "next-i18next";
import type { PropsWithChildren, ReactNode } from "react";
import React from "react";
import { CgExport } from "react-icons/cg";
import { FaImage } from "react-icons/fa";
import { FiClipboard } from "react-icons/fi";
import type { Message } from "../../types/message";
import Menu from "../Menu";
import Expand from "../motions/expand";
import PopIn from "../motions/popin";
import PDFButton from "../pdf/PDFButton";
import WindowButton from "../WindowButton";
export const messageListId = "chat-window-message-list";
export interface HeaderProps {
title?: string | ReactNode;
messages: Message[];
}
export const MacWindowHeader = (props: HeaderProps) => {
const [t] = useTranslation();
const saveElementAsImage = (elementId: string) => {
const element = document.getElementById(elementId);
if (!element) {
return;
}
htmlToImage
.toJpeg(element, {
height: element.scrollHeight,
style: {
overflowY: "visible",
maxHeight: "none",
border: "none",
},
})
.then((dataUrl) => {
const link = document.createElement("a");
link.href = dataUrl;
link.download = "agent-gpt-output.png";
link.click();
})
.catch(() =>
alert("Error saving image! Note this doesn't work if the AI generated an image")
);
};
const copyElementText = (elementId: string) => {
const element = document.getElementById(elementId);
if (!element) {
return;
}
const text = element.innerText;
if (navigator.clipboard) {
void navigator.clipboard.writeText(text);
} else {
// Fallback to a different method for unsupported browsers
const textArea = document.createElement("textarea");
textArea.value = text;
document.body.appendChild(textArea);
textArea.focus();
textArea.select();
try {
document.execCommand("copy");
console.log("Text copied to clipboard");
} catch (err) {
console.error("Unable to copy text to clipboard", err);
}
document.body.removeChild(textArea);
}
};
const exportOptions = [
<WindowButton
key="Image"
onClick={(): void => saveElementAsImage(messageListId)}
icon={<FaImage size={12} />}
text={t("IMAGE", { ns: "common" })}
/>,
<WindowButton
key="Copy"
onClick={(): void => copyElementText(messageListId)}
icon={<FiClipboard size={12} />}
text={t("COPY", { ns: "common" })}
/>,
<PDFButton key="PDF" name="PDF" messages={props.messages} />,
];
return (
<div className="flex items-center gap-1 overflow-visible rounded-t-3xl p-1.5 px-1">
<PopIn delay={0.4}>
<div className="h-3 w-3 rounded-full bg-red-500" />
</PopIn>
<PopIn delay={0.5}>
<div className="h-3 w-3 rounded-full bg-yellow-500" />
</PopIn>
<PopIn delay={0.6}>
<div className="h-3 w-3 rounded-full bg-green-500" />
</PopIn>
<Expand
delay={0.75}
className="flex flex-grow font-mono text-xs font-bold text-gray-500 sm:ml-2 sm:text-sm"
>
{props.title}
</Expand>
<Menu icon={<CgExport size={15} />} items={exportOptions} />
</div>
);
};
interface MacWindowInternalProps extends PropsWithChildren {
className?: string;
}
export const MacWindowInternal = (props: MacWindowInternalProps) => {
return (
<div
className={clsx(
"ml-2 flex items-baseline gap-1 overflow-visible rounded-t-3xl p-1.5",
props.className
)}
>
<PopIn delay={0.4}>
<div className="h-2 w-2 rounded-full bg-red-500" />
</PopIn>
<PopIn delay={0.5}>
<div className="h-2 w-2 rounded-full bg-yellow-500" />
</PopIn>
<PopIn delay={0.6}>
<div className="h-2 w-2 rounded-full bg-green-500" />
</PopIn>
<Expand
delay={0.75}
className="ml-1 flex flex-grow font-mono text-[8pt] font-bold text-gray-400"
>
{props.children}
</Expand>
</div>
);
};
|