fix: final review polish before documentation

- Handle base64 encoding from Upstash GETRANGE (atob fallback)
- Add optimistic credit deduction on pixel placement
- Handle non-ok API responses in placePixel
- Enable WebSocket proxy in Vite dev config
- Remove dead CANVAS_WIDTH/HEIGHT vars from wrangler.json
- Suppress favicon 404 with empty data URI
This commit is contained in:
tiennm99 committed 2026-04-16 17:03:38 +07:00
1 parent 75441d650a
commit 078ccaa70e
5 files changed
+24 -12

No files matched your search

+8 -1
View File
@@ -56,6 +56,8 @@
if (x < 0 || x >= CANVAS_WIDTH || y < 0 || y >= CANVAS_HEIGHT) return; if (x < 0 || x >= CANVAS_WIDTH || y < 0 || y >= CANVAS_HEIGHT) return;
if (credits <= 0) return; if (credits <= 0) return;
// Optimistic deduction + render
onCreditsChange(credits - 1);
updatePixel(x, y, selectedColor); updatePixel(x, y, selectedColor);
render(); render();
@@ -66,7 +68,12 @@
body: JSON.stringify({ pixels: [{ x, y, color: selectedColor }] }), body: JSON.stringify({ pixels: [{ x, y, color: selectedColor }] }),
}); });
const data = await res.json(); const data = await res.json();
if (data.ok) onCreditsChange(data.credits); if (data.ok) {
onCreditsChange(data.credits);
} else {
// Server rejected — log reason (pixel stays rendered, WS will correct)
console.warn('Place rejected:', data.error);
}
} catch (err) { } catch (err) {
console.error('Failed to place pixel:', err); console.error('Failed to place pixel:', err);
} }
+1 -1
View File
@@ -4,7 +4,7 @@
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>rplace — Collaborative Pixel Canvas</title> <title>rplace — Collaborative Pixel Canvas</title>
<link rel="icon" href="/favicon.ico" /> <link rel="icon" href="data:," />
</head> </head>
<body> <body>
<div id="app"></div> <div id="app"></div>
+10 -4
View File
@@ -21,11 +21,17 @@ export async function getFullCanvas(env) {
return new Uint8Array(CANVAS_BYTES); return new Uint8Array(CANVAS_BYTES);
} }
// Upstash REST returns string — convert to bytes // Upstash REST may return base64 or raw string for binary data
if (typeof data === 'string') { if (typeof data === 'string') {
const bytes = new Uint8Array(data.length); let raw;
for (let i = 0; i < data.length; i++) { try {
bytes[i] = data.charCodeAt(i); raw = atob(data);
} catch {
raw = data; // Already a raw string
}
const bytes = new Uint8Array(raw.length);
for (let i = 0; i < raw.length; i++) {
bytes[i] = raw.charCodeAt(i);
} }
// Pad to full canvas size if shorter // Pad to full canvas size if shorter
if (bytes.length < CANVAS_BYTES) { if (bytes.length < CANVAS_BYTES) {
+4 -1
View File
@@ -10,7 +10,10 @@ export default defineConfig({
}, },
server: { server: {
proxy: { proxy: {
'/api': 'http://localhost:8787', '/api': {
target: 'http://localhost:8787',
ws: true,
},
}, },
}, },
}); });
+1 -5
View File
@@ -18,9 +18,5 @@
"tag": "v1", "tag": "v1",
"new_classes": ["CanvasRoom"] "new_classes": ["CanvasRoom"]
} }
], ]
"vars": {
"CANVAS_WIDTH": "2048",
"CANVAS_HEIGHT": "2048"
}
} }