diff --git a/web/src/pages/admin/PluginsPage.tsx b/web/src/pages/admin/PluginsPage.tsx index e447e18..5e8dad1 100644 --- a/web/src/pages/admin/PluginsPage.tsx +++ b/web/src/pages/admin/PluginsPage.tsx @@ -1,4 +1,4 @@ -import { useState, useRef, useEffect } from 'react'; +import { useState, useRef, useEffect, type DragEvent } from 'react'; import { useTranslation } from 'react-i18next'; import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; import { pluginsApi } from '../../shared/api/plugins'; @@ -459,9 +459,11 @@ function InstallPluginModal({ const { t } = useTranslation(); const { toast } = useToast(); const fileInputRef = useRef(null); + const dragCounterRef = useRef(0); const [installTab, setInstallTab] = useState<'upload' | 'github'>('upload'); const [selectedFile, setSelectedFile] = useState(null); + const [dragActive, setDragActive] = useState(false); const [pluginName, setPluginName] = useState(''); const [githubRepo, setGithubRepo] = useState(''); @@ -491,14 +493,46 @@ function InstallPluginModal({ setSelectedFile(null); setPluginName(''); setGithubRepo(''); + dragCounterRef.current = 0; if (fileInputRef.current) fileInputRef.current.value = ''; } function handleClose() { resetForm(); + setDragActive(false); onClose(); } + function handleFileSelect(file: File | null) { + setSelectedFile(file); + setDragActive(false); + } + + function handleDragEvent(e: DragEvent) { + e.preventDefault(); + e.stopPropagation(); + } + + function handleDragEnter(e: DragEvent) { + handleDragEvent(e); + dragCounterRef.current += 1; + setDragActive(true); + } + + function handleDragLeave(e: DragEvent) { + handleDragEvent(e); + dragCounterRef.current = Math.max(0, dragCounterRef.current - 1); + if (dragCounterRef.current === 0) { + setDragActive(false); + } + } + + function handleDrop(e: DragEvent) { + handleDragEvent(e); + dragCounterRef.current = 0; + handleFileSelect(e.dataTransfer.files?.[0] || null); + } + const installing = uploadMutation.isPending || githubMutation.isPending; const installTabs = [ @@ -564,18 +598,23 @@ function InstallPluginModal({ {t('plugins.plugin_file')} *
fileInputRef.current?.click()} + onDragOver={handleDragEvent} + onDragEnter={handleDragEnter} + onDragLeave={handleDragLeave} + onDrop={handleDrop} > setSelectedFile(e.target.files?.[0] || null)} + onChange={(e) => handleFileSelect(e.target.files?.[0] || null)} /> {selectedFile ? (
@@ -587,7 +626,7 @@ function InstallPluginModal({
) : (
- +

{t('plugins.upload_hint')}