Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions src/components/FileUpload.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,16 @@ export default function FileUpload({
setError("");
setWarning("");

if (!file.type.startsWith("video/")) {
const validExtensions = [".mp4", ".mov", ".avi", ".webm", ".mkv"];
const filename = file.name.toLowerCase();
const hasValidExtension = validExtensions.some((ext) => filename.endsWith(ext));
const isVideoMime = file.type.startsWith("video/");
const isGenericMime =
!file.type ||
file.type === "application/octet-stream" ||
file.type === "application/x-matroska";

if (!isVideoMime && (!hasValidExtension || !isGenericMime)) {
setError("Please drop a valid video file (MP4, MOV, AVI, WebM, etc.)");
return;
}
Expand Down Expand Up @@ -429,7 +438,7 @@ export default function FileUpload({
<input
ref={inputRef}
type="file"
accept="video/*"
accept="video/*,.mp4,.mov,.avi,.webm,.mkv"
className="hidden"
onChange={(e) => {
const f = e.target.files?.[0];
Expand Down
29 changes: 29 additions & 0 deletions src/hooks/tests/useVideoEditor.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ describe("useVideoEditor core controller", () => {
beforeEach(() => {
vi.clearAllMocks();
localStorageMock.clear();
window.history.replaceState(null, "", "/");
});

it("should initialize with the default recipe", () => {
Expand All @@ -62,6 +63,7 @@ describe("useVideoEditor core controller", () => {

it("should ignore invalid patch values via isValidValue check", () => {
const { result } = renderHook(() => useVideoEditor());
expect(result.current.recipe.speed).toBe(DEFAULT_RECIPE.speed);
act(() => {
// 9999 is invalid for speed, -50 is invalid for quality
result.current.updateRecipe({ speed: 9999, quality: -50 } as any);
Expand All @@ -83,4 +85,31 @@ describe("useVideoEditor core controller", () => {
});
expect(result.current.recipe.speed).toBe(DEFAULT_RECIPE.speed);
});

it("should accept video file with empty or generic MIME type if extension is valid", () => {
const { result } = renderHook(() => useVideoEditor());
const validFileWithGenericMime = new File(["dummy content"], "test.mp4", {
type: "",
});

act(() => {
result.current.handleFileSelect(validFileWithGenericMime);
});

expect(result.current.fileError).toBe("");
expect(result.current.error).toBeNull();
});

it("should reject non-video files even if MIME type is empty or generic", () => {
const { result } = renderHook(() => useVideoEditor());
const invalidFile = new File(["dummy content"], "document.pdf", {
type: "",
});

act(() => {
result.current.handleFileSelect(invalidFile);
});

expect(result.current.fileError).toBe("Please upload a video file only.");
});
});
17 changes: 12 additions & 5 deletions src/hooks/useVideoEditor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -424,7 +424,17 @@ export function useVideoEditor() {
return;
}

if (!selectedFile.type.startsWith("video/")) {
const validExtensions = [".mp4", ".mov", ".avi", ".webm", ".mkv"];
const filename = selectedFile.name.toLowerCase();
const hasValidExtension = validExtensions.some((ext) => filename.endsWith(ext));

const isVideoMime = selectedFile.type.startsWith("video/");
const isGenericMime =
!selectedFile.type ||
selectedFile.type === "application/octet-stream" ||
selectedFile.type === "application/x-matroska";

if (!isVideoMime && (!hasValidExtension || !isGenericMime)) {
setFileError("Please upload a video file only.");
return;
}
Expand All @@ -438,9 +448,6 @@ export function useVideoEditor() {
return;
}

const validExtensions = [".mp4", ".mov", ".avi", ".webm", ".mkv"];
const filename = selectedFile.name.toLowerCase();
const hasValidExtension = validExtensions.some((ext) => filename.endsWith(ext));
if (!hasValidExtension) {
setError(
`Layer 1 Validation Failed: Invalid file extension. Expected one of: ${validExtensions.join(", ")}`
Expand All @@ -449,7 +456,7 @@ export function useVideoEditor() {
return;
}

if (!selectedFile.type.startsWith("video/")) {
if (!isVideoMime && !isGenericMime) {
setError(
`Layer 2 Validation Failed: Invalid MIME type. Expected video/*, got ${selectedFile.type || "unknown"}`
);
Expand Down
Loading