Initial commit
This commit is contained in:
@@ -0,0 +1,295 @@
|
||||
[2026-05-14T20:01:08.011Z] PROMPT
|
||||
============================================================
|
||||
Analyze this codebase for performance optimizations:
|
||||
- Identify N+1 query patterns
|
||||
- Find unnecessary re-renders in React
|
||||
- Suggest caching opportunities
|
||||
- Identify memory leaks
|
||||
- Find redundant computations
|
||||
|
||||
Provide actionable suggestions with code examples.
|
||||
|
||||
## Codebase Context
|
||||
|
||||
--- src/canvas/types.ts ---
|
||||
export type CardId = string;
|
||||
|
||||
export type CardKind = "note" | "terminal" | "app" | "thumbnail";
|
||||
|
||||
export interface BaseCard {
|
||||
id: CardId;
|
||||
kind: CardKind;
|
||||
x: number;
|
||||
y: number;
|
||||
width: number;
|
||||
height: number;
|
||||
z: number;
|
||||
}
|
||||
|
||||
export interface NoteCard extends BaseCard {
|
||||
kind: "note";
|
||||
text: string;
|
||||
}
|
||||
|
||||
export interface TerminalCard extends BaseCard {
|
||||
kind: "terminal";
|
||||
ptyId: string;
|
||||
}
|
||||
|
||||
export interface AppCard extends BaseCard {
|
||||
kind: "app";
|
||||
xWindowId: number;
|
||||
command: string;
|
||||
title?: string;
|
||||
}
|
||||
|
||||
export interface ThumbnailCard extends BaseCard {
|
||||
kind: "thumbnail";
|
||||
refCardId: CardId;
|
||||
label: string;
|
||||
}
|
||||
|
||||
export type Card = NoteCard | TerminalCard | AppCard | ThumbnailCard;
|
||||
|
||||
export interface Viewport {
|
||||
x: number;
|
||||
y: number;
|
||||
scale: number;
|
||||
}
|
||||
|
||||
|
||||
--- src/App.tsx ---
|
||||
import { Canvas } from "./canvas/Canvas";
|
||||
import type { Card } from "./canvas/types";
|
||||
|
||||
const initialCards: Card[] = [
|
||||
{
|
||||
id: "welcome",
|
||||
kind: "note",
|
||||
x: 200,
|
||||
y: 200,
|
||||
width: 320,
|
||||
height: 180,
|
||||
z: 0,
|
||||
text: "Welcome to Infinite.\n\nPan: middle-drag or space+drag.\nZoom: Ctrl+wheel.",
|
||||
},
|
||||
{
|
||||
id: "todo",
|
||||
kind: "note",
|
||||
x: 600,
|
||||
y: 320,
|
||||
width: 260,
|
||||
height: 140,
|
||||
z: 0,
|
||||
text: "Next: terminal cards, then X11 embedding.",
|
||||
},
|
||||
];
|
||||
|
||||
export function App() {
|
||||
return <Canvas initialCards={initialCards} />;
|
||||
}
|
||||
|
||||
|
||||
--- src/canvas/Canvas.tsx ---
|
||||
import { useEffect, useRef, useState, useCallback } from "react";
|
||||
import type { Card, Viewport } from "./types";
|
||||
import { NoteCardView } from "./cards/NoteCardView";
|
||||
import "./canvas.css";
|
||||
|
||||
const MIN_SCALE = 0.1;
|
||||
const MAX_SCALE = 4;
|
||||
const ZOOM_SENSITIVITY = 0.0015;
|
||||
|
||||
interface CanvasProps {
|
||||
initialCards: Card[];
|
||||
}
|
||||
|
||||
export function Canvas({ initialCards }: CanvasProps) {
|
||||
const [cards, setCards] = useState<Card[]>(initialCards);
|
||||
const [vp, setVp] = useState<Viewport>({ x: 0, y: 0, scale: 1 });
|
||||
const [spaceHeld, setSpaceHeld] = useState(false);
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
const panState = useRef<{ startX: number; startY: number; vpX: number; vpY: number } | null>(
|
||||
null,
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
const onKeyDown = (e: KeyboardEvent) => {
|
||||
if (e.code === "Space" && !e.repeat) setSpaceHeld(true);
|
||||
};
|
||||
const onKeyUp = (e: KeyboardEvent) => {
|
||||
if (e.code === "Space") setSpaceHeld(false);
|
||||
};
|
||||
window.addEventListener("keydown", onKeyDown);
|
||||
window.addEventListener("keyup", onKeyUp);
|
||||
return () => {
|
||||
window.removeEventListener("keydown", onKeyDown);
|
||||
window.removeEventListener("keyup", onKeyUp);
|
||||
};
|
||||
}, []);
|
||||
|
||||
const onWheel = useCallback(
|
||||
(e: React.WheelEvent) => {
|
||||
if (!e.ctrlKey && !e.metaKey) return;
|
||||
e.preventDefault();
|
||||
const rect = containerRef.current!.getBoundingClientRect();
|
||||
const mx = e.clientX - rect.left;
|
||||
const my = e.clientY - rect.top;
|
||||
setVp((prev) => {
|
||||
const factor = Math.exp(-e.deltaY * ZOOM_SENSITIVITY);
|
||||
const next = Math.max(MIN_SCALE, Math.min(MAX_SCALE, prev.scale * factor));
|
||||
const k = next / prev.scale;
|
||||
return { x: mx - (mx - prev.x) * k, y: my - (my - prev.y) * k, scale: next };
|
||||
});
|
||||
},
|
||||
[],
|
||||
);
|
||||
|
||||
const onPointerDown = (e: React.PointerEvent) => {
|
||||
const isPan = e.button === 1 || (e.button === 0 && spaceHeld);
|
||||
if (!isPan) return;
|
||||
e.preventDefault();
|
||||
(e.target as Element).setPointerCapture(e.pointerId);
|
||||
panState.current = { startX: e.clientX, startY: e.clientY, vpX: vp.x, vpY: vp.y };
|
||||
};
|
||||
|
||||
const onPointerMove = (e: React.PointerEvent) => {
|
||||
if (!panState.current) return;
|
||||
const dx = e.clientX - panState.current.startX;
|
||||
const dy = e.clientY - panState.current.startY;
|
||||
setVp((prev) => ({ ...prev, x: panState.current!.vpX + dx, y: panState.current!.vpY + dy }));
|
||||
};
|
||||
|
||||
const onPointerUp = (e: React.PointerEvent) => {
|
||||
if (panState.current) {
|
||||
(e.target as Element).releasePointerCapture(e.pointerId);
|
||||
panState.current = null;
|
||||
}
|
||||
};
|
||||
|
||||
const updateCard = (id: string, patch: Partial<Card>) => {
|
||||
setCards((cs) => cs.map((c) => (c.id === id ? ({ ...c, ...patch } as Card) : c)));
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={containerRef}
|
||||
className={`canvas-container ${spaceHeld ? "pan-mode" : ""}`}
|
||||
onWheel={onWheel}
|
||||
onPointerDown={onPointerDown}
|
||||
onPointerMove={onPointerMove}
|
||||
onPointerUp={onPointerUp}
|
||||
onPointerCancel={onPointerUp}
|
||||
>
|
||||
<div
|
||||
className="canvas-grid"
|
||||
style={{
|
||||
backgroundPosition: `${vp.x}px ${vp.y}px`,
|
||||
backgroundSize: `${40 * vp.scale}px ${40 * vp.scale}px`,
|
||||
}}
|
||||
/>
|
||||
<div
|
||||
className="canvas-world"
|
||||
style={{ transform: `translate(${vp.x}px, ${vp.y}px) scale(${vp.scale})` }}
|
||||
>
|
||||
{cards.map((c) => {
|
||||
if (c.kind === "note") {
|
||||
return <NoteCardView key={c.id} card={c} onUpdate={(p) => updateCard(c.id, p)} />;
|
||||
}
|
||||
return null;
|
||||
})}
|
||||
</div>
|
||||
<div className="canvas-hud">
|
||||
<span>x {vp.x.toFixed(0)}</span>
|
||||
<span>y {vp.y.toFixed(0)}</span>
|
||||
<span>{(vp.scale * 100).toFixed(0)}%</span>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
--- src/canvas/cards/NoteCardView.tsx ---
|
||||
import { useRef } from "react";
|
||||
import type { NoteCard } from "../types";
|
||||
|
||||
interface Props {
|
||||
card: NoteCard;
|
||||
onUpdate: (patch: Partial<NoteCard>) => void;
|
||||
}
|
||||
|
||||
export function NoteCardView({ card, onUpdate }: Props) {
|
||||
const dragState = useRef<{ startX: number; startY: number; cardX: number; cardY: number } | null>(
|
||||
null,
|
||||
);
|
||||
|
||||
const onHeaderPointerDown = (e: React.PointerEvent) => {
|
||||
if (e.button !== 0) return;
|
||||
e.stopPropagation();
|
||||
(e.target as Element).setPointerCapture(e.pointerId);
|
||||
dragState.current = { startX: e.clientX, startY: e.clientY, cardX: card.x, cardY: card.y };
|
||||
};
|
||||
|
||||
const onHeaderPointerMove = (e: React.PointerEvent) => {
|
||||
if (!dragState.current) return;
|
||||
const worldEl = (e.currentTarget as HTMLElement).closest(".canvas-world") as HTMLElement;
|
||||
const scale = worldEl ? parseTransformScale(worldEl.style.transform) : 1;
|
||||
const dx = (e.clientX - dragState.current.startX) / scale;
|
||||
const dy = (e.clientY - dragState.current.startY) / scale;
|
||||
onUpdate({ x: dragState.current.cardX + dx, y: dragState.current.cardY + dy });
|
||||
};
|
||||
|
||||
const onHeaderPointerUp = (e: React.PointerEvent) => {
|
||||
if (dragState.current) {
|
||||
(e.target as Element).releasePointerCapture(e.pointerId);
|
||||
dragState.current = null;
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
className="card note-card"
|
||||
style={{ left: card.x, top: card.y, width: card.width, height: card.height, zIndex: card.z }}
|
||||
>
|
||||
<div
|
||||
className="card-header"
|
||||
onPointerDown={onHeaderPointerDown}
|
||||
onPointerMove={onHeaderPointerMove}
|
||||
onPointerUp={onHeaderPointerUp}
|
||||
onPointerCancel={onHeaderPointerUp}
|
||||
>
|
||||
note
|
||||
</div>
|
||||
<div className="card-body">
|
||||
<textarea
|
||||
value={card.text}
|
||||
onChange={(e) => onUpdate({ text: e.target.value })}
|
||||
onPointerDown={(e) => e.stopPropagation()}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function parseTransformScale(transform: string): number {
|
||||
const m = transform.match(/scale\(([^)]+)\)/);
|
||||
return m ? parseFloat(m[1]) : 1;
|
||||
}
|
||||
|
||||
|
||||
--- src/main.tsx ---
|
||||
import React from "react";
|
||||
import ReactDOM from "react-dom/client";
|
||||
import { App } from "./App";
|
||||
import "./styles.css";
|
||||
|
||||
ReactDOM.createRoot(document.getElementById("root")!).render(
|
||||
<React.StrictMode>
|
||||
<App />
|
||||
</React.StrictMode>,
|
||||
);
|
||||
|
||||
|
||||
## Instructions
|
||||
|
||||
Analyze the above codebase context and provide your response following the format specified in the task.
|
||||
Reference in New Issue
Block a user