From df8974697cdf382739bae9638253a6062aec9f2f Mon Sep 17 00:00:00 2001 From: Ivan Date: Sun, 10 May 2026 05:38:51 -0500 Subject: [PATCH 1/4] fix(docker): include CHANGELOG.md, logo/, and reticulum manual in Docker images; fix markdown table styling in docs --- Dockerfile | 7 +++- Dockerfile.hardened | 7 +++- .../src/frontend/components/docs/DocsPage.vue | 37 +++++++++++++++++++ 3 files changed, 47 insertions(+), 4 deletions(-) diff --git a/Dockerfile b/Dockerfile index 5689195..5f1d777 100644 --- a/Dockerfile +++ b/Dockerfile @@ -22,11 +22,13 @@ COPY patches ./patches COPY scripts/fetch-micron-wasm.mjs scripts/fetch-micron-wasm.mjs COPY scripts/micron-wasm-resolve-bundled.mjs scripts/micron-wasm-resolve-bundled.mjs COPY scripts/micron-parser-go-version.mjs scripts/micron-parser-go-version.mjs +COPY scripts/build/fetch_reticulum_manual.py scripts/build/fetch_reticulum_manual.py COPY meshchatx/src/frontend ./meshchatx/src/frontend RUN npm install -g pnpm@10.33.0 && \ pnpm config set verify-store-integrity true && \ pnpm install --frozen-lockfile && \ - pnpm run build-frontend + pnpm run build-frontend && \ + pnpm run build-docs # ---- STAGE 2: Python Builder ---- @@ -45,7 +47,8 @@ ENV PATH="/opt/venv/bin:$PATH" # Install essential runtime tools in the venv (cffi verify needs setuptools on Python 3.12+) RUN pip install --no-cache-dir --upgrade "pip>=26.0" "setuptools" "jaraco.context>=6.1.0" -COPY pyproject.toml uv.lock README.md ./ +COPY pyproject.toml uv.lock README.md CHANGELOG.md ./ +COPY logo ./logo COPY vendor ./vendor RUN uv sync --no-group dev --no-install-project && \ rm -rf /root/.cache/pip /root/.cache/uv diff --git a/Dockerfile.hardened b/Dockerfile.hardened index 95481bd..72e56ff 100644 --- a/Dockerfile.hardened +++ b/Dockerfile.hardened @@ -19,11 +19,13 @@ COPY patches ./patches COPY scripts/fetch-micron-wasm.mjs scripts/fetch-micron-wasm.mjs COPY scripts/micron-wasm-resolve-bundled.mjs scripts/micron-wasm-resolve-bundled.mjs COPY scripts/micron-parser-go-version.mjs scripts/micron-parser-go-version.mjs +COPY scripts/build/fetch_reticulum_manual.py scripts/build/fetch_reticulum_manual.py COPY meshchatx/src/frontend ./meshchatx/src/frontend RUN npm install -g pnpm@10.33.0 && \ pnpm config set verify-store-integrity true && \ pnpm install --frozen-lockfile && \ - pnpm run build-frontend + pnpm run build-frontend && \ + pnpm run build-docs FROM ${PYTHON_BUILD_IMAGE} AS builder USER root @@ -37,7 +39,8 @@ ENV PATH="/opt/venv/bin:$PATH" RUN pip install --no-cache-dir --upgrade "pip>=26.0" "setuptools" "jaraco.context>=6.1.0" -COPY pyproject.toml uv.lock README.md ./ +COPY pyproject.toml uv.lock README.md CHANGELOG.md ./ +COPY logo ./logo COPY vendor ./vendor RUN uv sync --no-group dev --no-install-project && \ rm -rf /root/.cache/pip /root/.cache/uv diff --git a/meshchatx/src/frontend/components/docs/DocsPage.vue b/meshchatx/src/frontend/components/docs/DocsPage.vue index deb7be4..1ccb9e2 100644 --- a/meshchatx/src/frontend/components/docs/DocsPage.vue +++ b/meshchatx/src/frontend/components/docs/DocsPage.vue @@ -856,4 +856,41 @@ iframe { .dark :deep(.max-w-none) h4 { color: #f4f4f5; /* zinc-100 */ } + +/* Markdown table styling */ +:deep(.max-w-none) table { + width: 100%; + border-collapse: collapse; + margin: 1rem 0; + font-size: 0.875rem; +} + +:deep(.max-w-none) th, +:deep(.max-w-none) td { + border: 1px solid #d1d5db; + padding: 0.5rem 0.75rem; + text-align: left; +} + +:deep(.max-w-none) th { + background-color: #f3f4f6; + font-weight: 700; +} + +:deep(.max-w-none) tr:nth-child(even) { + background-color: #f9fafb; +} + +.dark :deep(.max-w-none) th, +.dark :deep(.max-w-none) td { + border-color: #3f3f46; +} + +.dark :deep(.max-w-none) th { + background-color: #27272a; +} + +.dark :deep(.max-w-none) tr:nth-child(even) { + background-color: #18181b; +} From e1de656219431914a3395e5b33e9d49223ce8898 Mon Sep 17 00:00:00 2001 From: Ivan Date: Sun, 10 May 2026 05:44:44 -0500 Subject: [PATCH 2/4] feat(map): drag-and-drop GeoJSON/KML/KMZ import on map window --- .../src/frontend/components/map/MapPage.vue | 86 ++++++++++++++++++- meshchatx/src/frontend/locales/en.json | 4 +- 2 files changed, 85 insertions(+), 5 deletions(-) diff --git a/meshchatx/src/frontend/components/map/MapPage.vue b/meshchatx/src/frontend/components/map/MapPage.vue index b90b51e..8ebe60f 100644 --- a/meshchatx/src/frontend/components/map/MapPage.vue +++ b/meshchatx/src/frontend/components/map/MapPage.vue @@ -149,7 +149,24 @@ /> -
+
+ + +
+ +

{{ $t("map.drop_geo_files") }}

+

GeoJSON, KML, or KMZ

+
{ + const name = f.name.toLowerCase(); + return name.endsWith(".geojson") || name.endsWith(".json") || name.endsWith(".kml") || name.endsWith(".kmz"); + }); + if (!geoFiles.length) { + ToastUtils.warning(this.$t("map.drop_no_geo_files")); + return; + } + + for (const file of geoFiles) { + try { + const name = file.name.toLowerCase(); + let features = []; + if (name.endsWith(".kmz")) { + const buf = await this.readFileArrayBuffer(file); + features = await readKmzToFeatures(buf, "EPSG:3857"); + } else if (name.endsWith(".kml")) { + const text = await this.readFileText(file); + features = readKmlToFeatures(text, "EPSG:3857"); + } else { + const text = await this.readFileText(file); + features = readGeoJsonToFeatures(text, "EPSG:3857"); + } + this.onVectorExchangeImport({ features, merge: true }); + } catch (e) { + console.error("Map drop import failed:", e); + ToastUtils.error(this.$t("map.vector_import_failed") + ` — ${file.name}`); + } + } + }, + readFileText(file) { + return new Promise((resolve, reject) => { + const r = new FileReader(); + r.onload = () => resolve(String(r.result || "")); + r.onerror = () => reject(new Error("read failed")); + r.readAsText(file); + }); + }, + readFileArrayBuffer(file) { + return new Promise((resolve, reject) => { + const r = new FileReader(); + r.onload = () => resolve(/** @type {ArrayBuffer} */ (r.result)); + r.onerror = () => reject(new Error("read failed")); + r.readAsArrayBuffer(file); + }); + }, + exportVectorGeoJson() { if (!this.drawSource || !this.hasVectorDrawFeatures) { return; diff --git a/meshchatx/src/frontend/locales/en.json b/meshchatx/src/frontend/locales/en.json index 609510d..9893c55 100644 --- a/meshchatx/src/frontend/locales/en.json +++ b/meshchatx/src/frontend/locales/en.json @@ -1079,7 +1079,9 @@ "vector_import_ok": "Imported {count} feature(s).", "vector_import_empty": "No features found in file.", "vector_import_failed": "Could not read vector file.", - "vector_export_ok": "Export started." + "vector_export_ok": "Export started.", + "drop_geo_files": "Drop map file here", + "drop_no_geo_files": "No GeoJSON, KML, or KMZ files detected." }, "interface": { "disable": "Disable", From 3d60f7f7967d390c32ea7909697ce7dfd86f1a07 Mon Sep 17 00:00:00 2001 From: Ivan Date: Sun, 10 May 2026 06:17:30 -0500 Subject: [PATCH 3/4] fix(docker): add python3 to build-frontend stage for docs build; add i18n for map drag-drop --- Dockerfile | 2 +- Dockerfile.hardened | 2 +- meshchatx/src/frontend/components/map/MapPage.vue | 7 ++++++- meshchatx/src/frontend/locales/de.json | 4 +++- meshchatx/src/frontend/locales/es.json | 4 +++- meshchatx/src/frontend/locales/fr.json | 4 +++- meshchatx/src/frontend/locales/it.json | 4 +++- meshchatx/src/frontend/locales/nl.json | 4 +++- meshchatx/src/frontend/locales/ru.json | 4 +++- meshchatx/src/frontend/locales/zh.json | 4 +++- 10 files changed, 29 insertions(+), 10 deletions(-) diff --git a/Dockerfile b/Dockerfile index 5f1d777..c684069 100644 --- a/Dockerfile +++ b/Dockerfile @@ -16,7 +16,7 @@ ARG PYTHON_HASH=sha256:dd4d2bd5b53d9b25a51da13addf2be586beebd5387e289e798e4083d9 # ---- STAGE 1: Frontend Build ---- FROM --platform=linux/amd64 ${NODE_IMAGE}@${NODE_HASH} AS build-frontend WORKDIR /src -RUN apk add --no-cache git +RUN apk add --no-cache git python3 COPY package.json pnpm-lock.yaml vite.config.js ./ COPY patches ./patches COPY scripts/fetch-micron-wasm.mjs scripts/fetch-micron-wasm.mjs diff --git a/Dockerfile.hardened b/Dockerfile.hardened index 72e56ff..9078f46 100644 --- a/Dockerfile.hardened +++ b/Dockerfile.hardened @@ -13,7 +13,7 @@ ARG PYTHON_RUNTIME_IMAGE=cgr.dev/chainguard/python:latest-dev FROM --platform=linux/amd64 ${NODE_IMAGE} AS build-frontend USER root WORKDIR /src -RUN apk add --no-cache git +RUN apk add --no-cache git python3 COPY package.json pnpm-lock.yaml vite.config.js ./ COPY patches ./patches COPY scripts/fetch-micron-wasm.mjs scripts/fetch-micron-wasm.mjs diff --git a/meshchatx/src/frontend/components/map/MapPage.vue b/meshchatx/src/frontend/components/map/MapPage.vue index 8ebe60f..5e8dd7b 100644 --- a/meshchatx/src/frontend/components/map/MapPage.vue +++ b/meshchatx/src/frontend/components/map/MapPage.vue @@ -4341,7 +4341,12 @@ export default { const geoFiles = files.filter((f) => { const name = f.name.toLowerCase(); - return name.endsWith(".geojson") || name.endsWith(".json") || name.endsWith(".kml") || name.endsWith(".kmz"); + return ( + name.endsWith(".geojson") || + name.endsWith(".json") || + name.endsWith(".kml") || + name.endsWith(".kmz") + ); }); if (!geoFiles.length) { ToastUtils.warning(this.$t("map.drop_no_geo_files")); diff --git a/meshchatx/src/frontend/locales/de.json b/meshchatx/src/frontend/locales/de.json index 53c4df2..8e033eb 100644 --- a/meshchatx/src/frontend/locales/de.json +++ b/meshchatx/src/frontend/locales/de.json @@ -1131,7 +1131,9 @@ "vector_import_ok": "Imported {count} feature(s).", "vector_import_empty": "No features found in file.", "vector_import_failed": "Could not read vector file.", - "vector_export_ok": "Export started." + "vector_export_ok": "Export started.", + "drop_geo_files": "Kartendatei hier ablegen", + "drop_no_geo_files": "Keine GeoJSON-, KML- oder KMZ-Dateien erkannt." }, "interface": { "disable": "Deaktivieren", diff --git a/meshchatx/src/frontend/locales/es.json b/meshchatx/src/frontend/locales/es.json index 170c931..d36039c 100644 --- a/meshchatx/src/frontend/locales/es.json +++ b/meshchatx/src/frontend/locales/es.json @@ -1079,7 +1079,9 @@ "vector_import_ok": "Imported {count} feature(s).", "vector_import_empty": "No features found in file.", "vector_import_failed": "Could not read vector file.", - "vector_export_ok": "Export started." + "vector_export_ok": "Export started.", + "drop_geo_files": "Suelta el archivo del mapa aquí", + "drop_no_geo_files": "No se detectaron archivos GeoJSON, KML o KMZ." }, "interface": { "disable": "Inhabilitación", diff --git a/meshchatx/src/frontend/locales/fr.json b/meshchatx/src/frontend/locales/fr.json index 9cae253..701c125 100644 --- a/meshchatx/src/frontend/locales/fr.json +++ b/meshchatx/src/frontend/locales/fr.json @@ -1079,7 +1079,9 @@ "vector_import_ok": "Imported {count} feature(s).", "vector_import_empty": "No features found in file.", "vector_import_failed": "Could not read vector file.", - "vector_export_ok": "Export started." + "vector_export_ok": "Export started.", + "drop_geo_files": "Déposez le fichier carte ici", + "drop_no_geo_files": "Aucun fichier GeoJSON, KML ou KMZ détecté." }, "interface": { "disable": "Désactiver", diff --git a/meshchatx/src/frontend/locales/it.json b/meshchatx/src/frontend/locales/it.json index 50dc856..e483eaf 100644 --- a/meshchatx/src/frontend/locales/it.json +++ b/meshchatx/src/frontend/locales/it.json @@ -1131,7 +1131,9 @@ "vector_import_ok": "Imported {count} feature(s).", "vector_import_empty": "No features found in file.", "vector_import_failed": "Could not read vector file.", - "vector_export_ok": "Export started." + "vector_export_ok": "Export started.", + "drop_geo_files": "Rilascia il file della mappa qui", + "drop_no_geo_files": "Nessun file GeoJSON, KML o KMZ rilevato." }, "interface": { "disable": "Disabilita", diff --git a/meshchatx/src/frontend/locales/nl.json b/meshchatx/src/frontend/locales/nl.json index 6ad1eac..931f055 100644 --- a/meshchatx/src/frontend/locales/nl.json +++ b/meshchatx/src/frontend/locales/nl.json @@ -1079,7 +1079,9 @@ "vector_import_ok": "Imported {count} feature(s).", "vector_import_empty": "No features found in file.", "vector_import_failed": "Could not read vector file.", - "vector_export_ok": "Export started." + "vector_export_ok": "Export started.", + "drop_geo_files": "Sleep kaartbestand hierheen", + "drop_no_geo_files": "Geen GeoJSON-, KML- of KMZ-bestanden gedetecteerd." }, "interface": { "disable": "Uitschakelen", diff --git a/meshchatx/src/frontend/locales/ru.json b/meshchatx/src/frontend/locales/ru.json index 0ccdab3..5f95c08 100644 --- a/meshchatx/src/frontend/locales/ru.json +++ b/meshchatx/src/frontend/locales/ru.json @@ -1131,7 +1131,9 @@ "vector_import_ok": "Imported {count} feature(s).", "vector_import_empty": "No features found in file.", "vector_import_failed": "Could not read vector file.", - "vector_export_ok": "Export started." + "vector_export_ok": "Export started.", + "drop_geo_files": "Перетащите файл карты сюда", + "drop_no_geo_files": "Не обнаружено файлов GeoJSON, KML или KMZ." }, "interface": { "disable": "Выключить", diff --git a/meshchatx/src/frontend/locales/zh.json b/meshchatx/src/frontend/locales/zh.json index c9fa026..76b32b2 100644 --- a/meshchatx/src/frontend/locales/zh.json +++ b/meshchatx/src/frontend/locales/zh.json @@ -1079,7 +1079,9 @@ "vector_import_ok": "Imported {count} feature(s).", "vector_import_empty": "No features found in file.", "vector_import_failed": "Could not read vector file.", - "vector_export_ok": "Export started." + "vector_export_ok": "Export started.", + "drop_geo_files": "将地图文件拖放到此处", + "drop_no_geo_files": "未检测到 GeoJSON、KML 或 KMZ 文件。" }, "interface": { "disable": "禁用", From 84d67a46a2a5b07462504e6b30d54cb52b6824dd Mon Sep 17 00:00:00 2001 From: Ivan Date: Sun, 10 May 2026 06:26:04 -0500 Subject: [PATCH 4/4] docs(CHANGELOG): update 4.6.2 with UV migration, hardened Docker, Linux CI, and map drag-drop --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9e3d15f..5150f3e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,8 @@ All notable changes to this project will be documented in this file. - **NomadNet file downloads (cancel)**: Fixed `AttributeError` when cancelling a download — `RequestReceipt` has no `.cancel()`; we now cancel the underlying `Resource` if present, or mark the receipt `FAILED` and remove it from the link queue. - **NomadNet browser (links)**: Relative `/page/` and `/file/` URLs from the Micron parser (which include backtick parameters) are now parsed correctly so they no longer show "Unsupported URL". - **NomadNet browser (hover)**: Links with `data-destination` now show the full URL including backtick parameters in the browser hover title. +- **Docker build**: `build-frontend` stage now installs `python3` so docs generation succeeds in `node:24-alpine`. +- **Docs manager**: Markdown tables in generated documentation render with proper borders and padding. ### Added @@ -47,6 +49,9 @@ All notable changes to this project will be documented in this file. - **NomadNet query tests**: Frontend and backend tests for `parseNomadnetworkUrl` with query strings and `downloadNomadNetFile` data payload handling. - **Android RNode protection**: On Android, `RNodeInterface`, `RNodeIPInterface`, and `RNodeMultiInterface` entries in the Reticulum config are automatically disabled before startup to prevent crashes from missing serial/BLE support in Chaquopy. - **Android external storage**: On Android, MeshChatX now defaults to `getExternalFilesDir()` (user-accessible via file managers) instead of private internal storage. +- **CI (Linux packages)**: AppImage, deb, and rpm release assets are now built and tested on every push to `dev` for both x64 and arm64. +- **Docker**: Added a hardened image variant (`-hardened` suffix) with non-root user, read-only rootfs, and restricted capabilities. +- **Map**: Drag-and-drop import of GeoJSON, KML, and KMZ files directly onto the map window, with localized drop hint overlays. ### Changed @@ -61,6 +66,7 @@ All notable changes to this project will be documented in this file. - **Sidebar order**: Reordered sidebar so **Telephone** appears directly below **Messages** for faster access. - **Telephone announce**: Disabled by default in `config_manager`. - **CONTRIBUTING.md**: Updated generative AI policy to emphasize local/offline models and reference the Reticulum Zen and License. +- **Dependencies**: Migrated Python dependency management from **Poetry** to **UV** (0.11.12) across all CI scripts, Dockerfiles, and dev tooling. `poetry.lock` replaced with `uv.lock`. ## [4.6.1] - 2026-05-04