mirror of
https://github.com/tiennm99/rplace.git
synced 2026-10-11 03:13:48 +00:00
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:
1 parent
75441d650a
commit
078ccaa70e
5 files changed
+24
-12
No files matched your search
@@ -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
@@ -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>
|
||||||
|
|||||||
@@ -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
@@ -10,7 +10,10 @@ export default defineConfig({
|
|||||||
},
|
},
|
||||||
server: {
|
server: {
|
||||||
proxy: {
|
proxy: {
|
||||||
'/api': 'http://localhost:8787',
|
'/api': {
|
||||||
|
target: 'http://localhost:8787',
|
||||||
|
ws: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
+1
-5
@@ -18,9 +18,5 @@
|
|||||||
"tag": "v1",
|
"tag": "v1",
|
||||||
"new_classes": ["CanvasRoom"]
|
"new_classes": ["CanvasRoom"]
|
||||||
}
|
}
|
||||||
],
|
]
|
||||||
"vars": {
|
|
||||||
"CANVAS_WIDTH": "2048",
|
|
||||||
"CANVAS_HEIGHT": "2048"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user