Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
a83d4d3
refactor: move loading more styles inside the _style function for con…
devvaannsh Sep 25, 2025
4baf7be
feat: localize all the strings used in image ribbon gallery
devvaannsh Sep 25, 2025
59fe651
fix: downloaded images are blurry compared to previewed images
devvaannsh Sep 25, 2025
a9a45b6
feat: use local storage instead of cache to reduce API calls
devvaannsh Sep 26, 2025
4bd71be
fix: live preview getting scrolled even when the element is completel…
devvaannsh Sep 26, 2025
c928b8f
fix: info box and more options box points at different elements after…
devvaannsh Sep 27, 2025
e8b2d79
refactor: remove redundant dismissed tracking
devvaannsh Sep 27, 2025
6bd2b18
fix: select parent click function throws error when element is of svg…
devvaannsh Sep 27, 2025
e563f1d
fix: shouldn't show edit text button for svg children elements
devvaannsh Sep 27, 2025
6dbe12b
refactor: improve UI to make it consistent
devvaannsh Sep 27, 2025
7eaeecb
refactor: use more intuitive icon for select image from computer button
devvaannsh Sep 28, 2025
9a24027
feat: move image gallery inside more options box
devvaannsh Sep 28, 2025
665e817
feat: remove show image gallery option from dropdown
devvaannsh Oct 3, 2025
5e32775
refactor: use distinct icon for select image from computer button
devvaannsh Oct 3, 2025
a0634ef
feat: ask users to select the folder where they want to download the …
devvaannsh Oct 4, 2025
a0e4ae8
feat: show folder suggestions when typing a folder name in the dialog
devvaannsh Oct 5, 2025
7e34ec5
feat: add keyboard navigation in the suggestions list
devvaannsh Oct 5, 2025
0fe69e6
feat: improve match goodness algorithm to show more useful hints
devvaannsh Oct 6, 2025
cf0fc5a
feat: make the folder suggestion list scrollable
devvaannsh Oct 6, 2025
8f4adb0
fix: feels laggy because of transition
devvaannsh Oct 6, 2025
26bf5ab
feat: save folder location in state manager project wise
devvaannsh Oct 6, 2025
bd25b9a
feat: add download folder button reset mechanism
devvaannsh Oct 7, 2025
dfebe26
feat: localize all strings
devvaannsh Oct 7, 2025
1c7a508
feat: make drag drop more intuitive
devvaannsh Oct 14, 2025
5a47bbc
feat: set selected state for image gallery when its clicked
devvaannsh Oct 15, 2025
9828ec0
feat: trigger the unsplash download endpoint as required by the unspl…
devvaannsh Oct 17, 2025
56afcd2
refactor: move image gallery button after select parent button so UI …
devvaannsh Oct 17, 2025
54e7925
fix: scroll live preview when image gallery and image element overlap…
devvaannsh Oct 17, 2025
e9df8b2
fix: prevent image gallery and AI box to disappear when live preview …
devvaannsh Oct 18, 2025
343ed56
fix: improvise drag-drop by looking for elements with same size
devvaannsh Oct 18, 2025
6545634
refactor: make drag over elements background a bit darker so that the…
devvaannsh Oct 18, 2025
572538c
refactor: make image gallery UI consistent
devvaannsh Oct 18, 2025
28a52ed
fix: buttons jumping on hover
devvaannsh Oct 18, 2025
14cf790
refactor: reduce border radius of the image gallery header buttons
devvaannsh Oct 19, 2025
03a1dca
refactor: make image gallery search bar styles consistent to Phoenix UI
devvaannsh Oct 19, 2025
dc3d2f2
refactor: match live preview AI box styling with phoenix styling conv…
devvaannsh Oct 19, 2025
282bee0
fix: element backgroud color not getting properly cleared
devvaannsh Oct 20, 2025
70a24db
feat: show root folders when empty query is entered inside the folder…
devvaannsh Oct 21, 2025
dd8ca2c
fix: scroll suggestions list to top when query changes
devvaannsh Oct 21, 2025
73db037
feat: exclude folders that are redundant (starting with .)
devvaannsh Oct 21, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
906 changes: 661 additions & 245 deletions src/LiveDevelopment/BrowserScripts/RemoteFunctions.js

Large diffs are not rendered by default.

12 changes: 1 addition & 11 deletions src/LiveDevelopment/LiveDevMultiBrowser.js
Original file line number Diff line number Diff line change
Expand Up @@ -714,17 +714,8 @@ define(function (require, exports, module) {
*/
function dismissLivePreviewBoxes() {
if (_protocol) {
_protocol.evaluate("_LD.enableHoverListeners()"); // so that if hover lock is there it will get cleared
_protocol.evaluate("_LD.dismissUIAndCleanupState()");
_protocol.evaluate("_LD.dismissImageRibbonGallery()");
}
}

/**
* Dismiss image ribbon gallery if it's open
*/
function dismissImageRibbonGallery() {
if (_protocol) {
_protocol.evaluate("_LD.dismissImageRibbonGallery()");
}
}

Expand Down Expand Up @@ -814,7 +805,6 @@ define(function (require, exports, module) {
exports.redrawHighlight = redrawHighlight;
exports.hasVisibleLivePreviewBoxes = hasVisibleLivePreviewBoxes;
exports.dismissLivePreviewBoxes = dismissLivePreviewBoxes;
exports.dismissImageRibbonGallery = dismissImageRibbonGallery;
exports.registerHandlers = registerHandlers;
exports.updateConfig = updateConfig;
exports.init = init;
Expand Down
428 changes: 401 additions & 27 deletions src/LiveDevelopment/LivePreviewEdit.js

Large diffs are not rendered by default.

26 changes: 8 additions & 18 deletions src/LiveDevelopment/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,6 @@ define(function main(require, exports, module) {
},
isProUser: isProUser,
elemHighlights: "hover", // default value, this will get updated when the extension loads
imageRibbon: true, // default value, this will get updated when the extension loads
// this strings are used in RemoteFunctions.js
// we need to pass this through config as remoteFunctions runs in browser context and cannot
// directly reference Strings file
Expand All @@ -80,11 +79,17 @@ define(function main(require, exports, module) {
duplicate: Strings.LIVE_DEV_MORE_OPTIONS_DUPLICATE,
delete: Strings.LIVE_DEV_MORE_OPTIONS_DELETE,
ai: Strings.LIVE_DEV_MORE_OPTIONS_AI,
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,
imageGalleryChooseFolder: Strings.LIVE_DEV_IMAGE_GALLERY_CHOOSE_FOLDER,
imageGallerySearchPlaceholder: Strings.LIVE_DEV_IMAGE_GALLERY_SEARCH_PLACEHOLDER
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,
imageGalleryLoadingInitial: Strings.LIVE_DEV_IMAGE_GALLERY_LOADING_INITIAL,
imageGalleryLoadingMore: Strings.LIVE_DEV_IMAGE_GALLERY_LOADING_MORE,
imageGalleryNoImages: Strings.LIVE_DEV_IMAGE_GALLERY_NO_IMAGES,
imageGalleryLoadError: Strings.LIVE_DEV_IMAGE_GALLERY_LOAD_ERROR
}
};
// Status labels/styles are ordered: error, not connected, progress1, progress2, connected.
Expand Down Expand Up @@ -370,20 +375,6 @@ define(function main(require, exports, module) {
}
}

// this function is responsible to update image picker config
// called from live preview extension when preference changes
function updateImageRibbonConfig() {
const prefValue = PreferencesManager.get("livePreviewImagePicker");
config.imageRibbon = prefValue !== false; // default to true if undefined

if (MultiBrowserLiveDev && MultiBrowserLiveDev.status >= MultiBrowserLiveDev.STATUS_ACTIVE) {
if (!prefValue) { MultiBrowserLiveDev.dismissImageRibbonGallery(); } // to remove any existing image ribbons

MultiBrowserLiveDev.updateConfig(JSON.stringify(config));
MultiBrowserLiveDev.registerHandlers();
}
}

// init commands
CommandManager.register(Strings.CMD_LIVE_HIGHLIGHT, Commands.FILE_LIVE_HIGHLIGHT, togglePreviewHighlight);
CommandManager.register(Strings.CMD_RELOAD_LIVE_PREVIEW, Commands.CMD_RELOAD_LIVE_PREVIEW, _handleReloadLivePreviewCommand);
Expand Down Expand Up @@ -412,7 +403,6 @@ define(function main(require, exports, module) {
exports.togglePreviewHighlight = togglePreviewHighlight;
exports.setLivePreviewEditFeaturesActive = setLivePreviewEditFeaturesActive;
exports.updateElementHighlightConfig = updateElementHighlightConfig;
exports.updateImageRibbonConfig = updateImageRibbonConfig;
exports.getConnectionIds = MultiBrowserLiveDev.getConnectionIds;
exports.getLivePreviewDetails = MultiBrowserLiveDev.getLivePreviewDetails;
exports.hideHighlight = MultiBrowserLiveDev.hideHighlight;
Expand Down
29 changes: 0 additions & 29 deletions src/extensionsIntegrated/Phoenix-live-preview/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -113,12 +113,6 @@ define(function (require, exports, module) {
description: Strings.LIVE_DEV_SETTINGS_ELEMENT_HIGHLIGHT_PREFERENCE
});

// live preview image picker preference (whether to show image gallery when clicking images)
const PREFERENCE_PROJECT_IMAGE_RIBBON = "livePreviewImagePicker";
PreferencesManager.definePreference(PREFERENCE_PROJECT_IMAGE_RIBBON, "boolean", true, {
description: Strings.LIVE_PREVIEW_EDIT_IMAGE_RIBBON
});

const LIVE_PREVIEW_PANEL_ID = "live-preview-panel";
const LIVE_PREVIEW_IFRAME_ID = "panel-live-preview-frame";
const LIVE_PREVIEW_IFRAME_HTML = `
Expand Down Expand Up @@ -425,7 +419,6 @@ define(function (require, exports, module) {
if (isEditFeaturesActive) {
items.push("---");
items.push(Strings.LIVE_PREVIEW_EDIT_HIGHLIGHT_ON);
items.push(Strings.LIVE_PREVIEW_EDIT_IMAGE_RIBBON);
}

const rawMode = PreferencesManager.get(PREFERENCE_LIVE_PREVIEW_MODE) || _getDefaultMode();
Expand All @@ -451,12 +444,6 @@ define(function (require, exports, module) {
return `✓ ${Strings.LIVE_PREVIEW_EDIT_HIGHLIGHT_ON}`;
}
return `${'\u00A0'.repeat(4)}${Strings.LIVE_PREVIEW_EDIT_HIGHLIGHT_ON}`;
} else if (item === Strings.LIVE_PREVIEW_EDIT_IMAGE_RIBBON) {
const isImageRibbonEnabled = PreferencesManager.get(PREFERENCE_PROJECT_IMAGE_RIBBON) !== false;
if(isImageRibbonEnabled) {
return `✓ ${item}`;
}
return `${'\u00A0'.repeat(4)}${item}`;
}
return item;
});
Expand Down Expand Up @@ -505,15 +492,6 @@ define(function (require, exports, module) {
const newMode = currentMode !== "click" ? "click" : "hover";
PreferencesManager.set(PREFERENCE_PROJECT_ELEMENT_HIGHLIGHT, newMode);
return; // Don't dismiss highlights for this option
} else if (item === Strings.LIVE_PREVIEW_EDIT_IMAGE_RIBBON) {
// Don't allow image ribbon toggle if edit features are not active
if (!isEditFeaturesActive) {
return;
}
// Toggle image ribbon preference
const currentEnabled = PreferencesManager.get(PREFERENCE_PROJECT_IMAGE_RIBBON);
PreferencesManager.set(PREFERENCE_PROJECT_IMAGE_RIBBON, !currentEnabled);
return; // Don't dismiss highlights for this option
}

// need to dismiss the previous highlighting and stuff
Expand Down Expand Up @@ -1318,15 +1296,8 @@ define(function (require, exports, module) {
LiveDevelopment.updateElementHighlightConfig();
});

// Handle image ribbon preference changes from this extension
PreferencesManager.on("change", PREFERENCE_PROJECT_IMAGE_RIBBON, function() {
LiveDevelopment.updateImageRibbonConfig();
});

// Initialize element highlight config on startup
LiveDevelopment.updateElementHighlightConfig();
// Initialize image ribbon config on startup
LiveDevelopment.updateImageRibbonConfig();

LiveDevelopment.openLivePreview();
LiveDevelopment.on(LiveDevelopment.EVENT_OPEN_PREVIEW_URL, _openLivePreviewURL);
Expand Down
32 changes: 32 additions & 0 deletions src/htmlContent/image-folder-dialog.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<div class="image-folder-dialog template modal">
<div class="modal-header">
<h1 class="dialog-title">{{Strings.LIVE_DEV_IMAGE_FOLDER_DIALOG_TITLE}}</h1>
</div>
<div class="modal-body">
<p>{{Strings.LIVE_DEV_IMAGE_FOLDER_DIALOG_DESCRIPTION}}</p>
<input type="text"
id="folder-path-input"
placeholder="{{Strings.LIVE_DEV_IMAGE_FOLDER_DIALOG_PLACEHOLDER}}"
value=""
autocomplete="off"
spellcheck="false">

<!-- the folder suggestions will come here dynamically -->
<div id="folder-suggestions"></div>

<p class="folder-help-text">
{{Strings.LIVE_DEV_IMAGE_FOLDER_DIALOG_HELP}}
</p>

<div class="remember-folder-container">
<label>
<input type="checkbox" id="remember-folder-checkbox" checked>
<span>{{Strings.LIVE_DEV_IMAGE_FOLDER_DIALOG_REMEMBER}}</span>
</label>
</div>
</div>
<div class="modal-footer">
<button class="dialog-button btn" data-button-id="cancel">{{Strings.CANCEL}}</button>
<button class="dialog-button btn primary" data-button-id="ok">{{Strings.OK}}</button>
</div>
</div>
14 changes: 12 additions & 2 deletions src/nls/root/strings.js
Original file line number Diff line number Diff line change
Expand Up @@ -189,17 +189,27 @@ define({
"LIVE_DEV_MORE_OPTIONS_DUPLICATE": "Duplicate",
"LIVE_DEV_MORE_OPTIONS_DELETE": "Delete",
"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": "Select image from computer",
"LIVE_DEV_IMAGE_GALLERY_CHOOSE_FOLDER": "Choose download folder",
"LIVE_DEV_IMAGE_GALLERY_SELECT_DOWNLOAD_FOLDER": "Choose image download folder",
"LIVE_DEV_IMAGE_GALLERY_SEARCH_PLACEHOLDER": "Search images...",
"LIVE_DEV_IMAGE_GALLERY_SEARCH_BUTTON": "Search",
"LIVE_DEV_IMAGE_GALLERY_LOADING_INITIAL": "Loading images...",
"LIVE_DEV_IMAGE_GALLERY_LOADING_MORE": "Loading...",
"LIVE_DEV_IMAGE_GALLERY_NO_IMAGES": "No images found",
"LIVE_DEV_IMAGE_GALLERY_LOAD_ERROR": "Failed to load images",
"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/)",
"LIVE_DEV_IMAGE_FOLDER_DIALOG_HELP": "💡 Type folder path or leave empty to download in project root",
"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_PREVIEW": "Preview Mode",
"LIVE_PREVIEW_MODE_HIGHLIGHT": "Highlight Mode",
"LIVE_PREVIEW_MODE_EDIT": "Edit Mode",
"LIVE_PREVIEW_EDIT_HIGHLIGHT_ON": "Edit Highlights on Hover",
"LIVE_PREVIEW_EDIT_IMAGE_RIBBON": "Show Image Picker on Image click",
"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",
Expand Down
105 changes: 105 additions & 0 deletions src/styles/brackets_patterns_override.less
Original file line number Diff line number Diff line change
Expand Up @@ -2518,3 +2518,108 @@ code {
}
}
}

// image folder selection dialog
.image-folder-dialog {
#folder-path-input {
width: 100%;
height: 30px;
padding: 5px;
box-sizing: border-box;
margin-bottom: 8px;
}

#folder-suggestions {
max-height: 150px;
overflow-y: auto;
overflow-x: hidden;
border: 1px solid @bc-btn-border;
border-radius: @bc-border-radius;
background-color: @bc-panel-bg-alt;

.dark & {
border: 1px solid @dark-bc-btn-border;
background-color: @dark-bc-panel-bg-alt;
}

&:empty {
display: none;
}

.folder-suggestions-list {
margin: 0;
padding: 0;
list-style: none;
}

.folder-suggestion-item {
padding: 6px 10px;
cursor: pointer;
font-size: 12px;
color: @bc-text;
border-left: 3px solid transparent;

.dark & {
color: @dark-bc-text;
}

&:hover {
background-color: @bc-panel-bg-hover-alt;

.dark & {
background-color: @dark-bc-panel-bg-hover-alt;
}
}

&.selected {
background-color: @bc-bg-highlight;
border-left-color: @bc-primary-btn-bg;

.dark & {
background-color: @dark-bc-bg-highlight;
border-left-color: @dark-bc-primary-btn-bg;
}
}
}

.folder-match-highlight {
font-weight: @font-weight-semibold;
color: @bc-primary-btn-bg;

.dark & {
color: @dark-bc-primary-btn-bg;
}
}
}

.folder-help-text {
margin-top: 8px;
margin-bottom: 0;
font-size: 11px;
color: @bc-text-quiet;
user-select: none;

.dark & {
color: @dark-bc-text-quiet;
}
}

.remember-folder-container {
display: flex;
justify-content: right;
}

.remember-folder-container label {
font-size: 12px;
letter-spacing: 0.3px;
color: @bc-text-quiet;

.dark & {
color: @dark-bc-text-quiet;
}
}

.remember-folder-container input {
margin-top: 2px;
}
}
Loading