From 1e4e69e0189ffcc67648f60366278ca3100fdc09 Mon Sep 17 00:00:00 2001 From: Florian Hotze Date: Wed, 6 Nov 2024 14:12:51 +0100 Subject: [PATCH] oh-colorpicker: Fix color picker sends commands on external state change (#2860) Fixes #1268. Fixes #2849. Signed-off-by: Florian Hotze --- .../widgets/system/oh-colorpicker.vue | 71 ++++++++----------- 1 file changed, 28 insertions(+), 43 deletions(-) diff --git a/bundles/org.openhab.ui/web/src/components/widgets/system/oh-colorpicker.vue b/bundles/org.openhab.ui/web/src/components/widgets/system/oh-colorpicker.vue index 873a8feb64..734f5b9645 100644 --- a/bundles/org.openhab.ui/web/src/components/widgets/system/oh-colorpicker.vue +++ b/bundles/org.openhab.ui/web/src/components/widgets/system/oh-colorpicker.vue @@ -22,23 +22,22 @@ export default { widget: OhColorpickerDefinition, data () { return { - colorpicker: null, + colorPicker: null, + ignoreInput: false, delayCommand: false, - delayUpdate: false, pendingCommand: null, lastCommand: null, - pendingUpdate: null, init: false } }, mounted () { if (this.color) { - this.initColorpicker() + this.initColorPicker() } }, beforeDestroy () { - if (this.colorpicker) { - this.colorpicker.destroy() + if (this.colorPicker) { + this.colorPicker.destroy() } }, computed: { @@ -47,8 +46,8 @@ export default { if (state && state.split(',').length === 3) { let color = this.context.store[this.config.item].state.split(',') color[0] = parseInt(color[0]) - color[1] = color[1] / 100 - color[2] = color[2] / 100 + color[1] = Math.round(color[1]) / 100 + color[2] = Math.round(color[2]) / 100 return color } return [0, 0, 0] @@ -56,17 +55,17 @@ export default { }, watch: { color (val) { - if (this.colorpicker) { + if (this.colorPicker) { this.updateValue(val) } else { - this.initColorpicker() + this.initColorPicker() } } }, methods: { - initColorpicker () { + initColorPicker () { const vm = this - this.colorpicker = this.$f7.colorPicker.create(Object.assign({}, this.config, { + this.colorPicker = this.$f7.colorPicker.create(Object.assign({}, this.config, { containerEl: (!this.config.openIn) ? this.$refs.container : undefined, targetEl: (this.config.openIn) ? this.$refs.swatch : undefined, targetElSetBackgroundColor: true, @@ -76,29 +75,31 @@ export default { hsb: this.color }, on: { - change (colorpicker, value) { + change (colorPicker, value) { // skip the first update if (!vm.init || vm.context.store[vm.config.item].state === '-') { vm.init = true return } if (!value.hsb) return + // Ignore input for a few millis after a new state has been received to prevent sending a command on external state change + if (vm.ignoreInput) return vm.sendCommand(value.hsb) } } })) }, sendCommand (hsb) { - const state = this.commandFromHSB(hsb) - this.pendingUpdate = [...hsb] - this.pendingCommand = [...hsb] - if (!this.areHSBEqual(this.roundedHSB(state), this.roundedHSB(this.context.store[this.config.item].state))) { + console.debug('oh-colorpicker: Received command ' + hsb) + const cmd = this.commandFromHSB(hsb) + const state = this.commandFromHSB(this.color) + if (cmd !== state) { + this.pendingCommand = [...hsb] if (!this.delayCommand) { this.delayCommand = true - this.delayUpdate = true - console.debug(this.context.store[this.config.item].state + ' -> ' + state) - this.$store.dispatch('sendCommand', { itemName: this.config.item, cmd: state, updateState: true }) - this.lastCommand = state + console.debug(state + ' -> ' + cmd) + this.$store.dispatch('sendCommand', { itemName: this.config.item, cmd, updateState: true }) + this.lastCommand = cmd setTimeout(() => { const pendingCommand = [...this.pendingCommand] this.pendingCommand = null @@ -108,10 +109,6 @@ export default { } }, 200) } - setTimeout(() => { - this.updateValue(this.pendingUpdate) - this.delayUpdate = false - }, 2000) } }, commandFromHSB (hsb) { @@ -122,25 +119,13 @@ export default { state = state.join(',') return state }, - areHSBEqual (hsb1, hsb2) { - // for the purposes of NOT entering an endless loop, we consider transient non-HSB values to be equal - if (hsb1.length !== hsb2.length) return false - if (hsb1.length !== 3 || hsb2.length !== 3) return false - return (hsb1[0] === hsb2[0] && hsb1[1] === hsb2[1] && hsb1[2] === hsb2[2]) - }, - roundedHSB (state) { - if (!state) return [] - let hsb = state.split(',') - if (hsb.length !== 3) return hsb - return hsb.map((c) => Math.round(c)) - }, updateValue (val) { - if (!this.delayUpdate) { - this.colorpicker.setValue({ hsb: this.pendingUpdate || val }) - this.pendingUpdate = null - } else { - this.pendingUpdate = val - } + console.debug('oh-colorpicker: Updating value to ' + val) + this.ignoreInput = true + this.colorPicker.setValue({ hsb: val }) + setTimeout(() => { + this.ignoreInput = false + }, 10) } } }