Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
33 changes: 20 additions & 13 deletions src/LiveDevelopment/BrowserScripts/RemoteFunctions.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ function RemoteFunctions(config = {}) {
// 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 @@ -1577,10 +1581,6 @@ function RemoteFunctions(config = {}) {
create: function() {
this.remove(); // remove existing box if already present

if(!config.isProUser) {
return;
}

// this check because when there is no element visible to the user, we don't want to show the box
// for ex: when user clicks on a 'x' button and the button is responsible to hide a panel
// then clicking on that button shouldn't show the more options box
Expand Down Expand Up @@ -3822,6 +3822,9 @@ function RemoteFunctions(config = {}) {
* @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();
Expand Down Expand Up @@ -3931,12 +3934,7 @@ function RemoteFunctions(config = {}) {
event.stopPropagation();
event.stopImmediatePropagation();

// when in click mode, only select dynamic elements (without data-brackets-id) directly
// as for static elements, the editor will handle selection via highlight message
if (!shouldShowHighlightOnHover() && !element.hasAttribute("data-brackets-id")) {
_selectElement(element);
}

_selectElement(element);
activateHoverLock();
}
}
Expand Down Expand Up @@ -4021,7 +4019,10 @@ function RemoteFunctions(config = {}) {
var foundValidElement = false;
for (i = 0; i < nodes.length; i++) {
if(isElementInspectable(nodes[i], true) && nodes[i].tagName !== "BR") {
_selectElement(nodes[i]);
// only call _selectElement if it's a different element to avoid unnecessary box recreation
if (previouslyClickedElement !== nodes[i]) {
_selectElement(nodes[i]);
}
foundValidElement = true;
break;
}
Expand Down Expand Up @@ -4431,8 +4432,14 @@ function RemoteFunctions(config = {}) {

this.rememberedNodes = {};

// update highlight after applying diffs
redrawEverything();
// 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;
}
};

function applyDOMEdits(edits) {
Expand Down
91 changes: 85 additions & 6 deletions src/LiveDevelopment/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,14 +48,14 @@
EditorManager = require("editor/EditorManager");


// this is responsible to make the advanced live preview features active or inactive
// @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 KernalModeTrust = window.KernalModeTrust;

Check warning on line 51 in src/LiveDevelopment/main.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=AZqmMBe9pU-08slyxQlU&open=AZqmMBe9pU-08slyxQlU&pullRequest=2487

// this will later be assigned its correct values once entitlementsManager loads
let isProUser = false;
let isFreeTrialUser = false;

const EVENT_LIVE_HIGHLIGHT_PREF_CHANGED = "liveHighlightPrefChange";
const PREFERENCE_LIVE_PREVIEW_MODE = "livePreviewMode";

// state manager key to track image gallery selected state, by default we keep this as selected
// if this is true we show the image gallery when an image element is clicked
Expand Down Expand Up @@ -316,6 +316,69 @@
return false;
}

// default mode means on first load for pro user we have edit mode
// for free user we have highlight mode
function _getDefaultMode() {
return isProUser ? "edit" : "highlight";
}

// to set that mode in the preferences
function _initializeMode() {
if (isFreeTrialUser) {
PreferencesManager.set(PREFERENCE_LIVE_PREVIEW_MODE, "edit");
return;
}

const savedMode = PreferencesManager.get(PREFERENCE_LIVE_PREVIEW_MODE) || _getDefaultMode();

if (savedMode === "highlight" && isProUser) {
PreferencesManager.set(PREFERENCE_LIVE_PREVIEW_MODE, "edit");
} else if (savedMode === "edit" && !isProUser) {
PreferencesManager.set(PREFERENCE_LIVE_PREVIEW_MODE, "highlight");
}
}

// this is called everytime there is a change in entitlements
async function _updateProUserStatus() {
if (!KernalModeTrust) {
return;
}

try {
const entitlement = await KernalModeTrust.EntitlementsManager.getLiveEditEntitlement();

isProUser = entitlement.activated;
isFreeTrialUser = await KernalModeTrust.EntitlementsManager.isInProTrial();

config.isProUser = isProUser;
exports.isProUser = isProUser;
exports.isFreeTrialUser = isFreeTrialUser;

_initializeMode();

if (MultiBrowserLiveDev.status >= MultiBrowserLiveDev.STATUS_ACTIVE) {
MultiBrowserLiveDev.updateConfig(JSON.stringify(config));
MultiBrowserLiveDev.registerHandlers();
}
} catch (error) {
console.error("Error updating pro user status:", error);
isProUser = false;
isFreeTrialUser = false;
}
}

function setMode(mode) {
if (mode === "edit" && !exports.isProUser) {
return false;
}
PreferencesManager.set(PREFERENCE_LIVE_PREVIEW_MODE, mode);
return true;
}

function getCurrentMode() {
return PreferencesManager.get(PREFERENCE_LIVE_PREVIEW_MODE) || _getDefaultMode();
}

/** Initialize LiveDevelopment */
AppInit.appReady(function () {
params.parse();
Expand All @@ -330,6 +393,15 @@
_loadStyles();
_updateHighlightCheckmark();

// init pro user status and listen for changes
if (KernalModeTrust) {
_updateProUserStatus();
KernalModeTrust.EntitlementsManager.on(
KernalModeTrust.EntitlementsManager.EVENT_ENTITLEMENTS_CHANGED,
_updateProUserStatus
);
}

// update styles for UI status
_status = [
{ tooltip: Strings.LIVE_DEV_STATUS_TIP_NOT_CONNECTED, style: "warning" },
Expand Down Expand Up @@ -385,6 +457,11 @@
}
});

PreferencesManager.definePreference(PREFERENCE_LIVE_PREVIEW_MODE, "string", _getDefaultMode(), {
description: StringUtils.format(Strings.LIVE_PREVIEW_MODE_PREFERENCE, "'preview'", "'highlight'", "'edit'"),
values: ["preview", "highlight", "edit"]
});

config.highlight = PreferencesManager.getViewState("livedevHighlight");

function setLivePreviewEditFeaturesActive(enabled) {
Expand Down Expand Up @@ -441,4 +518,6 @@
exports.getLivePreviewDetails = MultiBrowserLiveDev.getLivePreviewDetails;
exports.hideHighlight = MultiBrowserLiveDev.hideHighlight;
exports.dismissLivePreviewBoxes = MultiBrowserLiveDev.dismissLivePreviewBoxes;
exports.setMode = setMode;
exports.getCurrentMode = getCurrentMode;
});
96 changes: 13 additions & 83 deletions src/extensionsIntegrated/Phoenix-live-preview/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,25 +87,9 @@
const PREVIEW_TRUSTED_PROJECT_KEY = "preview_trusted";
const PREVIEW_PROJECT_README_KEY = "preview_readme";

// live preview mode pref
const PREFERENCE_LIVE_PREVIEW_MODE = "livePreviewMode";

// holds the dropdown instance
let $dropdown = null;

/**
* Get the appropriate default mode based on whether edit features are active
* @returns {string} "highlight" if edit features inactive, "edit" if active
*/
function _getDefaultMode() {
return LiveDevelopment.isProUser ? "edit" : "highlight";
}

// define the live preview mode preference
PreferencesManager.definePreference(PREFERENCE_LIVE_PREVIEW_MODE, "string", _getDefaultMode(), {
description: StringUtils.format(Strings.LIVE_PREVIEW_MODE_PREFERENCE, "'preview'", "'highlight'", "'edit'"),
values: ["preview", "highlight", "edit"]
});
const PREFERENCE_LIVE_PREVIEW_MODE = "livePreviewMode";

// live preview element highlights preference (whether on hover or click)
const PREFERENCE_PROJECT_ELEMENT_HIGHLIGHT = "livePreviewElementHighlights";
Expand Down Expand Up @@ -372,43 +356,21 @@
}
}

/**
* init live preview mode from saved preferences
*/
function _initializeMode() {
// when user is on free trial we just push the edit mode to them every time they open/reload Phoenix
if(LiveDevelopment.isFreeTrialUser) {
PreferencesManager.set(PREFERENCE_LIVE_PREVIEW_MODE, "edit");
_LPEditMode();
$previewBtn.removeClass('selected');
_updateModeButton("edit");
return;
}

const savedMode = PreferencesManager.get(PREFERENCE_LIVE_PREVIEW_MODE) || _getDefaultMode();
const isEditFeaturesActive = LiveDevelopment.isProUser;
const currentMode = LiveDevelopment.getCurrentMode();

// If user has edit mode saved but edit features are not active, default to highlight
let effectiveMode = savedMode;
if (savedMode === "edit" && !isEditFeaturesActive) {
effectiveMode = "highlight";
// Update the preference to reflect the actual mode being used
PreferencesManager.set(PREFERENCE_LIVE_PREVIEW_MODE, "highlight");
}

// apply the effective mode
if (effectiveMode === "highlight") {
if (currentMode === "highlight") {
_LPHighlightMode();
$previewBtn.removeClass('selected');
} else if (effectiveMode === "edit" && isEditFeaturesActive) {
} else if (currentMode === "edit") {
_LPEditMode();
$previewBtn.removeClass('selected');
} else {
_LPPreviewMode();
$previewBtn.addClass('selected');
}

_updateModeButton(effectiveMode);
_updateModeButton(currentMode);
}

function _showModeSelectionDropdown(event) {
Expand All @@ -425,9 +387,7 @@
items.push(Strings.LIVE_PREVIEW_EDIT_HIGHLIGHT_ON);
}

const rawMode = PreferencesManager.get(PREFERENCE_LIVE_PREVIEW_MODE) || _getDefaultMode();
// this is to take care of invalid values in the pref file
const currentMode = ["preview", "highlight", "edit"].includes(rawMode) ? rawMode : _getDefaultMode();
const currentMode = LiveDevelopment.getCurrentMode();

$dropdown = new DropdownButton.DropdownButton("", items, function(item, index) {
if (item === Strings.LIVE_PREVIEW_MODE_PREVIEW) {
Expand Down Expand Up @@ -472,28 +432,22 @@

// handle the option selection
$dropdown.on("select", function (e, item, index) {
// here we just set the preference
// as the preferences listener will automatically handle the required changes
if (index === 0) {
PreferencesManager.set(PREFERENCE_LIVE_PREVIEW_MODE, "preview");
LiveDevelopment.setMode("preview");
} else if (index === 1) {
PreferencesManager.set(PREFERENCE_LIVE_PREVIEW_MODE, "highlight");
LiveDevelopment.setMode("highlight");
} else if (index === 2) {
if (!isEditFeaturesActive) {
// when the feature is not active we need to show a dialog to the user asking
// them to subscribe to pro
if (!LiveDevelopment.setMode("edit")) {
_showProFeatureDialog();
} else {
PreferencesManager.set(PREFERENCE_LIVE_PREVIEW_MODE, "edit");
}
} else if (item === Strings.LIVE_PREVIEW_EDIT_HIGHLIGHT_ON) {
// Don't allow edit highlight toggle if edit features are not active
if (!isEditFeaturesActive) {
return;
}
// Toggle between hover and click
const currentMode = PreferencesManager.get(PREFERENCE_PROJECT_ELEMENT_HIGHLIGHT);
const newMode = currentMode !== "click" ? "click" : "hover";
const currMode = PreferencesManager.get(PREFERENCE_PROJECT_ELEMENT_HIGHLIGHT);
const newMode = currMode !== "click" ? "click" : "hover";

Check warning on line 450 in src/extensionsIntegrated/Phoenix-live-preview/main.js

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Unexpected negated condition.

See more on https://sonarcloud.io/project/issues?id=phcode-dev_phoenix&issues=AZqmMBaXpU-08slyxQlT&open=AZqmMBaXpU-08slyxQlT&pullRequest=2487
PreferencesManager.set(PREFERENCE_PROJECT_ELEMENT_HIGHLIGHT, newMode);
return; // Don't dismiss highlights for this option
}
Expand Down Expand Up @@ -1268,32 +1222,8 @@
// init live preview mode from saved preferences
_initializeMode();
// listen for pref changes
PreferencesManager.on("change", PREFERENCE_LIVE_PREVIEW_MODE, function () {
// Get the current preference value directly
const newMode = PreferencesManager.get(PREFERENCE_LIVE_PREVIEW_MODE);
const isEditFeaturesActive = LiveDevelopment.isProUser;

// If user tries to set edit mode but edit features are not active, default to highlight
let effectiveMode = newMode;
if (newMode === "edit" && !isEditFeaturesActive) {
effectiveMode = "highlight";
// Update the preference to reflect the actual mode being used
PreferencesManager.set(PREFERENCE_LIVE_PREVIEW_MODE, "highlight");
return; // Return to avoid infinite loop
}

if (effectiveMode === "highlight") {
_LPHighlightMode();
$previewBtn.removeClass('selected');
} else if (effectiveMode === "edit" && isEditFeaturesActive) {
_LPEditMode();
$previewBtn.removeClass('selected');
} else {
_LPPreviewMode();
$previewBtn.addClass('selected');
}

_updateModeButton(effectiveMode);
PreferencesManager.on("change", "livePreviewMode", function () {
_initializeMode();
});

// Handle element highlight preference changes from this extension
Expand Down
Loading