feat: optimize profile image sizes, silent PWA updates, storage cleanup fixes

- Resize avatars/icons to 256px and banners to 1280px (client crop + server safety net)
- Add server-side resizeProfileImage() for federation/API uploads without crop modal
- Fix unconstrained crop on RegisterPage and CreateSpace (was missing maxOutputDimension)
- PWA: switch to autoUpdate with skipWaiting/clientsClaim for seamless deploys
- Storage janitor: exclude profile images from unlinked cleanup, delete stale thumbnails
- Add deleteAttachmentByFilename() to clean orphaned attachment records for profile images
- Migration: one-time cleanup of stale profile image attachment records
- GeneralPanel: wrap in <form> to prevent implicit submission
This commit is contained in:
Jannis Braun
2026-03-15 19:16:48 +01:00
parent 4d230711fc
commit 2e6fa3cdc6
15 changed files with 250 additions and 30 deletions
@@ -1,22 +1,22 @@
import { useRegisterSW } from 'virtual:pwa-register/react';
import { useEffect } from 'react';
export function SwUpdatePrompt() {
const {
needRefresh: [needRefresh],
updateServiceWorker,
} = useRegisterSW();
export function SwAutoUpdate() {
useRegisterSW({
onRegisteredSW(_swUrl, registration) {
if (!registration) return;
setInterval(() => {
registration.update();
}, 60_000);
},
});
if (!needRefresh) return null;
useEffect(() => {
if (!navigator.serviceWorker) return;
const onControllerChange = () => window.location.reload();
navigator.serviceWorker.addEventListener('controllerchange', onControllerChange);
return () => navigator.serviceWorker.removeEventListener('controllerchange', onControllerChange);
}, []);
return (
<div className="fixed bottom-6 left-1/2 -translate-x-1/2 z-[9999] glass-pill px-4 py-2.5 flex items-center gap-3 text-sm text-txt-primary shadow-lg">
<span>A new version is available</span>
<button
onClick={() => updateServiceWorker(true)}
className="px-3 py-1 rounded-md bg-accent-primary text-white text-xs font-medium hover:opacity-90 transition-opacity"
>
Reload
</button>
</div>
);
return null;
}