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) &&
+