diff --git a/docs/API-Reference/command/Commands.md b/docs/API-Reference/command/Commands.md index 631fa03621..37a71de251 100644 --- a/docs/API-Reference/command/Commands.md +++ b/docs/API-Reference/command/Commands.md @@ -458,6 +458,12 @@ Toggles sidebar visibility ## VIEW\_TOGGLE\_DESIGN\_MODE Toggles the design (full live-preview) mode — collapses/expands the editor +**Kind**: global variable + + +## VIEW\_TOGGLE\_LP\_FULL\_SCREEN +Toggles live-preview full screen (design mode with the sidebar hidden) + **Kind**: global variable diff --git a/docs/API-Reference/view/WorkspaceManager.md b/docs/API-Reference/view/WorkspaceManager.md index eff290c760..1f26abee19 100644 --- a/docs/API-Reference/view/WorkspaceManager.md +++ b/docs/API-Reference/view/WorkspaceManager.md @@ -29,6 +29,7 @@ Events: * [.EVENT_WORKSPACE_PANEL_SHOWN](#module_view/WorkspaceManager..EVENT_WORKSPACE_PANEL_SHOWN) * [.EVENT_WORKSPACE_PANEL_HIDDEN](#module_view/WorkspaceManager..EVENT_WORKSPACE_PANEL_HIDDEN) * [.EVENT_WORKSPACE_DESIGN_MODE_CHANGE](#module_view/WorkspaceManager..EVENT_WORKSPACE_DESIGN_MODE_CHANGE) + * [.EVENT_WORKSPACE_LP_FULL_SCREEN_CHANGE](#module_view/WorkspaceManager..EVENT_WORKSPACE_LP_FULL_SCREEN_CHANGE) * [.createBottomPanel(id, $panel, [minSize], [title], [options])](#module_view/WorkspaceManager..createBottomPanel) ⇒ Panel * [.destroyBottomPanel(id)](#module_view/WorkspaceManager..destroyBottomPanel) * [.createPluginPanel(id, $panel, [minSize], $toolbarIcon, [initialSize])](#module_view/WorkspaceManager..createPluginPanel) ⇒ Panel @@ -39,6 +40,8 @@ Events: * [.setPluginPanelWidth(width)](#module_view/WorkspaceManager..setPluginPanelWidth) * [.isInDesignMode()](#module_view/WorkspaceManager..isInDesignMode) ⇒ boolean * [.setDesignMode(active)](#module_view/WorkspaceManager..setDesignMode) + * [.isInLPFullScreen()](#module_view/WorkspaceManager..isInLPFullScreen) ⇒ boolean + * [.setLPFullScreen(active)](#module_view/WorkspaceManager..setLPFullScreen) * [.addEscapeKeyEventHandler(consumerName, eventHandler)](#module_view/WorkspaceManager..addEscapeKeyEventHandler) ⇒ boolean * [.removeEscapeKeyEventHandler(consumerName)](#module_view/WorkspaceManager..removeEscapeKeyEventHandler) ⇒ boolean @@ -96,6 +99,13 @@ Event triggered when a panel is hidden. Event triggered when design mode (editor collapsed, full live preview) is entered or exited. Payload: `(active: boolean)`. +**Kind**: inner constant of [view/WorkspaceManager](#module_view/WorkspaceManager) + + +### view/WorkspaceManager.EVENT\_WORKSPACE\_LP\_FULL\_SCREEN\_CHANGE +Event triggered when live-preview full screen (design mode with the sidebar +hidden) is entered or exited. Payload: `(active: boolean)`. + **Kind**: inner constant of [view/WorkspaceManager](#module_view/WorkspaceManager) @@ -220,6 +230,32 @@ callers should use the dedicated toggle command instead. | --- | --- | | active | boolean | + + +### view/WorkspaceManager.isInLPFullScreen() ⇒ boolean +Returns true while live preview is expanded to full screen, meaning design mode +with the sidebar hidden so live preview owns everything to the right of the +central control bar. + +Full screen is a superset of design mode, so `isInDesignMode()` is true here +too. Use `isInDesignMode()` if you only care that the editor is collapsed; +use this only when the sidebar state matters. + +**Kind**: inner method of [view/WorkspaceManager](#module_view/WorkspaceManager) + + +### view/WorkspaceManager.setLPFullScreen(active) +Sets the live-preview full-screen flag and fires +EVENT_WORKSPACE_LP_FULL_SCREEN_CHANGE when the value actually changes. +Intended to be called by the control bar; other callers should use the +dedicated toggle command instead. + +**Kind**: inner method of [view/WorkspaceManager](#module_view/WorkspaceManager) + +| Param | Type | +| --- | --- | +| active | boolean | + ### view/WorkspaceManager.addEscapeKeyEventHandler(consumerName, eventHandler) ⇒ boolean diff --git a/src/command/Commands.js b/src/command/Commands.js index b2586a1656..11a39c1ed4 100644 --- a/src/command/Commands.js +++ b/src/command/Commands.js @@ -260,6 +260,9 @@ define(function (require, exports, module) { /** Toggles the design (full live-preview) mode — collapses/expands the editor */ exports.VIEW_TOGGLE_DESIGN_MODE = "view.toggleDesignMode"; // view/CentralControlBar.js _setEditorCollapsed() + /** Toggles live-preview full screen (design mode with the sidebar hidden) */ + exports.VIEW_TOGGLE_LP_FULL_SCREEN = "view.toggleLivePreviewFullScreen"; // view/CentralControlBar.js _setLPFullScreen() + /** Toggles tabbar visibility */ exports.TOGGLE_TABBAR = "view.toggleTabbar"; // extensionsIntegrated/TabBar/main.js diff --git a/src/extensionsIntegrated/Phoenix-live-preview/live-preview.css b/src/extensionsIntegrated/Phoenix-live-preview/live-preview.css index 40fcf5e973..cfc18c4e57 100644 --- a/src/extensionsIntegrated/Phoenix-live-preview/live-preview.css +++ b/src/extensionsIntegrated/Phoenix-live-preview/live-preview.css @@ -370,13 +370,13 @@ } #reloadLivePreviewButton, -#designModeToggleLivePreviewButton { +#fullScreenLivePreviewButton { border: 1px solid transparent; border-radius: 3px; } #live-preview-plugin-toolbar #reloadLivePreviewButton:hover, -#live-preview-plugin-toolbar #designModeToggleLivePreviewButton:hover { +#live-preview-plugin-toolbar #fullScreenLivePreviewButton:hover { border-color: rgba(255, 255, 255, 0.1) !important; background: transparent !important; box-shadow: none !important; diff --git a/src/extensionsIntegrated/Phoenix-live-preview/main.js b/src/extensionsIntegrated/Phoenix-live-preview/main.js index 3e99097216..1f8dc1e25b 100644 --- a/src/extensionsIntegrated/Phoenix-live-preview/main.js +++ b/src/extensionsIntegrated/Phoenix-live-preview/main.js @@ -190,7 +190,7 @@ define(function (require, exports, module) { $modeBtn, $modeBtnGroup, $previewBtn, - $designModeBtn; + $fullScreenBtn; let customLivePreviewBannerShown = false; @@ -800,7 +800,7 @@ define(function (require, exports, module) { livePreview: Strings.LIVE_DEV_STATUS_TIP_OUT_OF_SYNC, clickToReload: Strings.LIVE_DEV_CLICK_TO_RELOAD_PAGE, clickToToggleEdit: Strings.LIVE_PREVIEW_MODE_TOGGLE_EDIT, - switchToDesignMode: Strings.CCB_SWITCH_TO_DESIGN_MODE, + fullScreenLivePreview: Strings.LIVE_PREVIEW_FULL_SCREEN, livePreviewSettings: Strings.LIVE_DEV_SETTINGS, livePreviewConfigureModes: Strings.LIVE_PREVIEW_CONFIGURE_MODES, clickToPopout: Strings.LIVE_DEV_CLICK_POPOUT, @@ -833,7 +833,7 @@ define(function (require, exports, module) { $modeBtn = $panel.find("#livePreviewModeBtn"); $modeBtnGroup = $panel.find("#lpModeBtnGroup"); $previewBtn = $panel.find("#previewModeLivePreviewButton"); - $designModeBtn = $panel.find("#designModeToggleLivePreviewButton"); + $fullScreenBtn = $panel.find("#fullScreenLivePreviewButton"); // Markdown theme toggle — persist user choice MarkdownSync.setThemeToggleHandler((theme) => { @@ -918,28 +918,25 @@ define(function (require, exports, module) { Metrics.countEvent(Metrics.EVENT_TYPE.LIVE_PREVIEW, "reloadBtn", "click"); }); - // Design-mode toggle: mirrors the CCB's pen-nib button so the user can - // enter/exit design mode without moving focus to the sidebar strip. - // Icon swaps between fa-expand (enter) and fa-compress (exit). - function _updateDesignModeButton() { - const on = WorkspaceManager.isInDesignMode && WorkspaceManager.isInDesignMode(); - const $icon = $designModeBtn.find("i"); - $icon.removeClass("fa-expand fa-compress") + function _updateFullScreenButton() { + const on = WorkspaceManager.isInLPFullScreen && WorkspaceManager.isInLPFullScreen(); + $fullScreenBtn.find("i") + .removeClass("fa-expand fa-compress") .addClass(on ? "fa-compress" : "fa-expand"); - $designModeBtn.attr("title", - on ? Strings.CCB_SWITCH_TO_CODE_EDITOR : Strings.CCB_SWITCH_TO_DESIGN_MODE); - if ($modeBtn) { - $modeBtn.toggle(!on && !_isMdviewrActive); - } + $fullScreenBtn.attr("title", + on ? Strings.LIVE_PREVIEW_EXIT_FULL_SCREEN : Strings.LIVE_PREVIEW_FULL_SCREEN); } - $designModeBtn.click(()=>{ - CommandManager.execute(Commands.VIEW_TOGGLE_DESIGN_MODE); - Metrics.countEvent(Metrics.EVENT_TYPE.LIVE_PREVIEW, "designModeBtn", "click"); + $fullScreenBtn.click(()=>{ + CommandManager.execute(Commands.VIEW_TOGGLE_LP_FULL_SCREEN); + Metrics.countEvent(Metrics.EVENT_TYPE.LIVE_PREVIEW, "fullScreenBtn", "click"); }); WorkspaceManager.off(WorkspaceManager.EVENT_WORKSPACE_DESIGN_MODE_CHANGE + ".livePreview"); WorkspaceManager.on(WorkspaceManager.EVENT_WORKSPACE_DESIGN_MODE_CHANGE + ".livePreview", - _updateDesignModeButton); - _updateDesignModeButton(); + _updateLPControlsForMdviewer); + WorkspaceManager.off(WorkspaceManager.EVENT_WORKSPACE_LP_FULL_SCREEN_CHANGE + ".livePreview"); + WorkspaceManager.on(WorkspaceManager.EVENT_WORKSPACE_LP_FULL_SCREEN_CHANGE + ".livePreview", + _updateFullScreenButton); + _updateFullScreenButton(); // init the status overlay _initOverlay(); diff --git a/src/extensionsIntegrated/Phoenix-live-preview/panel.html b/src/extensionsIntegrated/Phoenix-live-preview/panel.html index 0a32900fd1..1a24d179a8 100644 --- a/src/extensionsIntegrated/Phoenix-live-preview/panel.html +++ b/src/extensionsIntegrated/Phoenix-live-preview/panel.html @@ -4,7 +4,7 @@ - diff --git a/src/nls/root/strings.js b/src/nls/root/strings.js index 704cad2a44..08b8a9eeac 100644 --- a/src/nls/root/strings.js +++ b/src/nls/root/strings.js @@ -1198,6 +1198,9 @@ define({ "CMD_TOGGLE_DESIGN_MODE": "Toggle Design Mode", "CCB_SWITCH_TO_DESIGN_MODE": "Switch to Design Mode", "CCB_SWITCH_TO_CODE_EDITOR": "Switch to Code Editor", + "CMD_TOGGLE_LP_FULL_SCREEN": "Toggle Live Preview Full Screen", + "LIVE_PREVIEW_FULL_SCREEN": "Expand Live Preview to Full Screen", + "LIVE_PREVIEW_EXIT_FULL_SCREEN": "Exit Full Screen", "CMD_TOGGLE_TABBAR": "File Tab Bar", "CMD_TOGGLE_PANELS": "Toggle Panels", "CMD_TOGGLE_PURE_CODE": "No Distractions", diff --git a/src/view/CentralControlBar.js b/src/view/CentralControlBar.js index 8610a82a4e..7d59861286 100644 --- a/src/view/CentralControlBar.js +++ b/src/view/CentralControlBar.js @@ -27,6 +27,7 @@ define(function (require, exports, module) { const LanguageManager = require("language/LanguageManager"); const MainViewManager = require("view/MainViewManager"); const Metrics = require("utils/Metrics"); + const PreferencesManager = require("preferences/PreferencesManager"); const Strings = require("strings"); const WorkspaceManager = require("view/WorkspaceManager"); const SidebarView = require("project/SidebarView"); @@ -43,6 +44,9 @@ define(function (require, exports, module) { let livePreviewWasOpen = false; let savedSidebarMaxSize = null; let applyingCollapsedLayout = false; + let lpFullScreen = false; + let sidebarHiddenByFullScreen = false; + let designModeEnabledByFullScreen = false; function _getRenderedSidebarWidth() { // Use offsetWidth (not jQuery's outerWidth) to force a synchronous reflow @@ -316,6 +320,11 @@ define(function (require, exports, module) { function _setEditorCollapsed(collapsed, opts) { const wantCollapsed = !!collapsed; + // Leaving design mode also leaves full screen, so give the sidebar back + // if full screen was what hid it. + if (!wantCollapsed) { + _restoreSidebarFromFullScreen(); + } if (wantCollapsed === editorCollapsed) { return; } @@ -347,15 +356,14 @@ define(function (require, exports, module) { _flushTracker(_mdDesignTracker); } $("body").toggleClass("ccb-editor-collapsed", editorCollapsed); - const $collapseBtn = $("#ccbCollapseEditorBtn"); - $collapseBtn.toggleClass("is-active", editorCollapsed) - .attr("title", editorCollapsed ? Strings.CCB_SWITCH_TO_CODE_EDITOR : Strings.CCB_SWITCH_TO_DESIGN_MODE); + _updateCollapseBtn(); if (_toggleDesignModeCommand) { _toggleDesignModeCommand.setChecked(editorCollapsed); } if (WorkspaceManager.setDesignMode) { WorkspaceManager.setDesignMode(editorCollapsed); } + _recomputeFullScreen(); if (editorCollapsed) { livePreviewWasOpen = _isLivePreviewOpen(); @@ -398,8 +406,110 @@ define(function (require, exports, module) { if (!$btn.length) { return; } - const isVisible = SidebarView.isVisible(); - $btn.find("i").attr("class", isVisible ? "fa-solid fa-angles-left" : "fa-solid fa-angles-right"); + const sidebarVisible = SidebarView.isVisible(); + $btn.find("i").attr("class", sidebarVisible ? "fa-solid fa-angles-left" : "fa-solid fa-angles-right"); + $btn.attr("title", lpFullScreen + ? Strings.LIVE_PREVIEW_EXIT_FULL_SCREEN : Strings.CMD_TOGGLE_SIDEBAR); + } + + function _updateCollapseBtn() { + $("#ccbCollapseEditorBtn") + .toggleClass("is-active", editorCollapsed) + .attr("title", editorCollapsed + ? Strings.CCB_SWITCH_TO_CODE_EDITOR : Strings.CCB_SWITCH_TO_DESIGN_MODE); + } + + function _hideSidebarForFullScreen() { + if (!SidebarView.isVisible()) { + return; + } + sidebarHiddenByFullScreen = true; + SidebarView.hide(); + // Resizer persists visible:false on hide, but full screen itself isn't + // persisted, so quitting from it would reopen the app with no sidebar. + // Put the stored flag back. + const sidebarViewState = PreferencesManager.getViewState("sidebar"); + if (sidebarViewState) { + sidebarViewState.visible = true; + PreferencesManager.setViewState("sidebar", sidebarViewState); + } + } + + function _restoreSidebarFromFullScreen() { + if (!sidebarHiddenByFullScreen) { + return; + } + sidebarHiddenByFullScreen = false; + if (!SidebarView.isVisible()) { + SidebarView.show(); + } + } + + /** + * Full screen is derived state: live preview is full screen exactly when the + * editor is collapsed and the sidebar is away, however the user got there. + * Call this after either of those two inputs changes. + * @private + */ + function _recomputeFullScreen() { + const nextFullScreen = editorCollapsed && !SidebarView.isVisible(); + if (nextFullScreen === lpFullScreen) { + return; + } + lpFullScreen = nextFullScreen; + if (!lpFullScreen) { + sidebarHiddenByFullScreen = false; + designModeEnabledByFullScreen = false; + } + $("body").toggleClass("lp-fullscreen", lpFullScreen); + if (WorkspaceManager.setLPFullScreen) { + WorkspaceManager.setLPFullScreen(lpFullScreen); + } + if (_toggleLPFullScreenCommand) { + _toggleLPFullScreenCommand.setChecked(lpFullScreen); + } + _updateSidebarToggleIcon(); + } + + /** + * Enters or exits live-preview full screen, meaning design mode with the sidebar + * hidden. + * + * Exiting undoes only what entering did, so it turns design mode off only when + * entering was what turned it on. Entering from design mode returns to design + * mode, not to the editor. + * @param {boolean} fullScreen + * @private + */ + function _setLPFullScreen(fullScreen) { + const wantFullScreen = !!fullScreen; + if (wantFullScreen === lpFullScreen) { + return; + } + if (wantFullScreen) { + designModeEnabledByFullScreen = !editorCollapsed; + if (!editorCollapsed) { + _setEditorCollapsed(true); + } + _hideSidebarForFullScreen(); + _recomputeFullScreen(); + _syncLeftPositions(); + _applyCollapsedLayout(); + return; + } + if (designModeEnabledByFullScreen) { + _restoreSidebarFromFullScreen(); + _setEditorCollapsed(false); + return; + } + // Design mode was already on, so bringing the sidebar back is the whole undo. + if (!SidebarView.isVisible()) { + SidebarView.show(); + } + sidebarHiddenByFullScreen = false; + _recomputeFullScreen(); + _syncLeftPositions(); + _applyCollapsedLayout(); } function _ccbClickMetric(label) { @@ -446,6 +556,11 @@ define(function (require, exports, module) { _setEditorCollapsed(!editorCollapsed); }, { supportsDesignMode: true }); + const _toggleLPFullScreenCommand = CommandManager.register(Strings.CMD_TOGGLE_LP_FULL_SCREEN, + Commands.VIEW_TOGGLE_LP_FULL_SCREEN, function () { + _setLPFullScreen(!lpFullScreen); + }, { supportsDesignMode: true }); + AppInit.htmlReady(function () { $bar = $("#centralControlBar"); $sidebar = $("#sidebar"); @@ -458,8 +573,7 @@ define(function (require, exports, module) { // strings; set the localized versions up front so the initial render // reflects the user's locale. (searchNav / navBackButton / // navForwardButton get their localized titles from NavigationProvider.) - $("#ccbCollapseEditorBtn").attr("title", Strings.CCB_SWITCH_TO_DESIGN_MODE); - $("#ccbSidebarToggleBtn").attr("title", Strings.CMD_TOGGLE_SIDEBAR); + _updateCollapseBtn(); $("#ccbUndoBtn").attr("title", Strings.CMD_UNDO); $("#ccbRedoBtn").attr("title", Strings.CMD_REDO); $("#ccbSaveBtn").attr("title", Strings.CMD_FILE_SAVE); @@ -511,6 +625,7 @@ define(function (require, exports, module) { _forwardResizeToMainToolbar("panelResizeUpdate"); }); $sidebar.on("panelResizeEnd.ccb panelCollapsed.ccb panelExpanded.ccb", function (e) { + _recomputeFullScreen(); _syncLeftPositions(); if (editorCollapsed) { _applyCollapsedLayout(); @@ -611,4 +726,17 @@ define(function (require, exports, module) { exports.isEditorCollapsed = function () { return editorCollapsed; }; exports.setEditorCollapsed = _setEditorCollapsed; + + /** + * True while live preview is expanded to full screen. Full screen implies design + * mode, so `isEditorCollapsed()` is true as well. + * @returns {boolean} + */ + exports.isLPFullScreen = function () { return lpFullScreen; }; + + /** + * Enters or exits live-preview full screen. + * @param {boolean} fullScreen + */ + exports.setLPFullScreen = _setLPFullScreen; }); diff --git a/src/view/WorkspaceManager.js b/src/view/WorkspaceManager.js index a17e5663ce..5f87fcb70d 100644 --- a/src/view/WorkspaceManager.js +++ b/src/view/WorkspaceManager.js @@ -81,6 +81,13 @@ define(function (require, exports, module) { */ const EVENT_WORKSPACE_DESIGN_MODE_CHANGE = "workspaceDesignModeChange"; + /** + * Event triggered when live-preview full screen (design mode with the sidebar + * hidden) is entered or exited. Payload: `(active: boolean)`. + * @const + */ + const EVENT_WORKSPACE_LP_FULL_SCREEN_CHANGE = "workspaceLPFullScreenChange"; + /** * Width of the main toolbar in pixels. * @const @@ -755,6 +762,38 @@ define(function (require, exports, module) { exports.trigger(EVENT_WORKSPACE_DESIGN_MODE_CHANGE, _isInDesignMode); } + let _isInLPFullScreen = false; + + /** + * Returns true while live preview is expanded to full screen, meaning design mode + * with the sidebar hidden so live preview owns everything to the right of the + * central control bar. + * + * Full screen is a superset of design mode, so `isInDesignMode()` is true here + * too. Use `isInDesignMode()` if you only care that the editor is collapsed; + * use this only when the sidebar state matters. + * @returns {boolean} + */ + function isInLPFullScreen() { + return _isInLPFullScreen; + } + + /** + * Sets the live-preview full-screen flag and fires + * EVENT_WORKSPACE_LP_FULL_SCREEN_CHANGE when the value actually changes. + * Intended to be called by the control bar; other callers should use the + * dedicated toggle command instead. + * @param {boolean} active + */ + function setLPFullScreen(active) { + const next = !!active; + if (_isInLPFullScreen === next) { + return; + } + _isInLPFullScreen = next; + exports.trigger(EVENT_WORKSPACE_LP_FULL_SCREEN_CHANGE, _isInLPFullScreen); + } + // Escape key and toggle panel special handling let _escapeKeyConsumers = {}; @@ -918,8 +957,11 @@ define(function (require, exports, module) { exports.EVENT_WORKSPACE_PANEL_SHOWN = EVENT_WORKSPACE_PANEL_SHOWN; exports.EVENT_WORKSPACE_PANEL_HIDDEN = EVENT_WORKSPACE_PANEL_HIDDEN; exports.EVENT_WORKSPACE_DESIGN_MODE_CHANGE = EVENT_WORKSPACE_DESIGN_MODE_CHANGE; + exports.EVENT_WORKSPACE_LP_FULL_SCREEN_CHANGE = EVENT_WORKSPACE_LP_FULL_SCREEN_CHANGE; exports.isInDesignMode = isInDesignMode; exports.setDesignMode = setDesignMode; + exports.isInLPFullScreen = isInLPFullScreen; + exports.setLPFullScreen = setLPFullScreen; exports.DEFAULT_PANEL_ID = DEFAULT_PANEL_ID; /** diff --git a/test/spec/CentralControlBar-integ-test.js b/test/spec/CentralControlBar-integ-test.js index 3fe377a13d..77c67f91fa 100644 --- a/test/spec/CentralControlBar-integ-test.js +++ b/test/spec/CentralControlBar-integ-test.js @@ -1316,5 +1316,162 @@ define(function (require, exports, module) { expect(CentralControlBar.isEditorCollapsed()).toBe(false); }); }); + + describe("14. Live preview full screen", function () { + // Full screen is derived state: live preview is full screen exactly when + // the editor is collapsed and the sidebar is away. These cover the state + // rule and the enter/exit contract, not icon classes or tooltip strings. + let PreferencesManager; + + beforeAll(function () { + PreferencesManager = brackets.test.PreferencesManager; + }); + + async function enterFullScreen() { + if (WorkspaceManager.isInLPFullScreen()) { + return; + } + CommandManager.execute(Commands.VIEW_TOGGLE_LP_FULL_SCREEN); + await awaitsFor(function () { return WorkspaceManager.isInLPFullScreen(); }, + "full screen to activate", 10000); + await awaitsFor(function () { + const p = livePanel(); + return p && p.isVisible(); + }, "live preview to be visible in full screen", 10000); + } + + async function exitFullScreen() { + if (!WorkspaceManager.isInLPFullScreen()) { + return; + } + CommandManager.execute(Commands.VIEW_TOGGLE_LP_FULL_SCREEN); + await awaitsFor(function () { return !WorkspaceManager.isInLPFullScreen(); }, + "full screen to deactivate", 10000); + } + + it("should collapse the editor and give live preview the full width minus the control bar", + async function () { + await openLivePreview(); + await enterFullScreen(); + + expect(WorkspaceManager.isInDesignMode()).toBe(true); + expect(SidebarView.isVisible()).toBe(false); + + const ccbLeft = _$("#centralControlBar")[0].getBoundingClientRect().left; + expect(ccbLeft).toBeLessThan(2); + + const mtWidth = _$("#main-toolbar").outerWidth(); + expect(Math.abs(mtWidth - (testWindow.innerWidth - CCB_WIDTH))).toBeLessThan(5); + }); + + it("should return to the code editor with the sidebar back when entered from the editor", + async function () { + await openLivePreview(); + await enterFullScreen(); + await exitFullScreen(); + + expect(WorkspaceManager.isInDesignMode()).toBe(false); + expect(SidebarView.isVisible()).toBe(true); + // Live preview was open before full screen, so it stays open. + expect(livePanel().isVisible()).toBe(true); + }); + + it("should return to design mode, not the editor, when entered from design mode", + async function () { + await enterDesignMode(); + await enterFullScreen(); + await exitFullScreen(); + + expect(WorkspaceManager.isInDesignMode()).toBe(true); + expect(SidebarView.isVisible()).toBe(true); + }); + + it("should turn on and off as the sidebar is hidden and shown in design mode", async function () { + await enterDesignMode(); + expect(WorkspaceManager.isInLPFullScreen()).toBe(false); + + SidebarView.hide(); + await awaitsFor(function () { return WorkspaceManager.isInLPFullScreen(); }, + "full screen to follow the sidebar collapsing", 3000); + + SidebarView.show(); + await awaitsFor(function () { return !WorkspaceManager.isInLPFullScreen(); }, + "full screen to follow the sidebar coming back", 3000); + // Only the sidebar came back, the editor stays collapsed. + expect(WorkspaceManager.isInDesignMode()).toBe(true); + }); + + it("should not be full screen when the sidebar is hidden but the editor is still up", + async function () { + expect(WorkspaceManager.isInDesignMode()).toBe(false); + + SidebarView.hide(); + await awaitsFor(function () { return !SidebarView.isVisible(); }, + "sidebar to hide", 2000); + + expect(WorkspaceManager.isInLPFullScreen()).toBe(false); + }); + + it("should drop to design mode when the CCB sidebar toggle is clicked in full screen", + async function () { + await openLivePreview(); + await enterFullScreen(); + + _$("#ccbSidebarToggleBtn").trigger("click"); + + await awaitsFor(function () { return !WorkspaceManager.isInLPFullScreen(); }, + "full screen to exit on sidebar toggle", 5000); + expect(WorkspaceManager.isInDesignMode()).toBe(true); + expect(SidebarView.isVisible()).toBe(true); + }); + + it("should leave the stored sidebar visibility alone so quitting from full screen restores it", + async function () { + await openLivePreview(); + await enterFullScreen(); + + // Resizer writes visible:false on hide. Full screen is not a + // persisted mode, so the stored flag must stay true or the next + // launch comes up with no sidebar. + expect(SidebarView.isVisible()).toBe(false); + expect(PreferencesManager.getViewState("sidebar").visible).toBe(true); + }); + + it("should keep the sidebar hidden on exit when the user hid it themselves", async function () { + await openLivePreview(); + SidebarView.hide(); + await awaitsFor(function () { return !SidebarView.isVisible(); }, + "sidebar to hide", 2000); + + await enterFullScreen(); + await exitFullScreen(); + + expect(SidebarView.isVisible()).toBe(false); + }); + + it("should exit and restore the sidebar when live preview is closed in full screen", + async function () { + await openLivePreview(); + await enterFullScreen(); + + livePanel().hide(); + + await awaitsFor(function () { return !WorkspaceManager.isInLPFullScreen(); }, + "full screen to exit when live preview closes", 5000); + expect(WorkspaceManager.isInDesignMode()).toBe(false); + expect(SidebarView.isVisible()).toBe(true); + }); + + it("should dispatch VIEW_TOGGLE_LP_FULL_SCREEN from the live preview expand button", + async function () { + await openLivePreview(); + + const executed = recordCommands(function () { + _$("#fullScreenLivePreviewButton").trigger("click"); + }); + + expect(executed).toContain(Commands.VIEW_TOGGLE_LP_FULL_SCREEN); + }); + }); }); });