From 9ac4d03a71902c2239cd772043084548cfaf964b Mon Sep 17 00:00:00 2001 From: Pluto Date: Sat, 28 Mar 2026 13:09:15 +0530 Subject: [PATCH 1/8] =?UTF-8?q?fix:=20element=20highlighting=20doesn?= =?UTF-8?q?=E2=80=99t=20have=20phoenix=20internal=20attribute?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/LiveDevelopment/BrowserScripts/RemoteFunctions.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/LiveDevelopment/BrowserScripts/RemoteFunctions.js b/src/LiveDevelopment/BrowserScripts/RemoteFunctions.js index 6f56eb2392..f051dd0966 100644 --- a/src/LiveDevelopment/BrowserScripts/RemoteFunctions.js +++ b/src/LiveDevelopment/BrowserScripts/RemoteFunctions.js @@ -357,6 +357,7 @@ function RemoteFunctions(config = {}) { // Container div — sized to the margin box so all rects fit inside it const div = window.document.createElement("div"); div.className = GLOBALS.HIGHLIGHT_CLASSNAME; + div.setAttribute(GLOBALS.PHCODE_INTERNAL_ATTR, "true"); div.trackingElement = element; const divStyle = div.style; divStyle.position = "absolute"; From df1089668182cc559dc113728ba3b2734b57fbc8 Mon Sep 17 00:00:00 2001 From: Pluto Date: Sat, 28 Mar 2026 19:43:49 +0530 Subject: [PATCH 2/8] chore: remove the preference for spacing handles --- .../Phoenix-live-preview/main.js | 32 ++++--------------- 1 file changed, 6 insertions(+), 26 deletions(-) diff --git a/src/extensionsIntegrated/Phoenix-live-preview/main.js b/src/extensionsIntegrated/Phoenix-live-preview/main.js index cbd86de9b1..659bc9e2cd 100644 --- a/src/extensionsIntegrated/Phoenix-live-preview/main.js +++ b/src/extensionsIntegrated/Phoenix-live-preview/main.js @@ -110,11 +110,11 @@ define(function (require, exports, module) { description: Strings.LIVE_DEV_SETTINGS_SHOW_RULER_LINES_PREFERENCE }); - // live preview spacing handles preference (show/hide spacing handles on element selection) - const PREFERENCE_SHOW_SPACING_HANDLES = CONSTANTS.PREFERENCE_SHOW_SPACING_HANDLES; - PreferencesManager.definePreference(PREFERENCE_SHOW_SPACING_HANDLES, "boolean", true, { - description: Strings.LIVE_DEV_SETTINGS_SHOW_SPACING_HANDLES_PREFERENCE - }); + // Spacing handles preference disabled for this release (incomplete feature). + // const PREFERENCE_SHOW_SPACING_HANDLES = CONSTANTS.PREFERENCE_SHOW_SPACING_HANDLES; + // PreferencesManager.definePreference(PREFERENCE_SHOW_SPACING_HANDLES, "boolean", true, { + // description: Strings.LIVE_DEV_SETTINGS_SHOW_SPACING_HANDLES_PREFERENCE + // }); // live preview sync source and preview preference const PREFERENCE_LIVE_PREVIEW_SYNC = CONSTANTS.PREFERENCE_LIVE_PREVIEW_SYNC; @@ -359,7 +359,6 @@ define(function (require, exports, module) { if (isEditFeaturesActive && isEditMode) { items.push(Strings.LIVE_PREVIEW_EDIT_HIGHLIGHT_ON); items.push(Strings.LIVE_PREVIEW_SHOW_RULER_LINES); - items.push(Strings.LIVE_PREVIEW_SHOW_SPACING_HANDLES); } $dropdown = new DropdownButton.DropdownButton("", items, function(item, index) { @@ -398,12 +397,6 @@ define(function (require, exports, module) { return `✓ ${Strings.LIVE_PREVIEW_SHOW_RULER_LINES}`; } return `${'\u00A0'.repeat(4)}${Strings.LIVE_PREVIEW_SHOW_RULER_LINES}`; - } else if (item === Strings.LIVE_PREVIEW_SHOW_SPACING_HANDLES) { - const isEnabled = PreferencesManager.get(PREFERENCE_SHOW_SPACING_HANDLES); - if(isEnabled) { - return `✓ ${Strings.LIVE_PREVIEW_SHOW_SPACING_HANDLES}`; - } - return `${'\u00A0'.repeat(4)}${Strings.LIVE_PREVIEW_SHOW_SPACING_HANDLES}`; } return item; }); @@ -466,15 +459,6 @@ define(function (require, exports, module) { const currentValue = PreferencesManager.get(PREFERENCE_SHOW_RULER_LINES); PreferencesManager.set(PREFERENCE_SHOW_RULER_LINES, !currentValue); return; // Don't dismiss highlights for this option - } else if (item === Strings.LIVE_PREVIEW_SHOW_SPACING_HANDLES) { - // Don't allow spacing handles toggle if edit features are not active - if (!isEditFeaturesActive) { - return; - } - // Toggle spacing handles on/off - const currentValue = PreferencesManager.get(PREFERENCE_SHOW_SPACING_HANDLES); - PreferencesManager.set(PREFERENCE_SHOW_SPACING_HANDLES, !currentValue); - return; // Don't dismiss highlights for this option } }); @@ -1273,17 +1257,13 @@ define(function (require, exports, module) { PreferencesManager.on("change", PREFERENCE_SHOW_RULER_LINES, function() { LiveDevelopment.updateRulerLinesConfig(); }); - PreferencesManager.on("change", PREFERENCE_SHOW_SPACING_HANDLES, function() { - LiveDevelopment.updateSpacingHandlesConfig(); - }); PreferencesManager.on("change", PREFERENCE_LIVE_PREVIEW_SYNC, function() { LiveDevelopment.updateSyncConfig(); }); - // Initialize element highlight, ruler lines, spacing handles, and sync config on startup + // Initialize element highlight, ruler lines, and sync config on startup LiveDevelopment.updateElementHighlightConfig(); LiveDevelopment.updateRulerLinesConfig(); - LiveDevelopment.updateSpacingHandlesConfig(); LiveDevelopment.updateSyncConfig(); LiveDevelopment.openLivePreview(); From 4cf61ff66e389985edbef3a01b162f4686d9e684 Mon Sep 17 00:00:00 2001 From: Pluto Date: Sat, 28 Mar 2026 19:45:51 +0530 Subject: [PATCH 3/8] fix: stale highlighting remains after sync mode setting updated --- src/LiveDevelopment/BrowserScripts/RemoteFunctions.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/LiveDevelopment/BrowserScripts/RemoteFunctions.js b/src/LiveDevelopment/BrowserScripts/RemoteFunctions.js index f051dd0966..32154de6c1 100644 --- a/src/LiveDevelopment/BrowserScripts/RemoteFunctions.js +++ b/src/LiveDevelopment/BrowserScripts/RemoteFunctions.js @@ -1219,8 +1219,12 @@ function RemoteFunctions(config = {}) { SHARED_STATE._hotCorner.updateState(config.mode === 'preview', true); } + // Clear highlights when sync is turned off + const syncTurnedOff = oldConfig.syncSourceAndPreview !== false && + config.syncSourceAndPreview === false; + // Handle configuration changes - if (highlightModeChanged || isModeChanged) { + if (highlightModeChanged || isModeChanged || syncTurnedOff) { _handleConfigurationChange(); } @@ -1229,8 +1233,8 @@ function RemoteFunctions(config = {}) { // doesn't clear the element highlighting. const selectedBeforeReregister = previouslySelectedElement; registerHandlers(); - if (!isModeChanged && !highlightModeChanged && selectedBeforeReregister - && config.mode === 'edit') { + if (!isModeChanged && !highlightModeChanged && !syncTurnedOff + && selectedBeforeReregister && config.mode === 'edit') { // Restore the click highlight for the previously selected element if (!_clickHighlight) { _clickHighlight = new Highlight(true); From cb91fac4d91fd15f4dcb07ab7dea170ea5ef41a1 Mon Sep 17 00:00:00 2001 From: Pluto Date: Sat, 28 Mar 2026 20:16:59 +0530 Subject: [PATCH 4/8] feat: move the link preview and editor setting to live preview settings --- .../LivePreviewSettings.js | 15 ++++++++++-- .../livePreviewSettings.html | 5 ++++ .../Phoenix-live-preview/main.js | 23 +++---------------- src/nls/root/strings.js | 4 ++-- 4 files changed, 23 insertions(+), 24 deletions(-) diff --git a/src/extensionsIntegrated/Phoenix-live-preview/LivePreviewSettings.js b/src/extensionsIntegrated/Phoenix-live-preview/LivePreviewSettings.js index 8fa32929fd..4b79fe124b 100644 --- a/src/extensionsIntegrated/Phoenix-live-preview/LivePreviewSettings.js +++ b/src/extensionsIntegrated/Phoenix-live-preview/LivePreviewSettings.js @@ -62,7 +62,8 @@ define(function (require, exports, module) { const SUPPORTED_FRAMEWORKS = {}; SUPPORTED_FRAMEWORKS[FRAMEWORK_DOCUSAURUS] = {configFile: "docusaurus.config.js", hotReloadSupported: true}; - const PREFERENCE_SHOW_LIVE_PREVIEW_PANEL = "livePreviewShowAtStartup", + const PREFERENCE_LINK_EDITOR_AND_PREVIEW = "livePreviewSyncSourceAndPreview", + PREFERENCE_SHOW_LIVE_PREVIEW_PANEL = "livePreviewShowAtStartup", PREFERENCE_PROJECT_SERVER_ENABLED = "livePreviewUseDevServer", PREFERENCE_PROJECT_SERVER_URL = "livePreviewServerURL", PREFERENCE_PROJECT_SERVER_PATH = "livePreviewServerProjectPath", @@ -122,7 +123,9 @@ define(function (require, exports, module) { {"settings": currentSettings, "Strings": Strings})); // Select the correct theme. - const $livePreviewServerURL = $template.find("#livePreviewServerURL"), + const $linkEditorAndPreviewChk = $template.find("#linkEditorAndPreviewChk"), + $linkEditorAndPreviewInfo = $template.find("#linkEditorAndPreviewInfo"), + $livePreviewServerURL = $template.find("#livePreviewServerURL"), $enableCustomServerChk = $template.find("#enableCustomServerChk"), $showLivePreviewAtStartup = $template.find("#showLivePreviewAtStartupChk"), $serveRoot = $template.find("#serveRoot"), @@ -133,6 +136,13 @@ define(function (require, exports, module) { $frameworkSelect = $template.find("#frameworkSelect"); // Initialize form values from preferences + $linkEditorAndPreviewChk.prop( + 'checked', PreferencesManager.get(PREFERENCE_LINK_EDITOR_AND_PREVIEW) !== false + ); + $linkEditorAndPreviewInfo.on("click", function(e) { + e.preventDefault(); + Phoenix.app.openURLInDefaultBrowser("https://docs.phcode.dev"); + }); $enableCustomServerChk.prop('checked', PreferencesManager.get(PREFERENCE_PROJECT_SERVER_ENABLED)); $showLivePreviewAtStartup.prop('checked', PreferencesManager.get(PREFERENCE_SHOW_LIVE_PREVIEW_PANEL)); $hotReloadChk.prop('checked', !!PreferencesManager.get(PREFERENCE_PROJECT_SERVER_HOT_RELOAD_SUPPORTED)); @@ -174,6 +184,7 @@ define(function (require, exports, module) { Metrics.countEvent(Metrics.EVENT_TYPE.LIVE_PREVIEW, "settings", "dialog"); Dialogs.showModalDialogUsingTemplate($template).done(function (id) { if (id === Dialogs.DIALOG_BTN_OK) { + PreferencesManager.set(PREFERENCE_LINK_EDITOR_AND_PREVIEW, $linkEditorAndPreviewChk.is(":checked")); PreferencesManager.set(PREFERENCE_SHOW_LIVE_PREVIEW_PANEL, $showLivePreviewAtStartup.is(":checked")); _saveProjectPreferences($enableCustomServerChk.is(":checked"), $livePreviewServerURL.val(), $serveRoot.val(), $hotReloadChk.is(":checked"), $frameworkSelect.val()); diff --git a/src/extensionsIntegrated/Phoenix-live-preview/livePreviewSettings.html b/src/extensionsIntegrated/Phoenix-live-preview/livePreviewSettings.html index ad3cd9aa89..60d4efc13f 100644 --- a/src/extensionsIntegrated/Phoenix-live-preview/livePreviewSettings.html +++ b/src/extensionsIntegrated/Phoenix-live-preview/livePreviewSettings.html @@ -8,6 +8,11 @@

{{Strings.LIVE_DEV_SETTINGS_TITLE}}

+
+ + + +
diff --git a/src/extensionsIntegrated/Phoenix-live-preview/main.js b/src/extensionsIntegrated/Phoenix-live-preview/main.js index 659bc9e2cd..9597abf570 100644 --- a/src/extensionsIntegrated/Phoenix-live-preview/main.js +++ b/src/extensionsIntegrated/Phoenix-live-preview/main.js @@ -116,10 +116,10 @@ define(function (require, exports, module) { // description: Strings.LIVE_DEV_SETTINGS_SHOW_SPACING_HANDLES_PREFERENCE // }); - // live preview sync source and preview preference + // live preview link editor and preview preference const PREFERENCE_LIVE_PREVIEW_SYNC = CONSTANTS.PREFERENCE_LIVE_PREVIEW_SYNC; PreferencesManager.definePreference(PREFERENCE_LIVE_PREVIEW_SYNC, "boolean", true, { - description: Strings.LIVE_DEV_SETTINGS_SYNC_SOURCE_AND_PREVIEW_PREFERENCE + description: Strings.LIVE_DEV_SETTINGS_LINK_EDITOR_AND_PREVIEW_PREFERENCE }); const LIVE_PREVIEW_PANEL_ID = "live-preview-panel"; @@ -341,22 +341,16 @@ define(function (require, exports, module) { function _showModeSelectionDropdown(event) { const isEditFeaturesActive = isProEditUser; const currentMode = LiveDevelopment.getCurrentMode(); - const isNotPreviewMode = currentMode !== LiveDevelopment.CONSTANTS.LIVE_PREVIEW_MODE; const items = [ Strings.LIVE_PREVIEW_MODE_PREVIEW, Strings.LIVE_PREVIEW_MODE_HIGHLIGHT, Strings.LIVE_PREVIEW_MODE_EDIT ]; - // Add sync toggle for highlight and edit modes - if (isNotPreviewMode) { - items.push("---"); - items.push(Strings.LIVE_PREVIEW_SYNC_SOURCE_AND_PREVIEW); - } - // Only add edit-specific options when in edit mode and edit features are active const isEditMode = currentMode === LiveDevelopment.CONSTANTS.LIVE_EDIT_MODE; if (isEditFeaturesActive && isEditMode) { + items.push("---"); items.push(Strings.LIVE_PREVIEW_EDIT_HIGHLIGHT_ON); items.push(Strings.LIVE_PREVIEW_SHOW_RULER_LINES); } @@ -378,12 +372,6 @@ define(function (require, exports, module) { html: `${checkmark}${item}${crownIcon}`, enabled: true }; - } else if (item === Strings.LIVE_PREVIEW_SYNC_SOURCE_AND_PREVIEW) { - const isEnabled = PreferencesManager.get(PREFERENCE_LIVE_PREVIEW_SYNC) !== false; - if(isEnabled) { - return `✓ ${Strings.LIVE_PREVIEW_SYNC_SOURCE_AND_PREVIEW}`; - } - return `${'\u00A0'.repeat(4)}${Strings.LIVE_PREVIEW_SYNC_SOURCE_AND_PREVIEW}`; } else if (item === Strings.LIVE_PREVIEW_EDIT_HIGHLIGHT_ON) { const isHoverMode = PreferencesManager.get(PREFERENCE_PROJECT_ELEMENT_HIGHLIGHT) === CONSTANTS.HIGHLIGHT_HOVER; @@ -434,11 +422,6 @@ define(function (require, exports, module) { Metrics.countEvent(Metrics.EVENT_TYPE.PRO, "proUpsellDlg", "fail"); } } - } else if (item === Strings.LIVE_PREVIEW_SYNC_SOURCE_AND_PREVIEW) { - // Toggle sync source and preview on/off - const currentValue = PreferencesManager.get(PREFERENCE_LIVE_PREVIEW_SYNC); - PreferencesManager.set(PREFERENCE_LIVE_PREVIEW_SYNC, currentValue === false); - return; // Don't dismiss for this option } else if (item === Strings.LIVE_PREVIEW_EDIT_HIGHLIGHT_ON) { // Don't allow edit highlight toggle if edit features are not active if (!isEditFeaturesActive) { diff --git a/src/nls/root/strings.js b/src/nls/root/strings.js index 56ea122d37..905dd6a6c1 100644 --- a/src/nls/root/strings.js +++ b/src/nls/root/strings.js @@ -517,8 +517,8 @@ define({ "LIVE_PREVIEW_SHOW_RULER_LINES": "Show Measurements", "LIVE_PREVIEW_SHOW_SPACING_HANDLES": "Show Spacing Handles", "LIVE_DEV_SETTINGS_SHOW_SPACING_HANDLES_PREFERENCE": "Show spacing handles when elements are selected in live preview edit mode. Defaults to 'true'", - "LIVE_PREVIEW_SYNC_SOURCE_AND_PREVIEW": "Sync Code & Preview", - "LIVE_DEV_SETTINGS_SYNC_SOURCE_AND_PREVIEW_PREFERENCE": "Sync source code cursor with live preview element highlighting. When enabled, moving the cursor in the editor highlights the corresponding element in the live preview, and clicking an element in the live preview jumps the cursor to its source code. Defaults to 'true'", + "LIVE_PREVIEW_LINK_EDITOR_AND_PREVIEW": "Link Editor and Preview", + "LIVE_DEV_SETTINGS_LINK_EDITOR_AND_PREVIEW_PREFERENCE": "Link editor cursor with live preview element highlighting. When enabled, moving the cursor in the editor highlights the corresponding element in the live preview, and clicking an element in the live preview jumps the cursor to its source code. Defaults to 'true'", "LIVE_PREVIEW_MODE_PREFERENCE": "'{0}' shows only the webpage, '{1}' connects the webpage to your code - click on elements to jump to their code and vice versa, '{2}' provides highlighting along with advanced element manipulation", "LIVE_PREVIEW_CONFIGURE_MODES": "Configure Live Preview Modes", From a0dd10b5279d6bb33d85f22773bf37455a5ec92d Mon Sep 17 00:00:00 2001 From: Pluto Date: Sat, 28 Mar 2026 20:19:21 +0530 Subject: [PATCH 5/8] chore: auto update API docs --- docs/API-Reference/widgets/Dialogs.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/API-Reference/widgets/Dialogs.md b/docs/API-Reference/widgets/Dialogs.md index 65509100a5..7a24c9302a 100644 --- a/docs/API-Reference/widgets/Dialogs.md +++ b/docs/API-Reference/widgets/Dialogs.md @@ -59,7 +59,7 @@ Left-aligned button class name **Kind**: global constant -## showModalDialogUsingTemplate(template, [autoDismiss]) ⇒ [Dialog](#new_Dialog_new) +## showModalDialogUsingTemplate(template, [autoDismiss], [closeToElement]) ⇒ [Dialog](#new_Dialog_new) Creates a new modal dialog from a given template. The template can either be a string or a jQuery object representing a DOM node that is *not* in the current DOM. @@ -69,6 +69,7 @@ The template can either be a string or a jQuery object representing a DOM node t | --- | --- | --- | | template | string | A string template or jQuery object to use as the dialog HTML. | | [autoDismiss] | boolean | Whether to automatically dismiss the dialog when one of the buttons is clicked. Default true. If false, you'll need to manually handle button clicks and the Esc key, and dismiss the dialog yourself when ready by calling `close()` on the returned dialog. | +| [closeToElement] | string | A CSS selector for a target element. If specified, the dialog will animate open from and close toward the target element (a "woosh" effect). If the target is not found or not visible, the dialog opens/closes normally. | From 22a9d773cb62f6cd70b973e28d09e32b4f78affe Mon Sep 17 00:00:00 2001 From: Pluto Date: Sun, 29 Mar 2026 19:21:28 +0530 Subject: [PATCH 6/8] build: 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 7cee151d68..8bc87cbf28 100644 --- a/tracking-repos.json +++ b/tracking-repos.json @@ -1,5 +1,5 @@ { "phoenixPro": { - "commitID": "4b7f18af0837e289a48e6064ef884f66397b5f61" + "commitID": "22a4744d60e122305f9f17cc74558ae5edc30ffa" } } From fd60bad8a3e4ccbd1d859669eaf8b940f0dc8fe3 Mon Sep 17 00:00:00 2001 From: Pluto Date: Sun, 29 Mar 2026 21:40:14 +0530 Subject: [PATCH 7/8] build: 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 8bc87cbf28..ea9cd529f2 100644 --- a/tracking-repos.json +++ b/tracking-repos.json @@ -1,5 +1,5 @@ { "phoenixPro": { - "commitID": "22a4744d60e122305f9f17cc74558ae5edc30ffa" + "commitID": "32329d425d68e2b3579ef9c06f263d52ae0d70ef" } } From 84943c3c1de41271be9f420edae0220aa16f8bf3 Mon Sep 17 00:00:00 2001 From: Pluto Date: Sun, 29 Mar 2026 22:36:21 +0530 Subject: [PATCH 8/8] build: 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 ea9cd529f2..cdce2c5ab2 100644 --- a/tracking-repos.json +++ b/tracking-repos.json @@ -1,5 +1,5 @@ { "phoenixPro": { - "commitID": "32329d425d68e2b3579ef9c06f263d52ae0d70ef" + "commitID": "1ba3165f6676357990600b04abdb9b77b4ebb8ce" } }