townie-126requests.ts3 matches
16price: number | null;
17finish_reason: string | null;
18num_images: number | null;
19our_api_token: number;
20}
68<th>Price</th>
69<th>Finish</th>
70<th>Images</th>
71<th>Our API</th>
72</tr>
87<td class="price">${formatPrice(row.price)}</td>
88<td>${row.finish_reason || '-'}</td>
89<td>${formatNumber(row.num_images)}</td>
90<td>${formatBoolean(row.our_api_token)}</td>
91</tr>
townie-126queries.tsx4 matches
141model,
142our_api_token,
143num_images,
144tablePrefix = "",
145}: {
149model: string;
150our_api_token: boolean;
151num_images: number;
152tablePrefix: string;
153}) {
162model,
163our_api_token,
164num_images
165) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
166`,
173model,
174our_api_token ? 1 : 0,
175num_images,
176],
177);
townie-126queries_test.tsx1 match
29model,
30our_api_token,
31num_images
32) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
33`,
townie-126ProjectsRoute.tsx7 matches
44user: {
45username: string;
46profileImageUrl: string | null;
47};
48project: any;
50return (
51<div className="card">
52{project.imageUrl ? (
53<img src={project.imageUrl} className="card-image" />
54) : user.profileImageUrl ? (
55<div className="card-image">
56<img
57src={user.profileImageUrl}
58width="48"
59height="48"
62</div>
63) : (
64<div className="card-image placeholder" />
65)}
66<div className="card-body">
townie-126InputBox.tsx47 matches
3import { Link } from "react-router";
4import { PlusIcon, ArrowUpIcon, Square, XIcon } from "./icons.tsx";
5import { processFiles } from "../utils/images.ts";
67export function InputBox ({
12running,
13error,
14images,
15setImages,
16} : {
17value: string;
21running: boolean;
22error: any;
23images: (string|null)[];
24setImages: (images: (string|null)[]) => void;
25}) {
26const form = useRef(null);
62/>
63</div>
64<ImageRow images={images} setImages={setImages} />
65<div className="toolbar">
66<UploadButton
67disabled={running}
68images={images}
69setImages={setImages}
70/>
71<div className="spacer" />
94}
9596export function ImageDropContainer ({
97images,
98setImages,
99running,
100children,
101}: {
102images: (string|null)[];
103setImages: (images: (string|null)[]) => void;
104running: boolean;
105children: React.ReactNode;
106}) {
107const dragging = useImageDrop({ images, setImages, running });
108109return (
111{children}
112{dragging && (
113<div className="image-drop-overlay">
114<div className="image-drop-inner">
115Drop images here to upload
116</div>
117</div>
121}
122123export function useImageDrop ({ images, setImages, running }: {
124images: (string|null)[];
125setImages(images: (string|null)[]) => void;
126running: boolean;
127}) {
149setDragging(false);
150if (e.dataTransfer?.files && !running) {
151processFiles(Array.from(e.dataTransfer.files), images, setImages);
152}
153}
165document.removeEventListener("drop", onDrop);
166}
167}, [images, setImages, running]);
168169return dragging;
170}
171172function ImageRow ({ images, setImages }: {
173images: (string|null)[];
174setImages: (images: (string|null)[]) => void;
175}) {
176return (
177<div className="image-row">
178{images.map((image, i) => (
179<Thumbnail
180key={i}
181image={image}
182onRemove={() => {
183setImages([
184...images.slice(0, i),
185...images.slice(i + 1),
186]);
187}}
192}
193194function Thumbnail ({ image, onRemove }: {
195image: string|null;
196onRemove: () => void;
197}) {
198if (!image) return null;
199200return (
201<div className="input-image">
202<img
203src={image}
204alt="User uploaded image"
205className="image-thumbnail"
206/>
207<button
208type="button"
209title="Remove image"
210className="remove-image-button"
211onClick={onRemove}
212>
218219function UploadButton ({
220images,
221setImages,
222disabled,
223}: {
224images: (string|null)[];
225setImages: (images: (string|null)[]) => void;
226disabled: boolean;
227}) {
232<button
233type="button"
234title="Upload image"
235disabled={disabled}
236onClick={e => {
240<PlusIcon />
241<div className="sr-only">
242Upload image
243</div>
244</button>
249onChange={e => {
250if (e.target.files) {
251processFiles(Array.from(e.target.files), images, setImages);
252}
253}}
townie-126images.ts12 matches
12export const PROMPT_IMAGE_LIMIT = 5;
34export const processFiles = async (files: File[], images: (string | null)[], setImages: (images: (string | null)[]) => void) => {
5const imageFiles = files.filter(file => file.type.startsWith('image/'));
6const filesToProcess = imageFiles.slice(0, PROMPT_IMAGE_LIMIT - images.filter(Boolean).length);
78if (filesToProcess.length === 0) return;
910const newImages = [...images, ...Array(filesToProcess.length).fill(null)];
11setImages(newImages);
1213const processedImages = await Promise.all(
14filesToProcess.map(async (file) => {
15return await readFileAsDataURL(file);
17);
1819const updatedImages = [...images];
20processedImages.forEach((dataUrl, index) => {
21updatedImages[images.length + index] = dataUrl;
22});
2324setImages(updatedImages.slice(0, PROMPT_IMAGE_LIMIT));
25};
2630reader.onload = () => {
31const result = reader.result as string;
32console.log("Image loaded, size:", result.length, "bytes");
33resolve(result);
34};
townie-126Header.tsx2 matches
7374function Avatar ({ user }) {
75if (!user?.profileImageUrl) {
76return (
77<div className="avatar" />
81return (
82<img
83src={user.profileImageUrl}
84alt={user.username}
85width="32"
townie-126favicon.http.tsx1 match
10return new Response(svg, {
11headers: {
12"Content-Type": "image/svg+xml",
13},
14});
townie-126dashboard.ts3 matches
12total_price: number;
13inference_price: number;
14total_images: number;
15used_inference_data?: boolean;
16}
44<th>Total Price</th>
45<th>Inference Price</th>
46<th>Images</th>
47</tr>
48</thead>
59<td class="price">${formatPrice(row.total_price)} ${row.used_inference_data ? '<span class="badge badge-info" title="Using inference data">I</span>' : ''}</td>
60<td class="price">${formatPrice(row.inference_price || 0)}</td>
61<td>${formatNumber(row.total_images)}</td>
62</tr>
63`).join("")}
townie-126.cursorrules2 matches
178179- **Redirects:** Use `return new Response(null, { status: 302, headers: { Location: "/place/to/redirect" }})` instead of `Response.redirect` which is broken
180- **Images:** Avoid external images or base64 images. Use emojis, unicode symbols, or icon fonts/libraries instead
181- **AI Image:** To inline generate an AI image use: `<img src="https://maxm-imggenurl.web.val.run/the-description-of-your-image" />`
182- **Storage:** DO NOT use the Deno KV module for storage
183- **Browser APIs:** DO NOT use the `alert()`, `prompt()`, or `confirm()` methods