From 62a2b274cdfc4999b0cb514f1ac04ef5c4bdaa30 Mon Sep 17 00:00:00 2001 From: Pluto Date: Sat, 22 Nov 2025 12:35:44 +0530 Subject: [PATCH 01/17] feat: show upsell dialog when free user selects edit mode --- .../Phoenix-live-preview/main.js | 32 ++----------------- src/nls/root/strings.js | 3 -- 2 files changed, 2 insertions(+), 33 deletions(-) diff --git a/src/extensionsIntegrated/Phoenix-live-preview/main.js b/src/extensionsIntegrated/Phoenix-live-preview/main.js index 5e88c35cb7..5528255016 100644 --- a/src/extensionsIntegrated/Phoenix-live-preview/main.js +++ b/src/extensionsIntegrated/Phoenix-live-preview/main.js @@ -72,6 +72,7 @@ define(function (require, exports, module) { panelHTML = require("text!./panel.html"), Dialogs = require("widgets/Dialogs"), DefaultDialogs = require("widgets/DefaultDialogs"), + ProDialogs = require("services/pro-dialogs"), utils = require('./utils'); const StateManager = PreferencesManager.stateManager; @@ -273,35 +274,6 @@ define(function (require, exports, module) { } } - function _showProFeatureDialog() { - const dialog = Dialogs.showModalDialog( - DefaultDialogs.DIALOG_ID_INFO, - Strings.LIVE_PREVIEW_PRO_FEATURE_TITLE, - Strings.LIVE_PREVIEW_PRO_FEATURE_MESSAGE, - [ - { - className: Dialogs.DIALOG_BTN_CLASS_NORMAL, - id: Dialogs.DIALOG_BTN_CANCEL, - text: Strings.CANCEL - }, - { - className: Dialogs.DIALOG_BTN_CLASS_PRIMARY, - id: "subscribe", - text: Strings.LIVE_PREVIEW_PRO_SUBSCRIBE - } - ] - ); - - dialog.done(function (buttonId) { - if (buttonId === "subscribe") { - // TODO: write the implementation here...@abose - console.log("the subscribe button got clicked"); - } - }); - - return dialog; - } - // this function is to check if the live highlight feature is enabled or not function _isLiveHighlightEnabled() { return CommandManager.get(Commands.FILE_LIVE_HIGHLIGHT).getChecked(); @@ -438,7 +410,7 @@ define(function (require, exports, module) { LiveDevelopment.setMode("highlight"); } else if (index === 2) { if (!LiveDevelopment.setMode("edit")) { - _showProFeatureDialog(); + ProDialogs.showProUpsellDialog(ProDialogs.UPSELL_TYPE_LIVE_EDIT); } } else if (item === Strings.LIVE_PREVIEW_EDIT_HIGHLIGHT_ON) { // Don't allow edit highlight toggle if edit features are not active diff --git a/src/nls/root/strings.js b/src/nls/root/strings.js index ed03f8e14b..217fd4208f 100644 --- a/src/nls/root/strings.js +++ b/src/nls/root/strings.js @@ -216,9 +216,6 @@ define({ "LIVE_PREVIEW_EDIT_HIGHLIGHT_ON": "Edit Highlights on Hover", "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", - "LIVE_PREVIEW_PRO_FEATURE_TITLE": "Pro Feature", - "LIVE_PREVIEW_PRO_FEATURE_MESSAGE": "This is a Pro feature. Subscribe to Phoenix Pro to keep using this feature.", - "LIVE_PREVIEW_PRO_SUBSCRIBE": "Subscribe", "LIVE_DEV_DETACHED_REPLACED_WITH_DEVTOOLS": "Live Preview was canceled because the browser's developer tools were opened", "LIVE_DEV_DETACHED_TARGET_CLOSED": "Live Preview was canceled because the page was closed in the browser", From 49d06b03c8840ecbd3bc5547a39c3bb2420944b0 Mon Sep 17 00:00:00 2001 From: Pluto Date: Sat, 22 Nov 2025 15:09:41 +0530 Subject: [PATCH 02/17] fix: revert redraw everything change --- .../BrowserScripts/RemoteFunctions.js | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/src/LiveDevelopment/BrowserScripts/RemoteFunctions.js b/src/LiveDevelopment/BrowserScripts/RemoteFunctions.js index 6c208d6c8b..6b607bc222 100644 --- a/src/LiveDevelopment/BrowserScripts/RemoteFunctions.js +++ b/src/LiveDevelopment/BrowserScripts/RemoteFunctions.js @@ -33,10 +33,6 @@ function RemoteFunctions(config = {}) { // we need this so that we can remove click styling from the previous element when a new element is clicked let previouslyClickedElement = null; - // this is needed so that when user starts typing we can dismiss all the boxes and highlights - // now with this variable we check if its a first keystroke on an element or a subsequent keystroke - let _uiHiddenDuringTyping = false; - var req, timeout; var animateHighlight = function (time) { if(req) { @@ -3822,9 +3818,6 @@ function RemoteFunctions(config = {}) { * @param {Element} element - The DOM element to select */ function _selectElement(element) { - // user selected a new element, we need to reset this variable - _uiHiddenDuringTyping = false; - dismissNodeMoreOptionsBox(); dismissAIPromptBox(); dismissNodeInfoBox(); @@ -4431,15 +4424,7 @@ function RemoteFunctions(config = {}) { }); this.rememberedNodes = {}; - - // when user starts typing in the editor we hide all the boxes and highlights - // _uiHiddenDuringTyping variable keeps track if its a first keystroke or subsequent - // so that we don't end up calling dismiss/hide kinda functions multiple times - if (!_uiHiddenDuringTyping) { - dismissUIAndCleanupState(); - hideHighlight(); - _uiHiddenDuringTyping = true; - } + redrawEverything(); }; function applyDOMEdits(edits) { From 15dd201d97d2e55cf08f207799d601f76b487aec Mon Sep 17 00:00:00 2001 From: Pluto Date: Sat, 22 Nov 2025 16:41:01 +0530 Subject: [PATCH 03/17] feat: ctrl s to work on live preview --- .../BrowserScripts/LiveDevProtocolRemote.js | 9 +++++++++ src/LiveDevelopment/LivePreviewEdit.js | 8 ++++++++ 2 files changed, 17 insertions(+) diff --git a/src/LiveDevelopment/BrowserScripts/LiveDevProtocolRemote.js b/src/LiveDevelopment/BrowserScripts/LiveDevProtocolRemote.js index a959721cd4..cdbaa944aa 100644 --- a/src/LiveDevelopment/BrowserScripts/LiveDevProtocolRemote.js +++ b/src/LiveDevelopment/BrowserScripts/LiveDevProtocolRemote.js @@ -455,6 +455,15 @@ redoLivePreviewOperation: true }); } + + // for save + if ((e.ctrlKey || e.metaKey) && e.key.toLowerCase() === "s") { + e.preventDefault(); + MessageBroker.send({ + livePreviewEditEnabled: true, + saveCurrentDocument: true + }); + } }); }(this)); diff --git a/src/LiveDevelopment/LivePreviewEdit.js b/src/LiveDevelopment/LivePreviewEdit.js index e6575bdcfd..6c855c619b 100644 --- a/src/LiveDevelopment/LivePreviewEdit.js +++ b/src/LiveDevelopment/LivePreviewEdit.js @@ -30,6 +30,8 @@ define(function (require, exports, module) { const LiveDevelopment = require("LiveDevelopment/main"); const CodeMirror = require("thirdparty/CodeMirror/lib/codemirror"); const ProjectManager = require("project/ProjectManager"); + const CommandManager = require("command/CommandManager"); + const Commands = require("command/Commands"); const FileSystem = require("filesystem/FileSystem"); const PathUtils = require("thirdparty/path-utils/path-utils"); const StringMatch = require("utils/StringMatch"); @@ -1289,6 +1291,12 @@ define(function (require, exports, module) { * these are the main properties that are passed through the message */ function handleLivePreviewEditOperation(message) { + // handle save current document in live preview (ctrl/cmd + s) + if (message.saveCurrentDocument) { + CommandManager.execute(Commands.FILE_SAVE); + return; + } + // handle reset image folder selection if (message.resetImageFolderSelection) { _handleResetImageFolderSelection(); From 7b7bb50f0811399df682cbbb657f2368d4c31cf3 Mon Sep 17 00:00:00 2001 From: Pluto Date: Sat, 22 Nov 2025 16:56:46 +0530 Subject: [PATCH 04/17] fix: save not working when user is between editing text --- .../BrowserScripts/LiveDevProtocolRemote.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/LiveDevelopment/BrowserScripts/LiveDevProtocolRemote.js b/src/LiveDevelopment/BrowserScripts/LiveDevProtocolRemote.js index cdbaa944aa..2df06cb441 100644 --- a/src/LiveDevelopment/BrowserScripts/LiveDevProtocolRemote.js +++ b/src/LiveDevelopment/BrowserScripts/LiveDevProtocolRemote.js @@ -459,6 +459,19 @@ // for save if ((e.ctrlKey || e.metaKey) && e.key.toLowerCase() === "s") { e.preventDefault(); + + // to check if user was in between editing text + // in such cases we first finish the editing and then save + const activeElement = document.activeElement; + if (activeElement && + activeElement.hasAttribute("contenteditable") && + activeElement.hasAttribute("data-brackets-id") && + window._LD && + window._LD.finishEditing) { + + window._LD.finishEditing(activeElement); + } + MessageBroker.send({ livePreviewEditEnabled: true, saveCurrentDocument: true From 147a09cb3c6250e376bd25253e244c900881f8cc Mon Sep 17 00:00:00 2001 From: Pluto Date: Sat, 22 Nov 2025 18:21:43 +0530 Subject: [PATCH 05/17] feat: add keyboard shortcut for preview mode button --- src/base-config/keyboard.json | 2 +- src/command/Commands.js | 3 +++ src/command/DefaultMenus.js | 2 -- src/extensionsIntegrated/Phoenix-live-preview/main.js | 1 + src/nls/root/strings.js | 1 + 5 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/base-config/keyboard.json b/src/base-config/keyboard.json index 8674ac0619..162f4c9748 100644 --- a/src/base-config/keyboard.json +++ b/src/base-config/keyboard.json @@ -28,7 +28,7 @@ "key": "Ctrl-Shift-R" } ], - "file.previewHighlight": [ + "file.livePreviewModeToggle": [ "Ctrl-Shift-C" ], "file.quit": [ diff --git a/src/command/Commands.js b/src/command/Commands.js index dd9d5b0e64..96959a9a82 100644 --- a/src/command/Commands.js +++ b/src/command/Commands.js @@ -106,6 +106,9 @@ define(function (require, exports, module) { /** Toggles live highlight */ exports.FILE_LIVE_HIGHLIGHT = "file.previewHighlight"; // LiveDevelopment/main.js _handlePreviewHighlightCommand() + /** Toggles live preview mode */ + exports.FILE_LIVE_PREVIEW_MODE_TOGGLE = "file.livePreviewModeToggle"; // Phoenix-live-preview/main.js _handlePreviewBtnClick() + /** Opens project settings */ exports.FILE_PROJECT_SETTINGS = "file.projectSettings"; // ProjectManager.js _projectSettings() diff --git a/src/command/DefaultMenus.js b/src/command/DefaultMenus.js index 8fec28a26e..31578dad57 100644 --- a/src/command/DefaultMenus.js +++ b/src/command/DefaultMenus.js @@ -230,8 +230,6 @@ define(function (require, exports, module) { menu.addMenuItem(Commands.TOGGLE_WORD_WRAP); menu.addMenuItem(Commands.TOGGLE_RULERS); menu.addMenuDivider(); - menu.addMenuItem(Commands.FILE_LIVE_HIGHLIGHT); - menu.addMenuDivider(); menu.addMenuItem(Commands.VIEW_TOGGLE_PROBLEMS); menu.addMenuItem(Commands.VIEW_TOGGLE_INSPECTION); diff --git a/src/extensionsIntegrated/Phoenix-live-preview/main.js b/src/extensionsIntegrated/Phoenix-live-preview/main.js index 5528255016..93605bf89b 100644 --- a/src/extensionsIntegrated/Phoenix-live-preview/main.js +++ b/src/extensionsIntegrated/Phoenix-live-preview/main.js @@ -1184,6 +1184,7 @@ define(function (require, exports, module) { }); CommandManager.register(Strings.CMD_LIVE_FILE_PREVIEW_SETTINGS, Commands.FILE_LIVE_FILE_PREVIEW_SETTINGS, _showSettingsDialog); + CommandManager.register(Strings.CMD_LIVE_PREVIEW_MODE_TOGGLE, Commands.FILE_LIVE_PREVIEW_MODE_TOGGLE, _handlePreviewBtnClick); let fileMenu = Menus.getMenu(Menus.AppMenuBar.FILE_MENU); fileMenu.addMenuItem(Commands.FILE_LIVE_FILE_PREVIEW, "", Menus.AFTER, Commands.FILE_EXTENSION_MANAGER); fileMenu.addMenuItem(Commands.FILE_LIVE_FILE_PREVIEW_SETTINGS, "", diff --git a/src/nls/root/strings.js b/src/nls/root/strings.js index 217fd4208f..24afe166de 100644 --- a/src/nls/root/strings.js +++ b/src/nls/root/strings.js @@ -607,6 +607,7 @@ define({ "CMD_TOGGLE_ACTIVE_LINE": "Highlight Active Line", "CMD_TOGGLE_WORD_WRAP": "Word Wrap", "CMD_LIVE_HIGHLIGHT": "Live Preview Highlight", + "CMD_LIVE_PREVIEW_MODE_TOGGLE": "Toggle Live Preview Mode", "CMD_VIEW_TOGGLE_INSPECTION": "Lint Files on Save", "CMD_VIEW_TOGGLE_PROBLEMS": "Problems", "CMD_WORKINGSET_SORT_BY_ADDED": "Sort by Added", From ac723fcad3494b6dec2a10faa21d8333dcaa4d22 Mon Sep 17 00:00:00 2001 From: Pluto Date: Sat, 22 Nov 2025 20:50:36 +0530 Subject: [PATCH 06/17] feat: remove live preview mode toggle from keyboard manager --- src/base-config/keyboard.json | 3 --- src/command/Commands.js | 3 --- src/extensionsIntegrated/Phoenix-live-preview/main.js | 1 - src/nls/root/strings.js | 1 - 4 files changed, 8 deletions(-) diff --git a/src/base-config/keyboard.json b/src/base-config/keyboard.json index 162f4c9748..6469aadec7 100644 --- a/src/base-config/keyboard.json +++ b/src/base-config/keyboard.json @@ -28,9 +28,6 @@ "key": "Ctrl-Shift-R" } ], - "file.livePreviewModeToggle": [ - "Ctrl-Shift-C" - ], "file.quit": [ "Ctrl-Q" ], diff --git a/src/command/Commands.js b/src/command/Commands.js index 96959a9a82..dd9d5b0e64 100644 --- a/src/command/Commands.js +++ b/src/command/Commands.js @@ -106,9 +106,6 @@ define(function (require, exports, module) { /** Toggles live highlight */ exports.FILE_LIVE_HIGHLIGHT = "file.previewHighlight"; // LiveDevelopment/main.js _handlePreviewHighlightCommand() - /** Toggles live preview mode */ - exports.FILE_LIVE_PREVIEW_MODE_TOGGLE = "file.livePreviewModeToggle"; // Phoenix-live-preview/main.js _handlePreviewBtnClick() - /** Opens project settings */ exports.FILE_PROJECT_SETTINGS = "file.projectSettings"; // ProjectManager.js _projectSettings() diff --git a/src/extensionsIntegrated/Phoenix-live-preview/main.js b/src/extensionsIntegrated/Phoenix-live-preview/main.js index 93605bf89b..5528255016 100644 --- a/src/extensionsIntegrated/Phoenix-live-preview/main.js +++ b/src/extensionsIntegrated/Phoenix-live-preview/main.js @@ -1184,7 +1184,6 @@ define(function (require, exports, module) { }); CommandManager.register(Strings.CMD_LIVE_FILE_PREVIEW_SETTINGS, Commands.FILE_LIVE_FILE_PREVIEW_SETTINGS, _showSettingsDialog); - CommandManager.register(Strings.CMD_LIVE_PREVIEW_MODE_TOGGLE, Commands.FILE_LIVE_PREVIEW_MODE_TOGGLE, _handlePreviewBtnClick); let fileMenu = Menus.getMenu(Menus.AppMenuBar.FILE_MENU); fileMenu.addMenuItem(Commands.FILE_LIVE_FILE_PREVIEW, "", Menus.AFTER, Commands.FILE_EXTENSION_MANAGER); fileMenu.addMenuItem(Commands.FILE_LIVE_FILE_PREVIEW_SETTINGS, "", diff --git a/src/nls/root/strings.js b/src/nls/root/strings.js index 24afe166de..217fd4208f 100644 --- a/src/nls/root/strings.js +++ b/src/nls/root/strings.js @@ -607,7 +607,6 @@ define({ "CMD_TOGGLE_ACTIVE_LINE": "Highlight Active Line", "CMD_TOGGLE_WORD_WRAP": "Word Wrap", "CMD_LIVE_HIGHLIGHT": "Live Preview Highlight", - "CMD_LIVE_PREVIEW_MODE_TOGGLE": "Toggle Live Preview Mode", "CMD_VIEW_TOGGLE_INSPECTION": "Lint Files on Save", "CMD_VIEW_TOGGLE_PROBLEMS": "Problems", "CMD_WORKINGSET_SORT_BY_ADDED": "Sort by Added", From ecd63ba03455984ccd45a0e973d7f0131d73f114 Mon Sep 17 00:00:00 2001 From: Pluto Date: Sat, 22 Nov 2025 23:35:02 +0530 Subject: [PATCH 07/17] fix: save both active and previewed file on live preview save --- src/LiveDevelopment/LivePreviewEdit.js | 18 +++++++++++++++++- src/LiveDevelopment/main.js | 1 - 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/LiveDevelopment/LivePreviewEdit.js b/src/LiveDevelopment/LivePreviewEdit.js index 6c855c619b..c16687e3f9 100644 --- a/src/LiveDevelopment/LivePreviewEdit.js +++ b/src/LiveDevelopment/LivePreviewEdit.js @@ -1267,6 +1267,22 @@ define(function (require, exports, module) { _showFolderSelectionDialog(null); } + /** + * this function is responsible to save the active file (and previewed file, both might be same though) + * when ctrl/cmd + s is pressed in the live preview + */ + function _handleLivePreviewSave() { + // this saves the active file + CommandManager.execute(Commands.FILE_SAVE); + + // we also save the previewed file, (active file might be same as previewed or different) + const currLiveDoc = LiveDevMultiBrowser.getCurrentLiveDoc(); + if (currLiveDoc && currLiveDoc.editor) { + const previewedDoc = currLiveDoc.editor.document; + CommandManager.execute(Commands.FILE_SAVE, { doc: previewedDoc }); + } + } + /** * This is the main function that is exported. * it will be called by LiveDevProtocol when it receives a message from RemoteFunctions.js @@ -1293,7 +1309,7 @@ define(function (require, exports, module) { function handleLivePreviewEditOperation(message) { // handle save current document in live preview (ctrl/cmd + s) if (message.saveCurrentDocument) { - CommandManager.execute(Commands.FILE_SAVE); + _handleLivePreviewSave(); return; } diff --git a/src/LiveDevelopment/main.js b/src/LiveDevelopment/main.js index 61ad9dba33..fef92e751f 100644 --- a/src/LiveDevelopment/main.js +++ b/src/LiveDevelopment/main.js @@ -465,7 +465,6 @@ define(function main(require, exports, module) { config.highlight = PreferencesManager.getViewState("livedevHighlight"); function setLivePreviewEditFeaturesActive(enabled) { - // TODO: @abose here add kernal mode trust check isProUser = enabled; config.isProUser = enabled; if (MultiBrowserLiveDev && MultiBrowserLiveDev.status >= MultiBrowserLiveDev.STATUS_ACTIVE) { From d44e6463364eec7a1b52dbca333d0ba746d873ad Mon Sep 17 00:00:00 2001 From: Pluto Date: Sat, 22 Nov 2025 23:58:04 +0530 Subject: [PATCH 08/17] feat: toggle live preview play button on f8 key --- .../BrowserScripts/LiveDevProtocolRemote.js | 9 +++++++++ src/LiveDevelopment/LivePreviewEdit.js | 17 +++++++++++++++++ .../Phoenix-live-preview/main.js | 7 +++++++ 3 files changed, 33 insertions(+) diff --git a/src/LiveDevelopment/BrowserScripts/LiveDevProtocolRemote.js b/src/LiveDevelopment/BrowserScripts/LiveDevProtocolRemote.js index 2df06cb441..72b95696fb 100644 --- a/src/LiveDevelopment/BrowserScripts/LiveDevProtocolRemote.js +++ b/src/LiveDevelopment/BrowserScripts/LiveDevProtocolRemote.js @@ -477,6 +477,15 @@ saveCurrentDocument: true }); } + + // for preview button (play icon) toggle + if (e.key === 'F8') { + e.preventDefault(); + MessageBroker.send({ + livePreviewEditEnabled: true, + toggleLivePreviewMode: true + }); + } }); }(this)); diff --git a/src/LiveDevelopment/LivePreviewEdit.js b/src/LiveDevelopment/LivePreviewEdit.js index c16687e3f9..851e84d094 100644 --- a/src/LiveDevelopment/LivePreviewEdit.js +++ b/src/LiveDevelopment/LivePreviewEdit.js @@ -1283,6 +1283,17 @@ define(function (require, exports, module) { } } + /** + * This function is responsible to toggle the live preview Preview mode (play icon) + * this is done when user presses F8 key in the live preview + */ + function _handlePreviewModeToggle() { + const $previewBtn = $("#previewModeLivePreviewButton"); + if ($previewBtn.length > 0) { + $previewBtn.trigger("click"); + } + } + /** * This is the main function that is exported. * it will be called by LiveDevProtocol when it receives a message from RemoteFunctions.js @@ -1313,6 +1324,12 @@ define(function (require, exports, module) { return; } + // toggle live preview mode using F8 key + if (message.toggleLivePreviewMode) { + _handlePreviewModeToggle(); + return; + } + // handle reset image folder selection if (message.resetImageFolderSelection) { _handleResetImageFolderSelection(); diff --git a/src/extensionsIntegrated/Phoenix-live-preview/main.js b/src/extensionsIntegrated/Phoenix-live-preview/main.js index 5528255016..b823391cf5 100644 --- a/src/extensionsIntegrated/Phoenix-live-preview/main.js +++ b/src/extensionsIntegrated/Phoenix-live-preview/main.js @@ -1146,6 +1146,13 @@ define(function (require, exports, module) { $(document).on("click", "#livePreviewModeBtn", function (e) { _handleLPModeBtnClick(e); }); + + $(document).on("keydown", function (e) { + if (e.key === "F8") { + e.preventDefault(); + _handlePreviewBtnClick(); + } + }); } AppInit.appReady(function () { From fc91e7fcdb5113afbfe63a4b2f441c5f92394338 Mon Sep 17 00:00:00 2001 From: Pluto Date: Sun, 23 Nov 2025 00:08:09 +0530 Subject: [PATCH 09/17] refactor: improvised play button tooltip to include the keyboard shortcut in that --- src/extensionsIntegrated/Phoenix-live-preview/main.js | 2 +- src/nls/root/strings.js | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/extensionsIntegrated/Phoenix-live-preview/main.js b/src/extensionsIntegrated/Phoenix-live-preview/main.js index b823391cf5..547851b0ea 100644 --- a/src/extensionsIntegrated/Phoenix-live-preview/main.js +++ b/src/extensionsIntegrated/Phoenix-live-preview/main.js @@ -690,7 +690,7 @@ define(function (require, exports, module) { Strings: Strings, livePreview: Strings.LIVE_DEV_STATUS_TIP_OUT_OF_SYNC, clickToReload: Strings.LIVE_DEV_CLICK_TO_RELOAD_PAGE, - clickToPreview: Strings.LIVE_PREVIEW_MODE_PREVIEW, + clickToPreview: Strings.LIVE_PREVIEW_MODE_TOGGLE_PREVIEW, livePreviewSettings: Strings.LIVE_DEV_SETTINGS, livePreviewConfigureModes: Strings.LIVE_PREVIEW_CONFIGURE_MODES, clickToPopout: Strings.LIVE_DEV_CLICK_POPOUT, diff --git a/src/nls/root/strings.js b/src/nls/root/strings.js index 217fd4208f..419f50bc72 100644 --- a/src/nls/root/strings.js +++ b/src/nls/root/strings.js @@ -210,6 +210,7 @@ define({ "LIVE_DEV_IMAGE_FOLDER_DIALOG_REMEMBER": "Don't ask again for this project", "LIVE_DEV_AI_PROMPT_PLACEHOLDER": "Ask Phoenix AI to modify this element...", "LIVE_PREVIEW_CUSTOM_SERVER_BANNER": "Getting preview from your custom server {0}", + "LIVE_PREVIEW_MODE_TOGGLE_PREVIEW": "Toggle Preview Mode (F8)", "LIVE_PREVIEW_MODE_PREVIEW": "Preview Mode", "LIVE_PREVIEW_MODE_HIGHLIGHT": "Highlight Mode", "LIVE_PREVIEW_MODE_EDIT": "Edit Mode", From 31b8cd79e04a35065bd8d2cfdadfa9b5aea220f8 Mon Sep 17 00:00:00 2001 From: Pluto Date: Sun, 23 Nov 2025 14:43:08 +0530 Subject: [PATCH 10/17] refactor: replace upload text with select from device --- src/LiveDevelopment/BrowserScripts/RemoteFunctions.js | 2 +- src/LiveDevelopment/main.js | 4 ++-- src/nls/root/strings.js | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/LiveDevelopment/BrowserScripts/RemoteFunctions.js b/src/LiveDevelopment/BrowserScripts/RemoteFunctions.js index 6b607bc222..d7e5dc6ce2 100644 --- a/src/LiveDevelopment/BrowserScripts/RemoteFunctions.js +++ b/src/LiveDevelopment/BrowserScripts/RemoteFunctions.js @@ -2703,7 +2703,7 @@ function RemoteFunctions(config = {}) { diff --git a/src/LiveDevelopment/main.js b/src/LiveDevelopment/main.js index fef92e751f..f001d43218 100644 --- a/src/LiveDevelopment/main.js +++ b/src/LiveDevelopment/main.js @@ -111,7 +111,6 @@ define(function main(require, exports, module) { imageGallery: Strings.LIVE_DEV_MORE_OPTIONS_IMAGE_GALLERY, aiPromptPlaceholder: Strings.LIVE_DEV_AI_PROMPT_PLACEHOLDER, imageGalleryUseImage: Strings.LIVE_DEV_IMAGE_GALLERY_USE_IMAGE, - imageGallerySelectFromComputer: Strings.LIVE_DEV_IMAGE_GALLERY_SELECT_FROM_COMPUTER, imageGallerySelectDownloadFolder: Strings.LIVE_DEV_IMAGE_GALLERY_SELECT_DOWNLOAD_FOLDER, imageGallerySearchPlaceholder: Strings.LIVE_DEV_IMAGE_GALLERY_SEARCH_PLACEHOLDER, imageGallerySearchButton: Strings.LIVE_DEV_IMAGE_GALLERY_SEARCH_BUTTON, @@ -120,7 +119,8 @@ define(function main(require, exports, module) { imageGalleryNoImages: Strings.LIVE_DEV_IMAGE_GALLERY_NO_IMAGES, imageGalleryLoadError: Strings.LIVE_DEV_IMAGE_GALLERY_LOAD_ERROR, imageGalleryClose: Strings.LIVE_DEV_IMAGE_GALLERY_CLOSE, - imageGalleryUpload: Strings.LIVE_DEV_IMAGE_GALLERY_UPLOAD, + imageGallerySelectFromComputer: Strings.LIVE_DEV_IMAGE_GALLERY_SELECT_FROM_COMPUTER, + imageGallerySelectFromComputerTooltip: Strings.LIVE_DEV_IMAGE_GALLERY_SELECT_FROM_COMPUTER_TOOLTIP, toastNotEditable: Strings.LIVE_DEV_TOAST_NOT_EDITABLE, toastDontShowAgain: Strings.LIVE_DEV_TOAST_DONT_SHOW_AGAIN } diff --git a/src/nls/root/strings.js b/src/nls/root/strings.js index 419f50bc72..ede2eba9d0 100644 --- a/src/nls/root/strings.js +++ b/src/nls/root/strings.js @@ -191,7 +191,6 @@ define({ "LIVE_DEV_MORE_OPTIONS_AI": "Edit with AI", "LIVE_DEV_MORE_OPTIONS_IMAGE_GALLERY": "Image Gallery", "LIVE_DEV_IMAGE_GALLERY_USE_IMAGE": "Use this image", - "LIVE_DEV_IMAGE_GALLERY_SELECT_FROM_COMPUTER": "Upload image from computer", "LIVE_DEV_IMAGE_GALLERY_SELECT_DOWNLOAD_FOLDER": "Choose image download folder", "LIVE_DEV_IMAGE_GALLERY_SEARCH_PLACEHOLDER": "Search images\u2026", "LIVE_DEV_IMAGE_GALLERY_SEARCH_BUTTON": "Search", @@ -200,7 +199,8 @@ define({ "LIVE_DEV_IMAGE_GALLERY_NO_IMAGES": "No images found", "LIVE_DEV_IMAGE_GALLERY_LOAD_ERROR": "Failed to load images", "LIVE_DEV_IMAGE_GALLERY_CLOSE": "Close", - "LIVE_DEV_IMAGE_GALLERY_UPLOAD": "Upload", + "LIVE_DEV_IMAGE_GALLERY_SELECT_FROM_COMPUTER_TOOLTIP": "Select an image from your device", + "LIVE_DEV_IMAGE_GALLERY_SELECT_FROM_COMPUTER": "Select from device", "LIVE_DEV_TOAST_NOT_EDITABLE": "Element not editable - generated by script.", "LIVE_DEV_TOAST_DONT_SHOW_AGAIN": "Don't show again", "LIVE_DEV_IMAGE_FOLDER_DIALOG_TITLE": "Select Folder to Save Image", From 51c5f774eb8ad2145b18da5d77c22480d6f015ef Mon Sep 17 00:00:00 2001 From: Pluto Date: Sun, 23 Nov 2025 14:46:08 +0530 Subject: [PATCH 11/17] refactor: replace upload icon with a plus icon --- src/LiveDevelopment/BrowserScripts/RemoteFunctions.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/LiveDevelopment/BrowserScripts/RemoteFunctions.js b/src/LiveDevelopment/BrowserScripts/RemoteFunctions.js index d7e5dc6ce2..ab3a599215 100644 --- a/src/LiveDevelopment/BrowserScripts/RemoteFunctions.js +++ b/src/LiveDevelopment/BrowserScripts/RemoteFunctions.js @@ -1364,10 +1364,10 @@ function RemoteFunctions(config = {}) { `, selectImageFromComputer: ` - - - - `, + + + + `, downloadImage: ` From 92a26dbf2a322eb70fd9a4c4f94eb5732f46dbb1 Mon Sep 17 00:00:00 2001 From: Pluto Date: Sun, 23 Nov 2025 14:51:46 +0530 Subject: [PATCH 12/17] fix: select from device text overlapping other content --- src/LiveDevelopment/BrowserScripts/RemoteFunctions.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/LiveDevelopment/BrowserScripts/RemoteFunctions.js b/src/LiveDevelopment/BrowserScripts/RemoteFunctions.js index ab3a599215..811a128689 100644 --- a/src/LiveDevelopment/BrowserScripts/RemoteFunctions.js +++ b/src/LiveDevelopment/BrowserScripts/RemoteFunctions.js @@ -2329,7 +2329,7 @@ function RemoteFunctions(config = {}) { margin-right: 10px !important; } - @media (max-width: 525px) { + @media (max-width: 565px) { .phoenix-image-gallery-header-title { display: none !important; } @@ -2415,7 +2415,7 @@ function RemoteFunctions(config = {}) { background: #3c3f41 !important; } - @media (max-width: 400px) { + @media (max-width: 450px) { .phoenix-image-gallery-upload-container button { font-size: 0 !important; padding: 3px 6px !important; From 5732d5215e7071fea8724260d787a39d4f4a6d60 Mon Sep 17 00:00:00 2001 From: Pluto Date: Sun, 23 Nov 2025 14:58:21 +0530 Subject: [PATCH 13/17] feat: remove don't show again button from toast notification --- .../BrowserScripts/RemoteFunctions.js | 47 ++----------------- src/LiveDevelopment/main.js | 3 +- src/nls/root/strings.js | 1 - 3 files changed, 5 insertions(+), 46 deletions(-) diff --git a/src/LiveDevelopment/BrowserScripts/RemoteFunctions.js b/src/LiveDevelopment/BrowserScripts/RemoteFunctions.js index 811a128689..3354c33c4f 100644 --- a/src/LiveDevelopment/BrowserScripts/RemoteFunctions.js +++ b/src/LiveDevelopment/BrowserScripts/RemoteFunctions.js @@ -3843,12 +3843,9 @@ function RemoteFunctions(config = {}) { } // if element is not editable and user clicks on it, then we show a toast notification saying - // that this element is not editable (unless user dismissed it permanently) + // that this element is not editable if (!element.hasAttribute("data-brackets-id")) { - const hideToast = localStorage.getItem('phoenix-hide-dynamic-toast'); - if (!hideToast) { - showToast(config.strings.toastNotEditable); - } + showToast(config.strings.toastNotEditable); } // make sure that the element is actually visible to the user @@ -4592,27 +4589,6 @@ function RemoteFunctions(config = {}) { animation: slideUp 0.3s ease-out !important; } - .toast-message { - margin-bottom: 6px !important; - } - - .toast-button { - background: none !important; - border: none !important; - color: #A0A0A0 !important; - cursor: pointer !important; - font-size: 12px !important; - font-family: Arial, sans-serif !important; - text-decoration: none !important; - pointer-events: auto !important; - transition: opacity 0.2s !important; - } - - .toast-button:hover { - opacity: 0.8 !important; - text-decoration: underline !important; - } - @keyframes slideUp { from { opacity: 0; @@ -4628,34 +4604,19 @@ function RemoteFunctions(config = {}) { const content = `
${message}
-
`; shadow.innerHTML = `${content}`; window.document.body.appendChild(toast); - // add click handler to "Don't show again" button - const button = shadow.querySelector('.toast-button'); - button.addEventListener('click', () => { - // save to localStorage to never show again and close toast rn - localStorage.setItem('phoenix-hide-dynamic-toast', 'true'); - if (toast && toast.parentNode) { - toast.remove(); - } - if (_toastTimeout) { - clearTimeout(_toastTimeout); - _toastTimeout = null; - } - }); - - // Auto-dismiss after 6 seconds + // Auto-dismiss after 3 seconds _toastTimeout = setTimeout(() => { if (toast && toast.parentNode) { toast.remove(); } _toastTimeout = null; - }, 6000); + }, 3000); } /** diff --git a/src/LiveDevelopment/main.js b/src/LiveDevelopment/main.js index f001d43218..ad343d5880 100644 --- a/src/LiveDevelopment/main.js +++ b/src/LiveDevelopment/main.js @@ -121,8 +121,7 @@ define(function main(require, exports, module) { imageGalleryClose: Strings.LIVE_DEV_IMAGE_GALLERY_CLOSE, imageGallerySelectFromComputer: Strings.LIVE_DEV_IMAGE_GALLERY_SELECT_FROM_COMPUTER, imageGallerySelectFromComputerTooltip: Strings.LIVE_DEV_IMAGE_GALLERY_SELECT_FROM_COMPUTER_TOOLTIP, - toastNotEditable: Strings.LIVE_DEV_TOAST_NOT_EDITABLE, - toastDontShowAgain: Strings.LIVE_DEV_TOAST_DONT_SHOW_AGAIN + toastNotEditable: Strings.LIVE_DEV_TOAST_NOT_EDITABLE } }; // Status labels/styles are ordered: error, not connected, progress1, progress2, connected. diff --git a/src/nls/root/strings.js b/src/nls/root/strings.js index ede2eba9d0..9db3935857 100644 --- a/src/nls/root/strings.js +++ b/src/nls/root/strings.js @@ -202,7 +202,6 @@ define({ "LIVE_DEV_IMAGE_GALLERY_SELECT_FROM_COMPUTER_TOOLTIP": "Select an image from your device", "LIVE_DEV_IMAGE_GALLERY_SELECT_FROM_COMPUTER": "Select from device", "LIVE_DEV_TOAST_NOT_EDITABLE": "Element not editable - generated by script.", - "LIVE_DEV_TOAST_DONT_SHOW_AGAIN": "Don't show again", "LIVE_DEV_IMAGE_FOLDER_DIALOG_TITLE": "Select Folder to Save Image", "LIVE_DEV_IMAGE_FOLDER_DIALOG_DESCRIPTION": "Choose where to download the image:", "LIVE_DEV_IMAGE_FOLDER_DIALOG_PLACEHOLDER": "Type folder path (e.g., assets/images/)", From ccf87e18094c25e7b27107e16d0a9979797793f3 Mon Sep 17 00:00:00 2001 From: Pluto Date: Sun, 23 Nov 2025 15:08:38 +0530 Subject: [PATCH 14/17] fix: toast message not disappearing when switched to preview mode --- .../BrowserScripts/RemoteFunctions.js | 28 +++++++++++++------ 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/src/LiveDevelopment/BrowserScripts/RemoteFunctions.js b/src/LiveDevelopment/BrowserScripts/RemoteFunctions.js index 3354c33c4f..ef0040cc02 100644 --- a/src/LiveDevelopment/BrowserScripts/RemoteFunctions.js +++ b/src/LiveDevelopment/BrowserScripts/RemoteFunctions.js @@ -3845,7 +3845,7 @@ function RemoteFunctions(config = {}) { // if element is not editable and user clicks on it, then we show a toast notification saying // that this element is not editable if (!element.hasAttribute("data-brackets-id")) { - showToast(config.strings.toastNotEditable); + showToastMessage(config.strings.toastNotEditable); } // make sure that the element is actually visible to the user @@ -4540,6 +4540,7 @@ function RemoteFunctions(config = {}) { dismissAIPromptBox(); dismissNodeInfoBox(); dismissImageRibbonGallery(); + dismissToastMessage(); } let _toastTimeout = null; @@ -4549,15 +4550,9 @@ function RemoteFunctions(config = {}) { * this toast message is used when user tries to edit a non-editable element * @param {String} message - the message to display in the toast */ - function showToast(message) { + function showToastMessage(message) { // clear any existing toast & timer, if there are any - const existingToast = window.document.getElementById('phoenix-toast-notification'); - if (existingToast) { - existingToast.remove(); - } - if (_toastTimeout) { - clearTimeout(_toastTimeout); - } + dismissToastMessage(); // create a new fresh toast container const toast = window.document.createElement('div'); @@ -4619,6 +4614,21 @@ function RemoteFunctions(config = {}) { }, 3000); } + /** + * this function is to dismiss the toast message + * and clear its timeout (if any) + */ + function dismissToastMessage() { + const toastMessage = window.document.getElementById('phoenix-toast-notification'); + if (toastMessage) { + toastMessage.remove(); + } + if (_toastTimeout) { + clearTimeout(_toastTimeout); + } + _toastTimeout = null; + } + /** * Helper function to cleanup previously clicked element highlighting and state */ From d7e68db3bb8f0ac38b86dafd3a493fca255fd046 Mon Sep 17 00:00:00 2001 From: Pluto Date: Sun, 23 Nov 2025 15:15:07 +0530 Subject: [PATCH 15/17] fix: toast message not getting dismissed when editable element is clicked --- 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 ef0040cc02..dd22586176 100644 --- a/src/LiveDevelopment/BrowserScripts/RemoteFunctions.js +++ b/src/LiveDevelopment/BrowserScripts/RemoteFunctions.js @@ -3821,6 +3821,7 @@ function RemoteFunctions(config = {}) { dismissNodeMoreOptionsBox(); dismissAIPromptBox(); dismissNodeInfoBox(); + dismissToastMessage(); cleanupPreviousElementState(); // this should also be there when users are in highlight mode From 300c2971d0cee5e383a03a527afc9aae0d897fa5 Mon Sep 17 00:00:00 2001 From: Pluto Date: Sun, 23 Nov 2025 17:25:01 +0530 Subject: [PATCH 16/17] fix: image gallery nav buttons positioning --- src/LiveDevelopment/BrowserScripts/RemoteFunctions.js | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/LiveDevelopment/BrowserScripts/RemoteFunctions.js b/src/LiveDevelopment/BrowserScripts/RemoteFunctions.js index dd22586176..e9cf61bc85 100644 --- a/src/LiveDevelopment/BrowserScripts/RemoteFunctions.js +++ b/src/LiveDevelopment/BrowserScripts/RemoteFunctions.js @@ -2418,7 +2418,7 @@ function RemoteFunctions(config = {}) { @media (max-width: 450px) { .phoenix-image-gallery-upload-container button { font-size: 0 !important; - padding: 3px 6px !important; + padding: 3px 5px 3px 6px !important; } .phoenix-image-gallery-upload-container button svg { @@ -2498,12 +2498,12 @@ function RemoteFunctions(config = {}) { color: #eaeaf0 !important; background: rgba(21,25,36,0.65) !important; cursor: pointer !important; - font-size: 20px !important; + font-size: 22px !important; font-weight: 600 !important; user-select: none !important; transition: all 0.2s ease !important; z-index: 2147483647 !important; - padding: 4px 12px 8px 12px !important; + padding: 2px 11px 7px 11px !important; display: none !important; align-items: center !important; justify-content: center !important; @@ -2514,8 +2514,6 @@ function RemoteFunctions(config = {}) { .phoenix-image-gallery-nav:hover { background: rgba(21,25,36,0.85) !important; border-color: rgba(255,255,255,0.25) !important; - transform: scale(1.05) !important; - box-shadow: 0 4px 12px rgba(0,0,0,0.3) !important; } .phoenix-image-gallery-nav:active { From 649379f952faf3193e68fee23f758b9e58ffdee7 Mon Sep 17 00:00:00 2001 From: Pluto Date: Mon, 24 Nov 2025 00:57:45 +0530 Subject: [PATCH 17/17] fix: info box is getting triggered for phoenix internal elements --- src/LiveDevelopment/BrowserScripts/RemoteFunctions.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/LiveDevelopment/BrowserScripts/RemoteFunctions.js b/src/LiveDevelopment/BrowserScripts/RemoteFunctions.js index e9cf61bc85..0b7beceaed 100644 --- a/src/LiveDevelopment/BrowserScripts/RemoteFunctions.js +++ b/src/LiveDevelopment/BrowserScripts/RemoteFunctions.js @@ -129,6 +129,7 @@ function RemoteFunctions(config = {}) { if(element && // element should exist element.tagName.toLowerCase() !== "body" && // shouldn't be the body tag element.tagName.toLowerCase() !== "html" && // shouldn't be the HTML tag + !element.closest("[data-phcode-internal-c15r5a9]") && // this attribute is used by phoenix internal elements !_isInsideHeadTag(element)) { // shouldn't be inside the head tag like meta tags and all return true; } @@ -1461,6 +1462,7 @@ function RemoteFunctions(config = {}) { _style: function() { this.body = window.document.createElement("div"); + this.body.setAttribute("data-phcode-internal-c15r5a9", "true"); // this is shadow DOM. // we need it because if we add the box directly to the DOM then users style might override it. @@ -1740,6 +1742,7 @@ function RemoteFunctions(config = {}) { _style: function() { this.body = window.document.createElement("div"); + this.body.setAttribute("data-phcode-internal-c15r5a9", "true"); // this is shadow DOM. // we need it because if we add the box directly to the DOM then users style might override it. @@ -1924,6 +1927,7 @@ function RemoteFunctions(config = {}) { _style: function() { this.body = window.document.createElement("div"); + this.body.setAttribute("data-phcode-internal-c15r5a9", "true"); // using shadow dom so that user styles doesn't override it const shadow = this.body.attachShadow({ mode: "open" }); @@ -2293,7 +2297,8 @@ function RemoteFunctions(config = {}) { ImageRibbonGallery.prototype = { _style: function () { this.body = window.document.createElement("div"); - this._shadow = this.body.attachShadow({mode: 'closed'}); + this.body.setAttribute("data-phcode-internal-c15r5a9", "true"); + this._shadow = this.body.attachShadow({ mode: 'open' }); this._shadow.innerHTML = `