Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(playground): enhance console output with timestamps and img tag …
Browse files Browse the repository at this point in the history
…support

- Add timestamp to each console message
- Support rendering and copying <img> tags in console output
- Add formatTimestamp utility function
- Update message type to include timestamp in context
yixyxiu committed Jan 20, 2025

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
1 parent 45c9292 commit a0761db
Showing 3 changed files with 65 additions and 11 deletions.
60 changes: 51 additions & 9 deletions packages/playground/src/app/context.tsx
Original file line number Diff line number Diff line change
@@ -41,7 +41,7 @@ export const APP_CONTEXT = createContext<
disconnect: () => void;
openAction: ReactNode;

messages: ["error" | "info", string, ReactNode][];
messages: ["error" | "info", string, ReactNode, number][];
sendMessage: (
level: "error" | "info",
title: string,
@@ -83,7 +83,7 @@ export function AppProvider({ children }: { children: React.ReactNode }) {
}, [signer]);

const [messages, setMessages] = useState<
["error" | "info", string, ReactNode][]
["error" | "info", string, ReactNode, number][]
>([]);

const sendMessage = (
@@ -97,13 +97,54 @@ export function AppProvider({ children }: { children: React.ReactNode }) {
level,
title,
msgs.map((msg, i) => {
if (typeof msg === "string" && (msg.startsWith(`"http://`) || msg.startsWith(`"https://`))) {
const url = msg.slice(1, -1);
return (
<a key={i} className="underline underline-offset-2 text-[#2D5FF5] px-2" href={url} target="_blank" rel="noopener noreferrer">
{url}
</a>
);
if (typeof msg === "string") {
if (msg.startsWith(`"http://`) || msg.startsWith(`"https://`)) {
const url = msg.slice(1, -1);
return (
<a key={i} className="underline underline-offset-2 text-[#2D5FF5] px-2" href={url} target="_blank" rel="noopener noreferrer">
{url}
</a>
);
} else if (msg.startsWith(`"<img`)){
// "<img src=\\\"https://world3.ai/dob/souldragonegg.jpg\\\" width='300' height='300/>"

// Remove the outer quotes and parse
const imgString = msg
.slice(1, -1)
.replace(/\\"/g, '"')
.replace(/\/$/, ''); // Remove trailing slash(if any)

// Parse the img string to extract src, width, and height
const parseImgAttributes = (imgStr: string) => {
const srcMatch = imgStr.match(/src=["']([^"']+)["']/);
const widthMatch = imgStr.match(/width=["'](\d+)["']/);
const heightMatch = imgStr.match(/height=["'](\d+)["']/);

return {
src: srcMatch ? srcMatch[1] : '',
width: widthMatch ? parseInt(widthMatch[1]) : 300,
height: heightMatch ? parseInt(heightMatch[1]) : 300
};
};

const imgAttributes = parseImgAttributes(imgString);

return (
<div className="relative p-2" key={i} >
<img className="rounded" src={imgAttributes.src} width={imgAttributes.width} height={imgAttributes.height} alt="" />
<span className="absolute top-2.5 left-2.5 px-2 flex items-center justify-center cursor-pointer bg-slate-800/50 rounded"
onClick={() => {
if (navigator.clipboard) {
// Copy the imgString to the clipboard
navigator.clipboard.writeText(imgString);
}
}}
>
Click to copy
</span>
</div>
);
}
}

return (
@@ -113,6 +154,7 @@ export function AppProvider({ children }: { children: React.ReactNode }) {
</React.Fragment>
);
}),
Date.now(),
],
]);

8 changes: 6 additions & 2 deletions packages/playground/src/app/tabs/Console.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import { useMemo } from "react";
import { useApp } from "../context";
import { Info, X } from "lucide-react";
import { formatTimestamp } from "../utils";

export function Console() {
const { messages } = useApp();

const consoles = useMemo(
() =>
// eslint-disable-next-line @typescript-eslint/no-unused-vars
messages.map(([level, _, message], i) => (
messages.map(([level, _, message, timestamp], i) => (
<div
key={i}
className={`border-t border-fuchsia-800 p-2 break-all ${
@@ -20,14 +21,17 @@ export function Console() {
) : (
<Info className="inline mr-2" size="16" />
)}
<span className="text-[#8F8F8F] pr-1">
{formatTimestamp(timestamp)}
</span>
{message}
</div>
)),
[messages]
);

return (
<div className="flex flex-col-reverse grow overflow-y-auto max-h-dvh font-mono">
<div className="flex flex-col-reverse grow overflow-y-auto max-h-dvh font-mono text-sm">
<div className="flex flex-col">{consoles}</div>
</div>
);
8 changes: 8 additions & 0 deletions packages/playground/src/app/utils.tsx
Original file line number Diff line number Diff line change
@@ -76,3 +76,11 @@ export function getScriptColor(script: ccc.ScriptLike): string {

return `hsl(${(ccc.numFrom(hash) % ccc.numFrom(360)).toString()} 65% 45%)`;
}

export function formatTimestamp(timestamp: number): string {
const date = new Date(timestamp);
return date.getHours().toString().padStart(2, '0') + ':' +
date.getMinutes().toString().padStart(2, '0') + ':' +
date.getSeconds().toString().padStart(2, '0') + '.' +
date.getMilliseconds().toString().padStart(3, '0');
}

0 comments on commit a0761db

Please sign in to comment.