diff --git a/client/src/components/Files/FileManager.tsx b/client/src/components/Files/FileManager.tsx index dbaefa73..4295c46a 100644 --- a/client/src/components/Files/FileManager.tsx +++ b/client/src/components/Files/FileManager.tsx @@ -1,7 +1,7 @@ import ReactDOM from 'react-dom' import { useState, useCallback, useRef, useEffect } from 'react' import { useDropzone } from 'react-dropzone' -import { Upload, Trash2, ExternalLink, X, FileText, FileImage, File, MapPin, Ticket, StickyNote, Star, RotateCcw, Pencil, Check, ChevronLeft, ChevronRight } from 'lucide-react' +import { Upload, Trash2, ExternalLink, Download, X, FileText, FileImage, File, MapPin, Ticket, StickyNote, Star, RotateCcw, Pencil, Check, ChevronLeft, ChevronRight } from 'lucide-react' import { useToast } from '../shared/Toast' import { useTranslation } from '../../i18n' import { filesApi } from '../../api/client' @@ -30,6 +30,18 @@ function formatSize(bytes) { return `${(bytes / 1024 / 1024).toFixed(1)} MB` } +async function triggerDownload(url: string, filename: string) { + const authUrl = await getAuthUrl(url, 'download') + const res = await fetch(authUrl) + const blob = await res.blob() + const a = document.createElement('a') + a.href = URL.createObjectURL(blob) + a.download = filename + document.body.appendChild(a) + a.click() + setTimeout(() => { URL.revokeObjectURL(a.href); a.remove() }, 100) +} + function formatDateWithLocale(dateStr, locale) { if (!dateStr) return '' try { @@ -113,6 +125,12 @@ function ImageLightbox({ files, initialIndex, onClose }: ImageLightboxProps) { title={t('files.openTab')}> + @@ -514,6 +532,10 @@ export default function FileManager({ files = [], onUpload, onDelete, onUpdate, onMouseEnter={e => e.currentTarget.style.color = 'var(--text-primary)'} onMouseLeave={e => e.currentTarget.style.color = 'var(--text-faint)'}> + {can('file_delete', trip) && +