From 2ed03fa8ae37c53cedff1d338a5edc76eafa2fd9 Mon Sep 17 00:00:00 2001 From: Radu Date: Thu, 7 Aug 2025 18:07:57 +0300 Subject: [PATCH 1/4] Add notification system for pre-releases campaigns --- l10n/bundle.l10n.es.json | 8 ++- l10n/bundle.l10n.pt.json | 8 ++- l10n/bundle.l10n.ru.json | 8 ++- l10n/bundle.l10n.zh-CN.json | 8 ++- src/config.ts | 6 ++ src/extension.ts | 4 ++ src/preReleaseNotification.ts | 120 ++++++++++++++++++++++++++++++++++ 7 files changed, 158 insertions(+), 4 deletions(-) create mode 100644 src/preReleaseNotification.ts diff --git a/l10n/bundle.l10n.es.json b/l10n/bundle.l10n.es.json index e3b4dd4a3..5085ef4bc 100644 --- a/l10n/bundle.l10n.es.json +++ b/l10n/bundle.l10n.es.json @@ -253,5 +253,11 @@ "Clear Build Error Hints": "Borrar Pistas de Error de Compilación", "Clear OpenOCD Error Hints": "Borrar Pistas de Error de OpenOCD", "Open Reference": "Abrir Referencia", - "Launch Debug": "Iniciar depuración" + "Launch Debug": "Iniciar depuración", + "🎉 New ESP-IDF Extension setup available! We've completely redesigned the installation process with the ESP-IDF Installer Manager (EIM) for a smoother, more reliable setup experience. Help us improve by trying the pre-release!": "🎉 ¡Nueva configuración de la extensión ESP-IDF disponible! Hemos rediseñado completamente el proceso de instalación con el Gestor de Instalación ESP-IDF (EIM) para una experiencia de configuración más fluida y confiable. ¡Ayúdanos a mejorar probando la versión preliminar!", + "Try New Pre-Release": "Probar nueva versión preliminar", + "Learn More": "Más información", + "Not Now": "Ahora no", + "To install the pre-release version, click the 'Switch to Pre-Release Version' button.": "Para instalar la versión preliminar, haga clic en el botón 'Cambiar a versión preliminar'.", + "Got it": "Entendido" } diff --git a/l10n/bundle.l10n.pt.json b/l10n/bundle.l10n.pt.json index 80e8b8e2c..9b7cfa71b 100644 --- a/l10n/bundle.l10n.pt.json +++ b/l10n/bundle.l10n.pt.json @@ -254,5 +254,11 @@ "Clear Build Error Hints": "Limpar Dicas de Erro de Compilação", "Clear OpenOCD Error Hints": "Limpar Dicas de Erro do OpenOCD", "Open Reference": "Abrir Referência", - "Launch Debug": "Iniciar depuração" + "Launch Debug": "Iniciar depuração", + "🎉 New ESP-IDF Extension setup available! We've completely redesigned the installation process with the ESP-IDF Installer Manager (EIM) for a smoother, more reliable setup experience. Help us improve by trying the pre-release!": "🎉 Nova configuração da extensão ESP-IDF disponível! Redesenhamos completamente o processo de instalação com o Gerenciador de Instalação ESP-IDF (EIM) para uma experiência de configuração mais suave e confiável. Ajude-nos a melhorar experimentando a versão pré-lançamento!", + "Try New Pre-Release": "Experimentar nova versão pré-lançamento", + "Learn More": "Saiba mais", + "Not Now": "Agora não", + "To install the pre-release version, click the 'Switch to Pre-Release Version' button.": "Para instalar a versão pré-lançamento, clique no botão 'Alternar para versão pré-lançamento'.", + "Got it": "Entendi" } diff --git a/l10n/bundle.l10n.ru.json b/l10n/bundle.l10n.ru.json index af93b0883..00c345b83 100644 --- a/l10n/bundle.l10n.ru.json +++ b/l10n/bundle.l10n.ru.json @@ -254,5 +254,11 @@ "Clear Build Error Hints": "Очистить подсказки по ошибкам сборки", "Clear OpenOCD Error Hints": "Очистить подсказки по ошибкам OpenOCD", "Open Reference": "Открыть ссылку", - "Launch Debug": "Запуск отладки" + "Launch Debug": "Запуск отладки", + "🎉 New ESP-IDF Extension setup available! We've completely redesigned the installation process with the ESP-IDF Installer Manager (EIM) for a smoother, more reliable setup experience. Help us improve by trying the pre-release!": "🎉 Доступна новая настройка расширения ESP-IDF! Мы полностью переработали процесс установки с помощью Менеджера установки ESP-IDF (EIM) для более плавного и надежного опыта настройки. Помогите нам улучшить его, попробовав предварительную версию!", + "Try New Pre-Release": "Попробовать новую предварительную версию", + "Learn More": "Узнать больше", + "Not Now": "Не сейчас", + "To install the pre-release version, click the 'Switch to Pre-Release Version' button.": "Для установки предварительной версии нажмите кнопку 'Переключиться на предварительную версию'.", + "Got it": "Понятно" } diff --git a/l10n/bundle.l10n.zh-CN.json b/l10n/bundle.l10n.zh-CN.json index 358d490a1..dffb775f8 100644 --- a/l10n/bundle.l10n.zh-CN.json +++ b/l10n/bundle.l10n.zh-CN.json @@ -254,5 +254,11 @@ "Clear Build Error Hints": "清除构建错误提示", "Clear OpenOCD Error Hints": "清除 OpenOCD 错误提示", "Open Reference": "打开参考", - "Launch Debug": "启动调试" + "Launch Debug": "启动调试", + "🎉 New ESP-IDF Extension setup available! We've completely redesigned the installation process with the ESP-IDF Installer Manager (EIM) for a smoother, more reliable setup experience. Help us improve by trying the pre-release!": "🎉 新的 ESP-IDF 扩展设置已发布!我们使用 ESP-IDF 安装管理器 (EIM) 完全重新设计了安装过程,提供更流畅、更可靠的设置体验。通过试用预发布版本帮助我们改进!", + "Try New Pre-Release": "试用新的预发布版本", + "Learn More": "了解更多", + "Not Now": "暂不使用", + "To install the pre-release version, click the 'Switch to Pre-Release Version' button.": "要安装预发布版本,请点击"切换到预发布版本"按钮。", + "Got it": "知道了" } diff --git a/src/config.ts b/src/config.ts index a787e4d88..eec066350 100644 --- a/src/config.ts +++ b/src/config.ts @@ -90,6 +90,12 @@ export namespace ESP { export const DB_VERSION_KEY = "esp.extension.version"; } + export namespace PreReleaseNotification { + export const SHOWN_KEY = "espIdf.prerelease.notification.shown"; + // Specific notification campaigns - add new ones for future campaigns + export const EIM_SETUP_CAMPAIGN = "eim-setup-2025"; + } + export namespace URL { export const IDF_GITHUB_ASSETS = "https://dl.espressif.com/github_assets"; export const IDF_VERSIONS = diff --git a/src/extension.ts b/src/extension.ts index b41517a92..95eed28f5 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -79,6 +79,7 @@ import { getEspAdf } from "./espAdf/espAdfDownload"; import { getEspMdf } from "./espMdf/espMdfDownload"; import { SetupPanel } from "./setup/SetupPanel"; import { ChangelogViewer } from "./changelog-viewer"; +import { PreReleaseNotification } from "./preReleaseNotification"; import { getSetupInitialValues, ISetupInitArgs } from "./setup/setupInit"; import { getVirtualEnvPythonPath, @@ -286,6 +287,9 @@ export async function activate(context: vscode.ExtensionContext) { Telemetry.init(idfConf.readParameter("idf.telemetry") || false); utils.setExtensionContext(context); ChangelogViewer.showChangeLogAndUpdateVersion(context); + + // Show pre-release notification if not shown for this version + PreReleaseNotification.showPreReleaseNotification(context); // Check if running in a VS Code fork and prompt for clangd extension installation if (PreCheck.isRunningInVSCodeFork()) { diff --git a/src/preReleaseNotification.ts b/src/preReleaseNotification.ts new file mode 100644 index 000000000..a3a27d538 --- /dev/null +++ b/src/preReleaseNotification.ts @@ -0,0 +1,120 @@ +/* + * Project: ESP-IDF VSCode Extension + * File Created: Thursday, 7th August 2025 + * Copyright 2024 Espressif Systems (Shanghai) CO LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ExtensionContext, window, env, Uri, l10n } from "vscode"; +import { ESP } from "./config"; +import { Logger } from "./logger/logger"; +import { packageJson } from "./utils"; +import { NotificationMode, readParameter } from "./idfConfiguration"; +import { Telemetry } from "./telemetry"; + +export namespace PreReleaseNotification { + export async function showPreReleaseNotification(context: ExtensionContext) { + // Check if this specific campaign was already shown + const campaignKey = ESP.PreReleaseNotification.EIM_SETUP_CAMPAIGN; + const shownCampaigns = context.globalState.get( + ESP.PreReleaseNotification.SHOWN_KEY, + [] + ); + + // Check notification settings + const notificationMode = readParameter("idf.notificationMode") as string; + const enableNotification = + notificationMode === NotificationMode.All || + notificationMode === NotificationMode.Notifications; + + // Only show if this campaign hasn't been shown and notifications are enabled + if (!shownCampaigns.includes(campaignKey) && enableNotification) { + // Track that the notification was shown + Telemetry.sendEvent("preReleaseNotification", { + campaign: campaignKey, + action: "shown", + extensionVersion: packageJson.version + }); + + const message = l10n.t( + "🎉 New ESP-IDF Extension setup available! We've completely redesigned the installation process with the ESP-IDF Installer Manager (EIM) for a smoother, more reliable setup experience. Help us improve by trying the pre-release!" + ); + + const tryPreRelease = l10n.t("Try New Pre-Release"); + const learnMore = l10n.t("Learn More"); + const notNow = l10n.t("Not Now"); + + const response = await window.showInformationMessage( + message, + { modal: false }, + tryPreRelease, + learnMore, + notNow + ); + + if (response === tryPreRelease) { + // Track user clicked to try pre-release + Telemetry.sendEvent("preReleaseNotification", { + campaign: campaignKey, + action: "tryPreRelease", + extensionVersion: packageJson.version + }); + + // Open the extension in Extensions view + const extensionUri = Uri.parse( + "vscode:extension/espressif.esp-idf-extension" + ); + await env.openExternal(extensionUri); + + // Show additional guidance for enabling pre-release + const preReleaseInfo = await window.showInformationMessage( + l10n.t("To install the pre-release version, click the 'Switch to Pre-Release Version' button."), + { modal: false }, + l10n.t("Got it") + ); + + Logger.info("User clicked to try pre-release from notification"); + } else if (response === learnMore) { + // Track user clicked to learn more + Telemetry.sendEvent("preReleaseNotification", { + campaign: campaignKey, + action: "learnMore", + extensionVersion: packageJson.version + }); + + // Open documentation about the new setup experience + const docsUri = Uri.parse( + "https://docs.espressif.com/projects/idf-im-ui/en/latest/" + ); + await env.openExternal(docsUri); + Logger.info("User clicked to learn more from pre-release notification"); + } else { + // Track user dismissed the notification (clicked "Not Now" or dismissed) + Telemetry.sendEvent("preReleaseNotification", { + campaign: campaignKey, + action: response ? "notNow" : "dismissed", + extensionVersion: packageJson.version + }); + Logger.info("User dismissed pre-release notification"); + } + + // Mark this campaign as shown + const updatedCampaigns = [...shownCampaigns, campaignKey]; + await context.globalState.update( + ESP.PreReleaseNotification.SHOWN_KEY, + updatedCampaigns + ); + } + } +} \ No newline at end of file From 4f766744368e29347598f500417050f5af3090a1 Mon Sep 17 00:00:00 2001 From: Radu Date: Fri, 8 Aug 2025 11:12:53 +0300 Subject: [PATCH 2/4] Fix lint Show notification again for "learn more" --- l10n/bundle.l10n.zh-CN.json | 2 +- src/extension.ts | 2 +- src/preReleaseNotification.ts | 87 +++++++++++++++++++---------------- 3 files changed, 49 insertions(+), 42 deletions(-) diff --git a/l10n/bundle.l10n.zh-CN.json b/l10n/bundle.l10n.zh-CN.json index dffb775f8..fdd48a7ed 100644 --- a/l10n/bundle.l10n.zh-CN.json +++ b/l10n/bundle.l10n.zh-CN.json @@ -259,6 +259,6 @@ "Try New Pre-Release": "试用新的预发布版本", "Learn More": "了解更多", "Not Now": "暂不使用", - "To install the pre-release version, click the 'Switch to Pre-Release Version' button.": "要安装预发布版本,请点击"切换到预发布版本"按钮。", + "To install the pre-release version, click the 'Switch to Pre-Release Version' button.": "要安装预发布版本,请点击\"切换到预发布版本\"按钮。", "Got it": "知道了" } diff --git a/src/extension.ts b/src/extension.ts index 95eed28f5..1a2e7e4d3 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -287,7 +287,7 @@ export async function activate(context: vscode.ExtensionContext) { Telemetry.init(idfConf.readParameter("idf.telemetry") || false); utils.setExtensionContext(context); ChangelogViewer.showChangeLogAndUpdateVersion(context); - + // Show pre-release notification if not shown for this version PreReleaseNotification.showPreReleaseNotification(context); diff --git a/src/preReleaseNotification.ts b/src/preReleaseNotification.ts index a3a27d538..94cee66dd 100644 --- a/src/preReleaseNotification.ts +++ b/src/preReleaseNotification.ts @@ -40,20 +40,20 @@ export namespace PreReleaseNotification { // Only show if this campaign hasn't been shown and notifications are enabled if (!shownCampaigns.includes(campaignKey) && enableNotification) { - // Track that the notification was shown - Telemetry.sendEvent("preReleaseNotification", { - campaign: campaignKey, - action: "shown", - extensionVersion: packageJson.version - }); + // Track that the notification was shown + Telemetry.sendEvent("preReleaseNotification", { + campaign: campaignKey, + action: "shown", + extensionVersion: packageJson.version, + }); - const message = l10n.t( - "🎉 New ESP-IDF Extension setup available! We've completely redesigned the installation process with the ESP-IDF Installer Manager (EIM) for a smoother, more reliable setup experience. Help us improve by trying the pre-release!" - ); + const message = l10n.t( + "🎉 New ESP-IDF Extension setup available! We've completely redesigned the installation process with the ESP-IDF Installer Manager (EIM) for a smoother, more reliable setup experience. Help us improve by trying the pre-release!" + ); - const tryPreRelease = l10n.t("Try New Pre-Release"); - const learnMore = l10n.t("Learn More"); - const notNow = l10n.t("Not Now"); + const tryPreRelease = l10n.t("Try New Pre-Release"); + const learnMore = l10n.t("Learn More"); + const notNow = l10n.t("Not Now"); const response = await window.showInformationMessage( message, @@ -63,34 +63,36 @@ export namespace PreReleaseNotification { notNow ); - if (response === tryPreRelease) { - // Track user clicked to try pre-release - Telemetry.sendEvent("preReleaseNotification", { - campaign: campaignKey, - action: "tryPreRelease", - extensionVersion: packageJson.version - }); + if (response === tryPreRelease) { + // Track user clicked to try pre-release + Telemetry.sendEvent("preReleaseNotification", { + campaign: campaignKey, + action: "tryPreRelease", + extensionVersion: packageJson.version, + }); + + // Open the extension in Extensions view + const extensionUri = Uri.parse( + "vscode:extension/espressif.esp-idf-extension" + ); + await env.openExternal(extensionUri); + + // Show additional guidance for enabling pre-release + const preReleaseInfo = await window.showInformationMessage( + l10n.t( + "To install the pre-release version, click the 'Switch to Pre-Release Version' button." + ), + { modal: false }, + l10n.t("Got it") + ); - // Open the extension in Extensions view - const extensionUri = Uri.parse( - "vscode:extension/espressif.esp-idf-extension" - ); - await env.openExternal(extensionUri); - - // Show additional guidance for enabling pre-release - const preReleaseInfo = await window.showInformationMessage( - l10n.t("To install the pre-release version, click the 'Switch to Pre-Release Version' button."), - { modal: false }, - l10n.t("Got it") - ); - - Logger.info("User clicked to try pre-release from notification"); + Logger.info("User clicked to try pre-release from notification"); } else if (response === learnMore) { // Track user clicked to learn more Telemetry.sendEvent("preReleaseNotification", { campaign: campaignKey, action: "learnMore", - extensionVersion: packageJson.version + extensionVersion: packageJson.version, }); // Open documentation about the new setup experience @@ -99,22 +101,27 @@ export namespace PreReleaseNotification { ); await env.openExternal(docsUri); Logger.info("User clicked to learn more from pre-release notification"); + + // Re-show the notification after viewing docs + setTimeout(() => { + showPreReleaseNotification(context); + }, 2000); // Small delay to let the external browser open } else { // Track user dismissed the notification (clicked "Not Now" or dismissed) Telemetry.sendEvent("preReleaseNotification", { campaign: campaignKey, action: response ? "notNow" : "dismissed", - extensionVersion: packageJson.version + extensionVersion: packageJson.version, }); Logger.info("User dismissed pre-release notification"); } - // Mark this campaign as shown - const updatedCampaigns = [...shownCampaigns, campaignKey]; - await context.globalState.update( + // Mark this campaign as shown + const updatedCampaigns = [...shownCampaigns, campaignKey]; + await context.globalState.update( ESP.PreReleaseNotification.SHOWN_KEY, updatedCampaigns - ); + ); } } -} \ No newline at end of file +} From 5e842ee13296fed3848abc4a572fe62f7c5982a0 Mon Sep 17 00:00:00 2001 From: Radu Date: Mon, 18 Aug 2025 19:20:05 +0300 Subject: [PATCH 3/4] fix lint --- src/preReleaseNotification.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/preReleaseNotification.ts b/src/preReleaseNotification.ts index 94cee66dd..c862a826e 100644 --- a/src/preReleaseNotification.ts +++ b/src/preReleaseNotification.ts @@ -101,7 +101,7 @@ export namespace PreReleaseNotification { ); await env.openExternal(docsUri); Logger.info("User clicked to learn more from pre-release notification"); - + // Re-show the notification after viewing docs setTimeout(() => { showPreReleaseNotification(context); From 30960a3b11d9b025c241d14a1951dbcb41941046 Mon Sep 17 00:00:00 2001 From: Radu Date: Mon, 18 Aug 2025 20:15:27 +0300 Subject: [PATCH 4/4] Fix notification for "learn more" --- src/preReleaseNotification.ts | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/src/preReleaseNotification.ts b/src/preReleaseNotification.ts index c862a826e..369ec72fa 100644 --- a/src/preReleaseNotification.ts +++ b/src/preReleaseNotification.ts @@ -87,6 +87,13 @@ export namespace PreReleaseNotification { ); Logger.info("User clicked to try pre-release from notification"); + + // Mark this campaign as shown when user tries pre-release + const updatedCampaigns = [...shownCampaigns, campaignKey]; + await context.globalState.update( + ESP.PreReleaseNotification.SHOWN_KEY, + updatedCampaigns + ); } else if (response === learnMore) { // Track user clicked to learn more Telemetry.sendEvent("preReleaseNotification", { @@ -114,14 +121,14 @@ export namespace PreReleaseNotification { extensionVersion: packageJson.version, }); Logger.info("User dismissed pre-release notification"); - } - // Mark this campaign as shown - const updatedCampaigns = [...shownCampaigns, campaignKey]; - await context.globalState.update( - ESP.PreReleaseNotification.SHOWN_KEY, - updatedCampaigns - ); + // Mark this campaign as shown only when dismissed or "Not Now" + const updatedCampaigns = [...shownCampaigns, campaignKey]; + await context.globalState.update( + ESP.PreReleaseNotification.SHOWN_KEY, + updatedCampaigns + ); + } } } }