Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
6df33d8
fix: background color gets removed from elements when its set inline
devvaannsh Aug 23, 2025
d5d707b
refactor: improved code readability
devvaannsh Aug 24, 2025
4ec6832
fix: dirty marker appears after undo operation
devvaannsh Aug 24, 2025
6e8996a
feat: when element from point fails find the closest target and drop …
devvaannsh Aug 24, 2025
187418f
feat: add play button icon in toolbar
devvaannsh Aug 25, 2025
3f38f98
feat: add preview page button after the reload page button
devvaannsh Aug 26, 2025
ce21ef8
Revert "feat: add preview page button after the reload page button"
devvaannsh Aug 26, 2025
408fa96
feat: add preview mode back to the dropdown
devvaannsh Aug 26, 2025
3a96870
chore: remove redundant '-live preview' text from live preview toolbar
devvaannsh Aug 26, 2025
3f6ca85
feat: show overlay messages in live preview when connecting or any sy…
devvaannsh Aug 27, 2025
9eb05b1
feat: add kernal mode initial check
devvaannsh Aug 28, 2025
ad89b0d
feat: always active edit mode when phoenix opens/reloads
devvaannsh Aug 29, 2025
7c6b481
fix: info box disappearing when elements selection set to click mode
devvaannsh Aug 29, 2025
e569a38
fix: buttons not properly aligned
devvaannsh Aug 29, 2025
70f991e
feat: add close button in live preview overlay so that it can be closed
devvaannsh Aug 29, 2025
d53b1ac
feat: show connecting overlay after a 3s timer so that it doesn't int…
devvaannsh Aug 29, 2025
179a148
fix: don't show overlay message no a no-preview html page
devvaannsh Aug 30, 2025
bba8c46
fix: tests failing as new mode features were added
devvaannsh Aug 31, 2025
726f308
feat: live preview edit mode basic tests to check for boxes presence
devvaannsh Aug 31, 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
420 changes: 206 additions & 214 deletions src/LiveDevelopment/BrowserScripts/RemoteFunctions.js

Large diffs are not rendered by default.

34 changes: 32 additions & 2 deletions src/LiveDevelopment/LivePreviewEdit.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,29 @@
/*
* GNU AGPL-3.0 License
*
* Copyright (c) 2021 - present core.ai . All rights reserved.
* Original work Copyright (c) 2012 - 2021 Adobe Systems Incorporated. All rights reserved.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License
* for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see https://opensource.org/licenses/AGPL-3.0.
*
*/

/*
* This file handles all the editor side source code handling after user performed some live preview edit operation
* when any operation is performed in the browser context (handled inside remoteFunctions.js) it sends a message through
* MessageBroker, now this file then makes the change in the source code
*/
define(function (require, exports, module) {
const HTMLInstrumentation = require("LiveDevelopment/MultiBrowserImpl/language/HTMLInstrumentation");
const LiveDevMultiBrowser = require("LiveDevelopment/LiveDevMultiBrowser");
Expand Down Expand Up @@ -194,8 +220,12 @@ define(function (require, exports, module) {
// this is a quick trick because as the code is changed for that element in the file,
// the live preview for that element gets refreshed and the changes are discarded in the live preview
if(!message.isEditSuccessful) {
editor.replaceRange(text, startPos, endPos);
editor.document._markClean();
editor.document.batchOperation(function () {
editor.replaceRange(text, startPos, endPos);
setTimeout(() => {
editor.undo(); // undo the replaceRange so dirty icon won't appear and no net change in undo history
}, 0);
});
} else {

// if the edit operation was successful, we call a helper function that
Expand Down
149 changes: 142 additions & 7 deletions src/LiveDevelopment/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,16 @@ define(function main(require, exports, module) {
ExtensionUtils = require("utils/ExtensionUtils"),
StringUtils = require("utils/StringUtils"),
EventDispatcher = require("utils/EventDispatcher"),
WorkspaceManager = require("view/WorkspaceManager");
WorkspaceManager = require("view/WorkspaceManager"),
EditorManager = require("editor/EditorManager");


// this is responsible to make the advanced live preview features active or inactive
// @abose (make this variable false when not a paid user, everything rest is handled automatically)
let isLPEditFeaturesActive = false;
// @abose (make the first value true when its a paid user, everything rest is handled automatically)
let isProUser = window.KernalModeTrust ? true : false;
// when isFreeTrialUser is true isProUser should also be true
// when its false, isProUser can be true/false doesn't matter
let isFreeTrialUser = true;

const EVENT_LIVE_HIGHLIGHT_PREF_CHANGED = "liveHighlightPrefChange";

Expand All @@ -64,7 +68,7 @@ define(function main(require, exports, module) {
paddingColor: {r: 147, g: 196, b: 125, a: 0.66},
showInfo: true
},
isLPEditFeaturesActive: isLPEditFeaturesActive,
isProUser: isProUser,
elemHighlights: "hover", // 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
Expand Down Expand Up @@ -269,6 +273,122 @@ define(function main(require, exports, module) {
return false;
}

let $livePreviewPanel = null; // stores the live preview panel, need this as overlay is appended inside this
let $overlayContainer = null; // the overlay container
let shouldShowSyncErrorOverlay = true; // once user closes the overlay we don't show them again
let shouldShowConnectingOverlay = true;
let connectingOverlayTimer = null; // this is needed as we show the connecting overlay after 3s
let connectingOverlayTimeDuration = 3000;

/**
* this function is responsible to check whether to show the overlay or not and how it should be shown
* because if user has closed the overlay manually, we don't show it again
* secondly, for connecting overlay we show that after a 3s timer, but sync error overlay is shown immediately
* @param {String} textMessage - the text that is written inside the overlay
* @param {Number} status - 1 for connect, 4 for sync error but we match it using MultiBrowserLiveDev
*/
function _handleOverlay(textMessage, status) {
if (!$livePreviewPanel) {
$livePreviewPanel = $("#panel-live-preview");
}

// remove any existing overlay & timer
_hideOverlay();

// to not show the overlays if user has already closed it before
if(status === MultiBrowserLiveDev.STATUS_CONNECTING && !shouldShowConnectingOverlay) { return; }
if(status === MultiBrowserLiveDev.STATUS_SYNC_ERROR && !shouldShowSyncErrorOverlay) { return; }

// for connecting status, we delay showing the overlay by 3 seconds
if(status === MultiBrowserLiveDev.STATUS_CONNECTING) {
connectingOverlayTimer = setTimeout(() => {
_createAndShowOverlay(textMessage, status);
connectingOverlayTimer = null;
}, connectingOverlayTimeDuration);
return;
}

// for sync error status, show immediately
_createAndShowOverlay(textMessage, status);
}

/**
* this function is responsible to create & show the overlay.
* so overlay is shown when the live preview is connecting or live preview stopped because of some syntax error
* @param {String} textMessage - the text that is written inside the overlay
* @param {Number} status - 1 for connect, 4 for sync error but we match it using MultiBrowserLiveDev
*/
function _createAndShowOverlay(textMessage, status) {
if (!$livePreviewPanel) {
$livePreviewPanel = $("#panel-live-preview");
}

// create the overlay element
// styled inside the 'src/extensionsIntegrated/Phoenix-live-preview/live-preview.css'
$overlayContainer = $("<div>").addClass("live-preview-status-overlay"); // the wrapper for overlay element
const $message = $("<div>").addClass("live-preview-overlay-message").text(textMessage);

// the close button at the right end of the overlay
const $close = $("<div>").addClass("live-preview-overlay-close")
.attr("title", Strings.LIVE_PREVIEW_HIDE_OVERLAY)
.on('click', () => {
if(status === MultiBrowserLiveDev.STATUS_CONNECTING) {
shouldShowConnectingOverlay = false;
} else if(status === MultiBrowserLiveDev.STATUS_SYNC_ERROR) {
shouldShowSyncErrorOverlay = false;
}
_hideOverlay();
});
const $closeIcon = $("<i>").addClass("fas fa-times");

$close.append($closeIcon);
$overlayContainer.append($message);
$overlayContainer.append($close);
$livePreviewPanel.append($overlayContainer);
}

/**
* responsible to hide the overlay
*/
function _hideOverlay() {
_clearConnectingOverlayTimer();
if ($overlayContainer) {
$overlayContainer.remove();
$overlayContainer = null;
}
}

/**
* This is a helper function that just checks that if connectingOverlayTimer exists, we clear it
*/
function _clearConnectingOverlayTimer() {
if (connectingOverlayTimer) {
clearTimeout(connectingOverlayTimer);
connectingOverlayTimer = null;
}
}

/**
* this function adds/remove the full-width class from the overlay container
* styled inside 'src/extensionsIntegrated/Phoenix-live-preview/live-preview.css'
*
* we need this because
* normally when live preview has a good width (more than 305px) then a 3px divider is shown at the left end
* so in that case we give the overlay a width of (100% - 3px),
* but when the live preview width is reduced
* then that divider line gets cut off, so in that case we make the width 100% for this overlay
*
* without this handling, a white gap appears on the left side, which is distracting
*/
function _setOverlayWidth() {
if(!$overlayContainer || !$livePreviewPanel.length) { return; }
if($livePreviewPanel.width() <= 305) {
$overlayContainer.addClass("full-width");
} else {
$overlayContainer.removeClass("full-width");
}
}

/** Initialize LiveDevelopment */
AppInit.appReady(function () {
params.parse();
Expand Down Expand Up @@ -323,6 +443,19 @@ define(function main(require, exports, module) {
exports.trigger(exports.EVENT_LIVE_PREVIEW_RELOAD, clientDetails);
});

MultiBrowserLiveDev.on(MultiBrowserLiveDev.EVENT_STATUS_CHANGE, function(event, status) {
if (status === MultiBrowserLiveDev.STATUS_CONNECTING) {
_handleOverlay(Strings.LIVE_DEV_STATUS_TIP_PROGRESS1, status);
} else if (status === MultiBrowserLiveDev.STATUS_SYNC_ERROR) {
_handleOverlay(Strings.LIVE_DEV_STATUS_TIP_SYNC_ERROR, status);
} else {
_hideOverlay();
}
});
// to understand why we need this, pls read the _setOverlayWidth function
new ResizeObserver(_setOverlayWidth).observe($("#main-plugin-panel")[0]);
EditorManager.on("activeEditorChange", _hideOverlay);

// allow live preview to handle escape key event
// Escape is mainly to hide boxes if they are visible
WorkspaceManager.addEscapeKeyEventHandler("livePreview", _handleLivePreviewEscapeKey);
Expand All @@ -341,8 +474,9 @@ define(function main(require, exports, module) {
config.highlight = PreferencesManager.getViewState("livedevHighlight");

function setLivePreviewEditFeaturesActive(enabled) {
isLPEditFeaturesActive = enabled;
config.isLPEditFeaturesActive = enabled;
// TODO: @abose here add kernal mode trust check
isProUser = enabled;
config.isProUser = enabled;
if (MultiBrowserLiveDev && MultiBrowserLiveDev.status >= MultiBrowserLiveDev.STATUS_ACTIVE) {
MultiBrowserLiveDev.updateConfig(JSON.stringify(config));
MultiBrowserLiveDev.registerHandlers();
Expand All @@ -368,7 +502,8 @@ define(function main(require, exports, module) {

EventDispatcher.makeEventDispatcher(exports);

exports.isLPEditFeaturesActive = isLPEditFeaturesActive;
exports.isProUser = isProUser;
exports.isFreeTrialUser = isFreeTrialUser;

// public events
exports.EVENT_OPEN_PREVIEW_URL = MultiBrowserLiveDev.EVENT_OPEN_PREVIEW_URL;
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
64 changes: 59 additions & 5 deletions src/extensionsIntegrated/Phoenix-live-preview/live-preview.css
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@

#panel-live-preview-frame{
background-color: white;
position: relative;
}

#panel-live-preview-frame[src*="no-preview.html"],
#panel-live-preview-frame[src*="live-preview-error.html"] {
z-index: 200;
}

#panel-live-preview-title {
Expand Down Expand Up @@ -54,15 +60,19 @@
}

.open-icon {
background: url("./images/sprites.svg#open-icon") center no-repeat;
background: url("./images/sprites.svg#open-icon") no-repeat 72.5%;
width: 30px;
margin-left: 4px;
}

.pin-icon {
background: url("./images/sprites.svg#pinned-icon") center no-repeat;
background: url("./images/sprites.svg#pinned-icon") no-repeat 72.5%;
width: 30px;
}

.unpin-icon {
background: url("./images/sprites.svg#unpinned-icon") center no-repeat;
background: url("./images/sprites.svg#unpinned-icon") no-repeat 72.5%;
width: 30px;
}

.reload-icon {
Expand All @@ -76,6 +86,7 @@
opacity: 1;
visibility: visible;
transition: unset;
padding-left: 7.5px;
}

.live-preview-settings input.error, .live-preview-settings input:focus.error{
Expand All @@ -91,13 +102,14 @@
align-items: center;
visibility: hidden;
transition: opacity 1s, visibility 0s linear 1s; /* Fade-out effect */
padding-left: 7.5px;
}

#livePreviewModeBtn {
min-width: fit-content;
display: flex;
align-items: center;
margin-right: 4px;
margin: 3px 4px 0 3px;
max-width: 80%;
text-overflow: ellipsis;
overflow: hidden;
Expand Down Expand Up @@ -127,7 +139,49 @@
#reloadLivePreviewButton {
margin-left: 3px;
margin-top: 3.5px;
width: 22px;
width: 30px;
height: 22px;
flex-shrink: 0;
}

#previewModeLivePreviewButton {
color: #a0a0a0;
margin-left: 3px;
margin-top: 3.3px;
width: 30px;
height: 22px;
flex-shrink: 0;
}

#previewModeLivePreviewButton.selected{
color: #FBB03B;
}

.live-preview-status-overlay {
width: calc(100% - 3px);
position: absolute;
top: 30px;
left: 3px;
z-index: 100;
}

.live-preview-status-overlay.full-width {
width: 100%;
left: 0;
}

.live-preview-overlay-message {
width: 100%;
color: #fff;
background-color: #666;
padding: 0.2em;
vertical-align: top;
text-align: center;
}

.live-preview-overlay-close {
position: absolute;
top: 4px;
right: 10px;
font-size: 12px;
}
Loading
Loading