mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-06-21 14:21:46 +00:00
feat(journey): convert HEIC/HEIF uploads to JPEG for cross-platform compatibility
HEIC is an Apple-only format not recognised as an image by many browsers and platforms. heic-to (lazy-loaded) now converts HEIC/HEIF files to JPEG before upload in both the gallery and entry editor photo pickers. Embedded metadata (EXIF, GPS) may be lost during conversion — documented in the Journey Journal wiki page.
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import { useEffect, useState, useRef, useCallback, useMemo } from 'react'
|
||||
import { formatLocationName } from '../utils/formatters'
|
||||
import { normalizeImageFiles } from '../utils/convertHeic'
|
||||
import { createPortal } from 'react-dom'
|
||||
import { useParams, useNavigate } from 'react-router-dom'
|
||||
import { useJourneyStore } from '../store/journeyStore'
|
||||
@@ -1027,8 +1028,9 @@ function GalleryView({ entries, gallery, journeyId, userId, trips, onPhotoClick,
|
||||
if (!files?.length) return
|
||||
setGalleryUploading(true)
|
||||
try {
|
||||
const normalized = await normalizeImageFiles(files)
|
||||
const formData = new FormData()
|
||||
for (const f of files) formData.append('photos', f)
|
||||
for (const f of normalized) formData.append('photos', f)
|
||||
await journeyApi.uploadGalleryPhotos(journeyId, formData)
|
||||
toast.success(t('journey.photosUploaded', { count: files.length }))
|
||||
onRefresh()
|
||||
@@ -2265,7 +2267,8 @@ function EntryEditor({ entry, journeyId, tripDates, galleryPhotos, onClose, onSa
|
||||
if (!files?.length) return
|
||||
// Queue files locally until Save so cancel/close actually discards. This
|
||||
// keeps photo behavior consistent with text fields — no silent persistence.
|
||||
setPendingFiles(prev => [...prev, ...Array.from(files)])
|
||||
const normalized = await normalizeImageFiles(files)
|
||||
setPendingFiles(prev => [...prev, ...normalized])
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
export async function normalizeImageFile(file: File): Promise<File> {
|
||||
const { isHeic, heicTo } = await import('heic-to')
|
||||
if (!(await isHeic(file))) return file
|
||||
const blob = await heicTo({ blob: file, type: 'image/jpeg', quality: 0.92 })
|
||||
const jpegName = file.name.replace(/\.(heic|heif)$/i, '.jpg')
|
||||
return new File([blob], jpegName, { type: 'image/jpeg' })
|
||||
}
|
||||
|
||||
export async function normalizeImageFiles(files: FileList | File[]): Promise<File[]> {
|
||||
return Promise.all(Array.from(files).map(normalizeImageFile))
|
||||
}
|
||||
Reference in New Issue
Block a user