fix(uploads): register HEIC/HEIF with the file validator + fix admin format hint (codex review of #832)

Two findings from the Codex review:

- validateFileType requires an ALLOWED_MEDIA_TYPES entry, which had neither
  image/heic nor image/heif — so HEIC was rejected before sharp ever saw it,
  despite the EXTENSION_TO_MIME additions. Added both with a single 'ftyp'
  (offset 4) magic number (the check is .every, so alternatives can't be
  separate entries).

- Changing the shared upload.fileRequirements string to interpolate {{formats}}
  left the admin PhotoUpload caller passing only { limit }, rendering the
  placeholder literally (it was also already dropping {{sizeLimit}} from #823).
  The admin caller now passes formats + sizeLimit + limit, from the admin
  settings it already loads.
This commit is contained in:
Paul Nothaft
2026-07-17 22:06:40 +02:00
parent 2b5b23b96f
commit c9b64d9c1a
2 changed files with 27 additions and 2 deletions
+11 -2
View File
@@ -8,7 +8,7 @@ import { useQuery } from '@tanstack/react-query';
import { categoriesService } from '../../services/categories.service';
import { settingsService } from '../../services/settings.service';
import { useTranslation } from 'react-i18next';
import { extensionsToMimeTypes, extensionsToAcceptString } from '../../utils/fileTypes';
import { extensionsToMimeTypes, extensionsToAcceptString, extensionsToLabel } from '../../utils/fileTypes';
import { useUploadProgress } from '../../hooks/useUploadProgress';
interface PhotoUploadProps {
@@ -118,6 +118,15 @@ export const PhotoUpload: React.FC<PhotoUploadProps> = ({ eventId, onUploadCompl
[settings?.general_allowed_file_types]
);
const formatsLabel = useMemo(
() => extensionsToLabel(settings?.general_allowed_file_types),
[settings?.general_allowed_file_types]
);
const maxFileSizeMb = Number.isFinite(Number(settings?.general_max_file_size_mb))
? Number(settings?.general_max_file_size_mb)
: 50;
const remainingSlots = Math.max(maxFilesPerUpload - selectedFiles.length, 0);
const [isDragOver, setIsDragOver] = useState(false);
@@ -511,7 +520,7 @@ export const PhotoUpload: React.FC<PhotoUploadProps> = ({ eventId, onUploadCompl
{t('upload.clickToUpload')}
</p>
<p className="text-sm text-neutral-500 dark:text-neutral-400">
{t('upload.fileRequirements', { limit: maxFilesPerUpload })}
{t('upload.fileRequirements', { formats: formatsLabel, limit: maxFilesPerUpload, sizeLimit: maxFileSizeMb })}
</p>
<p
className={clsx(