iobroker.mywebui 1.37.81 → 1.37.83
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
package/package.json
CHANGED
|
@@ -21,6 +21,7 @@ export class IobrokerWebuiScreenEditor extends BaseCustomWebComponentConstructor
|
|
|
21
21
|
_webuiBindings;
|
|
22
22
|
_styleBindings;
|
|
23
23
|
_settingsChanged;
|
|
24
|
+
_designerScriptObject = null;
|
|
24
25
|
async initialize(name, type, html, style, script, settings, properties, serviceContainer) {
|
|
25
26
|
if (name[0] == '/')
|
|
26
27
|
name = name.substring(1);
|
|
@@ -102,11 +103,23 @@ export class IobrokerWebuiScreenEditor extends BaseCustomWebComponentConstructor
|
|
|
102
103
|
this.applyBindings();
|
|
103
104
|
this.setWidth(this._settings.width);
|
|
104
105
|
this.setHeight(this._settings.height);
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
//
|
|
108
|
-
|
|
109
|
-
|
|
106
|
+
|
|
107
|
+
// Defer zoomToFit until after layout settles (rAF x2 ensures paint cycle completes).
|
|
108
|
+
// Without this, getBoundingClientRect().height may be 0 → zoomFactor=0 → invisible canvas.
|
|
109
|
+
requestAnimationFrame(() => {
|
|
110
|
+
requestAnimationFrame(() => {
|
|
111
|
+
const cvRect = this.documentContainer.designerView.designerCanvas.getBoundingClientRect();
|
|
112
|
+
if (cvRect.height > 0) {
|
|
113
|
+
this.documentContainer.designerView.zoomToFit();
|
|
114
|
+
} else {
|
|
115
|
+
// Layout not ready yet — keep zoomFactor=1 so canvas stays visible
|
|
116
|
+
this.documentContainer.designerView.designerCanvas.zoomFactor = 1;
|
|
117
|
+
}
|
|
118
|
+
// Run the control's script so JS-generated content is visible in the designer
|
|
119
|
+
this._applyDesignerScript();
|
|
120
|
+
});
|
|
121
|
+
});
|
|
122
|
+
|
|
110
123
|
this.documentContainer.designerView.designerCanvas.onContentChanged?.on(() => {
|
|
111
124
|
this.applyBindings();
|
|
112
125
|
});
|
|
@@ -182,11 +195,8 @@ export class IobrokerWebuiScreenEditor extends BaseCustomWebComponentConstructor
|
|
|
182
195
|
try {
|
|
183
196
|
if (window.appShell.controlpropertiesEditor.getProperties) {
|
|
184
197
|
prp = window.appShell.controlpropertiesEditor.getProperties();
|
|
185
|
-
console.log('✅ [Save] Got properties from editor:', prp);
|
|
186
198
|
} else {
|
|
187
|
-
// Fallback: direct access to propertiesObj
|
|
188
199
|
prp = window.appShell.controlpropertiesEditor.propertiesObj;
|
|
189
|
-
console.log('ℹ️ [Save] Got properties via propertiesObj:', prp);
|
|
190
200
|
}
|
|
191
201
|
|
|
192
202
|
// Update local copy
|
|
@@ -201,7 +211,6 @@ export class IobrokerWebuiScreenEditor extends BaseCustomWebComponentConstructor
|
|
|
201
211
|
// Final fallback
|
|
202
212
|
if (!prp || Object.keys(prp).length === 0) {
|
|
203
213
|
prp = this.properties || null;
|
|
204
|
-
console.log('ℹ️ [Save] Using fallback this.properties:', prp);
|
|
205
214
|
}
|
|
206
215
|
|
|
207
216
|
// Visibility configs are now stored as HTML attributes (data-visibility-*)
|
|
@@ -225,7 +234,6 @@ export class IobrokerWebuiScreenEditor extends BaseCustomWebComponentConstructor
|
|
|
225
234
|
const hashHex = hashArray.map(b => b.toString(16).padStart(2, '0')).join('');
|
|
226
235
|
|
|
227
236
|
this._settings._visibilityHash = hashHex;
|
|
228
|
-
console.log('🔐 [Security] Generated visibility settings hash');
|
|
229
237
|
}
|
|
230
238
|
|
|
231
239
|
let screen = { html, style, script, settings: this._settings, properties: prp };
|
|
@@ -234,8 +242,6 @@ export class IobrokerWebuiScreenEditor extends BaseCustomWebComponentConstructor
|
|
|
234
242
|
else {
|
|
235
243
|
let control = { html, style, script, settings: this._settings, properties: prp };
|
|
236
244
|
await iobrokerHandler.saveObject(this._type, this._name, control);
|
|
237
|
-
// Generate and save thumbnail for custom controls
|
|
238
|
-
console.log('💾 [Thumbnail] Saving custom control, generating thumbnail for:', this._name);
|
|
239
245
|
await this._generateAndSaveThumbnail();
|
|
240
246
|
}
|
|
241
247
|
}
|
|
@@ -243,13 +249,10 @@ export class IobrokerWebuiScreenEditor extends BaseCustomWebComponentConstructor
|
|
|
243
249
|
this.documentContainer.executeCommand(command);
|
|
244
250
|
}
|
|
245
251
|
async _generateAndSaveThumbnail() {
|
|
246
|
-
console.log('🎨 [Thumbnail] Starting thumbnail generation...');
|
|
247
252
|
try {
|
|
248
253
|
const canvas = this.documentContainer.designerView.designerCanvas;
|
|
249
254
|
const rootElement = canvas.rootDesignItem?.element;
|
|
250
|
-
console.log('📐 [Thumbnail] Canvas and root element:', { canvas, rootElement });
|
|
251
255
|
if (!rootElement) {
|
|
252
|
-
console.warn('❌ [Thumbnail] No root element found, skipping thumbnail generation');
|
|
253
256
|
return;
|
|
254
257
|
}
|
|
255
258
|
|
|
@@ -258,31 +261,20 @@ export class IobrokerWebuiScreenEditor extends BaseCustomWebComponentConstructor
|
|
|
258
261
|
// Method 1: Try to capture using getComputedStyle and manual rendering
|
|
259
262
|
try {
|
|
260
263
|
blob = await this._captureElementManually(rootElement);
|
|
261
|
-
if (blob) {
|
|
262
|
-
console.log('✅ [Thumbnail] Manual capture successful');
|
|
263
|
-
}
|
|
264
264
|
}
|
|
265
265
|
catch (err) {
|
|
266
|
-
|
|
266
|
+
// manual capture failed, use placeholder
|
|
267
267
|
}
|
|
268
|
-
|
|
269
|
-
// Method 2: Fallback to placeholder
|
|
268
|
+
|
|
270
269
|
if (!blob) {
|
|
271
|
-
console.log('🎨 [Thumbnail] Using placeholder thumbnail');
|
|
272
270
|
blob = await this._renderToCanvas(rootElement);
|
|
273
271
|
}
|
|
274
|
-
// Save thumbnail
|
|
275
272
|
if (blob) {
|
|
276
|
-
console.log('✅ [Thumbnail] Thumbnail blob created, size:', blob.size, 'bytes');
|
|
277
273
|
await iobrokerHandler.saveThumbnail(this._name, blob);
|
|
278
|
-
console.log('💾 [Thumbnail] Thumbnail saved successfully for:', this._name);
|
|
279
|
-
}
|
|
280
|
-
else {
|
|
281
|
-
console.warn('❌ [Thumbnail] Failed to create thumbnail blob');
|
|
282
274
|
}
|
|
283
275
|
}
|
|
284
276
|
catch (err) {
|
|
285
|
-
console.error('
|
|
277
|
+
console.error('Thumbnail generation failed:', err);
|
|
286
278
|
}
|
|
287
279
|
}
|
|
288
280
|
async _captureElementManually(rootElement) {
|
|
@@ -298,8 +290,6 @@ export class IobrokerWebuiScreenEditor extends BaseCustomWebComponentConstructor
|
|
|
298
290
|
if (width < 50) width = 200;
|
|
299
291
|
if (height < 50) height = 150;
|
|
300
292
|
|
|
301
|
-
console.log('📏 [Thumbnail] Element dimensions:', { width, height });
|
|
302
|
-
|
|
303
293
|
// Create canvas
|
|
304
294
|
const canvas = document.createElement('canvas');
|
|
305
295
|
const scale = Math.min(200 / width, 150 / height, 1);
|
|
@@ -314,11 +304,7 @@ export class IobrokerWebuiScreenEditor extends BaseCustomWebComponentConstructor
|
|
|
314
304
|
// Try to render the shadow DOM content
|
|
315
305
|
const shadowRoot = rootElement.shadowRoot;
|
|
316
306
|
if (shadowRoot) {
|
|
317
|
-
console.log('🔍 [Thumbnail] Shadow root found, rendering children...');
|
|
318
|
-
|
|
319
|
-
// Get all visible elements
|
|
320
307
|
const allElements = shadowRoot.querySelectorAll('*');
|
|
321
|
-
console.log('📦 [Thumbnail] Shadow DOM elements count:', allElements.length);
|
|
322
308
|
|
|
323
309
|
let renderedCount = 0;
|
|
324
310
|
for (const element of allElements) {
|
|
@@ -393,7 +379,6 @@ export class IobrokerWebuiScreenEditor extends BaseCustomWebComponentConstructor
|
|
|
393
379
|
}
|
|
394
380
|
}
|
|
395
381
|
|
|
396
|
-
console.log('✅ [Thumbnail] Rendered', renderedCount, 'elements');
|
|
397
382
|
}
|
|
398
383
|
|
|
399
384
|
return new Promise((resolve) => {
|
|
@@ -440,8 +425,6 @@ export class IobrokerWebuiScreenEditor extends BaseCustomWebComponentConstructor
|
|
|
440
425
|
if (width < 50) width = 200;
|
|
441
426
|
if (height < 50) height = 150;
|
|
442
427
|
|
|
443
|
-
console.log('📏 [Thumbnail] Capture dimensions:', { width, height });
|
|
444
|
-
|
|
445
428
|
// Create canvas
|
|
446
429
|
const canvas = document.createElement('canvas');
|
|
447
430
|
const scale = Math.min(200 / width, 150 / height, 1);
|
|
@@ -473,8 +456,6 @@ export class IobrokerWebuiScreenEditor extends BaseCustomWebComponentConstructor
|
|
|
473
456
|
.map(style => style.textContent)
|
|
474
457
|
.join('\n');
|
|
475
458
|
|
|
476
|
-
console.log('📦 [Thumbnail] Content HTML length:', content.length, 'Styles length:', styles.length);
|
|
477
|
-
|
|
478
459
|
if (content) {
|
|
479
460
|
const svgData = `
|
|
480
461
|
<svg xmlns="http://www.w3.org/2000/svg" width="${width}" height="${height}">
|
|
@@ -501,7 +482,6 @@ export class IobrokerWebuiScreenEditor extends BaseCustomWebComponentConstructor
|
|
|
501
482
|
|
|
502
483
|
// If SVG method failed, return simple canvas
|
|
503
484
|
if (!blob) {
|
|
504
|
-
console.log('🎨 [Thumbnail] Using fallback rendering');
|
|
505
485
|
blob = await new Promise(resolve => {
|
|
506
486
|
canvas.toBlob(resolve, 'image/png', 0.95);
|
|
507
487
|
});
|
|
@@ -539,7 +519,6 @@ export class IobrokerWebuiScreenEditor extends BaseCustomWebComponentConstructor
|
|
|
539
519
|
ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
|
|
540
520
|
canvas.toBlob((blob) => {
|
|
541
521
|
URL.revokeObjectURL(url);
|
|
542
|
-
console.log('✅ [Thumbnail] SVG rendered successfully');
|
|
543
522
|
resolve(blob);
|
|
544
523
|
}, 'image/png', 0.95);
|
|
545
524
|
}
|
|
@@ -666,6 +645,13 @@ export class IobrokerWebuiScreenEditor extends BaseCustomWebComponentConstructor
|
|
|
666
645
|
this.documentContainer.designerView.designerHeight = this._settings.height ?? defH;
|
|
667
646
|
}
|
|
668
647
|
dispose() {
|
|
648
|
+
if (this._designerScriptObject?.disconnectedCallback) {
|
|
649
|
+
try {
|
|
650
|
+
const rootEl = this.documentContainer.designerView.designerCanvas.rootDesignItem?.element;
|
|
651
|
+
this._designerScriptObject.disconnectedCallback(rootEl, rootEl?.shadowRoot);
|
|
652
|
+
} catch (err) {}
|
|
653
|
+
}
|
|
654
|
+
this._designerScriptObject = null;
|
|
669
655
|
this.removeBindings();
|
|
670
656
|
this.documentContainer.dispose();
|
|
671
657
|
this._configChangedListener?.dispose();
|
|
@@ -675,5 +661,25 @@ export class IobrokerWebuiScreenEditor extends BaseCustomWebComponentConstructor
|
|
|
675
661
|
window.appShell.styleEditor.model = null;
|
|
676
662
|
window.appShell.javascriptEditor.model = null;
|
|
677
663
|
}
|
|
664
|
+
async _applyDesignerScript() {
|
|
665
|
+
if (this._type !== 'control') return;
|
|
666
|
+
const scriptCode = this.scriptModel.getValue();
|
|
667
|
+
if (!scriptCode?.trim()) return;
|
|
668
|
+
const canvas = this.documentContainer.designerView.designerCanvas;
|
|
669
|
+
const rootEl = canvas.rootDesignItem?.element;
|
|
670
|
+
const shadowRoot = rootEl?.shadowRoot;
|
|
671
|
+
if (!rootEl || !shadowRoot) return;
|
|
672
|
+
try {
|
|
673
|
+
const url = URL.createObjectURL(new Blob([scriptCode], { type: 'application/javascript' }));
|
|
674
|
+
let scriptObj = await import(url);
|
|
675
|
+
if (scriptObj?.default && !scriptObj?.connectedCallback)
|
|
676
|
+
scriptObj = scriptObj.default;
|
|
677
|
+
this._designerScriptObject = scriptObj;
|
|
678
|
+
if (scriptObj?.connectedCallback)
|
|
679
|
+
scriptObj.connectedCallback(rootEl, shadowRoot);
|
|
680
|
+
} catch (err) {
|
|
681
|
+
console.warn('Designer script execution failed:', err);
|
|
682
|
+
}
|
|
683
|
+
}
|
|
678
684
|
}
|
|
679
685
|
customElements.define("iobroker-webui-screen-editor", IobrokerWebuiScreenEditor);
|
|
@@ -318,27 +318,13 @@ let ScreenViewer = class ScreenViewer extends BaseCustomWebComponentConstructorA
|
|
|
318
318
|
else
|
|
319
319
|
this._iobBindings = res;
|
|
320
320
|
this._scriptObject = await window.appShell.scriptSystem.assignAllScripts('screenviewer - ' + this.screenName, script, this._rootShadow, this, iobrokerHandler);
|
|
321
|
-
|
|
322
|
-
console.log('📜 [ScreenViewer] Script object for "' + this.screenName + '":', this._scriptObject);
|
|
323
|
-
console.log('📜 [ScreenViewer] Object type:', Object.prototype.toString.call(this._scriptObject));
|
|
324
|
-
console.log('📜 [ScreenViewer] Has default?', this._scriptObject?.default);
|
|
325
|
-
console.log('📜 [ScreenViewer] Has connectedCallback?', typeof this._scriptObject?.connectedCallback);
|
|
326
|
-
console.log('📜 [ScreenViewer] Has default.connectedCallback?', typeof this._scriptObject?.default?.connectedCallback);
|
|
327
|
-
|
|
328
|
-
// If module with default export, use it
|
|
329
|
-
if (this._scriptObject?.default && !this._scriptObject?.connectedCallback) {
|
|
330
|
-
console.log('🔄 [ScreenViewer] Using default export for "' + this.screenName + '"');
|
|
321
|
+
if (this._scriptObject?.default && !this._scriptObject?.connectedCallback)
|
|
331
322
|
this._scriptObject = this._scriptObject.default;
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
// Call connectedCallback after script is loaded
|
|
335
323
|
if (this._scriptObject?.connectedCallback) {
|
|
336
|
-
console.log('✅ [ScreenViewer] Calling connectedCallback after script load for "' + this.screenName + '"');
|
|
337
324
|
try {
|
|
338
325
|
this._scriptObject.connectedCallback(this, this._rootShadow);
|
|
339
|
-
console.log('✅ [ScreenViewer] connectedCallback executed successfully for "' + this.screenName + '"');
|
|
340
326
|
} catch (err) {
|
|
341
|
-
console.error('
|
|
327
|
+
console.error('connectedCallback error for "' + this.screenName + '":', err);
|
|
342
328
|
}
|
|
343
329
|
}
|
|
344
330
|
|