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
11 changes: 11 additions & 0 deletions src/editor/EditorCommandHandlers.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ define(function (require, exports, module) {
Editor = require("editor/Editor").Editor,
CommandManager = require("command/CommandManager"),
EditorManager = require("editor/EditorManager"),
WorkspaceManager = require("view/WorkspaceManager"),
StringUtils = require("utils/StringUtils"),
TokenUtils = require("utils/TokenUtils"),
CodeMirror = require("thirdparty/CodeMirror/lib/codemirror"),
Expand Down Expand Up @@ -1185,6 +1186,16 @@ define(function (require, exports, module) {
var editor = EditorManager.getFocusedEditor();
var result = new $.Deferred();

// In design mode the active document often lives behind an external
// surface that owns DOM focus (e.g. the markdown viewer iframe in
// edit mode), so getFocusedEditor() returns null even though there
// is an underlying Phoenix editor whose doc captures the changes.
// Fall back to the active-pane full editor so toolbar undo/redo
// still drives the document's history in that state.
if (!editor && WorkspaceManager.isInDesignMode()) {
editor = EditorManager.getCurrentFullEditor();
}

if (editor) {
editor[operation]();
result.resolve();
Expand Down
40 changes: 26 additions & 14 deletions src/extensionsIntegrated/Phoenix-live-preview/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@

// holds the dropdown instance
let $dropdown = null;
const PREFERENCE_LIVE_PREVIEW_MODE = "livePreviewMode";

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

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Remove the declaration of the unused 'PREFERENCE_LIVE_PREVIEW_MODE' variable.

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

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

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Remove this useless assignment to variable "PREFERENCE_LIVE_PREVIEW_MODE".

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

// live preview element highlights preference (whether on hover or click)
const PREFERENCE_PROJECT_ELEMENT_HIGHLIGHT = CONSTANTS.PREFERENCE_PROJECT_ELEMENT_HIGHLIGHT;
Expand Down Expand Up @@ -369,8 +369,10 @@
function _initializeMode() {
const currentMode = LiveDevelopment.getCurrentMode();

// when in preview mode, we need to give the play button a selected state
if (currentMode === LiveDevelopment.CONSTANTS.LIVE_PREVIEW_MODE) {
// Pencil button lights up only when edit mode is active; preview /
// highlight modes leave it un-tinted. Click toggles between edit
// and preview.
if (currentMode === LiveDevelopment.CONSTANTS.LIVE_EDIT_MODE) {
$previewBtn.addClass('selected');
} else {
$previewBtn.removeClass('selected');
Expand Down Expand Up @@ -744,19 +746,29 @@
}

/**
* Handle preview button click - toggles between preview mode and the user's default mode.
* PRO users toggle between preview and edit mode.
* community users toggle between preview and highlight mode.
* Toggles between edit mode and preview mode. The pencil button lights up
* (via .selected applied in _initializeMode) when edit mode is active;
* clicking it when already in edit drops back to preview. Clicking when
* NOT in edit tries to enter edit through LiveDevelopment.setMode, which
* returns false for users without the live-edit entitlement — in that
* case we show the same pro upsell dialog the mode dropdown uses,
* mirroring its "Edit Mode" item. _initializeMode reconciles the
* .selected class against the actual current mode after the pref
* change lands.
*/
function _handlePreviewBtnClick() {
if($previewBtn.hasClass('selected')) {
$previewBtn.removeClass('selected');
const defaultMode = isProEditUser ? 'edit' : 'highlight';
PreferencesManager.set(PREFERENCE_LIVE_PREVIEW_MODE, defaultMode);
} else {
// Currently NOT in preview mode - switch to preview
$previewBtn.addClass('selected');
PreferencesManager.set(PREFERENCE_LIVE_PREVIEW_MODE, "preview");
const currentMode = LiveDevelopment.getCurrentMode();
if (currentMode === LiveDevelopment.CONSTANTS.LIVE_EDIT_MODE) {
LiveDevelopment.setMode(LiveDevelopment.CONSTANTS.LIVE_PREVIEW_MODE);
return;
}
if (!LiveDevelopment.setMode(LiveDevelopment.CONSTANTS.LIVE_EDIT_MODE)) {
if (KernalModeTrust.ProDialogs) {
KernalModeTrust.ProDialogs.showProUpsellDialog(
KernalModeTrust.ProDialogs.UPSELL_TYPE_LIVE_EDIT);
} else {
Metrics.countEvent(Metrics.EVENT_TYPE.PRO, "proUpsellDlg", "fail");
}
}
}

Expand All @@ -765,7 +777,7 @@
Strings: Strings,
livePreview: Strings.LIVE_DEV_STATUS_TIP_OUT_OF_SYNC,
clickToReload: Strings.LIVE_DEV_CLICK_TO_RELOAD_PAGE,
clickToPreview: Strings.LIVE_PREVIEW_MODE_TOGGLE_PREVIEW,
clickToToggleEdit: Strings.LIVE_PREVIEW_MODE_TOGGLE_EDIT,
switchToDesignMode: Strings.CCB_SWITCH_TO_DESIGN_MODE,
livePreviewSettings: Strings.LIVE_DEV_SETTINGS,
livePreviewConfigureModes: Strings.LIVE_PREVIEW_CONFIGURE_MODES,
Expand Down
4 changes: 2 additions & 2 deletions src/extensionsIntegrated/Phoenix-live-preview/panel.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
<button id="designModeToggleLivePreviewButton" title="{{switchToDesignMode}}" class="btn-alt-quiet toolbar-button">
<i class="fa-solid fa-expand"></i>
</button>
<button id="previewModeLivePreviewButton" title="{{clickToPreview}}" class="btn-alt-quiet toolbar-button">
<i class="fa-solid fa-play"></i>
<button id="previewModeLivePreviewButton" title="{{clickToToggleEdit}}" class="btn-alt-quiet toolbar-button">
<i class="fa-solid fa-pencil"></i>
</button>
<button id="livePreviewModeBtn" title="{{livePreviewConfigureModes}}" class="btn-alt-quiet toolbar-button btn-dropdown btn"><!-- Content will come here dynamically --></button>
</div>
Expand Down
7 changes: 7 additions & 0 deletions src/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -969,6 +969,13 @@
<i class="fa-solid fa-floppy-disk"></i>
</a>
</div>
<div class="ccb-divider ccb-file-divider"></div>
<div class="ccb-group ccb-group-file">
<div id="ccbFileLabel" class="ccb-file-label">
<span class="ccb-file-dot">•</span>
<span class="ccb-file-name"></span>
</div>
</div>
</div>

<!--
Expand Down
3 changes: 2 additions & 1 deletion src/nls/root/strings.js
Original file line number Diff line number Diff line change
Expand Up @@ -544,6 +544,7 @@ define({
"IMAGE_SEARCH_PRO_THROTTLE_MESSAGE": "Image search is temporarily unavailable due to high demand. This usually clears within an hour — please try again shortly.",
"LIVE_PREVIEW_CUSTOM_SERVER_BANNER": "Getting preview from your custom server {0}",
"LIVE_PREVIEW_MODE_TOGGLE_PREVIEW": "Toggle Preview Mode (F8)",
"LIVE_PREVIEW_MODE_TOGGLE_EDIT": "Toggle Edit Mode (F8)",
"LIVE_PREVIEW_MODE_PREVIEW": "Preview Mode",
"LIVE_PREVIEW_MODE_HIGHLIGHT": "Highlight Mode",
"LIVE_PREVIEW_MODE_EDIT": "Edit Mode",
Expand Down Expand Up @@ -2357,7 +2358,7 @@ define({
"DEMO_EDIT_MODE_DESCRIPTION": "Select and change things on the page",
"DEMO_PREVIEW_MODE_LABEL": "Preview mode",
"DEMO_PREVIEW_MODE_DESCRIPTION": "See your page as visitors will see it",
"DEMO_MODE_SWITCH_HINT": "Press <strong>F8</strong> or click the <span class=\"play-button-hint\"><img src=\"images/playButton.svg\" alt=\"Play\" class=\"play-hint-svg svg-gold\"></span> buttons to switch modes.",
"DEMO_MODE_SWITCH_HINT": "Press <strong>F8</strong> or click the <span class=\"play-button-hint\"><i class=\"fa-solid fa-pencil\"></i></span> button to switch modes.",
"DEMO_TIPS_LABEL": "Tips:",
"DEMO_SECTION6_TIP1": "Click any link to select it for editing",
"DEMO_SECTION6_TIP2_NEWTAB": "Enable <strong>Open in new tab</strong> to open links on a separate page",
Expand Down
72 changes: 72 additions & 0 deletions src/styles/CentralControlBar.less
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,14 @@
flex-direction: column;
align-items: stretch;
gap: 2px;

&.ccb-group-file {
flex: 0 1 auto;
max-height: 220px;
overflow: hidden;
justify-content: flex-start;
padding: 4px 0;
}
}

.ccb-divider {
Expand Down Expand Up @@ -116,6 +124,70 @@
}
}

/* Vertical filename label — clicking reveals the current file in the
file tree (keeps the old binoculars-on-label affordance). */
.ccb-file-label {
display: flex;
flex-direction: column;
align-items: center;
gap: 4px;
padding: 4px 0;
color: @project-panel-text-2;
height: 100%;
overflow: hidden;
cursor: pointer;

.ccb-file-dot {
flex: 0 0 auto;
line-height: 1;
color: #f1b84e;
visibility: hidden;
font-size: 1rem;
}

&.is-dirty .ccb-file-dot {
visibility: visible;
}

.ccb-file-name {
flex: 1 1 auto;
min-height: 0;
/* `sideways-lr` rotates each glyph 90° CCW so the text reads
bottom-up naturally. Using this instead of `vertical-rl` +
`transform: rotate(180deg)` avoids the blurry sub-pixel
rasterization that the transform path produced on linux
electron, because Chromium can take its fast vertical-text
path for glyph layout and skip the rotated bitmap upscale. */
writing-mode: sideways-lr;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
color: @project-panel-text-1;
font-size: 13px;
font-weight: 500;
/* Promote to its own compositing layer + force AA — keeps the
rotated glyphs crisp even when the system falls back to the
slow text path. */
transform: translateZ(0);
backface-visibility: hidden;
-webkit-font-smoothing: antialiased;
text-rendering: geometricPrecision;
}

&:hover .ccb-file-name {
text-decoration: underline;
}
}

}

/* The file label is only useful in design mode — in code mode the active
file is already obvious from the tab bar / working-files list, so the
vertical label (and its preceding divider) would be redundant chrome
that steals vertical space in the CCB. */
body:not(.ccb-editor-collapsed) #centralControlBar .ccb-file-divider,
body:not(.ccb-editor-collapsed) #centralControlBar .ccb-group-file {
display: none;
}

/* Editor collapse: actual layout handled in JS via .content width/visibility */
Expand Down
44 changes: 44 additions & 0 deletions src/view/CentralControlBar.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
const AppInit = require("utils/AppInit");
const CommandManager = require("command/CommandManager");
const Commands = require("command/Commands");
const DocumentManager = require("document/DocumentManager");
const MainViewManager = require("view/MainViewManager");
const Strings = require("strings");
const WorkspaceManager = require("view/WorkspaceManager");
const SidebarView = require("project/SidebarView");
Expand All @@ -32,6 +34,8 @@
let $bar;
let $sidebar;
let $content;
let $fileLabel;
let $fileName;
let editorCollapsed = false;
let savedToolbarWidth = null;
let livePreviewWasOpen = false;
Expand Down Expand Up @@ -69,6 +73,35 @@
}
}

function _updateFileLabel() {
if (!$fileLabel) {
return;
}
// Use MainViewManager instead of DocumentManager.getCurrentDocument()
// so non-editable views (images, custom viewers, etc.) still show up
// on the label. getCurrentDocument() is CodeMirror-backed only and
// would leave the label blank whenever the active pane is an image
// or other non-CM surface.
const file = MainViewManager.getCurrentlyViewedFile(MainViewManager.ACTIVE_PANE);
if (!file) {
$fileLabel.removeClass("is-dirty");
$fileName.text("");
$fileLabel.attr("title", "");
return;
}
const name = file.name || "";
const fullPath = file.fullPath || "";
const displayPath = fullPath && Phoenix && Phoenix.app && Phoenix.app.getDisplayPath

Check warning on line 94 in src/view/CentralControlBar.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=AZ26iWM2Vk-tm9gMolac&open=AZ26iWM2Vk-tm9gMolac&pullRequest=2837
? Phoenix.app.getDisplayPath(fullPath)
: fullPath || name;
$fileName.text(name);
$fileLabel.attr("title", displayPath);
// Dirty only makes sense for files with a document behind them; for
// non-editable views there's no doc, so the class simply stays off.
const doc = DocumentManager.getOpenDocumentForPath(fullPath);
$fileLabel.toggleClass("is-dirty", !!(doc && doc.isDirty));

Check warning on line 102 in src/view/CentralControlBar.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=AZ26iWM2Vk-tm9gMolad&open=AZ26iWM2Vk-tm9gMolad&pullRequest=2837
}

function _executeCmd(id) {
CommandManager.execute(id);
}
Expand Down Expand Up @@ -263,6 +296,10 @@
e.preventDefault();
_executeCmd(Commands.VIEW_HIDE_SIDEBAR);
});
$("#ccbFileLabel").on("click", function (e) {
e.preventDefault();
_executeCmd(Commands.NAVIGATE_SHOW_IN_FILE_TREE);
});
}

const _toggleDesignModeCommand = CommandManager.register(Strings.CMD_TOGGLE_DESIGN_MODE,
Expand All @@ -274,6 +311,8 @@
$bar = $("#centralControlBar");
$sidebar = $("#sidebar");
$content = $(".content");
$fileLabel = $("#ccbFileLabel");
$fileName = $fileLabel.find(".ccb-file-name");

_wireButtons();
// The HTML titles on the control-bar buttons are fallback English
Expand Down Expand Up @@ -396,6 +435,11 @@
}

_updateSidebarToggleIcon();

MainViewManager.on("currentFileChange.ccb", _updateFileLabel);
DocumentManager.on("dirtyFlagChange.ccb", _updateFileLabel);
DocumentManager.on("pathDeleted.ccb fileNameChange.ccb", _updateFileLabel);
_updateFileLabel();
});


Expand Down
Loading
Loading