2 Commits

5 changed files with 35 additions and 38 deletions

View File

@@ -5,15 +5,32 @@ type props = {
dataSend: React.MouseEventHandler<HTMLButtonElement>;
handleDownload: React.MouseEventHandler<HTMLButtonElement>;
downloadable: boolean;
progress: number
progress: number;
uploading: boolean;
}
const ExportWidget = ({dataSend, handleDownload, downloadable, progress}: props) => {
const Spinner = () => (
<svg
className="animate-spin h-4 w-4"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
>
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4" />
<path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8v4a4 4 0 00-4 4H4z" />
</svg>
);
const ExportWidget = ({dataSend, handleDownload, downloadable, progress, uploading}: props) => {
return (
<div className={"flex flex-col gap-3"}>
<BlueButton
onClick={dataSend}>
Export
onClick={dataSend}
disabled={uploading}
className={uploading ? "opacity-60 cursor-not-allowed flex items-center justify-center gap-2" : ""}
>
{uploading && <Spinner />}
{uploading ? "Uploading..." : "Export"}
</BlueButton>
<div className="h-10 flex items-center">
@@ -33,4 +50,4 @@ const ExportWidget = ({dataSend, handleDownload, downloadable, progress}: props)
)
}
export default ExportWidget;
export default ExportWidget;

View File

@@ -34,6 +34,7 @@ const ClipEdit = () => {
});
const [progress, setProgress] = useState(0);
const [downloadable, setDownloadable] = useState(false);
const [uploading, setUploading] = useState(false);
const [error, setError] = useState<string | null>(null);
useEffect(() => {
@@ -59,7 +60,10 @@ const ClipEdit = () => {
};
const sendData = async () => {
if (!localFile) return;
if (!localFile || uploading) return;
setUploading(true);
setError(null);
let jobId: string;
try {
@@ -67,6 +71,7 @@ const ClipEdit = () => {
setUploadedId(jobId);
} catch (err: unknown) {
setError(`Failed to start compression: ${err instanceof Error ? err.message : 'Unknown error'}`);
setUploading(false);
return;
}
@@ -81,14 +86,17 @@ const ClipEdit = () => {
if (job.state === 'FAILED') {
setError(`Compression failed: ${job.errorOutput ?? 'Unknown error'}`);
clearInterval(intervalId);
setUploading(false);
} else if (job.isComplete) {
clearInterval(intervalId);
setDownloadable(true);
setUploading(false);
}
})
.catch((err: Error) => {
setError(`Failed to fetch progress: ${err.message}`);
clearInterval(intervalId);
setUploading(false);
});
};
@@ -166,6 +174,7 @@ const ClipEdit = () => {
handleDownload={handleDownload}
downloadable={downloadable}
progress={progress}
uploading={uploading}
/>
</Box>
</div>

View File

@@ -16,6 +16,7 @@ import java.nio.file.Path;
import java.time.Duration;
import java.time.Instant;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@Service
@@ -214,7 +215,7 @@ public class MediaService {
return segMs < endMs && (segMs + HLS_SEGMENT_LENGTH * 1000) > startMs;
})
.sorted(Comparator.comparingLong(this::parseTimestampMs))
.toList();
.collect(Collectors.toList());
}
}

View File

@@ -6,7 +6,6 @@ import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import java.io.IOException;
import java.nio.file.Path;
import java.util.List;
import java.util.concurrent.CompletableFuture;
@@ -76,13 +75,9 @@ public class StreamActionsService {
progressTracker.markComplete();
return CompletableFuture.completedFuture(outputFile);
} catch (IOException e) {
} catch (Exception e) {
logger.error("Failed to save section to '{}'", outputFile, e);
return CompletableFuture.failedFuture(e);
} catch (InterruptedException e) {
logger.error("Failed to save section");
Thread.currentThread().interrupt();
return CompletableFuture.failedFuture(e);
}
}
}

View File

@@ -1,25 +0,0 @@
INSERT INTO users ( google_id, username, email, name)
VALUES
('google-uid-001', 'alice', 'alice@example.com', 'Alice Example'),
( 'google-uid-002', 'bob', 'bob@example.com', 'Bob Example'),
('google-uid-003', 'carol', 'carol@example.com', 'Carol Example'),
( 'google-uid-004', 'wizard42', 'gandalf@middle.earth', 'Gandalf the Grey'),
( 'google-uid-005', 'catnap', 'whiskers@meowmail.com', 'Sir Whiskers McFluff'),
( 'google-uid-006', 'robotron', 'bender@futurama.tv', 'Bender Rodriguez'),
('google-uid-007', 'unicorn', 'sparkle@rainbow.com', 'Princess Sparklehoof'),
( 'google-uid-008', 'pirate', 'blackbeard@seas.com', 'Edward Teach'),
( 'google-uid-009', 'detective', 'holmes@bakerstreet.uk', 'Sherlock Holmes'),
( 'google-uid-010', 'timey', 'docbrown@delorean.net', 'Dr. Emmett Brown');
INSERT INTO clips (user_id, title, description, width, height, fps, duration, file_size, video_path)
VALUES
(4, 'Fireworks Over Hobbiton', 'A magical display of fireworks by Gandalf.', 1920, 1080, 30, 120, 104857600, '/videos/fireworks_hobbiton.mp4'),
(5, 'Catnap Chronicles', 'Sir Whiskers McFluff naps in 12 different positions.', 1280, 720, 24, 60, 52428800, '/videos/catnap_chronicles.mp4'),
(6, 'Bite My Shiny Metal...', 'Bender shows off his new upgrades.', 1920, 1080, 60, 45, 73400320, '/videos/bender_upgrades.mp4'),
(7, 'Rainbow Dash', 'Princess Sparklehoof gallops across a double rainbow.', 1920, 1080, 30, 90, 67108864, '/videos/rainbow_dash.mp4'),
( 8, 'Pirate Karaoke Night', 'Blackbeard sings sea shanties with his crew.', 1280, 720, 25, 180, 157286400, '/videos/pirate_karaoke.mp4'),
( 9, 'The Case of the Missing Sandwich', 'Sherlock Holmes investigates a lunchtime mystery.', 1920, 1080, 30, 75, 50331648, '/videos/missing_sandwich.mp4'),
( 10, '88 Miles Per Hour', 'Doc Brown demonstrates time travel with style.', 1920, 1080, 60, 30, 41943040, '/videos/88mph.mp4'),
( 1, 'Alice in Videoland', 'Alice explores a surreal digital wonderland.', 1280, 720, 30, 150, 94371840, '/videos/alice_videoland.mp4'),
( 2, 'Bob''s Building Bonanza', 'Bob constructs a house out of cheese.', 1920, 1080, 24, 200, 209715200, '/videos/bob_cheesehouse.mp4'),
( 3, 'Carol''s Coding Catastrophe', 'Carol debugs a spaghetti codebase.', 1280, 720, 30, 100, 73400320, '/videos/carol_coding.mp4');