uploads
This commit is contained in:
parent
d80d046f65
commit
1fac563618
@ -4,7 +4,7 @@ import { useNavigate } from 'react-router-dom';
|
||||
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription } from '@/components/ui/dialog';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { T, translate } from '@/i18n';
|
||||
import { Image, FilePlus, Zap, Mic, Loader2, Upload, Video, Layers, BookPlus, Plus } from 'lucide-react';
|
||||
import { Image, FilePlus, Zap, Mic, Loader2, Upload, Video, Layers, BookPlus, Plus, HardDrive } from 'lucide-react';
|
||||
|
||||
import { usePageGenerator } from '@/hooks/usePageGenerator';
|
||||
import VoiceRecordingPopup from './VoiceRecordingPopup';
|
||||
@ -20,6 +20,7 @@ import { createPicture } from '@/modules/posts/client-pictures';
|
||||
import { fetchPostById } from '@/modules/posts/client-posts';
|
||||
import { toast } from 'sonner';
|
||||
import { supabase } from '@/integrations/supabase/client';
|
||||
import { serverUrl } from '@/lib/db';
|
||||
|
||||
interface CreationWizardPopupProps {
|
||||
isOpen: boolean;
|
||||
@ -45,6 +46,8 @@ export const CreationWizardPopup: React.FC<CreationWizardPopupProps> = ({
|
||||
const [isUploadingImage, setIsUploadingImage] = useState(false);
|
||||
const [isUploadingVideo, setIsUploadingVideo] = useState(false);
|
||||
const [videoUploadProgress, setVideoUploadProgress] = useState(0);
|
||||
const [isUploadingFiles, setIsUploadingFiles] = useState(false);
|
||||
const [fileUploadProgress, setFileUploadProgress] = useState(0);
|
||||
|
||||
const imageInputRef = useRef<HTMLInputElement>(null);
|
||||
const videoInputRef = useRef<HTMLInputElement>(null);
|
||||
@ -283,6 +286,66 @@ export const CreationWizardPopup: React.FC<CreationWizardPopupProps> = ({
|
||||
imageInputRef.current?.click();
|
||||
};
|
||||
|
||||
const handleFileUpload = async () => {
|
||||
const filesToUpload = preloadedImages.filter(img => img.file);
|
||||
if (filesToUpload.length === 0) {
|
||||
toast.error(translate('No files to upload'));
|
||||
return;
|
||||
}
|
||||
|
||||
const { data: { session: authSession } } = await supabase.auth.getSession();
|
||||
if (!authSession?.access_token) {
|
||||
toast.error(translate('Please sign in to upload files'));
|
||||
return;
|
||||
}
|
||||
|
||||
setIsUploadingFiles(true);
|
||||
setFileUploadProgress(0);
|
||||
const mount = 'home';
|
||||
let done = 0;
|
||||
|
||||
try {
|
||||
await Promise.all(filesToUpload.map(img => new Promise<void>((resolve, reject) => {
|
||||
const file = img.file as File;
|
||||
const xhr = new XMLHttpRequest();
|
||||
xhr.open('POST', `${serverUrl}/api/vfs/upload/${mount}/${encodeURIComponent(file.name)}`, true);
|
||||
xhr.setRequestHeader('Authorization', `Bearer ${authSession.access_token}`);
|
||||
|
||||
xhr.upload.onprogress = (evt) => {
|
||||
if (evt.lengthComputable) {
|
||||
const filePct = (evt.loaded / evt.total) * 100;
|
||||
setFileUploadProgress(Math.round(((done * 100) + filePct) / filesToUpload.length));
|
||||
}
|
||||
};
|
||||
|
||||
xhr.onload = () => {
|
||||
done++;
|
||||
setFileUploadProgress(Math.round((done / filesToUpload.length) * 100));
|
||||
if (xhr.status >= 200 && xhr.status < 300) {
|
||||
resolve();
|
||||
} else {
|
||||
let msg = `Error ${xhr.status}`;
|
||||
try { const b = JSON.parse(xhr.responseText); msg = b.message || b.error || msg; } catch {}
|
||||
reject(new Error(msg));
|
||||
}
|
||||
};
|
||||
xhr.onerror = () => reject(new Error('Network error'));
|
||||
|
||||
const formData = new FormData();
|
||||
formData.append('file', file);
|
||||
xhr.send(formData);
|
||||
})));
|
||||
|
||||
toast.success(translate(`${filesToUpload.length} file(s) uploaded to storage`));
|
||||
onClose();
|
||||
} catch (error: any) {
|
||||
toast.error(error.message || translate('Upload failed'));
|
||||
} finally {
|
||||
setIsUploadingFiles(false);
|
||||
setFileUploadProgress(0);
|
||||
}
|
||||
};
|
||||
|
||||
// Helper function to upload internal video
|
||||
const uploadInternalVideo = async (file: File): Promise<void> => {
|
||||
// Get auth token before creating the XHR
|
||||
@ -526,6 +589,25 @@ export const CreationWizardPopup: React.FC<CreationWizardPopupProps> = ({
|
||||
<T>Append to Existing Post</T>
|
||||
</Button>
|
||||
)}
|
||||
{preloadedImages.length > 0 && (
|
||||
<Button
|
||||
variant="outline"
|
||||
onClick={handleFileUpload}
|
||||
disabled={isUploadingFiles}
|
||||
>
|
||||
{isUploadingFiles ? (
|
||||
<>
|
||||
<Loader2 className="h-4 w-4 mr-2 animate-spin" />
|
||||
<T>Uploading</T> {fileUploadProgress}%
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<HardDrive className="h-4 w-4 mr-2" />
|
||||
<T>Upload as Files</T>
|
||||
</>
|
||||
)}
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@ -28,18 +28,19 @@ const GlobalDragDrop = () => {
|
||||
// Check if it's a valid URL (simplistic check)
|
||||
const isUrl = url && (url.startsWith('http://') || url.startsWith('https://'));
|
||||
|
||||
if (supportedFiles.length === 0 && !isUrl) {
|
||||
if (files.length > 0) {
|
||||
toast.error("Unsupported file type. Please drop images or videos.");
|
||||
}
|
||||
// Any file type is acceptable — wizard has "Upload as Files" for non-media
|
||||
if (files.length === 0 && !isUrl) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Use all files if no media-specific ones found (for VFS file upload)
|
||||
const filesToPass = supportedFiles.length > 0 ? supportedFiles : files;
|
||||
|
||||
try {
|
||||
if (supportedFiles.length > 0) {
|
||||
// Normal file workflow
|
||||
if (files.length > 0) {
|
||||
// File workflow — wizard shows options incl. "Upload as Files"
|
||||
await set('share-target', {
|
||||
files: supportedFiles,
|
||||
files: filesToPass,
|
||||
title: '',
|
||||
text: '',
|
||||
url: isUrl ? url : '',
|
||||
@ -142,7 +143,7 @@ const GlobalDragDrop = () => {
|
||||
<T>Drop files to upload</T>
|
||||
</h2>
|
||||
<p className="text-muted-foreground mt-2">
|
||||
<T>Drag images or videos anywhere to start</T>
|
||||
<T>Drag files anywhere to start</T>
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user