pmtiles-swarm 0.45.0 → 0.45.2

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,31 @@
7
7
  ### 🐞 Bug fixes
8
8
  - _...Add new stuff here..._
9
9
 
10
+ ## 0.45.2
11
+ ### ✨ Features and improvements
12
+
13
+ ### 🐞 Bug fixes
14
+ - **A peer's pieces bar now gets a row of its own on the Peers tab.** As a column it took most of the
15
+ table and left every other cell wrapping a word at a time — `WebT orrent 0.3. 0` down four lines —
16
+ while the bar itself was still too narrow to read. The figures go on one line and the bar spans the
17
+ table beneath them, labelled **pieces** rather than **Has**.
18
+ - **A peer that describes itself with an object is no longer shown as `[object Object]`.** Engines
19
+ disagree about the shape: libtorrent sends a version string and a WebTorrent peer arrives as an
20
+ object, which went into the column unchanged — and that reads as a fault in this node rather than a
21
+ peer describing itself differently. Whatever the object carries that names it is used, and a dash
22
+ where nothing does.
23
+
24
+ ## 0.45.1
25
+ ### ✨ Features and improvements
26
+
27
+ ### 🐞 Bug fixes
28
+ - **The virtualenv route for libtorrent now says it can hand you an older version.** pip installs the
29
+ newest wheel the *Python* can take, not the newest libtorrent, and the wheels for Python 3.8 stop
30
+ at 2.0.9 — so on Ubuntu 20.04 the recipe as written produced a downgrade from the distribution's
31
+ own package, silently. The section now says how to read the `cp` tag in the filename, to compare
32
+ both interpreters before committing, and that a newer libtorrent on an older release needs a newer
33
+ Python first.
34
+
10
35
  ## 0.45.0
11
36
  ### ✨ Features and improvements
12
37
  - **Requires pmtiles-torrent 0.9.1**, which stops the sidecar rewriting resume data that has not
@@ -573,6 +573,22 @@ sudo -u pmtiles-swarm /var/lib/pmtiles-swarm/venv/bin/python -c "import libtor
573
573
  { "libtorrent": { "python": "/var/lib/pmtiles-swarm/venv/bin/python" } }
574
574
  ```
575
575
 
576
+ **Check what you got before pointing anything at it.** pip installs the newest
577
+ wheel _your Python_ can take, which is not the newest libtorrent. The filename
578
+ says which: `libtorrent-2.1.1-cp312-…` is Python 3.12, `libtorrent-2.0.9-cp38-…`
579
+ is Python 3.8 — and 2.0.9 is where the wheels for 3.8 stop. On Ubuntu 20.04,
580
+ whose `python3` is 3.8, this route hands you something **older** than the
581
+ distribution's own package. Compare the two before you commit to it:
582
+
583
+ ```sh
584
+ sudo -u pmtiles-swarm python3 -c "import libtorrent; print(libtorrent.__version__)"
585
+ sudo -u pmtiles-swarm /var/lib/pmtiles-swarm/venv/bin/python -c "import libtorrent; print(libtorrent.__version__)"
586
+ ```
587
+
588
+ If the venv is not newer, delete it and keep the distribution package. Getting a
589
+ newer libtorrent on an older release means a newer Python first — deadsnakes, or
590
+ the release upgrade — and building the venv from that interpreter.
591
+
576
592
  Reversible in one line: delete the key and the node is back on the distribution
577
593
  package, with no uninstall and nothing done to apt. `ReadWritePaths` already
578
594
  covers `/var/lib/pmtiles-swarm`, so the venv needs no unit change — put it
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pmtiles-swarm",
3
- "version": "0.45.0",
3
+ "version": "0.45.2",
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",
@@ -252,6 +252,12 @@
252
252
  word-break: break-all;
253
253
  }
254
254
  .rows th { color: var(--muted); font-size: 0.75rem; white-space: nowrap; }
255
+ /* A peer's figures fit on one line once the bar is not competing with
256
+ them for width; the bar gets the whole table on the row below. */
257
+ .rows.peers td { white-space: nowrap; word-break: normal; }
258
+ .rows.peers tr.peerbar > td { border-bottom: 1px solid var(--line); }
259
+ .rows.peers tr.peerbar .piecerow { margin: 0; }
260
+ .rows.peers tr:not(.peerbar) > td { border-bottom: none; padding-bottom: 0.1rem; }
255
261
  [hidden] { display: none !important; }
256
262
 
257
263
  /* A radio or checkbox beside its own label.
@@ -1588,6 +1594,30 @@
1588
1594
  * @param {object} entry - What the detail endpoint already returned.
1589
1595
  * @returns {Promise<void>} - Resolves once rendered.
1590
1596
  */
1597
+ /**
1598
+ * What a peer says it is, as a string.
1599
+ *
1600
+ * Engines disagree about the shape: libtorrent sends a version string,
1601
+ * and a WebTorrent peer arrives as an object. The object went through
1602
+ * escapeHtml unchanged and the column read "[object Object]" — which
1603
+ * looks like a fault in this node rather than a peer that described
1604
+ * itself differently.
1605
+ * @param {object} peer - One peer from the engine.
1606
+ * @returns {string} - Something worth printing.
1607
+ */
1608
+ function clientOf(peer) {
1609
+ const said = peer?.client;
1610
+ if (typeof said === 'string' && said.trim()) return said;
1611
+ if (said && typeof said === 'object') {
1612
+ // Whatever it does carry, in the order most likely to name it.
1613
+ for (const key of ['name', 'client', 'version', 'id', 'peerId']) {
1614
+ const value = said[key];
1615
+ if (typeof value === 'string' && value.trim()) return value;
1616
+ }
1617
+ }
1618
+ return '—';
1619
+ }
1620
+
1591
1621
  async function fillPane(name, infoHash, entry) {
1592
1622
  const pane = document.querySelector(`[data-pane="${name}"]`);
1593
1623
  if (!pane) return;
@@ -1677,39 +1707,58 @@
1677
1707
  (peer) => !listed.has(peer.address),
1678
1708
  );
1679
1709
 
1680
- const rows = [...peers, ...extra].map((peer, index) => {
1681
- const address = peer.address ?? peer.ip ?? '—';
1682
- const have = bitfields.get(address);
1683
- return [
1684
- escapeHtml(address),
1685
- escapeHtml(peer.client ?? '—'),
1686
- escapeHtml(peer.kind ?? 'peer'),
1687
- escapeHtml(peer.connection ?? '—'),
1688
- have
1689
- ? `<canvas class="piecebar thin" data-bar="peer-${index}"></canvas>`
1690
- : '<span class="sub">not reported</span>',
1691
- peer.progress != null ? pct(peer.progress) : '—',
1692
- rate(peer.downloadSpeed ?? peer.dlSpeed),
1693
- rate(peer.uploadSpeed ?? peer.upSpeed),
1694
- ];
1695
- });
1710
+ // Two rows a peer: the figures, then its pieces across the full
1711
+ // width. As a column the bar took most of the table and left every
1712
+ // other cell wrapping a word at a time -- "WebT orrent 0.3. 0" in
1713
+ // four lines -- while the bar itself was still too narrow to read.
1714
+ const columns = ['Address', 'Client', 'Kind', 'Conn', 'Progress', 'Down', 'Up'];
1715
+ const body = [...peers, ...extra]
1716
+ .map((peer, index) => {
1717
+ const address = peer.address ?? peer.ip ?? '—';
1718
+ const have = bitfields.get(address);
1719
+ const cells = [
1720
+ escapeHtml(address),
1721
+ escapeHtml(clientOf(peer)),
1722
+ escapeHtml(peer.kind ?? 'peer'),
1723
+ escapeHtml(peer.connection ?? '—'),
1724
+ peer.progress != null ? pct(peer.progress) : '—',
1725
+ rate(peer.downloadSpeed ?? peer.dlSpeed),
1726
+ rate(peer.uploadSpeed ?? peer.upSpeed),
1727
+ ];
1728
+ return (
1729
+ `<tr>${cells.map((cell) => `<td>${cell}</td>`).join('')}</tr>` +
1730
+ `<tr class="peerbar"><td colspan="${columns.length}">
1731
+ <div class="piecerow">
1732
+ <span class="label">pieces</span>
1733
+ ${
1734
+ have
1735
+ ? `<canvas class="piecebar thin" data-bar="peer-${index}"></canvas>`
1736
+ : '<span class="sub">not reported</span>'
1737
+ }
1738
+ <span class="value">${peer.progress != null ? pct(peer.progress) : ''}</span>
1739
+ </div>
1740
+ </td></tr>`
1741
+ );
1742
+ })
1743
+ .join('');
1696
1744
 
1697
1745
  pane.innerHTML =
1698
- table(
1699
- ['Address', 'Client', 'Kind', 'Conn', 'Has', 'Progress', 'Down', 'Up'],
1700
- rows,
1701
- ) +
1746
+ (body === ''
1747
+ ? '<div class="sub">Nothing to show.</div>'
1748
+ : `<table class="rows peers"><thead><tr>${columns
1749
+ .map((header) => `<th>${escapeHtml(header)}</th>`)
1750
+ .join('')}</tr></thead><tbody>${body}</tbody></table>`) +
1702
1751
  (failed
1703
1752
  ? `<div class="sub" style="margin-top:0.5rem">
1704
1753
  The engine could not list peers: ${escapeHtml(failed)}
1705
1754
  </div>`
1706
1755
  : '') +
1707
- (rows.length > 0
1756
+ (body !== ''
1708
1757
  ? `<div class="sub" style="margin-top:0.5rem">
1709
- <b>Has</b> is drawn the same way as the bars on General —
1710
- a column covers many pieces and is only filled when all of
1711
- them are held. <b>Progress</b> is the engine's own figure
1712
- for the same peer, which is exact.
1758
+ Each peer's <b>pieces</b> bar is drawn the way the bars on
1759
+ General are — a column covers many pieces and is only
1760
+ filled when all of them are held. <b>Progress</b> is the
1761
+ engine's own figure for the same peer, which is exact.
1713
1762
  </div>`
1714
1763
  : '');
1715
1764