Skip to content
11 changes: 8 additions & 3 deletions src/LiveDevelopment/BrowserScripts/RemoteFunctions.js
Original file line number Diff line number Diff line change
Expand Up @@ -357,6 +357,7 @@ function RemoteFunctions(config = {}) {
// Container div — sized to the margin box so all rects fit inside it
const div = window.document.createElement("div");
div.className = GLOBALS.HIGHLIGHT_CLASSNAME;
div.setAttribute(GLOBALS.PHCODE_INTERNAL_ATTR, "true");
div.trackingElement = element;
const divStyle = div.style;
divStyle.position = "absolute";
Expand Down Expand Up @@ -1218,8 +1219,12 @@ function RemoteFunctions(config = {}) {
SHARED_STATE._hotCorner.updateState(config.mode === 'preview', true);
}

// Clear highlights when sync is turned off
const syncTurnedOff = oldConfig.syncSourceAndPreview !== false &&
config.syncSourceAndPreview === false;

// Handle configuration changes
if (highlightModeChanged || isModeChanged) {
if (highlightModeChanged || isModeChanged || syncTurnedOff) {
_handleConfigurationChange();
}

Expand All @@ -1228,8 +1233,8 @@ function RemoteFunctions(config = {}) {
// doesn't clear the element highlighting.
const selectedBeforeReregister = previouslySelectedElement;
registerHandlers();
if (!isModeChanged && !highlightModeChanged && selectedBeforeReregister
&& config.mode === 'edit') {
if (!isModeChanged && !highlightModeChanged && !syncTurnedOff
&& selectedBeforeReregister && config.mode === 'edit') {
// Restore the click highlight for the previously selected element
if (!_clickHighlight) {
_clickHighlight = new Highlight(true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,8 @@ define(function (require, exports, module) {
const SUPPORTED_FRAMEWORKS = {};
SUPPORTED_FRAMEWORKS[FRAMEWORK_DOCUSAURUS] = {configFile: "docusaurus.config.js", hotReloadSupported: true};

const PREFERENCE_SHOW_LIVE_PREVIEW_PANEL = "livePreviewShowAtStartup",
const PREFERENCE_LINK_EDITOR_AND_PREVIEW = "livePreviewSyncSourceAndPreview",
PREFERENCE_SHOW_LIVE_PREVIEW_PANEL = "livePreviewShowAtStartup",
PREFERENCE_PROJECT_SERVER_ENABLED = "livePreviewUseDevServer",
PREFERENCE_PROJECT_SERVER_URL = "livePreviewServerURL",
PREFERENCE_PROJECT_SERVER_PATH = "livePreviewServerProjectPath",
Expand Down Expand Up @@ -122,7 +123,9 @@ define(function (require, exports, module) {
{"settings": currentSettings, "Strings": Strings}));

// Select the correct theme.
const $livePreviewServerURL = $template.find("#livePreviewServerURL"),
const $linkEditorAndPreviewChk = $template.find("#linkEditorAndPreviewChk"),
$linkEditorAndPreviewInfo = $template.find("#linkEditorAndPreviewInfo"),
$livePreviewServerURL = $template.find("#livePreviewServerURL"),
$enableCustomServerChk = $template.find("#enableCustomServerChk"),
$showLivePreviewAtStartup = $template.find("#showLivePreviewAtStartupChk"),
$serveRoot = $template.find("#serveRoot"),
Expand All @@ -133,6 +136,13 @@ define(function (require, exports, module) {
$frameworkSelect = $template.find("#frameworkSelect");

// Initialize form values from preferences
$linkEditorAndPreviewChk.prop(
'checked', PreferencesManager.get(PREFERENCE_LINK_EDITOR_AND_PREVIEW) !== false
);
$linkEditorAndPreviewInfo.on("click", function(e) {
e.preventDefault();
Phoenix.app.openURLInDefaultBrowser("https://docs.phcode.dev");
});
$enableCustomServerChk.prop('checked', PreferencesManager.get(PREFERENCE_PROJECT_SERVER_ENABLED));
$showLivePreviewAtStartup.prop('checked', PreferencesManager.get(PREFERENCE_SHOW_LIVE_PREVIEW_PANEL));
$hotReloadChk.prop('checked', !!PreferencesManager.get(PREFERENCE_PROJECT_SERVER_HOT_RELOAD_SUPPORTED));
Expand Down Expand Up @@ -174,6 +184,7 @@ define(function (require, exports, module) {
Metrics.countEvent(Metrics.EVENT_TYPE.LIVE_PREVIEW, "settings", "dialog");
Dialogs.showModalDialogUsingTemplate($template).done(function (id) {
if (id === Dialogs.DIALOG_BTN_OK) {
PreferencesManager.set(PREFERENCE_LINK_EDITOR_AND_PREVIEW, $linkEditorAndPreviewChk.is(":checked"));
PreferencesManager.set(PREFERENCE_SHOW_LIVE_PREVIEW_PANEL, $showLivePreviewAtStartup.is(":checked"));
_saveProjectPreferences($enableCustomServerChk.is(":checked"), $livePreviewServerURL.val(),
$serveRoot.val(), $hotReloadChk.is(":checked"), $frameworkSelect.val());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ <h1 class="dialog-title">{{Strings.LIVE_DEV_SETTINGS_TITLE}}</h1>
<input type="checkbox" class="form-check-input" id="showLivePreviewAtStartupChk" style="margin-top: -2px;">
<label class="form-check-label" for="showLivePreviewAtStartupChk" style="display: inline">{{Strings.LIVE_DEV_SETTINGS_STARTUP}}</label>
</div>
<div class="form-group form-check" style="margin-top: 9px;">
<input type="checkbox" class="form-check-input" id="linkEditorAndPreviewChk" style="margin-top: -2px;">
<label class="form-check-label" for="linkEditorAndPreviewChk" style="display: inline">{{Strings.LIVE_PREVIEW_LINK_EDITOR_AND_PREVIEW}}</label>
<a href="#" id="linkEditorAndPreviewInfo" title="{{Strings.LIVE_DEV_SETTINGS_LINK_EDITOR_AND_PREVIEW_PREFERENCE}}" style="margin-left: 4px; color: var(--content-color-weaker); text-decoration: none;"><i class="fa-solid fa-info-circle"></i></a>
</div>
<div class="form-group" style="margin-top: 9px;">
<input id="enableCustomServerChk" type="checkbox" class="form-check-input" style="margin-top: -1px;">
<label id="enableCustomServerLabel" class="form-check-label" for="enableCustomServerChk" style="display: inline">{{Strings.LIVE_DEV_SETTINGS_USE_SERVER}}</label>
Expand Down
55 changes: 9 additions & 46 deletions src/extensionsIntegrated/Phoenix-live-preview/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -111,16 +111,16 @@
description: Strings.LIVE_DEV_SETTINGS_SHOW_RULER_LINES_PREFERENCE
});

// live preview spacing handles preference (show/hide spacing handles on element selection)
const PREFERENCE_SHOW_SPACING_HANDLES = CONSTANTS.PREFERENCE_SHOW_SPACING_HANDLES;
PreferencesManager.definePreference(PREFERENCE_SHOW_SPACING_HANDLES, "boolean", true, {
description: Strings.LIVE_DEV_SETTINGS_SHOW_SPACING_HANDLES_PREFERENCE
});
// Spacing handles preference disabled for this release (incomplete feature).
// const PREFERENCE_SHOW_SPACING_HANDLES = CONSTANTS.PREFERENCE_SHOW_SPACING_HANDLES;
// PreferencesManager.definePreference(PREFERENCE_SHOW_SPACING_HANDLES, "boolean", true, {
// description: Strings.LIVE_DEV_SETTINGS_SHOW_SPACING_HANDLES_PREFERENCE
// });

// live preview sync source and preview preference
// live preview link editor and preview preference
const PREFERENCE_LIVE_PREVIEW_SYNC = CONSTANTS.PREFERENCE_LIVE_PREVIEW_SYNC;
PreferencesManager.definePreference(PREFERENCE_LIVE_PREVIEW_SYNC, "boolean", true, {
description: Strings.LIVE_DEV_SETTINGS_SYNC_SOURCE_AND_PREVIEW_PREFERENCE
description: Strings.LIVE_DEV_SETTINGS_LINK_EDITOR_AND_PREVIEW_PREFERENCE
});

const LIVE_PREVIEW_PANEL_ID = "live-preview-panel";
Expand Down Expand Up @@ -202,14 +202,14 @@
const wasProEditUser = isProEditUser;
isProEditUser = entitlement && entitlement.activated;
// Sync edit mode with md iframe on entitlement change
if (_isMdviewrActive && $iframe && $iframe[0] && $iframe[0].contentWindow) {

Check warning on line 205 in src/extensionsIntegrated/Phoenix-live-preview/main.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=AZ09qKEJLQrmbX5-dlKc&open=AZ09qKEJLQrmbX5-dlKc&pullRequest=2769
if (isProEditUser && !wasProEditUser) {
// Just got pro — switch to edit mode
$iframe[0].contentWindow.postMessage(

Check failure on line 208 in src/extensionsIntegrated/Phoenix-live-preview/main.js

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Specify a target origin for this message.

See more on https://sonarcloud.io/project/issues?id=phcode-dev_phoenix&issues=AZ09qKEJLQrmbX5-dlKd&open=AZ09qKEJLQrmbX5-dlKd&pullRequest=2769
{ type: "MDVIEWR_SET_EDIT_MODE", editMode: true }, "*");
} else if (!isProEditUser && wasProEditUser) {
// Lost pro — switch to reader mode
$iframe[0].contentWindow.postMessage(

Check failure on line 212 in src/extensionsIntegrated/Phoenix-live-preview/main.js

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Specify a target origin for this message.

See more on https://sonarcloud.io/project/issues?id=phcode-dev_phoenix&issues=AZ09qKEJLQrmbX5-dlKe&open=AZ09qKEJLQrmbX5-dlKe&pullRequest=2769
{ type: "MDVIEWR_SET_EDIT_MODE", editMode: false }, "*");
}
}
Expand Down Expand Up @@ -382,25 +382,18 @@
function _showModeSelectionDropdown(event) {
const isEditFeaturesActive = isProEditUser;
const currentMode = LiveDevelopment.getCurrentMode();
const isNotPreviewMode = currentMode !== LiveDevelopment.CONSTANTS.LIVE_PREVIEW_MODE;
const items = [
Strings.LIVE_PREVIEW_MODE_PREVIEW,
Strings.LIVE_PREVIEW_MODE_HIGHLIGHT,
Strings.LIVE_PREVIEW_MODE_EDIT
];

// Add sync toggle for highlight and edit modes
if (isNotPreviewMode) {
items.push("---");
items.push(Strings.LIVE_PREVIEW_SYNC_SOURCE_AND_PREVIEW);
}

// Only add edit-specific options when in edit mode and edit features are active
const isEditMode = currentMode === LiveDevelopment.CONSTANTS.LIVE_EDIT_MODE;
if (isEditFeaturesActive && isEditMode) {
items.push("---");
items.push(Strings.LIVE_PREVIEW_EDIT_HIGHLIGHT_ON);

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

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Do not call `Array#push()` multiple times.

See more on https://sonarcloud.io/project/issues?id=phcode-dev_phoenix&issues=AZ09qKEJLQrmbX5-dlKf&open=AZ09qKEJLQrmbX5-dlKf&pullRequest=2769
items.push(Strings.LIVE_PREVIEW_SHOW_RULER_LINES);
items.push(Strings.LIVE_PREVIEW_SHOW_SPACING_HANDLES);
}

$dropdown = new DropdownButton.DropdownButton("", items, function(item, index) {
Expand All @@ -420,12 +413,6 @@
html: `${checkmark}${item}${crownIcon}`,
enabled: true
};
} else if (item === Strings.LIVE_PREVIEW_SYNC_SOURCE_AND_PREVIEW) {
const isEnabled = PreferencesManager.get(PREFERENCE_LIVE_PREVIEW_SYNC) !== false;
if(isEnabled) {
return `✓ ${Strings.LIVE_PREVIEW_SYNC_SOURCE_AND_PREVIEW}`;
}
return `${'\u00A0'.repeat(4)}${Strings.LIVE_PREVIEW_SYNC_SOURCE_AND_PREVIEW}`;
} else if (item === Strings.LIVE_PREVIEW_EDIT_HIGHLIGHT_ON) {
const isHoverMode =
PreferencesManager.get(PREFERENCE_PROJECT_ELEMENT_HIGHLIGHT) === CONSTANTS.HIGHLIGHT_HOVER;
Expand All @@ -439,12 +426,6 @@
return `✓ ${Strings.LIVE_PREVIEW_SHOW_RULER_LINES}`;
}
return `${'\u00A0'.repeat(4)}${Strings.LIVE_PREVIEW_SHOW_RULER_LINES}`;
} else if (item === Strings.LIVE_PREVIEW_SHOW_SPACING_HANDLES) {
const isEnabled = PreferencesManager.get(PREFERENCE_SHOW_SPACING_HANDLES);
if(isEnabled) {
return `✓ ${Strings.LIVE_PREVIEW_SHOW_SPACING_HANDLES}`;
}
return `${'\u00A0'.repeat(4)}${Strings.LIVE_PREVIEW_SHOW_SPACING_HANDLES}`;
}
return item;
});
Expand Down Expand Up @@ -482,11 +463,6 @@
Metrics.countEvent(Metrics.EVENT_TYPE.PRO, "proUpsellDlg", "fail");
}
}
} else if (item === Strings.LIVE_PREVIEW_SYNC_SOURCE_AND_PREVIEW) {
// Toggle sync source and preview on/off
const currentValue = PreferencesManager.get(PREFERENCE_LIVE_PREVIEW_SYNC);
PreferencesManager.set(PREFERENCE_LIVE_PREVIEW_SYNC, currentValue === false);
return; // Don't dismiss for this option
} else if (item === Strings.LIVE_PREVIEW_EDIT_HIGHLIGHT_ON) {
// Don't allow edit highlight toggle if edit features are not active
if (!isEditFeaturesActive) {
Expand All @@ -507,15 +483,6 @@
const currentValue = PreferencesManager.get(PREFERENCE_SHOW_RULER_LINES);
PreferencesManager.set(PREFERENCE_SHOW_RULER_LINES, !currentValue);
return; // Don't dismiss highlights for this option
} else if (item === Strings.LIVE_PREVIEW_SHOW_SPACING_HANDLES) {
// Don't allow spacing handles toggle if edit features are not active
if (!isEditFeaturesActive) {
return;
}
// Toggle spacing handles on/off
const currentValue = PreferencesManager.get(PREFERENCE_SHOW_SPACING_HANDLES);
PreferencesManager.set(PREFERENCE_SHOW_SPACING_HANDLES, !currentValue);
return; // Don't dismiss highlights for this option
}
});

Expand Down Expand Up @@ -915,7 +882,7 @@
}

// Reuse persistent md iframe if it exists (e.g. returning from HTML preview)
if ($mdviewrIframe && $mdviewrIframe[0].parentNode) {

Check warning on line 885 in src/extensionsIntegrated/Phoenix-live-preview/main.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=AZ09qKEJLQrmbX5-dlKg&open=AZ09qKEJLQrmbX5-dlKg&pullRequest=2769
// Hide the current HTML iframe and show the md iframe
if ($iframe[0] !== $mdviewrIframe[0]) {
$iframe.remove();
Expand Down Expand Up @@ -1103,13 +1070,13 @@
const mdPaths = workingSet
.filter(file => utils.isMarkdownFile(file.fullPath))
.map(file => file.fullPath);
mdIframeWindow.postMessage({

Check failure on line 1073 in src/extensionsIntegrated/Phoenix-live-preview/main.js

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Specify a target origin for this message.

See more on https://sonarcloud.io/project/issues?id=phcode-dev_phoenix&issues=AZ09qKEJLQrmbX5-dlKh&open=AZ09qKEJLQrmbX5-dlKh&pullRequest=2769
type: "MDVIEWR_WORKING_SET_CHANGED",
paths: mdPaths
}, "*");
}

async function _projectOpened() {

Check failure on line 1079 in src/extensionsIntegrated/Phoenix-live-preview/main.js

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Refactor this function to reduce its Cognitive Complexity from 18 to the 15 allowed.

See more on https://sonarcloud.io/project/issues?id=phcode-dev_phoenix&issues=AZ09qKEJLQrmbX5-dlKi&open=AZ09qKEJLQrmbX5-dlKi&pullRequest=2769
// Deactivate mdviewr on project switch — keep iframe alive but clear cache
if(_isMdviewrActive) {
MarkdownSync.deactivate();
Expand All @@ -1118,7 +1085,7 @@
if ($mdviewrIframe) {
const mdIframeWindow = $mdviewrIframe[0].contentWindow;
if (mdIframeWindow) {
mdIframeWindow.postMessage({ type: "MDVIEWR_CLEAR_CACHE" }, "*");

Check failure on line 1088 in src/extensionsIntegrated/Phoenix-live-preview/main.js

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Specify a target origin for this message.

See more on https://sonarcloud.io/project/issues?id=phcode-dev_phoenix&issues=AZ09qKEJLQrmbX5-dlKj&open=AZ09qKEJLQrmbX5-dlKj&pullRequest=2769
}
$mdviewrIframe.hide();
}
Expand Down Expand Up @@ -1448,17 +1415,13 @@
PreferencesManager.on("change", PREFERENCE_SHOW_RULER_LINES, function() {
LiveDevelopment.updateRulerLinesConfig();
});
PreferencesManager.on("change", PREFERENCE_SHOW_SPACING_HANDLES, function() {
LiveDevelopment.updateSpacingHandlesConfig();
});
PreferencesManager.on("change", PREFERENCE_LIVE_PREVIEW_SYNC, function() {
LiveDevelopment.updateSyncConfig();
});

// Initialize element highlight, ruler lines, spacing handles, and sync config on startup
// Initialize element highlight, ruler lines, and sync config on startup
LiveDevelopment.updateElementHighlightConfig();
LiveDevelopment.updateRulerLinesConfig();
LiveDevelopment.updateSpacingHandlesConfig();
LiveDevelopment.updateSyncConfig();

LiveDevelopment.openLivePreview();
Expand Down Expand Up @@ -1542,8 +1505,8 @@
MarkdownSync.setEditModeRequestHandler(function () {
if (isProEditUser) {
// Entitled — send edit mode to iframe
if ($iframe && $iframe[0] && $iframe[0].contentWindow) {

Check warning on line 1508 in src/extensionsIntegrated/Phoenix-live-preview/main.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=AZ09qKEJLQrmbX5-dlKk&open=AZ09qKEJLQrmbX5-dlKk&pullRequest=2769
$iframe[0].contentWindow.postMessage(

Check failure on line 1509 in src/extensionsIntegrated/Phoenix-live-preview/main.js

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Specify a target origin for this message.

See more on https://sonarcloud.io/project/issues?id=phcode-dev_phoenix&issues=AZ09qKEJLQrmbX5-dlKl&open=AZ09qKEJLQrmbX5-dlKl&pullRequest=2769
{ type: "MDVIEWR_SET_EDIT_MODE", editMode: true }, "*");
}
} else {
Expand Down
4 changes: 2 additions & 2 deletions src/nls/root/strings.js
Original file line number Diff line number Diff line change
Expand Up @@ -530,8 +530,8 @@ define({
"LIVE_PREVIEW_SHOW_RULER_LINES": "Show Measurements",
"LIVE_PREVIEW_SHOW_SPACING_HANDLES": "Show Spacing Handles",
"LIVE_DEV_SETTINGS_SHOW_SPACING_HANDLES_PREFERENCE": "Show spacing handles when elements are selected in live preview edit mode. Defaults to 'true'",
"LIVE_PREVIEW_SYNC_SOURCE_AND_PREVIEW": "Sync Code & Preview",
"LIVE_DEV_SETTINGS_SYNC_SOURCE_AND_PREVIEW_PREFERENCE": "Sync source code cursor with live preview element highlighting. When enabled, moving the cursor in the editor highlights the corresponding element in the live preview, and clicking an element in the live preview jumps the cursor to its source code. Defaults to 'true'",
"LIVE_PREVIEW_LINK_EDITOR_AND_PREVIEW": "Link Editor and Preview",
"LIVE_DEV_SETTINGS_LINK_EDITOR_AND_PREVIEW_PREFERENCE": "Link editor cursor with live preview element highlighting. When enabled, moving the cursor in the editor highlights the corresponding element in the live preview, and clicking an element in the live preview jumps the cursor to its source code. Defaults to 'true'",
"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",

Expand Down
Loading