From 3b94da48a4dc2a06c6bdbc6db4dce2a27c50b3e6 Mon Sep 17 00:00:00 2001 From: abose Date: Thu, 30 Apr 2026 16:06:16 +0530 Subject: [PATCH 1/9] chore(i18n): add AI_LIVE_PREVIEW_BANNER_DISMISS_TOOLTIP string Used as the tooltip on the AI live preview inspection banner now that the whole banner is clickable to dismiss. --- src/nls/root/strings.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/nls/root/strings.js b/src/nls/root/strings.js index 740eb42db9..976b08d025 100644 --- a/src/nls/root/strings.js +++ b/src/nls/root/strings.js @@ -2216,6 +2216,7 @@ define({ "AI_CHAT_TOOL_RESIZE_PREVIEW": "Resize preview", "AI_LIVE_PREVIEW_BANNER_TEXT": "AI is inspecting the live preview", "AI_LIVE_PREVIEW_BANNER_RESIZE": "AI resized preview to {0}", + "AI_LIVE_PREVIEW_BANNER_DISMISS_TOOLTIP": "Click to dismiss", "AI_CHAT_TOOL_CONTROL_EDITOR": "Editor", "AI_CHAT_TOOL_TASKS": "Tasks", "AI_CHAT_TOOL_TASKS_SUMMARY": "{0} of {1} tasks done", From c38349480e610765762ced4e91c4536572148b97 Mon Sep 17 00:00:00 2001 From: abose Date: Thu, 30 Apr 2026 16:22:30 +0530 Subject: [PATCH 2/9] chore: update pro deps --- tracking-repos.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tracking-repos.json b/tracking-repos.json index d556c346d5..91d279ad78 100644 --- a/tracking-repos.json +++ b/tracking-repos.json @@ -1,5 +1,5 @@ { "phoenixPro": { - "commitID": "468fd0d0a1ae514613e3ddddf1df964681af3721" + "commitID": "9958b480125ed04fa29a8b86dc0c8e68b66d847e" } } From 17628fec97171303c357de175997ad94fcc50742 Mon Sep 17 00:00:00 2001 From: abose Date: Fri, 1 May 2026 16:07:51 +0530 Subject: [PATCH 3/9] style(ai-onboarding): styles for the prompt-overlay image strip Adds .ai-onboarding-prompt-images thumbnail row styling used by the onboarding review overlay when the iframe sends reference images alongside a userPrompt. --- src/styles/Extn-AIChatPanel.less | 42 ++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/src/styles/Extn-AIChatPanel.less b/src/styles/Extn-AIChatPanel.less index af7b30112f..839872e72a 100644 --- a/src/styles/Extn-AIChatPanel.less +++ b/src/styles/Extn-AIChatPanel.less @@ -419,6 +419,48 @@ } } + .ai-onboarding-prompt-images { + display: flex; + flex-wrap: wrap; + gap: 8px; + padding: 8px 12px; + border-top: 1px solid rgba(255, 255, 255, 0.06); + background: @bc-ai-input-bg; + + .ai-image-thumb { + position: relative; + + img { + display: block; + max-width: 64px; + max-height: 48px; + object-fit: cover; + border-radius: 4px; + border: 1px solid rgba(255, 255, 255, 0.12); + cursor: pointer; + } + + .ai-image-remove { + position: absolute; + top: -6px; + right: -6px; + width: 18px; + height: 18px; + border-radius: 50%; + background: rgba(0, 0, 0, 0.7); + border: 1px solid rgba(255, 255, 255, 0.3); + color: #fff; + font-size: 11px; + line-height: 1; + padding: 0; + display: flex; + align-items: center; + justify-content: center; + cursor: pointer; + } + } + } + .ai-onboarding-prompt-actions { display: flex; justify-content: flex-end; From 78b8f89f46af17764f926945e873ede78dd5aa2f Mon Sep 17 00:00:00 2001 From: abose Date: Fri, 1 May 2026 16:32:47 +0530 Subject: [PATCH 4/9] chore: update pro deps --- tracking-repos.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tracking-repos.json b/tracking-repos.json index 91d279ad78..e9e4f85f0a 100644 --- a/tracking-repos.json +++ b/tracking-repos.json @@ -1,5 +1,5 @@ { "phoenixPro": { - "commitID": "9958b480125ed04fa29a8b86dc0c8e68b66d847e" + "commitID": "d7d625627754a7842be1a73e75c3494aeac9e78c" } } From d6d9a1fe15aae175ebec010e445ab9c0e19a020e Mon Sep 17 00:00:00 2001 From: abose Date: Fri, 1 May 2026 16:46:04 +0530 Subject: [PATCH 5/9] feat(phoenix-tour): track ripple-target clicks and auto-peek AI panel Adds two pieces of instrumentation/UX to the onboarding tour: - Per-step click metrics. Every step's highlighted target now has a one-shot capture-phase listener that fires stepN_clicked when the user actually clicks the ripple target during the overlay session. Detaches automatically on first click, on step transitions, and on teardown so we never double-count. - Step 2 AI-panel auto-peek. When step 2 begins, briefly switch the sidebar to the AI tab for 2 seconds and then revert to whatever tab the user was on. Throttled and cleaned up on transitions/teardown so the sidebar can't get stranded on AI if the tour ends mid-peek. --- .../Phoenix/phoenix-tour.js | 96 +++++++++++++++++++ 1 file changed, 96 insertions(+) diff --git a/src/extensionsIntegrated/Phoenix/phoenix-tour.js b/src/extensionsIntegrated/Phoenix/phoenix-tour.js index 7eee1aadd8..33f8241764 100644 --- a/src/extensionsIntegrated/Phoenix/phoenix-tour.js +++ b/src/extensionsIntegrated/Phoenix/phoenix-tour.js @@ -33,6 +33,7 @@ define(function (require, exports, module) { StringUtils = require("utils/StringUtils"), Metrics = require("utils/Metrics"), SidebarView = require("project/SidebarView"), + SidebarTabs = require("view/SidebarTabs"), ProjectManager = require("project/ProjectManager"), EditorManager = require("editor/EditorManager"), CommandManager = require("command/CommandManager"), @@ -76,6 +77,21 @@ define(function (require, exports, module) { let _rafId = null; let _timers = []; + // Per-step: tracks a click on the highlighted target while the + // overlay is showing, fires a metric, then detaches. Cleared by + // _detachStepClickMetric on step transitions and teardown. + let _activeStepClickHandler = null; + let _activeStepClickTarget = null; + + // Step 2: when the step starts we briefly switch the sidebar to the + // AI tab as an automatic peek (2s) and revert to whatever the user + // was on. _peekPrevTab is non-null only while a peek is in flight so + // teardown can revert cleanly if the tour ends mid-peek. + let _step2PeekTimer = null; + let _step2PeekPrevTab = null; + const STEP2_PEEK_HOLD_MS = 2000; + const SIDEBAR_AI_TAB_ID = "ai"; + function _markComplete() { _state.version = CURRENT_TOUR_VERSION; _saveState(_state); @@ -92,8 +108,74 @@ define(function (require, exports, module) { } } + /** + * Attach a one-shot click listener to `$target` that fires a "stepN_clicked" + * metric. Captures real user clicks during the overlay session — not the + * synthetic class toggles the demos do. Replaces any previously attached + * step handler so we never double-count across step transitions. + */ + function _attachStepClickMetric(stepNum, $target) { + _detachStepClickMetric(); + if (!$target || !$target.length || !$target[0]) { + return; + } + const targetEl = $target[0]; + const handler = function () { + Metrics.countEvent(Metrics.EVENT_TYPE.GUIDE, "tour", "step" + stepNum + "_clicked"); + _detachStepClickMetric(); + }; + targetEl.addEventListener("click", handler, true); + _activeStepClickTarget = targetEl; + _activeStepClickHandler = handler; + } + + function _detachStepClickMetric() { + if (_activeStepClickTarget && _activeStepClickHandler) { + _activeStepClickTarget.removeEventListener("click", _activeStepClickHandler, true); + } + _activeStepClickTarget = null; + _activeStepClickHandler = null; + } + + /** + * Step 2 only: automatically switch the sidebar to the AI tab for a + * couple of seconds so the user sees what's behind the tab, then + * revert. No-op if the user is already on the AI tab. + */ + function _runStep2AIPeek() { + _cancelStep2AIPeek(); + const current = SidebarTabs.getActiveTab && SidebarTabs.getActiveTab(); + if (current === SIDEBAR_AI_TAB_ID) { + return; + } + _step2PeekPrevTab = current; + SidebarTabs.setActiveTab(SIDEBAR_AI_TAB_ID); + _step2PeekTimer = setTimeout(function () { + if (_step2PeekPrevTab) { + SidebarTabs.setActiveTab(_step2PeekPrevTab); + } + _step2PeekPrevTab = null; + _step2PeekTimer = null; + }, STEP2_PEEK_HOLD_MS); + } + + function _cancelStep2AIPeek() { + if (_step2PeekTimer) { + clearTimeout(_step2PeekTimer); + _step2PeekTimer = null; + } + // If we tore down or transitioned mid-peek, restore the previous + // tab so the sidebar doesn't get stranded on AI. + if (_step2PeekPrevTab) { + SidebarTabs.setActiveTab(_step2PeekPrevTab); + _step2PeekPrevTab = null; + } + } + function _teardown() { _clearTimers(); + _detachStepClickMetric(); + _cancelStep2AIPeek(); if ($overlay) { $overlay.remove(); $overlay = null; @@ -213,6 +295,7 @@ define(function (require, exports, module) { _trackTarget($btn, "right"); _setStep(1); Metrics.countEvent(Metrics.EVENT_TYPE.GUIDE, "tour", "step1"); + _attachStepClickMetric(1, $btn); // Single, stable message for the entire step. The visible toggle of // design mode does the explaining; rotating text under a 2-second // demo is too quick to read. @@ -248,6 +331,9 @@ define(function (require, exports, module) { } function _runStep2() { + // Each step transition cancels the previous step's instrumentation. + _detachStepClickMetric(); + _cancelStep2AIPeek(); _ensureSidebarVisible(); const $tab = $('.sidebar-tab[data-tab-id="ai"]'); if (!$tab.length) { @@ -269,11 +355,17 @@ define(function (require, exports, module) { } } ]); + _attachStepClickMetric(2, $tab); + // Auto-peek the AI panel for a couple of seconds so the user gets + // a glance at its contents, then revert. + _runStep2AIPeek(); // Intentionally do NOT advance on a real click of the target — the // user needs time to read the prompt; only the Next button advances. } function _runStep3() { + _detachStepClickMetric(); + _cancelStep2AIPeek(); _ensureSidebarVisible(); const $newBtn = $("#newProject"); if (!$newBtn.length) { @@ -286,6 +378,7 @@ define(function (require, exports, module) { _trackTarget($newBtn, "right"); _setStep(3); Metrics.countEvent(Metrics.EVENT_TYPE.GUIDE, "tour", "step3"); + _attachStepClickMetric(3, $newBtn); _setText(Strings.PHOENIX_TOUR_NEW_PROJECT); _setActions([ { @@ -354,6 +447,8 @@ define(function (require, exports, module) { } async function _runStep4() { + _detachStepClickMetric(); + _cancelStep2AIPeek(); _ensureSidebarVisible(); try { await _ensureLivePreviewReady(); @@ -375,6 +470,7 @@ define(function (require, exports, module) { _trackTarget($btn, "left"); _setStep(4); Metrics.countEvent(Metrics.EVENT_TYPE.GUIDE, "tour", "step4"); + _attachStepClickMetric(4, $btn); _setText(Strings.PHOENIX_TOUR_EDIT_MODE); _setActions([ { From fb4170849680857bdc7095b12c4e3e2899dcc48b Mon Sep 17 00:00:00 2001 From: abose Date: Fri, 1 May 2026 17:06:26 +0530 Subject: [PATCH 6/9] feat(view): add reusable VideoPlayer widget; intro video styles MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds src/view/VideoPlayer.js — small AMD module exporting createPlayer that returns a jQuery-wrapped