Skip to content

Commit 9349aac

Browse files
committed
deploy: 606b7d0
1 parent 4f0469d commit 9349aac

File tree

85 files changed

+852
-792
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

85 files changed

+852
-792
lines changed

LiveDevelopment/BrowserScripts/LiveDevProtocolRemote.js

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -455,6 +455,37 @@
455455
redoLivePreviewOperation: true
456456
});
457457
}
458+
459+
// for save
460+
if ((e.ctrlKey || e.metaKey) && e.key.toLowerCase() === "s") {
461+
e.preventDefault();
462+
463+
// to check if user was in between editing text
464+
// in such cases we first finish the editing and then save
465+
const activeElement = document.activeElement;
466+
if (activeElement &&
467+
activeElement.hasAttribute("contenteditable") &&
468+
activeElement.hasAttribute("data-brackets-id") &&
469+
window._LD &&
470+
window._LD.finishEditing) {
471+
472+
window._LD.finishEditing(activeElement);
473+
}
474+
475+
MessageBroker.send({
476+
livePreviewEditEnabled: true,
477+
saveCurrentDocument: true
478+
});
479+
}
480+
481+
// for preview button (play icon) toggle
482+
if (e.key === 'F8') {
483+
e.preventDefault();
484+
MessageBroker.send({
485+
livePreviewEditEnabled: true,
486+
toggleLivePreviewMode: true
487+
});
488+
}
458489
});
459490

460491
}(this));

LiveDevelopment/BrowserScripts/RemoteFunctions.js

Lines changed: 41 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,6 @@ function RemoteFunctions(config = {}) {
3333
// we need this so that we can remove click styling from the previous element when a new element is clicked
3434
let previouslyClickedElement = null;
3535

36-
// this is needed so that when user starts typing we can dismiss all the boxes and highlights
37-
// now with this variable we check if its a first keystroke on an element or a subsequent keystroke
38-
let _uiHiddenDuringTyping = false;
39-
4036
var req, timeout;
4137
var animateHighlight = function (time) {
4238
if(req) {
@@ -133,6 +129,7 @@ function RemoteFunctions(config = {}) {
133129
if(element && // element should exist
134130
element.tagName.toLowerCase() !== "body" && // shouldn't be the body tag
135131
element.tagName.toLowerCase() !== "html" && // shouldn't be the HTML tag
132+
!element.closest("[data-phcode-internal-c15r5a9]") && // this attribute is used by phoenix internal elements
136133
!_isInsideHeadTag(element)) { // shouldn't be inside the head tag like meta tags and all
137134
return true;
138135
}
@@ -1368,10 +1365,10 @@ function RemoteFunctions(config = {}) {
13681365
`,
13691366

13701367
selectImageFromComputer: `
1371-
<svg viewBox="0 0 24 24" fill="currentColor" width="19" height="19">
1372-
<path d="M9 16h6v-6h4l-7-7-7 7h4zm-4 2h14v2H5z"/>
1373-
</svg>
1374-
`,
1368+
<svg viewBox="0 0 24 24" fill="currentColor" width="19" height="19">
1369+
<path d="M11 5v6H5v2h6v6h2v-6h6v-2h-6V5h-2z"/>
1370+
</svg>
1371+
`,
13751372

13761373
downloadImage: `
13771374
<svg viewBox="0 0 640 640" fill="currentColor">
@@ -1465,6 +1462,7 @@ function RemoteFunctions(config = {}) {
14651462

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

14691467
// this is shadow DOM.
14701468
// we need it because if we add the box directly to the DOM then users style might override it.
@@ -1744,6 +1742,7 @@ function RemoteFunctions(config = {}) {
17441742

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

17481747
// this is shadow DOM.
17491748
// we need it because if we add the box directly to the DOM then users style might override it.
@@ -1928,6 +1927,7 @@ function RemoteFunctions(config = {}) {
19281927

19291928
_style: function() {
19301929
this.body = window.document.createElement("div");
1930+
this.body.setAttribute("data-phcode-internal-c15r5a9", "true");
19311931
// using shadow dom so that user styles doesn't override it
19321932
const shadow = this.body.attachShadow({ mode: "open" });
19331933

@@ -2297,7 +2297,8 @@ function RemoteFunctions(config = {}) {
22972297
ImageRibbonGallery.prototype = {
22982298
_style: function () {
22992299
this.body = window.document.createElement("div");
2300-
this._shadow = this.body.attachShadow({mode: 'closed'});
2300+
this.body.setAttribute("data-phcode-internal-c15r5a9", "true");
2301+
this._shadow = this.body.attachShadow({ mode: 'open' });
23012302

23022303
this._shadow.innerHTML = `
23032304
<style>
@@ -2333,7 +2334,7 @@ function RemoteFunctions(config = {}) {
23332334
margin-right: 10px !important;
23342335
}
23352336
2336-
@media (max-width: 525px) {
2337+
@media (max-width: 565px) {
23372338
.phoenix-image-gallery-header-title {
23382339
display: none !important;
23392340
}
@@ -2419,10 +2420,10 @@ function RemoteFunctions(config = {}) {
24192420
background: #3c3f41 !important;
24202421
}
24212422
2422-
@media (max-width: 400px) {
2423+
@media (max-width: 450px) {
24232424
.phoenix-image-gallery-upload-container button {
24242425
font-size: 0 !important;
2425-
padding: 3px 6px !important;
2426+
padding: 3px 5px 3px 6px !important;
24262427
}
24272428
24282429
.phoenix-image-gallery-upload-container button svg {
@@ -2502,12 +2503,12 @@ function RemoteFunctions(config = {}) {
25022503
color: #eaeaf0 !important;
25032504
background: rgba(21,25,36,0.65) !important;
25042505
cursor: pointer !important;
2505-
font-size: 20px !important;
2506+
font-size: 22px !important;
25062507
font-weight: 600 !important;
25072508
user-select: none !important;
25082509
transition: all 0.2s ease !important;
25092510
z-index: 2147483647 !important;
2510-
padding: 4px 12px 8px 12px !important;
2511+
padding: 2px 11px 7px 11px !important;
25112512
display: none !important;
25122513
align-items: center !important;
25132514
justify-content: center !important;
@@ -2518,8 +2519,6 @@ function RemoteFunctions(config = {}) {
25182519
.phoenix-image-gallery-nav:hover {
25192520
background: rgba(21,25,36,0.85) !important;
25202521
border-color: rgba(255,255,255,0.25) !important;
2521-
transform: scale(1.05) !important;
2522-
box-shadow: 0 4px 12px rgba(0,0,0,0.3) !important;
25232522
}
25242523
25252524
.phoenix-image-gallery-nav:active {
@@ -2707,7 +2706,7 @@ function RemoteFunctions(config = {}) {
27072706
</div>
27082707
27092708
<div class='phoenix-image-gallery-upload-container'>
2710-
<button title="${config.strings.imageGallerySelectFromComputer}">${ICONS.selectImageFromComputer} ${config.strings.imageGalleryUpload}</button>
2709+
<button title="${config.strings.imageGallerySelectFromComputerTooltip}">${ICONS.selectImageFromComputer} ${config.strings.imageGallerySelectFromComputer}</button>
27112710
<input type="file" class="phoenix-file-input" accept="image/*" style="display: none !important;">
27122711
</div>
27132712
@@ -3822,12 +3821,10 @@ function RemoteFunctions(config = {}) {
38223821
* @param {Element} element - The DOM element to select
38233822
*/
38243823
function _selectElement(element) {
3825-
// user selected a new element, we need to reset this variable
3826-
_uiHiddenDuringTyping = false;
3827-
38283824
dismissNodeMoreOptionsBox();
38293825
dismissAIPromptBox();
38303826
dismissNodeInfoBox();
3827+
dismissToastMessage();
38313828
cleanupPreviousElementState();
38323829

38333830
// this should also be there when users are in highlight mode
@@ -3850,12 +3847,9 @@ function RemoteFunctions(config = {}) {
38503847
}
38513848

38523849
// if element is not editable and user clicks on it, then we show a toast notification saying
3853-
// that this element is not editable (unless user dismissed it permanently)
3850+
// that this element is not editable
38543851
if (!element.hasAttribute("data-brackets-id")) {
3855-
const hideToast = localStorage.getItem('phoenix-hide-dynamic-toast');
3856-
if (!hideToast) {
3857-
showToast(config.strings.toastNotEditable);
3858-
}
3852+
showToastMessage(config.strings.toastNotEditable);
38593853
}
38603854

38613855
// make sure that the element is actually visible to the user
@@ -4431,15 +4425,7 @@ function RemoteFunctions(config = {}) {
44314425
});
44324426

44334427
this.rememberedNodes = {};
4434-
4435-
// when user starts typing in the editor we hide all the boxes and highlights
4436-
// _uiHiddenDuringTyping variable keeps track if its a first keystroke or subsequent
4437-
// so that we don't end up calling dismiss/hide kinda functions multiple times
4438-
if (!_uiHiddenDuringTyping) {
4439-
dismissUIAndCleanupState();
4440-
hideHighlight();
4441-
_uiHiddenDuringTyping = true;
4442-
}
4428+
redrawEverything();
44434429
};
44444430

44454431
function applyDOMEdits(edits) {
@@ -4558,6 +4544,7 @@ function RemoteFunctions(config = {}) {
45584544
dismissAIPromptBox();
45594545
dismissNodeInfoBox();
45604546
dismissImageRibbonGallery();
4547+
dismissToastMessage();
45614548
}
45624549

45634550
let _toastTimeout = null;
@@ -4567,19 +4554,14 @@ function RemoteFunctions(config = {}) {
45674554
* this toast message is used when user tries to edit a non-editable element
45684555
* @param {String} message - the message to display in the toast
45694556
*/
4570-
function showToast(message) {
4557+
function showToastMessage(message) {
45714558
// clear any existing toast & timer, if there are any
4572-
const existingToast = window.document.getElementById('phoenix-toast-notification');
4573-
if (existingToast) {
4574-
existingToast.remove();
4575-
}
4576-
if (_toastTimeout) {
4577-
clearTimeout(_toastTimeout);
4578-
}
4559+
dismissToastMessage();
45794560

45804561
// create a new fresh toast container
45814562
const toast = window.document.createElement('div');
45824563
toast.id = 'phoenix-toast-notification';
4564+
toast.setAttribute("data-phcode-internal-c15r5a9", "true");
45834565
const shadow = toast.attachShadow({ mode: 'open' });
45844566

45854567
const styles = `
@@ -4607,27 +4589,6 @@ function RemoteFunctions(config = {}) {
46074589
animation: slideUp 0.3s ease-out !important;
46084590
}
46094591
4610-
.toast-message {
4611-
margin-bottom: 6px !important;
4612-
}
4613-
4614-
.toast-button {
4615-
background: none !important;
4616-
border: none !important;
4617-
color: #A0A0A0 !important;
4618-
cursor: pointer !important;
4619-
font-size: 12px !important;
4620-
font-family: Arial, sans-serif !important;
4621-
text-decoration: none !important;
4622-
pointer-events: auto !important;
4623-
transition: opacity 0.2s !important;
4624-
}
4625-
4626-
.toast-button:hover {
4627-
opacity: 0.8 !important;
4628-
text-decoration: underline !important;
4629-
}
4630-
46314592
@keyframes slideUp {
46324593
from {
46334594
opacity: 0;
@@ -4643,34 +4604,34 @@ function RemoteFunctions(config = {}) {
46434604
const content = `
46444605
<div class="toast-container">
46454606
<div class="toast-message">${message}</div>
4646-
<button class="toast-button">${config.strings.toastDontShowAgain}</button>
46474607
</div>
46484608
`;
46494609

46504610
shadow.innerHTML = `<style>${styles}</style>${content}`;
46514611
window.document.body.appendChild(toast);
46524612

4653-
// add click handler to "Don't show again" button
4654-
const button = shadow.querySelector('.toast-button');
4655-
button.addEventListener('click', () => {
4656-
// save to localStorage to never show again and close toast rn
4657-
localStorage.setItem('phoenix-hide-dynamic-toast', 'true');
4658-
if (toast && toast.parentNode) {
4659-
toast.remove();
4660-
}
4661-
if (_toastTimeout) {
4662-
clearTimeout(_toastTimeout);
4663-
_toastTimeout = null;
4664-
}
4665-
});
4666-
4667-
// Auto-dismiss after 6 seconds
4613+
// Auto-dismiss after 3 seconds
46684614
_toastTimeout = setTimeout(() => {
46694615
if (toast && toast.parentNode) {
46704616
toast.remove();
46714617
}
46724618
_toastTimeout = null;
4673-
}, 6000);
4619+
}, 3000);
4620+
}
4621+
4622+
/**
4623+
* this function is to dismiss the toast message
4624+
* and clear its timeout (if any)
4625+
*/
4626+
function dismissToastMessage() {
4627+
const toastMessage = window.document.getElementById('phoenix-toast-notification');
4628+
if (toastMessage) {
4629+
toastMessage.remove();
4630+
}
4631+
if (_toastTimeout) {
4632+
clearTimeout(_toastTimeout);
4633+
}
4634+
_toastTimeout = null;
46744635
}
46754636

46764637
/**

LiveDevelopment/LivePreviewEdit.js

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ define(function (require, exports, module) {
3030
const LiveDevelopment = require("LiveDevelopment/main");
3131
const CodeMirror = require("thirdparty/CodeMirror/lib/codemirror");
3232
const ProjectManager = require("project/ProjectManager");
33+
const CommandManager = require("command/CommandManager");
34+
const Commands = require("command/Commands");
3335
const FileSystem = require("filesystem/FileSystem");
3436
const PathUtils = require("thirdparty/path-utils/path-utils");
3537
const StringMatch = require("utils/StringMatch");
@@ -1265,6 +1267,33 @@ define(function (require, exports, module) {
12651267
_showFolderSelectionDialog(null);
12661268
}
12671269

1270+
/**
1271+
* this function is responsible to save the active file (and previewed file, both might be same though)
1272+
* when ctrl/cmd + s is pressed in the live preview
1273+
*/
1274+
function _handleLivePreviewSave() {
1275+
// this saves the active file
1276+
CommandManager.execute(Commands.FILE_SAVE);
1277+
1278+
// we also save the previewed file, (active file might be same as previewed or different)
1279+
const currLiveDoc = LiveDevMultiBrowser.getCurrentLiveDoc();
1280+
if (currLiveDoc && currLiveDoc.editor) {
1281+
const previewedDoc = currLiveDoc.editor.document;
1282+
CommandManager.execute(Commands.FILE_SAVE, { doc: previewedDoc });
1283+
}
1284+
}
1285+
1286+
/**
1287+
* This function is responsible to toggle the live preview Preview mode (play icon)
1288+
* this is done when user presses F8 key in the live preview
1289+
*/
1290+
function _handlePreviewModeToggle() {
1291+
const $previewBtn = $("#previewModeLivePreviewButton");
1292+
if ($previewBtn.length > 0) {
1293+
$previewBtn.trigger("click");
1294+
}
1295+
}
1296+
12681297
/**
12691298
* This is the main function that is exported.
12701299
* it will be called by LiveDevProtocol when it receives a message from RemoteFunctions.js
@@ -1289,6 +1318,18 @@ define(function (require, exports, module) {
12891318
* these are the main properties that are passed through the message
12901319
*/
12911320
function handleLivePreviewEditOperation(message) {
1321+
// handle save current document in live preview (ctrl/cmd + s)
1322+
if (message.saveCurrentDocument) {
1323+
_handleLivePreviewSave();
1324+
return;
1325+
}
1326+
1327+
// toggle live preview mode using F8 key
1328+
if (message.toggleLivePreviewMode) {
1329+
_handlePreviewModeToggle();
1330+
return;
1331+
}
1332+
12921333
// handle reset image folder selection
12931334
if (message.resetImageFolderSelection) {
12941335
_handleResetImageFolderSelection();

0 commit comments

Comments
 (0)