From 97cd6573368a730c91026c5daeb60e1ce551d7e8 Mon Sep 17 00:00:00 2001 From: proddy Date: Tue, 14 Apr 2026 09:31:05 +0200 Subject: [PATCH 01/14] fix links --- interface/src/app/main/Help.tsx | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/interface/src/app/main/Help.tsx b/interface/src/app/main/Help.tsx index 16cb09c21..d68ffa591 100644 --- a/interface/src/app/main/Help.tsx +++ b/interface/src/app/main/Help.tsx @@ -11,6 +11,7 @@ import { Box, Button, Divider, + Grid, Link, List, ListItem, @@ -42,7 +43,7 @@ interface CustomSupport { html: string | null; } -const DEFAULT_IMAGE_URL = 'https://emsesp.org/_media/images/installer.jpeg'; +const DEFAULT_IMAGE_URL = 'https://emsesp.org/media/images/installer.jpeg'; const SUPPORT_BOX_STYLES: SxProps = { borderRadius: 3, @@ -182,17 +183,19 @@ const HelpComponent = () => { )} - - {LL.HELP_INFORMATION_4()}. - - + + + {LL.HELP_INFORMATION_4()}: + + + From 3317aa845aefbb3281e04022c8012ede8da5492c Mon Sep 17 00:00:00 2001 From: proddy Date: Tue, 14 Apr 2026 09:31:19 +0200 Subject: [PATCH 02/14] package update --- interface/pnpm-lock.yaml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/interface/pnpm-lock.yaml b/interface/pnpm-lock.yaml index 11eff743d..bbee8b712 100644 --- a/interface/pnpm-lock.yaml +++ b/interface/pnpm-lock.yaml @@ -1283,8 +1283,8 @@ packages: resolution: {integrity: sha512-DLIsRzJVBQu72meAKPkWQOLcujdXT32hwdfnkI1frSiSRMK1MofjKHf+MEx0SB6fjEFXL8fBDv1dKymBlOp4Qw==} engines: {node: '>=0.10.0'} - caniuse-lite@1.0.30001787: - resolution: {integrity: sha512-mNcrMN9KeI68u7muanUpEejSLghOKlVhRqS/Za2IeyGllJ9I9otGpR9g3nsw7n4W378TE/LyIteA0+/FOZm4Kg==} + caniuse-lite@1.0.30001788: + resolution: {integrity: sha512-6q8HFp+lOQtcf7wBK+uEenxymVWkGKkjFpCvw5W25cmMwEDU45p1xQFBQv8JDlMMry7eNxyBaR+qxgmTUZkIRQ==} caw@2.0.1: resolution: {integrity: sha512-Cg8/ZSBEa8ZVY9HspcGUYaK63d/bN7rqS3CYCzEGUxuYv6UlmcjzDUz2fCFFHyTvUW5Pk0I+3hkA3iXlIj6guA==} @@ -1519,8 +1519,8 @@ packages: duplexer3@0.1.5: resolution: {integrity: sha512-1A8za6ws41LQgv9HrE/66jyC5yuSjQ3L/KOpFtoBilsAK2iA2wuS5rTt1OCzIvtS2V7nVmedsUU+DGRcjBmOYA==} - electron-to-chromium@1.5.335: - resolution: {integrity: sha512-q9n5T4BR4Xwa2cwbrwcsDJtHD/enpQ5S1xF1IAtdqf5AAgqDFmR/aakqH3ChFdqd/QXJhS3rnnXFtexU7rax6Q==} + electron-to-chromium@1.5.336: + resolution: {integrity: sha512-AbH9q9J455r/nLmdNZes0G0ZKcRX73FicwowalLs6ijwOmCJSRRrLX63lcAlzy9ux3dWK1w1+1nsBJEWN11hcQ==} emoji-regex@10.6.0: resolution: {integrity: sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==} @@ -4408,8 +4408,8 @@ snapshots: browserslist@4.28.2: dependencies: baseline-browser-mapping: 2.10.18 - caniuse-lite: 1.0.30001787 - electron-to-chromium: 1.5.335 + caniuse-lite: 1.0.30001788 + electron-to-chromium: 1.5.336 node-releases: 2.0.37 update-browserslist-db: 1.2.3(browserslist@4.28.2) @@ -4471,7 +4471,7 @@ snapshots: camelcase@2.1.1: {} - caniuse-lite@1.0.30001787: {} + caniuse-lite@1.0.30001788: {} caw@2.0.1: dependencies: @@ -4773,7 +4773,7 @@ snapshots: duplexer3@0.1.5: {} - electron-to-chromium@1.5.335: {} + electron-to-chromium@1.5.336: {} emoji-regex@10.6.0: {} From 99c5e2230c5d89a4a2f5d7294b534ef8ceb35b18 Mon Sep 17 00:00:00 2001 From: proddy Date: Tue, 14 Apr 2026 09:31:35 +0200 Subject: [PATCH 03/14] fix link --- test/test_data/custom_support.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_data/custom_support.json b/test/test_data/custom_support.json index b528645a3..6d5b81502 100644 --- a/test/test_data/custom_support.json +++ b/test/test_data/custom_support.json @@ -13,6 +13,6 @@ "", "For help and questions please contact your installer." ], - "img_url": "https://emsesp.org/_media/images/designer.png" + "img_url": "https://emsesp.org/media/images/designer.png" } } \ No newline at end of file From 111145886379e790fd1b4200643fd9f6916c837a Mon Sep 17 00:00:00 2001 From: proddy Date: Tue, 14 Apr 2026 09:31:50 +0200 Subject: [PATCH 04/14] upgrade message warnings --- interface/src/components/upload/DragNdrop.tsx | 15 ++-- interface/src/i18n/cz/index.ts | 9 +- interface/src/i18n/de/index.ts | 9 +- interface/src/i18n/en/index.ts | 9 +- interface/src/i18n/fr/index.ts | 9 +- interface/src/i18n/it/index.ts | 9 +- interface/src/i18n/nl/index.ts | 3 - interface/src/i18n/no/index.ts | 9 +- interface/src/i18n/pl/index.ts | 9 +- interface/src/i18n/sk/index.ts | 9 +- interface/src/i18n/sv/index.ts | 9 +- interface/src/i18n/tr/index.ts | 9 +- mock-api/restServer.ts | 25 ++---- src/web/WebStatusService.cpp | 82 +++++++++++++++---- src/web/WebStatusService.h | 2 +- 15 files changed, 132 insertions(+), 85 deletions(-) diff --git a/interface/src/components/upload/DragNdrop.tsx b/interface/src/components/upload/DragNdrop.tsx index e0214b1bf..0f6feedf8 100644 --- a/interface/src/components/upload/DragNdrop.tsx +++ b/interface/src/components/upload/DragNdrop.tsx @@ -78,16 +78,19 @@ const DragNdrop = ({ text, onFileSelected }: DragNdropProps) => { useState(0); const { send: checkUpgradeImportantMessages } = useRequest( - (type: string) => - callAction({ action: 'upgradeImportantMessages', param: type }), + (version: string) => + callAction({ action: 'upgradeImportantMessages', param: version }), { immediate: false } ) - .onSuccess((event: { data: number }) => { - setUpgradeImportantMessageType(event.data); + .onSuccess((event) => { + setUpgradeImportantMessageType( + (event.data as { upgradeImportantMessageType: number }) + .upgradeImportantMessageType + ); }) - .onError((error: { error?: { message?: string } }) => { + .onError((error) => { toast.error(String(error.error?.message || 'An error occurred')); }); @@ -189,7 +192,7 @@ const DragNdrop = ({ text, onFileSelected }: DragNdropProps) => { {LL.UPLOAD()} - {showUpgradeDialog && ( + {showUpgradeDialog && upgradeImportantMessageType > 0 && ( contact your installer." ], - img_url: 'https://emsesp.org/_media/images/designer.png' + img_url: 'https://emsesp.org/media/images/designer.png' // img_url: 'https://picsum.photos/200/300' } }; @@ -5173,29 +5173,16 @@ router } else if (action === 'upgradeImportantMessages') { // check upgrade important messages console.log( - 'checking upgrade important messages for version ', + 'checking upgrade important messages for version', content.param ); // determine message based on if we're upgrading a minor or major version // TODO finish this - let message = 0; const version = content.param; - const majorVersion = version.split('.')[0]; - const minorVersion = version.split('.')[1]; - const currentMajorVersion = THIS_VERSION.split('.')[0]; - const currentMinorVersion = THIS_VERSION.split('.')[1]; - if (majorVersion > currentMajorVersion) { - message = 1; - } else if (majorVersion < currentMajorVersion) { - message = 2; - } else if (minorVersion > currentMinorVersion) { - message = 1; - } else if (minorVersion < currentMinorVersion) { - message = 2; - } else { - message = 0; - } - return message; + const data = { + upgradeImportantMessageType: 1 + }; + return data; } } return status(404); // cmd not found diff --git a/src/web/WebStatusService.cpp b/src/web/WebStatusService.cpp index 3978d6e91..81f548b20 100644 --- a/src/web/WebStatusService.cpp +++ b/src/web/WebStatusService.cpp @@ -217,7 +217,7 @@ void WebStatusService::action(AsyncWebServerRequest * request, JsonVariant json) EMSESP::mqtt_.reset_mqtt(); ok = true; } else if (action == "upgradeImportantMessages") { - ok = upgradeImportantMessages(param.c_str()); + ok = upgradeImportantMessages(root, param); } #if defined(EMSESP_STANDALONE) && !defined(EMSESP_UNITY) @@ -240,26 +240,76 @@ void WebStatusService::action(AsyncWebServerRequest * request, JsonVariant json) } // action = upgradeImportantMessages -// returns the type of upgrade important message to show\ -// 0 = no message -// 1 = major version upgrade -// 2 = minor version upgrade -// TODO finish this -bool WebStatusService::upgradeImportantMessages(const char * version) { - version::Semver200_version current_version(current_version_s); - version::Semver200_version latest_version(version); - if (latest_version > current_version) { - return 1; +// returns the type of upgrade important message to display in the UI +// 0 = no message (if just a minor version upgrade) +// 1 = going from <= 3.8 to 3.9 (new partition layout) +// 2 = major version upgrade +// version can be like 3.8.2 or a filename like EMS-ESP-3_8_2-dev_13-ESP32-16MB+.bin +bool WebStatusService::upgradeImportantMessages(JsonObject root, std::string & version) { + if (version.empty()) { + return false; } + + uint8_t upgradeImportantMessageType = 0; + + // it's a filename with a .bin extension, try and extract the version from it + version::Semver200_version latest_version; + if (version.find(".bin") != std::string::npos) { + // e.g. EMS-ESP-3_8_2-dev_13-ESP32-16MB+.bin -> major=3 minor=8 patch=2 + std::string filename = version; + auto pos = filename.find("EMS-ESP-"); + if (pos == std::string::npos) { + EMSESP::logger().err("Invalid version string: %s", version.c_str()); + return false; + } + pos += 8; // skip past "EMS-ESP-" + auto underscore1 = filename.find('_', pos); + auto underscore2 = filename.find('_', underscore1 + 1); + auto dash = filename.find('-', underscore2 + 1); + if (underscore1 == std::string::npos || underscore2 == std::string::npos || dash == std::string::npos) { + EMSESP::logger().err("Invalid version string: %s", version.c_str()); + return false; + } + std::string major_version = filename.substr(pos, underscore1 - pos); + std::string minor_version = filename.substr(underscore1 + 1, underscore2 - underscore1 - 1); + std::string patch_version = filename.substr(underscore2 + 1, dash - underscore2 - 1); + latest_version = version::Semver200_version(major_version + "." + minor_version + "." + patch_version); + } else { + latest_version = version::Semver200_version(version); + } + + // check if it's a valid version string + if (!latest_version.major()) { + EMSESP::logger().err("Invalid version string: %s", version.c_str()); + return false; + } + + version::Semver200_version current_version(current_version_s); // get current version + + if (current_version.major() <= 3 && current_version.minor() <= 8) { + upgradeImportantMessageType = 1; // if moving from below 3.8.x to 3.9.x return 1 + } else if (latest_version > current_version && current_version.minor() < latest_version.minor()) { + upgradeImportantMessageType = 0; // if it's just a minor version upgrade return 0 + } else if (latest_version > current_version && current_version.major() < latest_version.major()) { + upgradeImportantMessageType = 2; // if it's a major version upgrade return 2 + } + + // #if defined(EMSESP_DEBUG) + // EMSESP::logger().debug("upgradeImportantMessageType: %s %d", version.c_str(), upgradeImportantMessageType); + // #endif + + root["upgradeImportantMessageType"] = upgradeImportantMessageType; + + return true; } // action = checkUpgrade // versions holds the latest development version and stable version in one string, comma separated -bool WebStatusService::checkUpgrade(JsonObject root, std::string & versions) { - if (!versions.empty()) { +bool WebStatusService::checkUpgrade(JsonObject root, std::string & version) { + if (!version.empty()) { version::Semver200_version current_version(current_version_s); - version::Semver200_version latest_dev_version(versions.substr(0, versions.find(','))); - version::Semver200_version latest_stable_version(versions.substr(versions.find(',') + 1)); + version::Semver200_version latest_dev_version(version.substr(0, version.find(','))); + version::Semver200_version latest_stable_version(version.substr(version.find(',') + 1)); bool dev_upgradeable = latest_dev_version > current_version; bool stable_upgradeable = latest_stable_version > current_version; @@ -358,7 +408,7 @@ bool WebStatusService::getCustomSupport(JsonObject root) { #if defined(EMSESP_STANDALONE) // dummy test data for "test api3" - deserializeJson(doc, "{\"type\":\"customSupport\",\"Support\":{\"html\":[\"html code\",\"here\"], \"img_url\": \"https://emsesp.org/_media/images/designer.png\"}"); + deserializeJson(doc, "{\"type\":\"customSupport\",\"Support\":{\"html\":[\"html code\",\"here\"], \"img_url\": \"https://emsesp.org/media/images/designer.png\"}"); #else // check if we have custom support file uploaded File file = LittleFS.open(EMSESP_CUSTOMSUPPORT_FILE, "r"); diff --git a/src/web/WebStatusService.h b/src/web/WebStatusService.h index 7dd7e28f8..ff495d44a 100644 --- a/src/web/WebStatusService.h +++ b/src/web/WebStatusService.h @@ -36,7 +36,7 @@ class WebStatusService { bool uploadURL(const char * url); bool setSystemStatus(const char * status); void allvalues(JsonObject output); - bool upgradeImportantMessages(const char * version); + bool upgradeImportantMessages(JsonObject root, std::string & version); std::string current_version_s = EMSESP_APP_VERSION; }; From 3ac807bdd569da9a3e0b2280ca803446256ef70d Mon Sep 17 00:00:00 2001 From: proddy Date: Tue, 14 Apr 2026 21:08:04 +0200 Subject: [PATCH 05/14] text change --- src/ESP32React/UploadFileService.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ESP32React/UploadFileService.cpp b/src/ESP32React/UploadFileService.cpp index 4aa634c2a..3d4e99152 100644 --- a/src/ESP32React/UploadFileService.cpp +++ b/src/ESP32React/UploadFileService.cpp @@ -184,7 +184,7 @@ void UploadFileService::handleError(AsyncWebServerRequest * request, int code) { } void UploadFileService::handleEarlyDisconnect() { - emsesp::EMSESP::logger().info("Upload completed"); + emsesp::EMSESP::logger().info("Upload finished"); emsesp::EMSESP::system_.uart_init(); // re-enable UART _is_firmware = false; From 7c3782a43f7855e2a8708d1fa1d8f80eb4e9d043 Mon Sep 17 00:00:00 2001 From: proddy Date: Tue, 14 Apr 2026 21:08:45 +0200 Subject: [PATCH 06/14] upload warnings --- interface/pnpm-lock.yaml | 8 +-- interface/src/app/status/Version.tsx | 49 +++++++++++++++-- interface/src/components/upload/DragNdrop.tsx | 21 +++++-- interface/src/i18n/cz/index.ts | 8 +-- interface/src/i18n/de/index.ts | 8 +-- interface/src/i18n/en/index.ts | 6 +- interface/src/i18n/fr/index.ts | 8 +-- interface/src/i18n/it/index.ts | 8 +-- interface/src/i18n/nl/index.ts | 8 ++- interface/src/i18n/no/index.ts | 8 +-- interface/src/i18n/pl/index.ts | 8 +-- interface/src/i18n/sk/index.ts | 8 +-- interface/src/i18n/sv/index.ts | 8 +-- interface/src/i18n/tr/index.ts | 8 +-- mock-api/restServer.ts | 35 ++++++++---- src/web/WebSettingsService.cpp | 4 +- src/web/WebStatusService.cpp | 55 ++++++++++--------- src/web/WebStatusService.h | 14 ++--- 18 files changed, 171 insertions(+), 101 deletions(-) diff --git a/interface/pnpm-lock.yaml b/interface/pnpm-lock.yaml index bbee8b712..ad95f9a21 100644 --- a/interface/pnpm-lock.yaml +++ b/interface/pnpm-lock.yaml @@ -1184,8 +1184,8 @@ packages: base64-js@1.5.1: resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} - baseline-browser-mapping@2.10.18: - resolution: {integrity: sha512-VSnGQAOLtP5mib/DPyg2/t+Tlv65NTBz83BJBJvmLVHHuKJVaDOBvJJykiT5TR++em5nfAySPccDZDa4oSrn8A==} + baseline-browser-mapping@2.10.19: + resolution: {integrity: sha512-qCkNLi2sfBOn8XhZQ0FXsT1Ki/Yo5P90hrkRamVFRS7/KV9hpfA4HkoWNU152+8w0zPjnxo5psx5NL3PSGgv5g==} engines: {node: '>=6.0.0'} hasBin: true @@ -4346,7 +4346,7 @@ snapshots: base64-js@1.5.1: {} - baseline-browser-mapping@2.10.18: {} + baseline-browser-mapping@2.10.19: {} bin-build@3.0.0: dependencies: @@ -4407,7 +4407,7 @@ snapshots: browserslist@4.28.2: dependencies: - baseline-browser-mapping: 2.10.18 + baseline-browser-mapping: 2.10.19 caniuse-lite: 1.0.30001788 electron-to-chromium: 1.5.336 node-releases: 2.0.37 diff --git a/interface/src/app/status/Version.tsx b/interface/src/app/status/Version.tsx index 72b39cc0d..0930fbcc5 100644 --- a/interface/src/app/status/Version.tsx +++ b/interface/src/app/status/Version.tsx @@ -274,6 +274,7 @@ const InstallDialog = memo( fetchDevVersion, latestVersion, latestDevVersion, + upgradeImportantMessageType, downloadOnly, platform, LL, @@ -284,6 +285,7 @@ const InstallDialog = memo( fetchDevVersion: boolean; latestVersion?: VersionInfo; latestDevVersion?: VersionInfo; + upgradeImportantMessageType: number; downloadOnly: boolean; platform: string; LL: TranslationFunctions; @@ -313,6 +315,18 @@ const InstallDialog = memo( fetchDevVersion ? latestDevVersion?.name : latestVersion?.name )} + + {upgradeImportantMessageType === 1 && LL.UPGRADE_IMPORTANT_MESSAGES_1()} + {upgradeImportantMessageType === 2 && LL.UPGRADE_IMPORTANT_MESSAGES_2()} + + + {LL.ONLINE_HELP()} + + diff --git a/interface/src/components/upload/DragNdrop.tsx b/interface/src/components/upload/DragNdrop.tsx index 4bc865fc3..fdcc0cc9d 100644 --- a/interface/src/components/upload/DragNdrop.tsx +++ b/interface/src/components/upload/DragNdrop.tsx @@ -211,14 +211,26 @@ const DragNdrop = ({ text, onFileSelected }: DragNdropProps) => { {LL.UPGRADE_IMPORTANT_MESSAGES()} - {upgradeImportantMessageType === 1 && - LL.UPGRADE_IMPORTANT_MESSAGES_1()} {upgradeImportantMessageType === 2 && LL.UPGRADE_IMPORTANT_MESSAGES_2()} + {upgradeImportantMessageType === 1 && ( + <> + {LL.UPGRADE_IMPORTANT_MESSAGES_1()} + + + {LL.DOWNLOAD_SYSTEM_BACKUP()} + + + + )}{' '} {LL.ONLINE_HELP()}