Skip to content

Commit a71b3c0

Browse files
committed
fix(file-input): reject unsupported image formats on upload
When a user selects an image file whose MIME type is not in the allowed list (JPEG, PNG, GIF, WebP), the file is now rejected and an error modal is shown instead of silently accepting it. This prevents formats like AVIF from being uploaded when the backend does not support them. Signed-off-by: Dan <contact@danmyers.net>
1 parent addb6b7 commit a71b3c0

File tree

2 files changed

+27
-4
lines changed

2 files changed

+27
-4
lines changed

default.nix

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ let
2222

2323
in pkgs.mkShell {
2424
packages = with pkgs; [
25+
nodejs_24
2526
mise
2627
cargo-binstall
2728
(writeShellScriptBin "fish" ''
@@ -49,4 +50,4 @@ in pkgs.mkShell {
4950
echo "✅ Playwright versions in nix and npm are the same"
5051
fi
5152
'';
52-
}
53+
}

packages/client/components/ui/components/utils/Form2.tsx

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,14 @@ import {
99
splitProps,
1010
} from "solid-js";
1111

12-
import { Trans } from "@lingui-solid/solid/macro";
12+
import { Trans, useLingui } from "@lingui-solid/solid/macro";
1313
import { VirtualContainer } from "@minht11/solid-virtual-container";
1414
import { css } from "styled-system/css";
1515
import { styled } from "styled-system/jsx";
1616

17+
import { useModals } from "../../../modal";
18+
import { ALLOWED_IMAGE_TYPES } from "../../../state/stores/Draft";
19+
1720
import { Button, Checkbox, Radio2, Text, TextField } from "../design";
1821
import { TextEditor2 } from "../features/texteditor/TextEditor2";
1922

@@ -138,6 +141,11 @@ const FormFileInput = (
138141
>,
139142
) => {
140143
const [local, remote] = splitProps(props, ["label", "control"]);
144+
const { t } = useLingui();
145+
const { openModal } = useModals();
146+
147+
// track last accepted value so we can restore it if an invalid file is rejected
148+
let lastAcceptedValue = local.control.value;
141149

142150
return (
143151
<>
@@ -148,8 +156,22 @@ const FormFileInput = (
148156
{...remote}
149157
file={local.control.value}
150158
onFiles={(files) => {
151-
// TODO: do validation of files here
152-
159+
if (files && remote.accept === "image/*") {
160+
const file = files[0];
161+
if (!ALLOWED_IMAGE_TYPES.includes(file.type)) {
162+
const error = new Error(
163+
t`The file "${file.name}" has an unsupported format.`,
164+
);
165+
error.name = t`Unsupported file format`;
166+
openModal({ type: "error2", error });
167+
// FileInput resets to null before passing the new file for
168+
// reactivity reasons, so restore the last accepted value
169+
local.control.setValue(lastAcceptedValue);
170+
return;
171+
}
172+
}
173+
174+
if (files) lastAcceptedValue = files;
153175
local.control.setValue(files);
154176
local.control.markDirty(true);
155177
}}

0 commit comments

Comments
 (0)