2024-08-14 15:36:25 +07:00
|
|
|
import clsx from "clsx";
|
|
|
|
import { toast } from "sonner";
|
|
|
|
import { twMerge } from "tailwind-merge";
|
|
|
|
|
|
|
|
export const cn = (...args: any[]) => {
|
|
|
|
return twMerge(clsx(...args));
|
|
|
|
};
|
|
|
|
|
|
|
|
export const ucfirst = (text?: string | null) => {
|
|
|
|
return text ? text.charAt(0).toUpperCase() + text.slice(1) : null;
|
|
|
|
};
|
|
|
|
|
|
|
|
export const readableBytes = (bytes?: number | null, divider = 1024) => {
|
|
|
|
if (bytes == null || Number.isNaN(bytes)) return "n/a";
|
|
|
|
|
2024-08-17 00:21:23 +07:00
|
|
|
const sizes = ["B", "KB", "MB", "GB", "TB"];
|
2024-08-16 23:10:19 +07:00
|
|
|
const i = Math.max(0, Math.floor(Math.log(bytes) / Math.log(divider)));
|
2024-08-14 15:36:25 +07:00
|
|
|
|
|
|
|
return `${(bytes / Math.pow(divider, i)).toFixed(1)} ${sizes[i]}`;
|
|
|
|
};
|
|
|
|
|
|
|
|
export const handleError = (err: unknown) => {
|
|
|
|
toast.error((err as Error)?.message || "Unknown error");
|
|
|
|
};
|
2024-08-17 00:51:57 +07:00
|
|
|
|
|
|
|
export const copyToClipboard = async (text: string) => {
|
2024-08-18 06:37:51 +07:00
|
|
|
let textArea: HTMLTextAreaElement | undefined;
|
|
|
|
|
2024-08-17 00:51:57 +07:00
|
|
|
try {
|
2024-08-18 06:37:51 +07:00
|
|
|
if (navigator.clipboard && window.isSecureContext) {
|
|
|
|
await navigator.clipboard.writeText(text);
|
|
|
|
} else {
|
|
|
|
textArea = document.createElement("textarea");
|
|
|
|
textArea.value = text;
|
|
|
|
|
|
|
|
textArea.style.position = "absolute";
|
|
|
|
textArea.style.left = "-999999px";
|
|
|
|
|
|
|
|
document.body.prepend(textArea);
|
|
|
|
textArea.select();
|
|
|
|
document.execCommand("copy");
|
|
|
|
}
|
|
|
|
|
2024-08-17 00:51:57 +07:00
|
|
|
toast.success("Copied to clipboard");
|
|
|
|
} catch (err) {
|
|
|
|
handleError(err);
|
2024-08-18 06:37:51 +07:00
|
|
|
} finally {
|
|
|
|
textArea?.remove();
|
2024-08-17 00:51:57 +07:00
|
|
|
}
|
|
|
|
};
|