pmtiles-swarm 0.40.0 → 0.41.0

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/CHANGELOG.md CHANGED
@@ -7,6 +7,20 @@
7
7
  ### 🐞 Bug fixes
8
8
  - _...Add new stuff here..._
9
9
 
10
+ ## 0.41.0
11
+ ### ✨ Features and improvements
12
+ - **An archive's details now open directly under the row you clicked**, instead of below the whole
13
+ table. On a node with a page of archives the panel appeared off-screen, so clicking a row looked
14
+ like it had done nothing but highlight it.
15
+
16
+ The panel sits in a `<tbody>` of its own, between the rows above it and the rows below — a table
17
+ may have several, and that is what keeps the three-second refresh from disturbing it. Rebuilding
18
+ the rows around the panel leaves it alone; holding it among them and re-inserting it each render
19
+ would blur whatever was focused inside, which would have made the seeding limit fields impossible
20
+ to type into for longer than one poll.
21
+
22
+ ### 🐞 Bug fixes
23
+
10
24
  ## 0.40.0
11
25
  ### ✨ Features and improvements
12
26
  - **Restore now checks that what it handed over is actually being seeded.** "20 of 20 archives handed
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pmtiles-swarm",
3
- "version": "0.40.0",
3
+ "version": "0.41.0",
4
4
  "description": "BitTorrent distribution for PMTiles map archives: create torrents, watch folders, publish and subscribe to RSS feeds, and seed through qBittorrent or an embedded client",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
@@ -89,6 +89,19 @@
89
89
  tbody tr { cursor: pointer; }
90
90
  tbody tr:hover { background: var(--panel); }
91
91
  tbody tr.on { background: var(--panel); box-shadow: inset 3px 0 0 var(--accent); }
92
+ /* The open archive's details, sitting in the table under the row they
93
+ belong to. Not a row anybody clicks: it carries the panel rather than
94
+ describing an archive, so it takes none of the row affordances. */
95
+ tbody tr.detailrow { cursor: default; }
96
+ tbody tr.detailrow:hover { background: none; }
97
+ tbody tr.detailrow > td {
98
+ padding: 0;
99
+ white-space: normal;
100
+ border-bottom: 1px solid var(--line);
101
+ }
102
+ /* Flush with the row above it, where the margin that separated it from
103
+ the table would now be a gap in the middle of one. */
104
+ tbody tr.detailrow .panel { margin-top: 0; border-radius: 0; border-width: 0; }
92
105
  td.name { white-space: normal; word-break: break-word; min-width: 16rem; }
93
106
  .sub { color: var(--muted); font-size: 0.8rem; }
94
107
  .track {
@@ -396,6 +409,21 @@
396
409
  </tr>
397
410
  </thead>
398
411
  <tbody id="rows"></tbody>
412
+ <!-- The open archive's details, in a tbody of their own between the
413
+ rows above it and the rows below. A table may have several, and
414
+ that is what makes this work: the three-second refresh rebuilds
415
+ the rows on either side without touching the panel. Putting it
416
+ in with them and moving it each render would blur whatever was
417
+ focused inside it, every three seconds, while it was being
418
+ typed into. -->
419
+ <tbody id="detail-body" hidden>
420
+ <tr class="detailrow">
421
+ <td colspan="12">
422
+ <div class="panel" id="detail" hidden></div>
423
+ </td>
424
+ </tr>
425
+ </tbody>
426
+ <tbody id="rows-below"></tbody>
399
427
  </table>
400
428
  <div id="fetching"></div>
401
429
  <div class="empty" id="empty" hidden>
@@ -403,7 +431,7 @@
403
431
  pull in what your torrent client already seeds.
404
432
  </div>
405
433
 
406
- <div class="panel" id="detail" hidden></div>
434
+
407
435
  </section>
408
436
 
409
437
  <section id="view-categories" hidden>
@@ -1235,9 +1263,28 @@
1235
1263
  return `${minutes}m`;
1236
1264
  }
1237
1265
 
1266
+ /**
1267
+ * Closes the details, panel and row together.
1268
+ *
1269
+ * Two elements have to agree now that the panel sits in the table: the
1270
+ * panel carries the content, and the tbody around it is what makes a row
1271
+ * of the list. Hiding only the panel leaves an empty bordered row in the
1272
+ * middle of the archives until the next refresh tidies it.
1273
+ * @returns {void}
1274
+ */
1275
+ function closeDetail() {
1276
+ $('detail').hidden = true;
1277
+ $('detail-body').hidden = true;
1278
+ }
1279
+
1238
1280
  function renderRows() {
1239
1281
  const rows = $('rows');
1282
+ const below = $('rows-below');
1240
1283
  rows.innerHTML = '';
1284
+ below.innerHTML = '';
1285
+ // Filled into the first until the open archive has been written, and
1286
+ // into the second afterwards, so its details sit between the two.
1287
+ let target = rows;
1241
1288
 
1242
1289
  // Filtered and sorted here rather than where the data arrives, so the
1243
1290
  // three-second poll keeps refreshing what is on screen without
@@ -1308,10 +1355,18 @@
1308
1355
  selected = selected === entry.infoHash ? null : entry.infoHash;
1309
1356
  renderRows();
1310
1357
  if (selected) renderDetail(selected, false);
1311
- else $('detail').hidden = true;
1358
+ else closeDetail();
1312
1359
  };
1313
- rows.append(tr);
1360
+ target.append(tr);
1361
+
1362
+ // Everything after the open archive goes below its details. The
1363
+ // panel itself is never appended here — see the tbody it lives in.
1364
+ if (entry.infoHash === selected) target = below;
1314
1365
  }
1366
+
1367
+ $('detail-body').hidden = !shown.some(
1368
+ (entry) => entry.infoHash === selected,
1369
+ );
1315
1370
  }
1316
1371
 
1317
1372
  /**
@@ -2092,7 +2147,7 @@ Every piece is hashed against the ` +
2092
2147
  { method: 'DELETE' },
2093
2148
  );
2094
2149
  selected = null;
2095
- $('detail').hidden = true;
2150
+ closeDetail();
2096
2151
  refresh();
2097
2152
  } catch (error) {
2098
2153
  toast(error.message);