Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
9f1989b
refactor: move loading more styles inside the _style function for con…
devvaannsh Sep 25, 2025
f858f2c
feat: localize all the strings used in image ribbon gallery
devvaannsh Sep 25, 2025
e4d023a
fix: downloaded images are blurry compared to previewed images
devvaannsh Sep 25, 2025
6944562
feat: use local storage instead of cache to reduce API calls
devvaannsh Sep 26, 2025
1613989
fix: live preview getting scrolled even when the element is completel…
devvaannsh Sep 26, 2025
5a3326d
fix: info box and more options box points at different elements after…
devvaannsh Sep 27, 2025
612edb7
refactor: remove redundant dismissed tracking
devvaannsh Sep 27, 2025
a739ac7
fix: select parent click function throws error when element is of svg…
devvaannsh Sep 27, 2025
712e4bb
fix: shouldn't show edit text button for svg children elements
devvaannsh Sep 27, 2025
3acb735
refactor: improve UI to make it consistent
devvaannsh Sep 27, 2025
87f89e5
refactor: use more intuitive icon for select image from computer button
devvaannsh Sep 28, 2025
d981f0f
feat: move image gallery inside more options box
devvaannsh Sep 28, 2025
c89db6c
feat: remove show image gallery option from dropdown
devvaannsh Oct 3, 2025
3b3ea08
refactor: use distinct icon for select image from computer button
devvaannsh Oct 3, 2025
0d22c60
feat: ask users to select the folder where they want to download the …
devvaannsh Oct 4, 2025
3ad4ab3
feat: show folder suggestions when typing a folder name in the dialog
devvaannsh Oct 5, 2025
9e897a3
feat: add keyboard navigation in the suggestions list
devvaannsh Oct 5, 2025
8245fde
feat: improve match goodness algorithm to show more useful hints
devvaannsh Oct 6, 2025
44d8ab0
feat: make the folder suggestion list scrollable
devvaannsh Oct 6, 2025
1e5e112
fix: feels laggy because of transition
devvaannsh Oct 6, 2025
3529ad3
feat: save folder location in state manager project wise
devvaannsh Oct 6, 2025
a138cb8
feat: add download folder button reset mechanism
devvaannsh Oct 7, 2025
c353390
feat: localize all strings
devvaannsh Oct 7, 2025
d38fbd8
feat: make drag drop more intuitive
devvaannsh Oct 14, 2025
3399462
feat: set selected state for image gallery when its clicked
devvaannsh Oct 15, 2025
f197333
feat: trigger the unsplash download endpoint as required by the unspl…
devvaannsh Oct 17, 2025
99a6049
refactor: move image gallery button after select parent button so UI …
devvaannsh Oct 17, 2025
37695fb
fix: scroll live preview when image gallery and image element overlap…
devvaannsh Oct 17, 2025
2e4fef2
fix: prevent image gallery and AI box to disappear when live preview …
devvaannsh Oct 18, 2025
6caf5cd
fix: improvise drag-drop by looking for elements with same size
devvaannsh Oct 18, 2025
90be0a1
refactor: make drag over elements background a bit darker so that the…
devvaannsh Oct 18, 2025
6ab49f1
refactor: make image gallery UI consistent
devvaannsh Oct 18, 2025
ccd8393
fix: buttons jumping on hover
devvaannsh Oct 18, 2025
99f5af6
refactor: reduce border radius of the image gallery header buttons
devvaannsh Oct 19, 2025
3f728c6
refactor: make image gallery search bar styles consistent to Phoenix UI
devvaannsh Oct 19, 2025
3e6d83a
refactor: match live preview AI box styling with phoenix styling conv…
devvaannsh Oct 19, 2025
f3f2ebd
fix: element backgroud color not getting properly cleared
devvaannsh Oct 20, 2025
daa9059
feat: show root folders when empty query is entered inside the folder…
devvaannsh Oct 21, 2025
db8726c
fix: scroll suggestions list to top when query changes
devvaannsh Oct 21, 2025
3249792
feat: exclude folders that are redundant (starting with .)
devvaannsh Oct 21, 2025
a388445
feat: show drilled down results inside a folder when query ends with …
devvaannsh Oct 22, 2025
a36f01f
refactor: hide the AI button from the more options box
devvaannsh Oct 22, 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
915 changes: 666 additions & 249 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
455 changes: 428 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 @@ -429,7 +423,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 @@ -455,12 +448,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 @@ -509,15 +496,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 @@ -1323,15 +1301,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...",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of ..., use unicode \u2026. That is the convention that we use in other places.

eg: "LIVE_DEV_OPEN_CHROME": "Open In Chrome\u2026"

"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 @@ -2514,3 +2514,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