mirror of
https://github.com/Monadical-SAS/reflector.git
synced 2025-12-20 20:29:06 +00:00
- Migrated all components from useApi compatibility layer to direct React Query hooks - Added new hooks for participant operations, room meetings, and speaker operations - Updated all imports from old api module to api-types - Fixed TypeScript types and API endpoint signatures - Removed deprecated useApi.ts compatibility layer - Fixed SourceKind enum values to match OpenAPI spec - Added @ts-ignore for Zulip endpoints not in OpenAPI spec yet - Fixed all compilation errors and type issues
98 lines
2.5 KiB
TypeScript
98 lines
2.5 KiB
TypeScript
import React, { useState } from "react";
|
|
import { useTranscriptUploadAudio } from "../../lib/api-hooks";
|
|
import { Button, Spinner } from "@chakra-ui/react";
|
|
import { useError } from "../../(errors)/errorContext";
|
|
|
|
type FileUploadButton = {
|
|
transcriptId: string;
|
|
};
|
|
|
|
export default function FileUploadButton(props: FileUploadButton) {
|
|
const fileInputRef = React.useRef<HTMLInputElement>(null);
|
|
const uploadMutation = useTranscriptUploadAudio();
|
|
const { setError } = useError();
|
|
const [progress, setProgress] = useState(0);
|
|
const triggerFileUpload = () => {
|
|
fileInputRef.current?.click();
|
|
};
|
|
|
|
const handleFileUpload = async (
|
|
event: React.ChangeEvent<HTMLInputElement>,
|
|
) => {
|
|
const file = event.target.files?.[0];
|
|
|
|
if (file) {
|
|
const maxChunkSize = 50 * 1024 * 1024; // 50 MB
|
|
const totalChunks = Math.ceil(file.size / maxChunkSize);
|
|
let chunkNumber = 0;
|
|
let start = 0;
|
|
let uploadedSize = 0;
|
|
|
|
const uploadNextChunk = async () => {
|
|
if (chunkNumber == totalChunks) {
|
|
setProgress(0);
|
|
return;
|
|
}
|
|
|
|
const chunkSize = Math.min(maxChunkSize, file.size - start);
|
|
const end = start + chunkSize;
|
|
const chunk = file.slice(start, end);
|
|
|
|
try {
|
|
const formData = new FormData();
|
|
formData.append("chunk", chunk);
|
|
|
|
await uploadMutation.mutateAsync({
|
|
params: {
|
|
path: {
|
|
transcript_id: props.transcriptId,
|
|
},
|
|
query: {
|
|
chunk_number: chunkNumber,
|
|
total_chunks: totalChunks,
|
|
},
|
|
},
|
|
body: formData as any,
|
|
});
|
|
|
|
uploadedSize += chunkSize;
|
|
const currentProgress = Math.floor((uploadedSize / file.size) * 100);
|
|
setProgress(currentProgress);
|
|
|
|
chunkNumber++;
|
|
start = end;
|
|
|
|
await uploadNextChunk();
|
|
} catch (error) {
|
|
setError(error as Error, "Failed to upload file");
|
|
setProgress(0);
|
|
}
|
|
};
|
|
|
|
uploadNextChunk();
|
|
}
|
|
};
|
|
|
|
return (
|
|
<>
|
|
<Button onClick={triggerFileUpload} mr={2} disabled={progress > 0}>
|
|
{progress > 0 && progress < 100 ? (
|
|
<>
|
|
Uploading...
|
|
<Spinner size="sm" />
|
|
</>
|
|
) : (
|
|
<>Select File</>
|
|
)}
|
|
</Button>
|
|
|
|
<input
|
|
type="file"
|
|
ref={fileInputRef}
|
|
style={{ display: "none" }}
|
|
onChange={handleFileUpload}
|
|
/>
|
|
</>
|
|
);
|
|
}
|