iobroker.mywebui 1.37.65 → 1.37.67

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/io-package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "common": {
3
3
  "name": "mywebui",
4
- "version": "1.37.65",
4
+ "version": "1.37.67",
5
5
  "titleLang": {
6
6
  "en": "mywebui",
7
7
  "de": "mywebui",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "iobroker.mywebui",
3
- "version": "1.37.65",
3
+ "version": "1.37.67",
4
4
  "description": "ioBroker mywebui - Custom edited mywebui by gokturk413",
5
5
  "type": "module",
6
6
  "main": "dist/backend/main.js",
@@ -874,38 +874,31 @@ export class IobrokerWebuiAppShell extends BaseCustomWebComponentConstructorAppe
874
874
  headText.textContent = label;
875
875
  head.appendChild(headText);
876
876
  wrap.appendChild(head);
877
- const oidInp = document.createElement('input');
878
- oidInp.type = 'text'; oidInp.value = ctrlCfg.oid || '';
879
- oidInp.placeholder = 'OID…';
880
- oidInp.style.cssText = 'width:100%;box-sizing:border-box;padding:3px 5px;font-size:11px;border:1px solid #ccc;border-radius:3px;margin-bottom:3px;';
881
- oidInp.onchange = save;
882
- const pickBtn = document.createElement('button');
883
- pickBtn.textContent = '…';
884
- pickBtn.style.cssText = 'padding:2px 6px;font-size:11px;cursor:pointer;border:1px solid #aaa;border-radius:3px;margin-left:3px;';
885
- pickBtn.onclick = async () => {
886
- const picked = await openSelectIdDialog(document.body, { id: oidInp.value });
887
- if (picked) { oidInp.value = picked; save(); }
888
- };
889
- const oidRow2 = document.createElement('div');
890
- oidRow2.style.cssText = 'display:flex;margin-bottom:3px;';
891
- oidRow2.appendChild(oidInp); oidRow2.appendChild(pickBtn);
892
- wrap.appendChild(oidRow2);
893
877
  const condSel = sel([
894
878
  ['equal','='],['not_equal','≠'],['less_than','<'],['less_equal','≤'],
895
879
  ['greater_than','>'],['greater_equal','≥'],['exists','exists']
896
880
  ], ctrlCfg.condition || 'equal');
897
- condSel.style.cssText += 'width:70px;flex:none;margin-right:4px;';
881
+ condSel.style.cssText += 'flex:1;';
882
+ condSel.onchange = save;
883
+ const condRow = document.createElement('div');
884
+ condRow.style.cssText = 'display:flex;align-items:center;gap:4px;margin-bottom:4px;';
885
+ condRow.appendChild(this._makeBindSquare('condition', ctrlCfg, designItem, 'data-animation', saveAndRefresh));
886
+ condRow.appendChild(condSel);
887
+ wrap.appendChild(condRow);
898
888
  const valInp = document.createElement('input');
899
889
  valInp.type = 'text'; valInp.value = ctrlCfg.value ?? 'true';
900
890
  valInp.style.cssText = 'flex:1;padding:3px 5px;font-size:11px;border:1px solid #ccc;border-radius:3px;';
901
- condSel.onchange = save; valInp.onchange = save;
902
- const condRow = document.createElement('div');
903
- condRow.style.cssText = 'display:flex;gap:3px;';
904
- condRow.appendChild(condSel); condRow.appendChild(valInp);
905
- wrap.appendChild(condRow);
891
+ valInp.onchange = save;
892
+ const valRow = document.createElement('div');
893
+ valRow.style.cssText = 'display:flex;align-items:center;gap:4px;';
894
+ valRow.appendChild(this._makeBindSquare('value', ctrlCfg, designItem, 'data-animation', saveAndRefresh));
895
+ valRow.appendChild(valInp);
896
+ wrap.appendChild(valRow);
906
897
  wrap._getCtrl = () => {
907
- const v = { oid: oidInp.value || undefined, condition: condSel.value, value: valInp.value };
898
+ const v = { condition: condSel.value, value: valInp.value };
908
899
  if (ctrlCfg.oid_bind) v.oid_bind = ctrlCfg.oid_bind;
900
+ if (ctrlCfg.condition_bind) v.condition_bind = ctrlCfg.condition_bind;
901
+ if (ctrlCfg.value_bind) v.value_bind = ctrlCfg.value_bind;
909
902
  return v;
910
903
  };
911
904
  return wrap;
@@ -1071,8 +1064,7 @@ export class IobrokerWebuiAppShell extends BaseCustomWebComponentConstructorAppe
1071
1064
  if (parseFloat(delayInp.value)) out.delay = parseFloat(delayInp.value);
1072
1065
  if (parseInt(repeatInp.value)) out.repeat = parseInt(repeatInp.value);
1073
1066
  out.ease = easeSel.value || 'power2.out';
1074
- if (triggerSel.value === 'oid' && (oidInp.value || cfg.oid_bind)) {
1075
- if (oidInp.value) out.oid = oidInp.value;
1067
+ if (triggerSel.value === 'oid') {
1076
1068
  out.condition = condSel.value;
1077
1069
  out.conditionValue = condValInp.value;
1078
1070
  }
@@ -1153,21 +1145,12 @@ export class IobrokerWebuiAppShell extends BaseCustomWebComponentConstructorAppe
1153
1145
  ['elastic.out(1,0.3)','elastic.out'],['back.inOut(1.7)','back.inOut'],['none','none']
1154
1146
  ], cfg.ease || 'power2.out');
1155
1147
 
1156
- const oidInp = inp(cfg.oid || '');
1157
1148
  const condSel = sel([['equal','='],['not_equal','≠'],['less_than','<'],['greater_than','>'],['exists','exists']], cfg.condition || 'equal');
1158
1149
  const condValInp = inp(cfg.conditionValue ?? 'true');
1159
1150
  const glowColorInp = inp(cfg.glowColor || 'yellow', 'color');
1160
1151
  const glowSizeInp = inp(cfg.glowSize || 10, 'number');
1161
1152
  const blurInp = inp(cfg.blurAmount || 5, 'number');
1162
1153
 
1163
- const oidPickBtn = document.createElement('button');
1164
- oidPickBtn.textContent = '…';
1165
- oidPickBtn.style.cssText = 'padding:2px 6px;font-size:11px;cursor:pointer;border:1px solid #aaa;border-radius:3px;flex-shrink:0;';
1166
- oidPickBtn.onclick = async () => {
1167
- const picked = await openSelectIdDialog(document.body, { id: oidInp.value });
1168
- if (picked) { oidInp.value = picked; save(); }
1169
- };
1170
-
1171
1154
  // ── Build UI ──────────────────────────────────────────────────────────
1172
1155
  content.innerHTML = '';
1173
1156
 
@@ -1192,15 +1175,17 @@ export class IobrokerWebuiAppShell extends BaseCustomWebComponentConstructorAppe
1192
1175
  const oidLabelText = document.createElement('span');
1193
1176
  oidLabelText.textContent = 'OID';
1194
1177
  oidLabel.appendChild(oidLabelText);
1195
- const oidRowDiv = document.createElement('div');
1196
- oidRowDiv.style.cssText = 'display:flex;gap:3px;margin-bottom:4px;padding-left:15px;';
1197
- oidRowDiv.appendChild(oidInp); oidRowDiv.appendChild(oidPickBtn);
1198
1178
  const condRowDiv = document.createElement('div');
1199
- condRowDiv.style.cssText = 'display:flex;gap:3px;margin-bottom:6px;padding-left:15px;';
1200
- condRowDiv.appendChild(condSel); condRowDiv.appendChild(condValInp);
1179
+ condRowDiv.style.cssText = 'display:flex;align-items:center;gap:4px;margin-bottom:4px;padding-left:4px;';
1180
+ condRowDiv.appendChild(this._makeBindSquare('condition', cfg, designItem, 'data-effects', saveAndRefresh));
1181
+ condRowDiv.appendChild(condSel);
1182
+ const condValRowDiv = document.createElement('div');
1183
+ condValRowDiv.style.cssText = 'display:flex;align-items:center;gap:4px;margin-bottom:6px;padding-left:4px;';
1184
+ condValRowDiv.appendChild(this._makeBindSquare('conditionValue', cfg, designItem, 'data-effects', saveAndRefresh));
1185
+ condValRowDiv.appendChild(condValInp);
1201
1186
  oidSection.appendChild(oidLabel);
1202
- oidSection.appendChild(oidRowDiv);
1203
1187
  oidSection.appendChild(condRowDiv);
1188
+ oidSection.appendChild(condValRowDiv);
1204
1189
  content.appendChild(oidSection);
1205
1190
  triggerSel.addEventListener('change', () => { oidSection.style.display = triggerSel.value === 'oid' ? '' : 'none'; });
1206
1191
 
@@ -160,30 +160,37 @@ class AnimationInstance {
160
160
  const ctrl = controls[key];
161
161
  if (!ctrl) return;
162
162
 
163
- // If OID itself is bound via binding square, resolve it first
164
- if (ctrl.oid_bind?.signal) {
163
+ // condition_bind: dynamically update which condition operator to use
164
+ if (ctrl.condition_bind?.signal) {
165
165
  try {
166
- const s = await iobrokerHandler.connection.getState(ctrl.oid_bind.signal);
167
- if (s?.val != null) ctrl.oid = String(s.val);
166
+ const s = await iobrokerHandler.connection.getState(ctrl.condition_bind.signal);
167
+ if (s?.val != null) ctrl.condition = String(s.val);
168
168
  } catch (e) {}
169
- const oidBindHandler = (id, state) => {
170
- if (state?.val != null) ctrl.oid = String(state.val);
171
- };
169
+ const h = (id, state) => { if (state?.val != null) ctrl.condition = String(state.val); };
170
+ try { iobrokerHandler.connection.subscribeState(ctrl.condition_bind.signal, h); this._subs.push({ oid: ctrl.condition_bind.signal, handler: h }); } catch (e) {}
171
+ }
172
+
173
+ // value_bind: dynamically update the trigger value
174
+ if (ctrl.value_bind?.signal) {
172
175
  try {
173
- iobrokerHandler.connection.subscribeState(ctrl.oid_bind.signal, oidBindHandler);
174
- this._subs.push({ oid: ctrl.oid_bind.signal, handler: oidBindHandler });
176
+ const s = await iobrokerHandler.connection.getState(ctrl.value_bind.signal);
177
+ if (s?.val != null) ctrl.value = String(s.val);
175
178
  } catch (e) {}
179
+ const h = (id, state) => { if (state?.val != null) ctrl.value = String(state.val); };
180
+ try { iobrokerHandler.connection.subscribeState(ctrl.value_bind.signal, h); this._subs.push({ oid: ctrl.value_bind.signal, handler: h }); } catch (e) {}
176
181
  }
177
182
 
178
- if (!ctrl.oid) return;
183
+ // oid_bind.signal IS the OID to watch (binding square directly holds the target OID)
184
+ const oid = ctrl.oid || ctrl.oid_bind?.signal;
185
+ if (!oid) return;
179
186
  const handler = (id, state) => {
180
187
  if (checkCond(state?.val, ctrl.condition || 'equal', ctrl.value ?? 'true')) action();
181
188
  };
182
189
  try {
183
- iobrokerHandler.connection.subscribeState(ctrl.oid, handler);
184
- this._subs.push({ oid: ctrl.oid, handler });
190
+ iobrokerHandler.connection.subscribeState(oid, handler);
191
+ this._subs.push({ oid, handler });
185
192
  } catch (e) {}
186
- iobrokerHandler.connection.getState(ctrl.oid).then(state => {
193
+ iobrokerHandler.connection.getState(oid).then(state => {
187
194
  if (state && checkCond(state.val, ctrl.condition || 'equal', ctrl.value ?? 'true')) action();
188
195
  }).catch(() => {});
189
196
  };
@@ -200,16 +207,27 @@ class AnimationInstance {
200
207
  'fillColorFrom', 'fillColorTo', 'transformOriginX', 'transformOriginY',
201
208
  'svgAttr', 'pathId', 'alignToPath', 'orientToPath'
202
209
  ];
210
+ let _restartTimer = null;
203
211
  for (const prop of dynamicProps) {
204
212
  const bindCfg = this.cfg[prop + '_bind'];
205
213
  if (!bindCfg?.signal) continue;
206
214
  const propCapture = prop;
207
215
  const handler = (id, state) => {
208
- if (state?.val != null) {
209
- this.cfg[propCapture] = state.val;
210
- // Rebuild tween if currently playing
211
- if (this.tween && !this.tween.paused()) this._play();
216
+ if (state?.val == null) return;
217
+ this.cfg[propCapture] = state.val;
218
+ if (!this.tween) return;
219
+ // Duration: adjust timeScale without restarting (smooth for repeat:-1)
220
+ if (propCapture === 'duration' && this.tween.vars) {
221
+ const origDur = parseFloat(this.tween.vars.duration) || 1;
222
+ const newDur = parseFloat(state.val) || 1;
223
+ this.tween.timeScale(origDur / newDur);
224
+ return;
212
225
  }
226
+ // Other props: debounced restart so rapid changes don't freeze
227
+ clearTimeout(_restartTimer);
228
+ _restartTimer = setTimeout(() => {
229
+ if (this.tween && !this.tween.paused()) this._play();
230
+ }, 60);
213
231
  };
214
232
  try {
215
233
  iobrokerHandler.connection.subscribeState(bindCfg.signal, handler);
@@ -378,24 +396,26 @@ async function _applyEffect(el, cfg) {
378
396
  _clickFn = applyTween;
379
397
  el.addEventListener('click', _clickFn);
380
398
  } else if (cfg.trigger === 'oid') {
381
- // Resolve OID — may come from a binding square binding
382
- if (cfg.oid_bind?.signal) {
383
- try {
384
- const s = await iobrokerHandler.connection.getState(cfg.oid_bind.signal);
385
- if (s?.val != null) cfg.oid = String(s.val);
386
- } catch (e) {}
387
- const oidBindHandler = (id, state) => { if (state?.val != null) cfg.oid = String(state.val); };
388
- try { iobrokerHandler.connection.subscribeState(cfg.oid_bind.signal, oidBindHandler); } catch (e) {}
389
- _oidId = cfg.oid_bind.signal;
390
- _oidHandler = oidBindHandler;
399
+ // condition_bind and conditionValue_bind
400
+ if (cfg.condition_bind?.signal) {
401
+ try { const s = await iobrokerHandler.connection.getState(cfg.condition_bind.signal); if (s?.val != null) cfg.condition = String(s.val); } catch (e) {}
402
+ const h = (id, state) => { if (state?.val != null) cfg.condition = String(state.val); };
403
+ try { iobrokerHandler.connection.subscribeState(cfg.condition_bind.signal, h); } catch (e) {}
404
+ }
405
+ if (cfg.conditionValue_bind?.signal) {
406
+ try { const s = await iobrokerHandler.connection.getState(cfg.conditionValue_bind.signal); if (s?.val != null) cfg.conditionValue = String(s.val); } catch (e) {}
407
+ const h = (id, state) => { if (state?.val != null) cfg.conditionValue = String(state.val); };
408
+ try { iobrokerHandler.connection.subscribeState(cfg.conditionValue_bind.signal, h); } catch (e) {}
391
409
  }
392
- if (cfg.oid) {
393
- _oidId = cfg.oid;
410
+ // oid_bind.signal IS the OID to watch (same as for animation controls)
411
+ const oid = cfg.oid || cfg.oid_bind?.signal;
412
+ if (oid) {
413
+ _oidId = oid;
394
414
  _oidHandler = (id, state) => {
395
415
  if (checkCond(state?.val, cfg.condition || 'equal', cfg.conditionValue ?? 'true')) applyTween();
396
416
  };
397
- try { iobrokerHandler.connection.subscribeState(cfg.oid, _oidHandler); } catch (e) {}
398
- iobrokerHandler.connection.getState(cfg.oid).then(state => {
417
+ try { iobrokerHandler.connection.subscribeState(oid, _oidHandler); } catch (e) {}
418
+ iobrokerHandler.connection.getState(oid).then(state => {
399
419
  if (state && checkCond(state.val, cfg.condition || 'equal', cfg.conditionValue ?? 'true')) applyTween();
400
420
  }).catch(() => {});
401
421
  }