iobroker.staticsfilefolder 0.0.18 → 0.0.20

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/README.md CHANGED
@@ -64,8 +64,11 @@ Once configured and the instance is running (green status):
64
64
  Placeholder for the next version (at the beginning of the line):
65
65
  ### **WORK IN PROGRESS**
66
66
  -->
67
- ### 0.0.18
68
- * Cleaned up npm lockfile and forced hoisting of test dependencies.
67
+ ### 0.0.20
68
+ * Fixed dependabot auto-merge workflow write permissions.
69
+
70
+ ### 0.0.19
71
+ * Fixed PDF printing layout margins to fit 1 page, removed file title header from print view, and added zoom controls to PDF viewer.
69
72
 
70
73
  ### 0.0.15
71
74
  * Reverted minimum Node.js engine requirement to 20 to support GitHub Actions runners.
package/io-package.json CHANGED
@@ -1,20 +1,20 @@
1
1
  {
2
2
  "common": {
3
3
  "name": "staticsfilefolder",
4
- "version": "0.0.18",
4
+ "version": "0.0.20",
5
5
  "news": {
6
- "0.0.18": {
7
- "en": "Cleaned up npm lockfile and forced hoisting of test dependencies.",
8
- "de": "Npm-Lockfile bereinigt und das Hosten von Test-Abhängigkeiten erzwungen.",
9
- "ru": "Очищен npm lockfile и принудительно подняты зависимости для тестирования.",
10
- "pt": "Limpo o lockfile do npm e forçado o hoisting das dependências de teste.",
11
- "nl": "Npm lockfile opgeschoond en hoisting van test-afhankelijkheden geforceerd.",
12
- "fr": "Nettoyage du fichier de verrouillage npm et forçage du hoisting des dépendances de test.",
13
- "it": "Pulito il file di blocco npm e forzato l'hoisting delle dipendenze di test.",
14
- "es": "Se limpió el archivo de bloqueo npm y se forzó la elevación de las dependencias de prueba.",
15
- "pl": "Oczyszczono plik blokady npm i wymuszono hoisting zależności testowych.",
16
- "uk": "Очищено файл блокування npm та примусово піднято залежності для тестування.",
17
- "zh-cn": "清理了npm锁文件并强制提升测试依赖项。"
6
+ "0.0.20": {
7
+ "en": "Fixed dependabot auto-merge workflow write permissions.",
8
+ "de": "Schreibrechte für den Dependabot-Auto-Merge-Workflow behoben.",
9
+ "ru": "Исправлены права на запись для рабочего процесса автоматического слияния Dependabot.",
10
+ "pt": "Corrigidas as permissões de gravação do fluxo de trabalho de fusão automática do dependabot.",
11
+ "nl": "Schrijfrechten voor dependabot auto-merge workflow gecorrigeerd.",
12
+ "fr": "Correction des autorisations d'écriture pour le workflow de fusion automatique dependabot.",
13
+ "it": "Corretti i permessi di scrittura per il workflow di fusione automatica dependabot.",
14
+ "es": "Se corrigieron los permisos de escritura del flujo de trabajo de fusión automática de dependabot.",
15
+ "pl": "Naprawiono uprawnienia do zapisu dla przepływu pracy automatycznego scalania dependabot.",
16
+ "uk": "Виправлено права на запис для робочого процесу автоматичного злиття dependabot.",
17
+ "zh-cn": "修复了dependabot自动合并工作流写入权限。"
18
18
  },
19
19
  "0.0.15": {
20
20
  "en": "Reverted minimum Node.js engine requirement to 20 to support GitHub Actions runners.",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "iobroker.staticsfilefolder",
3
- "version": "0.0.18",
3
+ "version": "0.0.20",
4
4
  "description": "Static Files Folder",
5
5
  "author": {
6
6
  "name": "gokturk413",
package/www/app.js CHANGED
@@ -28,11 +28,14 @@ const modalTitle = document.getElementById('modal-title');
28
28
  const modalBtnPrev = document.getElementById('modal-btn-prev');
29
29
  const modalBtnNext = document.getElementById('modal-btn-next');
30
30
  const modalBtnPrint = document.getElementById('modal-btn-print');
31
+ const modalPdfZoom = document.getElementById('modal-pdf-zoom');
31
32
  const modalBtnDownload = document.getElementById('modal-btn-download');
32
33
 
33
34
  // Modal Navigation State
34
35
  let currentOpenItem = null;
35
36
  let currentFilesList = [];
37
+ let currentPdfDoc = null;
38
+ let currentPdfZoom = 1.5;
36
39
 
37
40
  // Localization Settings
38
41
  const translations = {
@@ -240,12 +243,20 @@ document.addEventListener('DOMContentLoaded', () => {
240
243
  modalBtnPrev.addEventListener('click', navigateModalPrev);
241
244
  modalBtnNext.addEventListener('click', navigateModalNext);
242
245
  modalBtnPrint.addEventListener('click', printModalContent);
246
+ modalPdfZoom.addEventListener('change', (e) => {
247
+ currentPdfZoom = parseFloat(e.target.value);
248
+ renderPdfPages();
249
+ });
243
250
  modalBtnDownload.addEventListener('click', downloadCurrentFile);
244
251
 
245
252
  closeModal.addEventListener('click', () => {
246
253
  viewerModal.style.display = 'none';
247
254
  viewerBody.innerHTML = ''; // clear memory
248
255
  currentOpenItem = null;
256
+ currentPdfDoc = null;
257
+ currentPdfZoom = 1.5;
258
+ modalPdfZoom.value = '1.5';
259
+ modalPdfZoom.style.display = 'none';
249
260
  });
250
261
  });
251
262
 
@@ -420,6 +431,7 @@ function handleItemClick(item) {
420
431
  function openFile(item) {
421
432
  currentOpenItem = item;
422
433
  modalTitle.textContent = item.name;
434
+ modalPdfZoom.style.display = 'none';
423
435
 
424
436
  // Find index of current file in currentFilesList
425
437
  const index = currentFilesList.findIndex(f => f.name === item.name);
@@ -464,12 +476,13 @@ function printModalContent() {
464
476
 
465
477
  const canvases = viewerBody.querySelectorAll('canvas');
466
478
  let contentHtml = '';
479
+ let isPdf = canvases.length > 0;
467
480
 
468
- if (canvases.length > 0) {
481
+ if (isPdf) {
469
482
  // PDF (which is rendered in canvases)
470
483
  canvases.forEach(canvas => {
471
484
  const dataUrl = canvas.toDataURL();
472
- contentHtml += `<img src="${dataUrl}" style="max-width: 100%; margin-bottom: 20px; display: block;" />`;
485
+ contentHtml += `<img src="${dataUrl}" class="pdf-page-img" />`;
473
486
  });
474
487
  } else {
475
488
  // Excel table or Word document HTML
@@ -482,16 +495,34 @@ function printModalContent() {
482
495
  <head>
483
496
  <title>${currentOpenItem.name}</title>
484
497
  <style>
485
- body { margin: 20px; font-family: sans-serif; background: white; color: black; }
486
- img, table { max-width: 100%; page-break-inside: avoid; }
498
+ @page {
499
+ size: auto;
500
+ margin: 0mm;
501
+ }
502
+ body {
503
+ margin: 0;
504
+ padding: ${isPdf ? '0' : '20px'};
505
+ font-family: sans-serif;
506
+ background: white;
507
+ color: black;
508
+ }
509
+ .pdf-page-img {
510
+ width: 100%;
511
+ max-width: 100%;
512
+ height: auto;
513
+ display: block;
514
+ page-break-after: always;
515
+ }
516
+ .pdf-page-img:last-child {
517
+ page-break-after: avoid;
518
+ }
487
519
  table { border-collapse: collapse; width: 100%; margin-top: 10px; }
488
520
  table th, table td { border: 1px solid #ddd; padding: 8px; text-align: left; }
489
521
  table th { background-color: #f2f2f2; }
522
+ img, table { page-break-inside: avoid; }
490
523
  </style>
491
524
  </head>
492
525
  <body>
493
- <h2>${currentOpenItem.name}</h2>
494
- <hr />
495
526
  ${contentHtml}
496
527
  <script>
497
528
  window.onload = function() {
@@ -525,23 +556,36 @@ function downloadCurrentFile() {
525
556
  async function openPdf(url) {
526
557
  viewerModal.style.display = 'block';
527
558
  viewerBody.innerHTML = `<h2>${translations[currentLang]?.loadingPdf || 'Loading PDF...'}</h2>`;
559
+ modalPdfZoom.style.display = 'inline-block';
528
560
 
529
561
  try {
530
562
  const loadingTask = window.pdfjsLib.getDocument({ url: url });
531
- const pdf = await loadingTask.promise;
532
- viewerBody.innerHTML = ''; // clear loading
533
-
534
- // Render all pages
535
- for (let pageNum = 1; pageNum <= pdf.numPages; pageNum++) {
536
- const page = await pdf.getPage(pageNum);
537
- const scale = 1.5;
538
- const viewport = page.getViewport({ scale: scale });
563
+ currentPdfDoc = await loadingTask.promise;
564
+ renderPdfPages();
565
+ } catch (e) {
566
+ const errorText = translations[currentLang]?.errorLoading || 'An error occurred: ';
567
+ viewerBody.innerHTML = `<h2 style="color:red">${errorText}${e.message}</h2>`;
568
+ }
569
+ }
570
+
571
+ async function renderPdfPages() {
572
+ if (!currentPdfDoc) return;
573
+ viewerBody.innerHTML = '';
574
+
575
+ try {
576
+ for (let pageNum = 1; pageNum <= currentPdfDoc.numPages; pageNum++) {
577
+ const page = await currentPdfDoc.getPage(pageNum);
578
+ const viewport = page.getViewport({ scale: currentPdfZoom });
539
579
 
540
580
  const canvas = document.createElement('canvas');
541
581
  const context = canvas.getContext('2d');
542
582
  canvas.height = viewport.height;
543
583
  canvas.width = viewport.width;
544
584
 
585
+ canvas.style.display = 'block';
586
+ canvas.style.margin = '10px auto';
587
+ canvas.style.boxShadow = '0 4px 8px rgba(0,0,0,0.15)';
588
+
545
589
  viewerBody.appendChild(canvas);
546
590
 
547
591
  const renderContext = {
@@ -551,8 +595,7 @@ async function openPdf(url) {
551
595
  await page.render(renderContext).promise;
552
596
  }
553
597
  } catch (e) {
554
- const errorText = translations[currentLang]?.errorLoading || 'An error occurred: ';
555
- viewerBody.innerHTML = `<h2 style="color:red">${errorText}${e.message}</h2>`;
598
+ console.error("Error rendering PDF pages:", e);
556
599
  }
557
600
  }
558
601
 
package/www/index.html CHANGED
@@ -67,6 +67,13 @@
67
67
  <button id="modal-btn-prev" class="nav-btn" data-i18n="modalBack" title="Previous">&larr; Back</button>
68
68
  <button id="modal-btn-next" class="nav-btn" data-i18n="modalForward" title="Next">Next &rarr;</button>
69
69
  <button id="modal-btn-print" class="nav-btn" data-i18n="modalPrint" title="Print / Save as PDF">🖨️ Print / PDF</button>
70
+ <select id="modal-pdf-zoom" class="nav-btn" title="Zoom" style="display: none; height: 32px; padding: 0 6px; margin: 0 4px; font-size: 14px; border-radius: 4px; border: 1px solid var(--border-color); background: var(--bg-card); color: var(--text-color); cursor: pointer; vertical-align: middle;">
71
+ <option value="1.0">100%</option>
72
+ <option value="1.25">125%</option>
73
+ <option value="1.5" selected>150%</option>
74
+ <option value="2.0">200%</option>
75
+ <option value="2.5">250%</option>
76
+ </select>
70
77
  <button id="modal-btn-download" class="nav-btn" data-i18n="modalDownload" title="Download File">📥 Download</button>
71
78
  <span id="close-modal" class="close-button">&times;</span>
72
79
  </div>