Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
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
31 changes: 31 additions & 0 deletions src/LiveDevelopment/BrowserScripts/LiveDevProtocolRemote.js
Original file line number Diff line number Diff line change
Expand Up @@ -455,6 +455,37 @@
redoLivePreviewOperation: true
});
}

// 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") &&

Check failure on line 468 in src/LiveDevelopment/BrowserScripts/LiveDevProtocolRemote.js

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Prefer `.dataset` over `hasAttribute(…)`.

See more on https://sonarcloud.io/project/issues?id=phcode-dev_phoenix&issues=AZqrUhm81NG8ykCpyNoF&open=AZqrUhm81NG8ykCpyNoF&pullRequest=2488
window._LD &&

Check warning on line 469 in src/LiveDevelopment/BrowserScripts/LiveDevProtocolRemote.js

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Prefer `globalThis` over `window`.

See more on https://sonarcloud.io/project/issues?id=phcode-dev_phoenix&issues=AZqrUhm81NG8ykCpyNoG&open=AZqrUhm81NG8ykCpyNoG&pullRequest=2488
window._LD.finishEditing) {

Check warning on line 470 in src/LiveDevelopment/BrowserScripts/LiveDevProtocolRemote.js

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Prefer `globalThis` over `window`.

See more on https://sonarcloud.io/project/issues?id=phcode-dev_phoenix&issues=AZqrUhm81NG8ykCpyNoI&open=AZqrUhm81NG8ykCpyNoI&pullRequest=2488

Check warning on line 470 in src/LiveDevelopment/BrowserScripts/LiveDevProtocolRemote.js

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Prefer using an optional chain expression instead, as it's more concise and easier to read.

See more on https://sonarcloud.io/project/issues?id=phcode-dev_phoenix&issues=AZqrUhm81NG8ykCpyNoH&open=AZqrUhm81NG8ykCpyNoH&pullRequest=2488

window._LD.finishEditing(activeElement);

Check warning on line 472 in src/LiveDevelopment/BrowserScripts/LiveDevProtocolRemote.js

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Prefer `globalThis` over `window`.

See more on https://sonarcloud.io/project/issues?id=phcode-dev_phoenix&issues=AZqrUhm81NG8ykCpyNoJ&open=AZqrUhm81NG8ykCpyNoJ&pullRequest=2488
}

MessageBroker.send({
livePreviewEditEnabled: true,
saveCurrentDocument: true
});
}

// for preview button (play icon) toggle
if (e.key === 'F8') {
e.preventDefault();
MessageBroker.send({
livePreviewEditEnabled: true,
toggleLivePreviewMode: true
});
}
});

}(this));
121 changes: 41 additions & 80 deletions src/LiveDevelopment/BrowserScripts/RemoteFunctions.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,6 @@
// 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) {
Expand Down Expand Up @@ -133,6 +129,7 @@
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;
}
Expand Down Expand Up @@ -1368,10 +1365,10 @@
`,

selectImageFromComputer: `
<svg viewBox="0 0 24 24" fill="currentColor" width="19" height="19">
<path d="M9 16h6v-6h4l-7-7-7 7h4zm-4 2h14v2H5z"/>
</svg>
`,
<svg viewBox="0 0 24 24" fill="currentColor" width="19" height="19">
<path d="M11 5v6H5v2h6v6h2v-6h6v-2h-6V5h-2z"/>
</svg>
`,

downloadImage: `
<svg viewBox="0 0 640 640" fill="currentColor">
Expand Down Expand Up @@ -1465,6 +1462,7 @@

_style: function() {
this.body = window.document.createElement("div");
this.body.setAttribute("data-phcode-internal-c15r5a9", "true");

Check failure on line 1465 in src/LiveDevelopment/BrowserScripts/RemoteFunctions.js

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Prefer `.dataset` over `setAttribute(…)`.

See more on https://sonarcloud.io/project/issues?id=phcode-dev_phoenix&issues=AZqyMMz1XrFv6bfNgNEB&open=AZqyMMz1XrFv6bfNgNEB&pullRequest=2488

// this is shadow DOM.
// we need it because if we add the box directly to the DOM then users style might override it.
Expand Down Expand Up @@ -1744,6 +1742,7 @@

_style: function() {
this.body = window.document.createElement("div");
this.body.setAttribute("data-phcode-internal-c15r5a9", "true");

Check failure on line 1745 in src/LiveDevelopment/BrowserScripts/RemoteFunctions.js

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Prefer `.dataset` over `setAttribute(…)`.

See more on https://sonarcloud.io/project/issues?id=phcode-dev_phoenix&issues=AZqyMMz1XrFv6bfNgNEC&open=AZqyMMz1XrFv6bfNgNEC&pullRequest=2488

// this is shadow DOM.
// we need it because if we add the box directly to the DOM then users style might override it.
Expand Down Expand Up @@ -1928,6 +1927,7 @@

_style: function() {
this.body = window.document.createElement("div");
this.body.setAttribute("data-phcode-internal-c15r5a9", "true");

Check failure on line 1930 in src/LiveDevelopment/BrowserScripts/RemoteFunctions.js

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Prefer `.dataset` over `setAttribute(…)`.

See more on https://sonarcloud.io/project/issues?id=phcode-dev_phoenix&issues=AZqyMMz1XrFv6bfNgNED&open=AZqyMMz1XrFv6bfNgNED&pullRequest=2488
// using shadow dom so that user styles doesn't override it
const shadow = this.body.attachShadow({ mode: "open" });

Expand Down Expand Up @@ -2297,7 +2297,8 @@
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");

Check failure on line 2300 in src/LiveDevelopment/BrowserScripts/RemoteFunctions.js

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Prefer `.dataset` over `setAttribute(…)`.

See more on https://sonarcloud.io/project/issues?id=phcode-dev_phoenix&issues=AZqyMMz1XrFv6bfNgNEE&open=AZqyMMz1XrFv6bfNgNEE&pullRequest=2488
this._shadow = this.body.attachShadow({ mode: 'open' });

this._shadow.innerHTML = `
<style>
Expand Down Expand Up @@ -2333,7 +2334,7 @@
margin-right: 10px !important;
}

@media (max-width: 525px) {
@media (max-width: 565px) {
.phoenix-image-gallery-header-title {
display: none !important;
}
Expand Down Expand Up @@ -2419,10 +2420,10 @@
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;
padding: 3px 5px 3px 6px !important;
}

.phoenix-image-gallery-upload-container button svg {
Expand Down Expand Up @@ -2502,12 +2503,12 @@
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;
Expand All @@ -2518,8 +2519,6 @@
.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 {
Expand Down Expand Up @@ -2707,7 +2706,7 @@
</div>

<div class='phoenix-image-gallery-upload-container'>
<button title="${config.strings.imageGallerySelectFromComputer}">${ICONS.selectImageFromComputer} ${config.strings.imageGalleryUpload}</button>
<button title="${config.strings.imageGallerySelectFromComputerTooltip}">${ICONS.selectImageFromComputer} ${config.strings.imageGallerySelectFromComputer}</button>
<input type="file" class="phoenix-file-input" accept="image/*" style="display: none !important;">
</div>

Expand Down Expand Up @@ -3822,12 +3821,10 @@
* @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();
dismissToastMessage();
cleanupPreviousElementState();

// this should also be there when users are in highlight mode
Expand All @@ -3850,12 +3847,9 @@
}

// 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);
}
showToastMessage(config.strings.toastNotEditable);
}

// make sure that the element is actually visible to the user
Expand Down Expand Up @@ -4431,15 +4425,7 @@
});

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) {
Expand Down Expand Up @@ -4558,6 +4544,7 @@
dismissAIPromptBox();
dismissNodeInfoBox();
dismissImageRibbonGallery();
dismissToastMessage();
}

let _toastTimeout = null;
Expand All @@ -4567,19 +4554,14 @@
* 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');
toast.id = 'phoenix-toast-notification';
toast.setAttribute("data-phcode-internal-c15r5a9", "true");

Check failure on line 4564 in src/LiveDevelopment/BrowserScripts/RemoteFunctions.js

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Prefer `.dataset` over `setAttribute(…)`.

See more on https://sonarcloud.io/project/issues?id=phcode-dev_phoenix&issues=AZqyMMz1XrFv6bfNgNEF&open=AZqyMMz1XrFv6bfNgNEF&pullRequest=2488
const shadow = toast.attachShadow({ mode: 'open' });

const styles = `
Expand Down Expand Up @@ -4607,27 +4589,6 @@
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;
Expand All @@ -4643,34 +4604,34 @@
const content = `
<div class="toast-container">
<div class="toast-message">${message}</div>
<button class="toast-button">${config.strings.toastDontShowAgain}</button>
</div>
`;

shadow.innerHTML = `<style>${styles}</style>${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);
}

/**
* this function is to dismiss the toast message
* and clear its timeout (if any)
*/
function dismissToastMessage() {
const toastMessage = window.document.getElementById('phoenix-toast-notification');

Check warning on line 4627 in src/LiveDevelopment/BrowserScripts/RemoteFunctions.js

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Prefer `globalThis` over `window`.

See more on https://sonarcloud.io/project/issues?id=phcode-dev_phoenix&issues=AZqwG97RhJMJg08I7hbC&open=AZqwG97RhJMJg08I7hbC&pullRequest=2488
if (toastMessage) {
toastMessage.remove();
}
if (_toastTimeout) {
clearTimeout(_toastTimeout);
}
_toastTimeout = null;
}

/**
Expand Down
41 changes: 41 additions & 0 deletions src/LiveDevelopment/LivePreviewEdit.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@
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");
Expand Down Expand Up @@ -1265,6 +1267,33 @@
_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) {

Check warning on line 1280 in src/LiveDevelopment/LivePreviewEdit.js

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Prefer using an optional chain expression instead, as it's more concise and easier to read.

See more on https://sonarcloud.io/project/issues?id=phcode-dev_phoenix&issues=AZqsvvDi8JCxfjKb_FNQ&open=AZqsvvDi8JCxfjKb_FNQ&pullRequest=2488
const previewedDoc = currLiveDoc.editor.document;
CommandManager.execute(Commands.FILE_SAVE, { doc: previewedDoc });
}
}

/**
* 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() {

Check warning on line 1290 in src/LiveDevelopment/LivePreviewEdit.js

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Move function '_handlePreviewModeToggle' to the outer scope.

See more on https://sonarcloud.io/project/issues?id=phcode-dev_phoenix&issues=AZqs3Y7X1NG8ykCp55xm&open=AZqs3Y7X1NG8ykCp55xm&pullRequest=2488
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
Expand All @@ -1289,6 +1318,18 @@
* 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) {
_handleLivePreviewSave();
return;
}

// toggle live preview mode using F8 key
if (message.toggleLivePreviewMode) {
_handlePreviewModeToggle();
return;
}

// handle reset image folder selection
if (message.resetImageFolderSelection) {
_handleResetImageFolderSelection();
Expand Down
Loading
Loading