diff --git a/src/components/settings/Presets/PresetsForm.vue b/src/components/settings/Presets/PresetsForm.vue index d13c71eeb8..8db2b5177d 100644 --- a/src/components/settings/Presets/PresetsForm.vue +++ b/src/components/settings/Presets/PresetsForm.vue @@ -139,10 +139,8 @@ export default class PresetsForm extends Mixins(BaseMixin) { } existsPresetName(name: string) { - return ( - this.presets.findIndex( - (preset: GuiPresetsStatePreset) => preset.name === name && preset.id !== this.preset.id - ) !== -1 + return this.presets.some( + (preset: GuiPresetsStatePreset) => preset.name === name && preset.id !== this.preset.id ) } @@ -156,9 +154,9 @@ export default class PresetsForm extends Mixins(BaseMixin) { savePreset() { let setValues = 0 - for (const key of Object.keys(this.preset.values)) { + Object.keys(this.preset.values).forEach((key: string) => { if (this.preset.values[key].bool) setValues++ - } + }) if (this.preset.gcode.length) setValues++ // stop here, when no values are set @@ -167,15 +165,17 @@ export default class PresetsForm extends Mixins(BaseMixin) { return } + const values = structuredClone(this.preset) + // create new preset, if id === null if (this.preset.id === null) { - this.$store.dispatch('gui/presets/store', { values: this.preset }) + this.$store.dispatch('gui/presets/store', { values }) this.closeForm() return } // update existing preset - this.$store.dispatch('gui/presets/update', { id: this.preset.id, values: this.preset }) + this.$store.dispatch('gui/presets/update', { id: this.preset.id, values }) this.closeForm() } } diff --git a/src/components/settings/SettingsPresetsTab.vue b/src/components/settings/SettingsPresetsTab.vue index 536f0359ad..28beb142a7 100644 --- a/src/components/settings/SettingsPresetsTab.vue +++ b/src/components/settings/SettingsPresetsTab.vue @@ -62,7 +62,7 @@ export default class SettingsPresetsTab extends Mixins(BaseMixin) { } edit(preset: GuiPresetsStatePreset) { - this.formPreset = { ...preset } + this.formPreset = structuredClone(preset) this.boolForm = true } } diff --git a/src/components/webcams/streamers/Hlsstreamer.vue b/src/components/webcams/streamers/Hlsstreamer.vue index 63b5184222..962293c0d9 100644 --- a/src/components/webcams/streamers/Hlsstreamer.vue +++ b/src/components/webcams/streamers/Hlsstreamer.vue @@ -1,18 +1,11 @@ diff --git a/src/components/webcams/streamers/JMuxerStream.vue b/src/components/webcams/streamers/JMuxerStream.vue index b408935a0a..a66fa814b4 100644 --- a/src/components/webcams/streamers/JMuxerStream.vue +++ b/src/components/webcams/streamers/JMuxerStream.vue @@ -20,6 +20,7 @@ import WebcamMixin from '@/components/mixins/webcam' @Component export default class JMuxerStreamer extends Mixins(BaseMixin, WebcamMixin) { jmuxer: JMuxer | null = null + ws: WebSocket | null = null status: string = 'connecting' aspectRatio: number | null = null @@ -52,7 +53,7 @@ export default class JMuxerStreamer extends Mixins(BaseMixin, WebcamMixin) { play() { this.status = 'connecting' - this.jmuxer?.destroy() + this.stop() // Only websocket streams supported if (!this.url.startsWith('ws://') && !this.url.startsWith('wss://')) { @@ -80,21 +81,37 @@ export default class JMuxerStreamer extends Mixins(BaseMixin, WebcamMixin) { }) const ws = new WebSocket(this.url) + this.ws = ws ws.binaryType = 'arraybuffer' + + // guard every handler against `ws` having been replaced by a later play(), + // so a socket still closing down can never feed the current jmuxer instance ws.addEventListener('message', (event) => { + if (this.ws !== ws) return + this.jmuxer?.feed({ video: new Uint8Array(event.data), }) }) ws.addEventListener('error', (event) => { + if (this.ws !== ws) return + this.status = 'error' console.log('jmuxer ws error:', event) }) } - beforeUnmount() { + stop() { + this.ws?.close() + this.ws = null + this.jmuxer?.destroy() + this.jmuxer = null + } + + beforeDestroy() { + this.stop() } @Watch('camSettings', { deep: true }) diff --git a/src/locales/en.json b/src/locales/en.json index a46e38bcff..538ceb463b 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -949,12 +949,6 @@ }, "Unknown": "Unknown" }, - "PowerControlPanel": { - "Error": "Error", - "Off": "Off", - "On": "On", - "PowerControl": "Power Control" - }, "SpoolmanPanel": { "ActiveSpool": "Active Spool", "ChangeSpool": "Change Spool", @@ -1056,8 +1050,6 @@ "State": "State", "Target": "Target", "TemperaturesInChart": "Temperature [°C]", - "TempTooHigh": "Temperature too high for {name}! (max: {max})", - "TempTooLow": "Temperature too low for {name}! (min: {min})", "TurnHeaterOff": "Turn Heater Off" }, "ToolheadControlPanel": { @@ -1600,6 +1592,7 @@ "Create": "Create", "CreateNewDirectory": "create directory", "CurrentPath": "Current Path", + "Delete": "Delete", "DeleteDirectory": "Delete Directory", "DeleteDirectoryQuestion": "Do you really want to delete the \"{name}\" directory with all its contents?", "DeleteSelectedQuestion": "Do you really want to delete {count} selected files?",