From b0ccf17527848eebba5081176a7c5a60911cb59e Mon Sep 17 00:00:00 2001 From: Rob Watson Date: Mon, 10 Jan 2022 21:35:21 +0100 Subject: [PATCH] poc: legacy HTTP download for audio clips --- backend/server/handler.go | 1 + backend/server/handler_test.go | 19 +++++++++------ frontend/src/App.tsx | 44 +++++++++++++++++++++++++++++++--- 3 files changed, 54 insertions(+), 10 deletions(-) diff --git a/backend/server/handler.go b/backend/server/handler.go index f481811..d028083 100644 --- a/backend/server/handler.go +++ b/backend/server/handler.go @@ -124,6 +124,7 @@ func (h *httpHandler) handleClip(w http.ResponseWriter, r *http.Request) { } w.Header().Set("content-type", "audio/"+format.String()) + w.Header().Set("content-disposition", "attachment; filename=clip."+format.String()) w.WriteHeader(http.StatusOK) var closing bool diff --git a/backend/server/handler_test.go b/backend/server/handler_test.go index b1ad507..ec4bdbd 100644 --- a/backend/server/handler_test.go +++ b/backend/server/handler_test.go @@ -20,13 +20,13 @@ import ( func TestHandler(t *testing.T) { testCases := []struct { - name string - path, body, method, contentType string - config config.Config - wantStartFrame, wantEndFrame int64 - wantAudioFormat media.AudioFormat - wantStatus int - wantContentType, wantBody string + name string + path, body, method, contentType string + config config.Config + wantStartFrame, wantEndFrame int64 + wantAudioFormat media.AudioFormat + wantStatus int + wantContentType, wantContentDisp, wantBody string }{ { name: "assets disabled, file system store disabled, GET /", @@ -148,6 +148,7 @@ func TestHandler(t *testing.T) { wantEndFrame: 1024, wantAudioFormat: media.AudioFormatMP3, wantContentType: "audio/mp3", + wantContentDisp: "attachment; filename=clip.mp3", wantStatus: http.StatusOK, wantBody: "an audio file", }, @@ -162,6 +163,7 @@ func TestHandler(t *testing.T) { wantEndFrame: 8192, wantAudioFormat: media.AudioFormatWAV, wantContentType: "audio/wav", + wantContentDisp: "attachment; filename=clip.wav", wantStatus: http.StatusOK, wantBody: "an audio file", }, @@ -207,6 +209,9 @@ func TestHandler(t *testing.T) { if tc.wantContentType != "" { assert.Equal(t, tc.wantContentType, resp.Header.Get("content-type")) } + if tc.wantContentDisp != "" { + assert.Equal(t, tc.wantContentDisp, resp.Header.Get("content-disposition")) + } }) } } diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 8b5c7e4..3d98a5a 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -248,14 +248,52 @@ function App(): JSX.Element { }, [audio, video, selection]); const handleClip = useCallback(() => { - (async function () { - console.debug('clip', selection); + if (!window.showSaveFilePicker) { + downloadClipHTTP(); + return; + } + downloadClipFileSystemAccessAPI(); + }, [mediaSet, selection]); + + const downloadClipHTTP = useCallback(() => { + (async function () { if (mediaSet == null) { return; } - // TODO: support File System Access API fallback + console.debug('clip http', selection); + + const form = document.createElement('form'); + form.method = 'POST'; + form.action = `${apiURL}/api/media_sets/${mediaSet.id}/clip`; + const startFrameInput = document.createElement('input'); + startFrameInput.type = 'hidden'; + startFrameInput.name = 'start_frame'; + startFrameInput.value = String(selection.start); + form.appendChild(startFrameInput); + const endFrameInput = document.createElement('input'); + endFrameInput.type = 'hidden'; + endFrameInput.name = 'end_frame'; + endFrameInput.value = String(selection.end); + form.appendChild(endFrameInput); + const formatInput = document.createElement('input'); + formatInput.type = 'hidden'; + formatInput.name = 'format'; + formatInput.value = 'mp3'; + form.appendChild(formatInput); + document.body.appendChild(form); + form.submit(); + })(); + }, [mediaSet, selection]); + + const downloadClipFileSystemAccessAPI = useCallback(() => { + (async function () { + if (mediaSet == null) { + return; + } + + console.debug('clip grpc', selection); const h = await window.showSaveFilePicker({ suggestedName: 'clip.mp3' }); const fileStream = await h.createWritable();