Sight groups, DM reveal areas (cones), client-side image shrink for map upload
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HJhXuLD2Z6hv3Wqeq9UL9K
This commit is contained in:
+20
-2
@@ -2,7 +2,24 @@ import { useCallback, useEffect, useState } from 'react'
|
||||
import { MapEditor } from './MapView.jsx'
|
||||
|
||||
const J = { 'Content-Type': 'application/json' }
|
||||
const errText = async (r, fallback) => (await r.json().catch(() => ({}))).detail || fallback
|
||||
const errText = async (r, fallback) => {
|
||||
if (r.status === 413) return 'The file is too big for the web server (nginx client_max_body_size). Use a smaller image or ask the server admin to raise the limit.'
|
||||
return (await r.json().catch(() => ({}))).detail || fallback
|
||||
}
|
||||
|
||||
// Big images are scaled down and re-encoded in the browser first (the server does it again anyway), so they fit through proxies with small upload limits.
|
||||
async function shrink(f) {
|
||||
if (f.size < 900_000) return f
|
||||
try {
|
||||
const bmp = await createImageBitmap(f)
|
||||
const k = Math.min(1, 4096 / Math.max(bmp.width, bmp.height))
|
||||
const c = document.createElement('canvas')
|
||||
c.width = Math.max(1, Math.round(bmp.width * k)); c.height = Math.max(1, Math.round(bmp.height * k))
|
||||
c.getContext('2d').drawImage(bmp, 0, 0, c.width, c.height)
|
||||
const blob = await new Promise((res) => c.toBlob(res, 'image/webp', 0.9))
|
||||
return blob && blob.size < f.size ? blob : f
|
||||
} catch { return f }
|
||||
}
|
||||
|
||||
function SharePanel({ m, reload }) {
|
||||
const [name, setName] = useState('')
|
||||
@@ -45,7 +62,8 @@ export default function Maps() {
|
||||
e.target.value = ''
|
||||
if (!f) return
|
||||
setErr(''); setBusy(true)
|
||||
const r = await fetch(`/api/maps?name=${encodeURIComponent(f.name.replace(/\.[^.]+$/, ''))}`, { method: 'POST', headers: { 'Content-Type': f.type || 'application/octet-stream' }, body: f }).catch(() => null)
|
||||
const body = await shrink(f)
|
||||
const r = await fetch(`/api/maps?name=${encodeURIComponent(f.name.replace(/\.[^.]+$/, ''))}`, { method: 'POST', headers: { 'Content-Type': body.type || 'application/octet-stream' }, body }).catch(() => null)
|
||||
setBusy(false)
|
||||
if (!r || !r.ok) return setErr(r ? await errText(r, 'Upload failed') : 'Upload failed')
|
||||
load()
|
||||
|
||||
Reference in New Issue
Block a user