diff --git a/assets/js/hooks/audio_input.js b/assets/js/hooks/audio_input.js index c9c677418..12cdea7af 100644 --- a/assets/js/hooks/audio_input.js +++ b/assets/js/hooks/audio_input.js @@ -32,14 +32,21 @@ const AudioInput = { this.mediaRecorder = null; - // Render initial value - this.handleEvent(`audio_input_init:${this.props.id}`, (audioInfo) => { - this.updatePreview({ - data: this.decodeAudio(base64ToBuffer(audioInfo.data)), - numChannels: audioInfo.num_channels, - samplingRate: audioInfo.sampling_rate, - }); - }); + // Render updated value + this.handleEvent( + `audio_input_change:${this.props.id}`, + ({ audio_info: audioInfo }) => { + if (audioInfo) { + this.updatePreview({ + data: this.decodeAudio(base64ToBuffer(audioInfo.data)), + numChannels: audioInfo.num_channels, + samplingRate: audioInfo.sampling_rate, + }); + } else { + this.clearPreview(); + } + } + ); // File selection @@ -173,7 +180,6 @@ const AudioInput = { context.decodeAudioData(buffer, (audioBuffer) => { const audioInfo = audioBufferToAudioInfo(audioBuffer); - this.updatePreview(audioInfo); this.pushAudio(audioInfo); }); }, @@ -185,6 +191,12 @@ const AudioInput = { oldUrl && URL.revokeObjectURL(oldUrl); }, + clearPreview() { + const oldUrl = this.audioEl.src; + this.audioEl.src = ""; + oldUrl && URL.revokeObjectURL(oldUrl); + }, + pushAudio(audioInfo) { this.pushEventTo(this.props.phxTarget, "change", { data: bufferToBase64(this.encodeAudio(audioInfo)), diff --git a/assets/js/hooks/image_input.js b/assets/js/hooks/image_input.js index b78396806..b19f00d12 100644 --- a/assets/js/hooks/image_input.js +++ b/assets/js/hooks/image_input.js @@ -32,6 +32,8 @@ const ImageInput = { this.inputEl = this.el.querySelector(`[data-input]`); this.previewEl = this.el.querySelector(`[data-preview]`); + this.initialPreviewContentEl = this.previewEl.firstElementChild; + this.cameraPreviewEl = this.el.querySelector(`[data-camera-preview]`); this.cameraListEl = this.el.querySelector(`[data-camera-list]`); this.cameraItemTemplateEl = this.cameraListEl.firstElementChild; @@ -48,11 +50,18 @@ const ImageInput = { this.cameraVideoEl = null; this.cameraStream = null; - // Render initial value - this.handleEvent(`image_input_init:${this.props.id}`, (imageInfo) => { - const canvas = imageInfoToElement(imageInfo, this.props.format); - this.setPreview(canvas); - }); + // Render updated value + this.handleEvent( + `image_input_change:${this.props.id}`, + ({ image_info: imageInfo }) => { + if (imageInfo) { + const canvas = imageInfoToElement(imageInfo, this.props.format); + this.setPreview(canvas); + } else { + this.setPreview(this.initialPreviewContentEl); + } + } + ); // File selection @@ -119,7 +128,6 @@ const ImageInput = { this.cameraVideoEl.videoWidth, this.cameraVideoEl.videoHeight ); - this.setPreview(canvas); this.pushImage(canvas); this.closeCameraView(); }); @@ -152,7 +160,6 @@ const ImageInput = { imgEl.addEventListener("load", (loadEvent) => { const canvas = this.toCanvas(imgEl, imgEl.width, imgEl.height); - this.setPreview(canvas); this.pushImage(canvas); }); @@ -379,11 +386,13 @@ const ImageInput = { setPreview(element) { element.style.maxHeight = "300px"; + element.style.maxWidth = "100%"; this.previewEl.replaceChildren(element); }, setCameraPreview(element) { element.style.maxHeight = "300px"; + element.style.maxWidth = "100%"; this.cameraPreviewEl.replaceChildren(element); }, }; diff --git a/lib/livebook_web/live/output/audio_input_component.ex b/lib/livebook_web/live/output/audio_input_component.ex index e1a4ade15..457c4469c 100644 --- a/lib/livebook_web/live/output/audio_input_component.ex +++ b/lib/livebook_web/live/output/audio_input_component.ex @@ -3,7 +3,7 @@ defmodule LivebookWeb.Output.AudioInputComponent do @impl true def mount(socket) do - {:ok, assign(socket, endianness: System.endianness(), initialized: false)} + {:ok, assign(socket, endianness: System.endianness(), value: nil)} end @impl true @@ -13,24 +13,22 @@ defmodule LivebookWeb.Output.AudioInputComponent do socket = assign(socket, assigns) socket = - if socket.assigns.initialized do + if value == socket.assigns.value do socket else - socket = + audio_info = if value do - push_event(socket, "audio_input_init:#{socket.assigns.id}", %{ + %{ data: Base.encode64(value.data), num_channels: value.num_channels, sampling_rate: value.sampling_rate - }) - else - socket + } end - assign(socket, initialized: true) + push_event(socket, "audio_input_change:#{socket.assigns.id}", %{audio_info: audio_info}) end - {:ok, socket} + {:ok, assign(socket, value: value)} end @impl true diff --git a/lib/livebook_web/live/output/image_input_component.ex b/lib/livebook_web/live/output/image_input_component.ex index ecd603c44..0488ae709 100644 --- a/lib/livebook_web/live/output/image_input_component.ex +++ b/lib/livebook_web/live/output/image_input_component.ex @@ -3,7 +3,7 @@ defmodule LivebookWeb.Output.ImageInputComponent do @impl true def mount(socket) do - {:ok, assign(socket, initialized: false)} + {:ok, assign(socket, value: nil)} end @impl true @@ -13,24 +13,18 @@ defmodule LivebookWeb.Output.ImageInputComponent do socket = assign(socket, assigns) socket = - if socket.assigns.initialized do + if value == socket.assigns.value do socket else - socket = + image_info = if value do - push_event(socket, "image_input_init:#{socket.assigns.id}", %{ - data: Base.encode64(value.data), - height: value.height, - width: value.width - }) - else - socket + %{data: Base.encode64(value.data), height: value.height, width: value.width} end - assign(socket, initialized: true) + push_event(socket, "image_input_change:#{socket.assigns.id}", %{image_info: image_info}) end - {:ok, socket} + {:ok, assign(socket, value: value)} end @impl true