Przeglądaj źródła

Supported video format warning

Sviluppo_Carrello_Immagini
Lorenzo Pollutri 1 miesiąc temu
rodzic
commit
8703e27286
2 zmienionych plików z 50 dodań i 13 usunięć
  1. +48
    -12
      app/admin/page.tsx
  2. +2
    -1
      components/PublicGrid.tsx

+ 48
- 12
app/admin/page.tsx Wyświetl plik

@@ -66,11 +66,18 @@ function CardTypeSelect({
);
}
const isVideoUrl = (url: string) => /\.(mp4|webm|mov|m4v|ogv)(\?|$)/i.test(url);
const VIDEO_EXTENSIONS = 'mp4|m4v|webm|mov|qt|mkv|avi|divx|wmv|asf|flv|f4v|3gp|3gpp|3g2|mts|m2ts|ts|mpg|mpeg|vob|mxf|ogv|ogg';
// Sottoinsieme di formati video davvero riproducibili dai browser moderni
const PLAYBACK_SUPPORTED_VIDEO = 'mp4|m4v|webm|mov|qt|ogv|ogg';
const PLAYBACK_SUPPORTED_LABEL = 'MP4, M4V, WebM, MOV, OGV';
const isVideoUrl = (url: string) => new RegExp(`\\.(${VIDEO_EXTENSIONS})(\\?|$)`, 'i').test(url);
const isPdfFile = (file: File) =>
file.type === 'application/pdf' || /\.pdf$/i.test(file.name);
const isVideoFile = (file: File) =>
file.type.startsWith('video/') || /\.(mp4|webm|mov|m4v|ogv)$/i.test(file.name);
file.type.startsWith('video/') || new RegExp(`\\.(${VIDEO_EXTENSIONS})$`, 'i').test(file.name);
const isPlayableVideoFile = (file: File) =>
new RegExp(`\\.(${PLAYBACK_SUPPORTED_VIDEO})$`, 'i').test(file.name);
const extractFileName = (url: string): string => {
const match = url.match(/[?&]name=([^&]+)/);
@@ -171,7 +178,7 @@ export default function AdminDashboard() {
const [uploading, setUploading] = useState<{ [key: string]: boolean }>({});
// NEW UI STATES: Toast and Confirm Dialog
const [toast, setToast] = useState<string | null>(null);
const [toast, setToast] = useState<{ message: string; type: 'success' | 'error' } | null>(null);
const [confirmDialog, setConfirmDialog] = useState<{ message: string, onConfirm: () => void } | null>(null);
const [pdfProgress, setPdfProgress] = useState<{ name: string; page: number; total: number } | null>(null);
@@ -179,9 +186,9 @@ export default function AdminDashboard() {
const externalLinksOn = portal.externalLinkEnabled ?? EXTERNAL_LINK_DEFAULT;
// Helper to show auto-dismissing toast
const showToast = (message: string) => {
setToast(message);
setTimeout(() => setToast(null), 3000);
const showToast = (message: string, type: 'success' | 'error' = 'success') => {
setToast({ message, type });
setTimeout(() => setToast(null), type === 'error' ? 6000 : 3000);
};
useEffect(() => {
@@ -217,8 +224,33 @@ export default function AdminDashboard() {
let pendingCover: string | null = null;
const canPromote = () => startedWithoutCover && !pendingCover;
const uploaded: MediaItem[] = [];
// Pre-filtro: scarta video con formati non riproducibili nei browser
const rejected: string[] = [];
const acceptedFiles: File[] = [];
for (const file of Array.from(files)) {
if (isVideoFile(file) && !isPlayableVideoFile(file)) {
rejected.push(file.name);
} else {
acceptedFiles.push(file);
}
}
if (rejected.length > 0) {
const list = rejected.length <= 3
? rejected.join(', ')
: `${rejected.slice(0, 3).join(', ')} e altri ${rejected.length - 3}`;
showToast(
`Formato non supportato! I formati supportati sono: ${PLAYBACK_SUPPORTED_LABEL}. File ignorati: ${list}`,
'error'
);
}
if (acceptedFiles.length === 0) {
setUploading(prev => ({ ...prev, extraMedia: false }));
e.target.value = '';
return;
}
const uploaded: MediaItem[] = [];
for (const file of acceptedFiles) {
try {
if (isPdfFile(file)) {
const items = await pdfToImageItems(file, (page, total) =>
@@ -701,7 +733,7 @@ export default function AdminDashboard() {
<div className="border-2 border-dashed border-gray-300 rounded-lg p-3 hover:bg-gray-50 transition-colors">
<input
type="file"
accept="image/*,video/*,application/pdf,.pdf"
accept="image/*,video/*,application/pdf,.pdf,.mov,.qt,.mkv,.avi,.divx,.wmv,.asf,.flv,.f4v,.3gp,.3gpp,.3g2,.mts,.m2ts,.ts,.mpg,.mpeg,.vob,.mxf,.ogv,.ogg"
multiple
onChange={handleUploadExtraMedia}
className="block w-full text-sm text-gray-700 file:mr-4 file:py-2 file:px-4 file:rounded-full file:border-0 file:text-sm file:font-semibold file:bg-purple-50 file:text-purple-700 hover:file:bg-purple-100 cursor-pointer"
@@ -818,11 +850,15 @@ export default function AdminDashboard() {
{/* CUSTOM TOAST NOTIFICATION */}
{toast && (
<div className="fixed bottom-6 right-6 z-[70] bg-gray-900 text-white px-6 py-4 rounded-lg shadow-2xl flex items-center gap-3 animate-in slide-in-from-bottom-5 fade-in duration-300">
<div className="w-6 h-6 bg-green-500 rounded-full flex items-center justify-center text-gray-900 font-bold text-sm">
<div className={`fixed bottom-6 right-6 z-[70] text-white px-6 py-4 rounded-lg shadow-2xl flex items-start gap-3 animate-in slide-in-from-bottom-5 fade-in duration-300 max-w-md ${
toast.type === 'error' ? 'bg-red-700' : 'bg-gray-900'
}`}>
<div className={`w-6 h-6 rounded-full flex items-center justify-center font-bold text-sm shrink-0 mt-0.5 ${
toast.type === 'error' ? 'bg-white text-red-700' : 'bg-green-500 text-gray-900'
}`}>
{toast.type === 'error' ? '!' : '✓'}
</div>
<span className="font-medium">{toast}</span>
<span className="font-medium leading-snug">{toast.message}</span>
</div>
)}


+ 2
- 1
components/PublicGrid.tsx Wyświetl plik

@@ -2,7 +2,8 @@
import { useState, useEffect, useCallback, useRef } from 'react';
import { Card, MediaItem } from '@/types';

const isVideoUrl = (url: string) => /\.(mp4|webm|mov|m4v|ogv)(\?|$)/i.test(url);
const VIDEO_EXTENSIONS = 'mp4|m4v|webm|mov|qt|mkv|avi|divx|wmv|asf|flv|f4v|3gp|3gpp|3g2|mts|m2ts|ts|mpg|mpeg|vob|mxf|ogv|ogg';
const isVideoUrl = (url: string) => new RegExp(`\\.(${VIDEO_EXTENSIONS})(\\?|$)`, 'i').test(url);

function MediaCarousel({
items,


Ładowanie…
Anuluj
Zapisz