diff --git a/assets/css/tailwind.css b/assets/css/tailwind.css index dcc95dcbf..1197f1345 100644 --- a/assets/css/tailwind.css +++ b/assets/css/tailwind.css @@ -329,6 +329,18 @@ mark { pointer-events: none; opacity: 0.6; } + +/* Faint HUD scanlines laid over event banner media, so photography/video + reads as composed into the tactical chrome instead of pasted above it. */ +.tac-scanlines { + background-image: repeating-linear-gradient( + 180deg, + hsl(0 0% 100% / 0.03) 0px, + hsl(0 0% 100% / 0.03) 1px, + transparent 1px, + transparent 4px + ); +} /* One-shot pulse for clip share buttons — toast is far from the click target, so the button itself flashes amber + scales briefly. Used by MatchHighlightsReel queue/featured share, HighlightCard, and diff --git a/cloudflare-workers/backblaze-proxy/index.ts b/cloudflare-workers/backblaze-proxy/index.ts index b71e6db89..dd446ac24 100644 --- a/cloudflare-workers/backblaze-proxy/index.ts +++ b/cloudflare-workers/backblaze-proxy/index.ts @@ -441,7 +441,9 @@ export default { }, }; -const UPLOAD_PREFIX = "demo-uploads/"; +// Every write is still individually authorized by the API-minted HMAC token +// below; the prefix list only bounds which trees are writable at all. +const UPLOAD_PREFIXES = ["demo-uploads/", "events/"]; // B2 multipart part ceiling we accept; the API chunks at 64MiB so anything // larger is a malformed/abusive request. const MAX_PART_BYTES = 64 * 1024 * 1024; @@ -462,7 +464,12 @@ async function handleUpload( const uploadId = url.searchParams.get("uploadId"); const token = url.searchParams.get("token"); - if (!key.startsWith(UPLOAD_PREFIX) || !partNumber || !uploadId || !token) { + if ( + !UPLOAD_PREFIXES.some((prefix) => key.startsWith(prefix)) || + !partNumber || + !uploadId || + !token + ) { return new Response("forbidden", { status: 403, headers: corsHeaders(reqOrigin), diff --git a/components/BreadCrumbs.vue b/components/BreadCrumbs.vue index 6138beb15..46ad1f6e2 100644 --- a/components/BreadCrumbs.vue +++ b/components/BreadCrumbs.vue @@ -41,6 +41,7 @@ + + diff --git a/components/events/EventAudioPlayer.vue b/components/events/EventAudioPlayer.vue new file mode 100644 index 000000000..b9fa085c7 --- /dev/null +++ b/components/events/EventAudioPlayer.vue @@ -0,0 +1,136 @@ + + + diff --git a/components/events/EventBannerEditor.vue b/components/events/EventBannerEditor.vue new file mode 100644 index 000000000..517bb01db --- /dev/null +++ b/components/events/EventBannerEditor.vue @@ -0,0 +1,198 @@ + + + diff --git a/components/events/EventBannerUpload.vue b/components/events/EventBannerUpload.vue new file mode 100644 index 000000000..a3140ec07 --- /dev/null +++ b/components/events/EventBannerUpload.vue @@ -0,0 +1,227 @@ + + + diff --git a/components/events/EventCard.vue b/components/events/EventCard.vue new file mode 100644 index 000000000..9d5942721 --- /dev/null +++ b/components/events/EventCard.vue @@ -0,0 +1,89 @@ + + + diff --git a/components/events/EventForm.vue b/components/events/EventForm.vue new file mode 100644 index 000000000..2f8730893 --- /dev/null +++ b/components/events/EventForm.vue @@ -0,0 +1,541 @@ + + +