chore(release): bump version to 4.5.1 and update changelog

This commit is contained in:
Ivan
2026-04-23 17:50:09 -05:00
parent eaf8d72faf
commit bec1129169
19 changed files with 73 additions and 59 deletions
+21 -1
View File
@@ -2,7 +2,27 @@
All notable changes to this project will be documented in this file.
## [4.5.0] - 2026-04-24
## [4.5.1] - 2026-04-24
### Identity switching
- **Hotswap API**: Identity switch responses now include **display name** and **identity hash** so the client can refresh state without guessing from partial payloads.
- **Event handling**: Identity switch events are **deduplicated** in **`App.vue`** and **`IdentitiesPage.vue`** so rapid or repeated signals do not stack duplicate work.
- **Locales**: Confirmation copy for switching identities no longer tells users to restart when that is not required (aligned strings across supported languages).
- **Tests**: New **HTTP** coverage for the identity switch API (success paths, validation, and error responses).
### Desktop (Electron)
- **Boot experience**: **Splash screen** on startup and **Codec2** loader scripts use **retry** logic so transient load failures are less likely to strand voice features.
- **Developer tools**: **F12** toggles **DevTools**; the menu bar **auto-hides** in main windows for a cleaner ui.
- **Content Security Policy**: CSP now allows **`wasm-unsafe-eval`** where needed so **WebAssembly** used by the stack (for example audio codec paths) can run under the hardened policy.
### Microphone and translations
- **Recording**: Microphone capture updates **error handling** and adjusts **AudioWorklet** import so failures surface more reliably instead of failing silently.
- **Locales**: New and updated strings for **microphone** errors so users get clearer guidance when capture or permissions go wrong.
## [4.5.0] - 2026-04-23
### TL;DR
+1 -1
View File
@@ -300,7 +300,7 @@ task build:all
## Versioning
Current version in this repo is `4.5.0`.
Current version in this repo is `4.5.1`.
- `package.json` is the JavaScript/Electron version source.
- `meshchatx/src/version.py` is synced from `package.json` using:
+3 -3
View File
@@ -61,17 +61,17 @@ source ~/.profile
## 3) Install MeshChatX with pipx (recommended)
Preferred option (recommended): install from a release wheel (4.5.0 or newer),
Preferred option (recommended): install from a release wheel (4.5.1 or newer),
because the wheel bundles frontend assets.
```bash
pipx install /path/to/reticulum_meshchatx-<version>-py3-none-any.whl
```
Direct example (v4.5.0):
Direct example (v4.5.1):
```bash
pipx install "https://git.quad4.io/RNS-Things/MeshChatX/releases/download/v4.4.0/reticulum_meshchatx-4.5.0-py3-none-any.whl"
pipx install "https://git.quad4.io/RNS-Things/MeshChatX/releases/download/v4.5.1/reticulum_meshchatx-4.5.1-py3-none-any.whl"
```
`py3-none-any` wheels are architecture-independent, so the same wheel artifact
+1 -1
View File
@@ -295,7 +295,7 @@ task build:all
## Versionierung
Aktuelle Version in diesem Repository: `4.5.0`.
Aktuelle Version in diesem Repository: `4.5.1`.
- `package.json` ist die Quelle fuer die JavaScript/Electron-Version.
- `meshchatx/src/version.py` wird aus `package.json` synchronisiert mit:
+1 -1
View File
@@ -295,7 +295,7 @@ Scorciatoie `Makefile`:
## Versioning
Versione attuale nel repository: `4.5.0`.
Versione attuale nel repository: `4.5.1`.
- La fonte della versione JavaScript/Electron e `package.json`.
- `meshchatx/src/version.py` e sincronizzato da `package.json` con:
+1 -1
View File
@@ -295,7 +295,7 @@ task build:all
## バージョン管理
このリポジトリの現在のバージョンは `4.5.0` です。
このリポジトリの現在のバージョンは `4.5.1` です。
- JavaScript / Electron のバージョンソースは `package.json`
- `meshchatx/src/version.py` は次で `package.json` と同期します:
+1 -1
View File
@@ -295,7 +295,7 @@ task build:all
## Версионирование
Текущая версия в репозитории: `4.5.0`.
Текущая версия в репозитории: `4.5.1`.
- Источник версии JS/Electron — `package.json`.
- `meshchatx/src/version.py` синхронизируется из `package.json`:
+1 -1
View File
@@ -295,7 +295,7 @@ task build:all
## 版本
本仓库当前版本: `4.5.0`
本仓库当前版本: `4.5.1`
- JavaScript/Electron 版本以 `package.json` 为准。
- `meshchatx/src/version.py` 通过以下命令与 `package.json` 同步:
+1 -1
View File
@@ -2,4 +2,4 @@
"""Reticulum MeshChatX - A mesh network communications app."""
__version__ = "4.5.0"
__version__ = "4.5.1"
+3 -2
View File
@@ -11593,9 +11593,10 @@ class ReticulumMeshChat:
if path.startswith("/reticulum-docs/") or path.startswith(
"/rnode-flasher/"
):
script_sources = ["'self'", "'unsafe-inline'"]
script_sources = ["'self'", "'unsafe-inline'", "'wasm-unsafe-eval'"]
else:
script_sources = ["'self'"]
# wasm-unsafe-eval: Codec2 / sox Emscripten WASM (sox.js) without full unsafe-eval
script_sources = ["'self'", "'wasm-unsafe-eval'"]
style_sources = ["'self'", "'unsafe-inline'"]
if self.current_context and self.current_context.config:
@@ -76,7 +76,7 @@ pycparser 3.0
pyserial 3.5
License: BSD
Author: Chris Liechti
reticulum-meshchatx 4.5.0
reticulum-meshchatx 4.5.1
License: 0BSD AND MIT
Author: Quad4
rns 1.1.9
+1 -1
View File
@@ -3,4 +3,4 @@
Do not edit by hand. Run: pnpm run version:sync
"""
__version__ = "4.5.0"
__version__ = "4.5.1"
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "reticulum-meshchatx",
"version": "4.5.0",
"version": "4.5.1",
"description": "A simple mesh network communications app powered by the Reticulum Network Stack",
"homepage": "https://git.quad4.io/RNS-Things/MeshChatX",
"desktopName": "reticulum-meshchatx.desktop",
+2 -2
View File
@@ -1,7 +1,7 @@
# Maintainer: Ivan <ivan@quad4.io>
pkgname=reticulum-meshchatx-git
_pkgname=reticulum-meshchatx
pkgver=4.5.0.r0.gebacc00
pkgver=4.5.1.r0.gebacc00
pkgrel=1
pkgdesc="A simple mesh network communications app powered by the Reticulum Network Stack"
arch=('x86_64' 'aarch64')
@@ -19,7 +19,7 @@ sha256sums=('SKIP'
pkgver() {
cd "$_pkgname"
git describe --long --tags 2>/dev/null | sed 's/^v//;s/\([^-]*-g\)/r\1/;s/-/./g' || \
printf "4.5.0.r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
printf "4.5.1.r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
}
prepare() {
Generated
+22 -29
View File
@@ -470,15 +470,15 @@ pycparser = {version = "*", markers = "implementation_name != \"PyPy\""}
[[package]]
name = "click"
version = "8.3.2"
version = "8.3.3"
description = "Composable command line interface toolkit"
optional = false
python-versions = ">=3.10"
groups = ["dev"]
markers = "python_version < \"4.0\""
files = [
{file = "click-8.3.2-py3-none-any.whl", hash = "sha256:1924d2c27c5653561cd2cae4548d1406039cb79b858b747cfea24924bbc1616d"},
{file = "click-8.3.2.tar.gz", hash = "sha256:14162b8b3b3550a7d479eafa77dfd3c38d9dc8951f6f69c78913a8f9a7540fd5"},
{file = "click-8.3.3-py3-none-any.whl", hash = "sha256:a2bf429bb3033c89fa4936ffb35d5cb471e3719e1f3c8a7c3fff0b8314305613"},
{file = "click-8.3.3.tar.gz", hash = "sha256:398329ad4837b2ff7cbe1dd166a4c0f8900c3ca3a218de04466f38f6497f18a2"},
]
[package.dependencies]
@@ -1022,18 +1022,18 @@ zoneinfo = ["tzdata (>=2026.1) ; sys_platform == \"win32\" or sys_platform == \"
[[package]]
name = "idna"
version = "3.11"
version = "3.13"
description = "Internationalized Domain Names in Applications (IDNA)"
optional = false
python-versions = ">=3.8"
groups = ["main"]
files = [
{file = "idna-3.11-py3-none-any.whl", hash = "sha256:771a87f49d9defaf64091e6e6fe9c18d4833f140bd19464795bc32d966ca37ea"},
{file = "idna-3.11.tar.gz", hash = "sha256:795dafcc9c04ed0c1fb032c2aa73654d8e8c5023a7df64a53f39190ada629902"},
{file = "idna-3.13-py3-none-any.whl", hash = "sha256:892ea0cde124a99ce773decba204c5552b69c3c67ffd5f232eb7696135bc8bb3"},
{file = "idna-3.13.tar.gz", hash = "sha256:585ea8fe5d69b9181ec1afba340451fba6ba764af97026f92a91d4eef164a242"},
]
[package.extras]
all = ["flake8 (>=7.1.1)", "mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2)"]
all = ["mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2)"]
[[package]]
name = "iniconfig"
@@ -2142,32 +2142,25 @@ testing = ["filelock"]
[[package]]
name = "python-msilib"
version = "0.5.0"
version = "0.6.0"
description = "Read and write Microsoft Installer files"
optional = false
python-versions = ">=3.13"
groups = ["dev"]
markers = "sys_platform == \"win32\" and python_version >= \"3.13\""
files = [
{file = "python_msilib-0.5.0-cp313-cp313-win32.whl", hash = "sha256:240c9cebc402361e6fe32fb94020ce5a2674343122cb4dbd036fa59068d153c4"},
{file = "python_msilib-0.5.0-cp313-cp313-win_amd64.whl", hash = "sha256:cb1db6fa79cfff539a0f313c80f27760b3c452b8fb59878c4b1ce2959711541e"},
{file = "python_msilib-0.5.0-cp313-cp313-win_arm64.whl", hash = "sha256:3904771a9e31276da9d2de4e431e09b122a354b84b41746c6feaa14b91d2fd0d"},
{file = "python_msilib-0.5.0-cp313-cp313t-win32.whl", hash = "sha256:67ab7fe107b6dbed42e609d0731ae9863c8aaf58e6015995e42671a9d215fe86"},
{file = "python_msilib-0.5.0-cp313-cp313t-win_amd64.whl", hash = "sha256:dc3d895c1cb4f695344a7149909d460020d0e6f987d33ab40ea687d65dd1f2ad"},
{file = "python_msilib-0.5.0-cp313-cp313t-win_arm64.whl", hash = "sha256:cc62a3d0500c1d6d21bea347c55215ae16c81bc749134c47e466f284a46b56fe"},
{file = "python_msilib-0.5.0-cp314-cp314-win32.whl", hash = "sha256:e5023ab8da04a13769d1054e64415c02c198d442ce0f7cd9637204341d997379"},
{file = "python_msilib-0.5.0-cp314-cp314-win_amd64.whl", hash = "sha256:24cd942d097bafc97018698e1e66652143529eecaf8b8df55a624d580d81df7c"},
{file = "python_msilib-0.5.0-cp314-cp314-win_arm64.whl", hash = "sha256:f9da5045835d0de30b1087ff6fd6e0b6d076e248cd26405c0d399d8649ef9684"},
{file = "python_msilib-0.5.0-cp314-cp314t-win32.whl", hash = "sha256:821a164e72d77786d9e6d7cd28c060e6668665632a29f2c76abac85651f05f11"},
{file = "python_msilib-0.5.0-cp314-cp314t-win_amd64.whl", hash = "sha256:3fafe94d66f00bd3b26159b7ff43078421738288af5212744a1cb4a1cea52bc8"},
{file = "python_msilib-0.5.0-cp314-cp314t-win_arm64.whl", hash = "sha256:1c0b7a595dd457f7df5bd102c4c5abe5337ba0362aab2ece31bea29e6e7d9f2d"},
{file = "python_msilib-0.5.0.tar.gz", hash = "sha256:5d9d0c2af2cafbc50d484cce4cfab1cb8cfd65d705d7111d216bc525a059113b"},
{file = "python_msilib-0.6.0-cp313-cp313-win32.whl", hash = "sha256:1145ce1e0eaf2af2948a02147415c621323cb2b2ff118fccdac333941547c11b"},
{file = "python_msilib-0.6.0-cp313-cp313-win_amd64.whl", hash = "sha256:41b83e39c622a79042b3d1745421ce3492b954d701d7aeaf942d974c31291431"},
{file = "python_msilib-0.6.0-cp313-cp313-win_arm64.whl", hash = "sha256:3ac47071f27755b11f9e01d7222c2babd84997410f4f0d96ded55c187b0b1fb8"},
{file = "python_msilib-0.6.0-cp314-cp314-win32.whl", hash = "sha256:8144e6249d12768e08844672175404b21a1f7ce4b7b6d539858a4f9ad6d6ca6c"},
{file = "python_msilib-0.6.0-cp314-cp314-win_amd64.whl", hash = "sha256:281421203401afef589321f16d92d7aea8e5cf35f0345e47174346a3dde24808"},
{file = "python_msilib-0.6.0-cp314-cp314-win_arm64.whl", hash = "sha256:c2fbc0d9388c937222f2ef717385aade5a3696bdc3b81150a0098c0cb79b58b9"},
{file = "python_msilib-0.6.0-cp314-cp314t-win32.whl", hash = "sha256:e511a1b4e247901416a39167090a5e58d1b65d1a5b401d0250dce983f4ab0980"},
{file = "python_msilib-0.6.0-cp314-cp314t-win_amd64.whl", hash = "sha256:848e7dd1fc61407d207fa4a2b7ac12b3a2de376d394a1d3f70ac4034bc9cd1a9"},
{file = "python_msilib-0.6.0-cp314-cp314t-win_arm64.whl", hash = "sha256:a645358b02e17b0de61ea3f1dcd9f5d6b738148b1f317e2e864a08e04eeb80f3"},
{file = "python_msilib-0.6.0.tar.gz", hash = "sha256:47a6c16aa8528b797bd81e71cc544505b5444543319dbaf12011123b750c9d3c"},
]
[package.extras]
dev = ["bump-my-version (==1.2.4)", "cibuildwheel (==3.3.0)", "pre-commit (==4.5.0)"]
tests = ["coverage (==7.12.0)", "pytest (==9.0.2)"]
[[package]]
name = "pyyaml"
version = "6.0.3"
@@ -2632,19 +2625,19 @@ files = [
[[package]]
name = "striprtf"
version = "0.0.29"
version = "0.0.31"
description = "A simple library to convert rtf to text"
optional = false
python-versions = ">=3.8"
groups = ["dev"]
markers = "sys_platform == \"win32\""
files = [
{file = "striprtf-0.0.29-py3-none-any.whl", hash = "sha256:0fc6a41999d015358d19627776b616424dd501ad698105c81d76734d1e14d91b"},
{file = "striprtf-0.0.29.tar.gz", hash = "sha256:5a822d075e17417934ed3add6fc79b5fc8fb544fe4370b2f894cdd28f0ddd78e"},
{file = "striprtf-0.0.31-py3-none-any.whl", hash = "sha256:8ec8150a4213951675f711750a4a5b8a98a6da3ef85deeff0bb6e39cd2beeda4"},
{file = "striprtf-0.0.31.tar.gz", hash = "sha256:ce4b6403427d7d5cda95fdb61365432225f6fbe5ea6797e1357f4045d351ba2d"},
]
[package.extras]
dev = ["build (>=1.0.0)", "pytest (>=7.0.0)"]
dev = ["build (>=1.0.0)", "pytest (>=7.0.0)", "twine (>=6.1.0)"]
[[package]]
name = "textual"
+1 -1
View File
@@ -1,6 +1,6 @@
[project]
name = "reticulum-meshchatx"
version = "4.5.0"
version = "4.5.1"
description = "A simple mesh network communications app powered by the Reticulum Network Stack"
authors = [
{name = "Quad4"}
+3 -3
View File
@@ -96,8 +96,8 @@ async def test_app_status_endpoints(mock_rns_minimal, temp_dir):
app_instance.config.set("tutorial_seen", True)
assert app_instance.config.get("tutorial_seen") == "true"
app_instance.config.set("changelog_seen_version", "4.5.0")
assert app_instance.config.get("changelog_seen_version") == "4.5.0"
app_instance.config.set("changelog_seen_version", "4.5.1")
assert app_instance.config.get("changelog_seen_version") == "4.5.1"
# Test app_info returns these values
with ExitStack() as info_stack:
@@ -113,4 +113,4 @@ async def test_app_status_endpoints(mock_rns_minimal, temp_dir):
assert val == "true"
val = app_instance.config.get("changelog_seen_version")
assert val == "4.5.0"
assert val == "4.5.1"
+5 -5
View File
@@ -62,9 +62,9 @@ describe("App.vue Modals", () => {
return Promise.resolve({
data: {
app_info: {
version: "4.5.0",
version: "4.5.1",
tutorial_seen: true,
changelog_seen_version: "4.5.0",
changelog_seen_version: "4.5.1",
},
},
});
@@ -94,7 +94,7 @@ describe("App.vue Modals", () => {
return Promise.resolve({
data: {
app_info: {
version: "4.5.0",
version: "4.5.1",
tutorial_seen: false,
changelog_seen_version: "0.0.0",
},
@@ -153,7 +153,7 @@ describe("App.vue Modals", () => {
return Promise.resolve({
data: {
app_info: {
version: "4.5.0",
version: "4.5.1",
tutorial_seen: true,
changelog_seen_version: "3.9.0",
},
@@ -161,7 +161,7 @@ describe("App.vue Modals", () => {
});
}
if (url === "/api/v1/app/changelog") {
return Promise.resolve({ data: { html: "<h1>New Features</h1>", version: "4.5.0" } });
return Promise.resolve({ data: { html: "<h1>New Features</h1>", version: "4.5.1" } });
}
if (url === "/api/v1/config") return Promise.resolve({ data: { config: { theme: "dark" } } });
if (url === "/api/v1/auth/status") return Promise.resolve({ data: { auth_enabled: false } });
+3 -3
View File
@@ -78,7 +78,7 @@ describe("ChangelogModal.vue", () => {
axiosMock.get.mockResolvedValue({
data: {
html: "<h1>Test</h1>",
version: "4.5.0",
version: "4.5.1",
},
});
@@ -95,7 +95,7 @@ describe("ChangelogModal.vue", () => {
axiosMock.get.mockResolvedValue({
data: {
html: "<h1>Test</h1>",
version: "4.5.0",
version: "4.5.1",
},
});
@@ -114,7 +114,7 @@ describe("ChangelogModal.vue", () => {
axiosMock.get.mockResolvedValue({
data: {
html: "<h1>Test</h1>",
version: "4.5.0",
version: "4.5.1",
},
});