diff --git a/app/components/timeline/MediaBin.tsx b/app/components/timeline/MediaBin.tsx
index 454fe966..4c821272 100644
--- a/app/components/timeline/MediaBin.tsx
+++ b/app/components/timeline/MediaBin.tsx
@@ -230,6 +230,29 @@ const AudioPreview = ({ src }: { src: string }) => {
);
};
+// Empty state component for when no media files are present
+const EmptyState = memo(({ onUploadClick }: { onUploadClick: () => void }) => {
+ return (
+
+
+
+ );
+});
+
// This is required for the data router
export function loader() {
return null;
@@ -251,6 +274,9 @@ export default function MediaBin() {
// Drag & Drop state for external file imports
const [isDragOver, setIsDragOver] = useState(false);
+ // File input ref for click-to-upload
+ const fileInputRef = useRef(null);
+
// Arrange & sorting state
const [arrangeMode, setArrangeMode] = useState<"default" | "group">(
"default"
@@ -360,6 +386,28 @@ export default function MediaBin() {
[onAddMedia]
);
+ const handleUploadClick = useCallback(() => {
+ fileInputRef.current?.click();
+ }, []);
+
+ const handleFileInputChange = useCallback(
+ async (e: React.ChangeEvent) => {
+ const files = Array.from(e.target.files || []);
+ for (const file of files) {
+ try {
+ await onAddMedia(file);
+ } catch (err) {
+ console.error("Failed to import file:", file.name, err);
+ }
+ }
+ // Reset input so same file can be selected again
+ if (fileInputRef.current) {
+ fileInputRef.current.value = "";
+ }
+ },
+ [onAddMedia]
+ );
+
const getMediaIcon = (mediaType: string) => {
switch (mediaType) {
case "video":
@@ -711,13 +759,7 @@ export default function MediaBin() {
))}
{defaultArrangedItems.length === 0 && (
-
-
-
No media files
-
- Import videos, images, or audio to get started
-
-
+
)}
>
)}
@@ -884,13 +926,7 @@ export default function MediaBin() {
))}
{counts.all === 0 && (
-
-
-
No media files
-
- Import videos, images, or audio to get started
-
-
+
)}
)}
@@ -1019,6 +1055,16 @@ export default function MediaBin() {
)}
+
+ {/* Hidden file input for click-to-upload */}
+
);
}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 6acb83ba..1ee5ee10 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -2080,11 +2080,11 @@ packages:
peerDependencies:
ajv: ^8.8.2
- ajv@6.12.6:
- resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==}
+ ajv@6.14.0:
+ resolution: {integrity: sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==}
- ajv@8.17.1:
- resolution: {integrity: sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==}
+ ajv@8.18.0:
+ resolution: {integrity: sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==}
ansi-styles@4.3.0:
resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
@@ -4958,7 +4958,7 @@ snapshots:
'@eslint/eslintrc@3.3.1':
dependencies:
- ajv: 6.12.6
+ ajv: 6.14.0
debug: 4.4.1
espree: 10.4.0
globals: 14.0.0
@@ -6272,27 +6272,27 @@ snapshots:
acorn@8.15.0: {}
- ajv-formats@2.1.1(ajv@8.17.1):
+ ajv-formats@2.1.1(ajv@8.18.0):
optionalDependencies:
- ajv: 8.17.1
+ ajv: 8.18.0
- ajv-keywords@3.5.2(ajv@6.12.6):
+ ajv-keywords@3.5.2(ajv@6.14.0):
dependencies:
- ajv: 6.12.6
+ ajv: 6.14.0
- ajv-keywords@5.1.0(ajv@8.17.1):
+ ajv-keywords@5.1.0(ajv@8.18.0):
dependencies:
- ajv: 8.17.1
+ ajv: 8.18.0
fast-deep-equal: 3.1.3
- ajv@6.12.6:
+ ajv@6.14.0:
dependencies:
fast-deep-equal: 3.1.3
fast-json-stable-stringify: 2.1.0
json-schema-traverse: 0.4.1
uri-js: 4.4.1
- ajv@8.17.1:
+ ajv@8.18.0:
dependencies:
fast-deep-equal: 3.1.3
fast-uri: 3.0.6
@@ -6993,7 +6993,7 @@ snapshots:
'@humanwhocodes/retry': 0.4.3
'@types/estree': 1.0.8
'@types/json-schema': 7.0.15
- ajv: 6.12.6
+ ajv: 6.14.0
chalk: 4.1.2
cross-spawn: 7.0.6
debug: 4.4.1
@@ -8276,15 +8276,15 @@ snapshots:
schema-utils@3.3.0:
dependencies:
'@types/json-schema': 7.0.15
- ajv: 6.12.6
- ajv-keywords: 3.5.2(ajv@6.12.6)
+ ajv: 6.14.0
+ ajv-keywords: 3.5.2(ajv@6.14.0)
schema-utils@4.3.3:
dependencies:
'@types/json-schema': 7.0.15
- ajv: 8.17.1
- ajv-formats: 2.1.1(ajv@8.17.1)
- ajv-keywords: 5.1.0(ajv@8.17.1)
+ ajv: 8.18.0
+ ajv-formats: 2.1.1(ajv@8.18.0)
+ ajv-keywords: 5.1.0(ajv@8.18.0)
semver@6.3.1: {}