Bug 1892941 - Add a "Always Show" sidebar visibility setting r=sidebar-reviewers,fluent-reviewers,sessionstore-reviewers,bolsson,sclements,reusable-components-reviewers,mstriemer

Differential Revision: https://phabricator.services.mozilla.com/D212285
This commit is contained in:
Jonathan Sudiaman
2024-06-27 19:34:08 +00:00
parent 27036e30ca
commit 52e63f2908
14 changed files with 258 additions and 21 deletions

View File

@@ -1916,6 +1916,7 @@ pref("sidebar.position_start", true);
pref("sidebar.revamp", false);
pref("sidebar.main.tools", "history,syncedtabs");
pref("sidebar.verticalTabs", false);
pref("sidebar.visibility", "always-show");
pref("browser.ml.chat.enabled", false);
pref("browser.ml.chat.hideLocalhost", true);

View File

@@ -48,6 +48,13 @@ XPCOMUtils.defineLazyPreferenceGetter(
false
);
XPCOMUtils.defineLazyPreferenceGetter(
lazy,
"sidebarRevampEnabled",
"sidebar.revamp",
false
);
function setAttributes(aNode, aAttrs) {
let doc = aNode.ownerDocument;
for (let [name, value] of Object.entries(aAttrs)) {
@@ -281,14 +288,15 @@ export const CustomizableWidgets = [
defaultArea: "nav-bar",
_introducedByPref: "sidebar.revamp",
onCommand(aEvent) {
let { SidebarController } = aEvent.target.ownerGlobal;
if (SidebarController.sidebarRevampEnabled) {
SidebarController.toggleExpanded();
const { SidebarController } = aEvent.target.ownerGlobal;
if (lazy.sidebarRevampEnabled) {
SidebarController.handleToolbarButtonClick();
} else {
SidebarController.toggle();
}
},
onCreated(aNode) {
if (!lazy.sidebarRevampEnabled) {
// Add an observer so the button is checked while the sidebar is open
let doc = aNode.ownerDocument;
let obChecked = doc.createXULElement("observes");
@@ -300,6 +308,7 @@ export const CustomizableWidgets = [
aNode.appendChild(obChecked);
aNode.appendChild(obPosition);
}
},
},
{

View File

@@ -4553,6 +4553,12 @@ var SessionStoreInternal = {
delete winData.sidebar.command;
}
if (aWindow.SidebarController.sidebarRevampEnabled) {
winData.sidebar = Object.assign(winData.sidebar || {}, {
expanded: aWindow.SidebarController.sidebarMain.expanded,
});
}
let workspaceID = aWindow.getWorkspaceID();
if (workspaceID) {
winData.workspaceID = workspaceID;
@@ -5609,6 +5615,9 @@ var SessionStoreInternal = {
sidebarBox.setAttribute("style", aSidebar.style);
}
}
if (aSidebar?.expanded) {
aWindow.SidebarController.sidebarMain.expanded = true;
}
},
/**
@@ -6303,7 +6312,7 @@ var SessionStoreInternal = {
}
// We want to preserve the sidebar if previously open in the window
if (window.sidebar?.command) {
if (window.sidebar) {
newWindowState.sidebar = window.sidebar;
}

View File

@@ -108,3 +108,40 @@ class TestSessionRestore(SessionStoreTestCase):
"viewHistorySidebar",
"Correct sidebar category has been restored.",
)
def test_revamp_restore(self):
self.marionette.execute_script(
"""
Services.prefs.setBoolPref("sidebar.revamp", true);
"""
)
self.marionette.restart()
self.marionette.set_context("chrome")
self.assertEqual(
len(self.marionette.chrome_window_handles),
1,
msg="Should have 1 window open.",
)
self.assertTrue(
self.marionette.execute_script(
"""
const window = BrowserWindowTracker.getTopWindow();
window.SidebarController.toggleExpanded();
return window.SidebarController.sidebarMain.expanded;
"""
),
"Sidebar is expanded before window is closed.",
)
self.marionette.restart()
self.assertTrue(
self.marionette.execute_script(
"""
const window = BrowserWindowTracker.getTopWindow();
return window.SidebarController.sidebarMain.expanded;
"""
),
"Sidebar expanded state has been restored.",
)

View File

@@ -211,6 +211,20 @@ var SidebarController = {
return this._inited;
},
get sidebarMain() {
if (!this._sidebarMain) {
this._sidebarMain = document.querySelector("sidebar-main");
}
return this._sidebarMain;
},
get toolbarButton() {
if (!this._toolbarButton) {
this._toolbarButton = document.getElementById("sidebar-button");
}
return this._toolbarButton;
},
async init() {
this._box = document.getElementById("sidebar-box");
this._splitter = document.getElementById("sidebar-splitter");
@@ -242,8 +256,7 @@ var SidebarController = {
await import("chrome://browser/content/sidebar/sidebar-main.mjs");
document.getElementById("sidebar-main").hidden = !window.toolbar.visible;
document.getElementById("sidebar-header").hidden = true;
this._sidebarMain = document.querySelector("sidebar-main");
mainResizeObserver.observe(this._sidebarMain);
mainResizeObserver.observe(this.sidebarMain);
if (this.sidebarVerticalTabsEnabled) {
this.toggleTabstrip();
@@ -479,6 +492,10 @@ var SidebarController = {
this._box.setAttribute("sidebarcommand", commandID);
}
if (this.sidebarRevampEnabled) {
this.sidebarMain.expanded = sourceController.sidebarMain.expanded;
}
if (sourceController._box.hidden) {
// just hidden means we have adopted the hidden state.
return true;
@@ -633,11 +650,16 @@ var SidebarController = {
return this.show(commandID, triggerNode);
},
handleToolbarButtonClick() {
// TODO (Bug 1892430) This behavior is subject to change based on visibility setting.
this.toggleExpanded();
},
/**
* Toggle the expansion state of the sidebar.
*/
toggleExpanded() {
this._sidebarMain.expanded = !this._sidebarMain.expanded;
this.sidebarMain.expanded = !this.sidebarMain.expanded;
},
_loadSidebarExtension(commandID) {
@@ -946,6 +968,11 @@ var SidebarController = {
this._box.dispatchEvent(
new CustomEvent("sidebar-show", { detail: { viewId: commandID } })
);
// Whenever a panel is shown, the sidebar is collapsed. Upon hiding
// that panel afterwards, `expanded` reverts back to what it was prior
// to calling `show()`. Thus, we store the expanded state at this point.
this._previousExpandedState = this.sidebarMain.expanded;
this.sidebarMain.expanded = false;
} else {
this.hideSwitcherPanel();
}
@@ -1019,6 +1046,7 @@ var SidebarController = {
this.hideSwitcherPanel();
if (this.sidebarRevampEnabled) {
this._box.dispatchEvent(new CustomEvent("sidebar-hide"));
this.sidebarMain.expanded = this._previousExpandedState;
}
this.selectMenuItem("");

View File

@@ -0,0 +1,6 @@
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg" fill="context-fill" fill-opacity="context-fill-opacity">
<path fill-rule="evenodd" clip-rule="evenodd" d="M2 2C0.895786 2 0 2.89579 0 4V12C0 13.1042 0.895786 14 2 14H14C15.1042 14 16 13.1042 16 12V4C16 2.89579 15.1042 2 14 2H2ZM6 12.5H14C14.2758 12.5 14.5 12.2758 14.5 12V4C14.5 3.72421 14.2758 3.5 14 3.5H6V12.5Z"/>
</svg>

After

Width:  |  Height:  |  Size: 619 B

View File

@@ -0,0 +1,6 @@
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg" fill="context-fill" fill-opacity="context-fill-opacity">
<path fill-rule="evenodd" clip-rule="evenodd" d="M2 3.5C1.72421 3.5 1.5 3.72421 1.5 4V12C1.5 12.2758 1.72421 12.5 2 12.5H14C14.2758 12.5 14.5 12.2758 14.5 12V4C14.5 3.72421 14.2758 3.5 14 3.5H2ZM0 4C0 2.89579 0.895786 2 2 2H14C15.1042 2 16 2.89579 16 4V12C16 13.1042 15.1042 14 14 14H2C0.895786 14 0 13.1042 0 12V4Z"/>
</svg>

After

Width:  |  Height:  |  Size: 678 B

View File

@@ -17,3 +17,5 @@ browser.jar:
content/browser/sidebar/sidebar-syncedtabs.html
content/browser/sidebar/sidebar-syncedtabs.mjs
content/browser/sidebar/sidebar.css
content/browser/sidebar/sidebar-expanded.svg (content/sidebar-expanded.svg)
content/browser/sidebar/sidebar-hidden.svg (content/sidebar-hidden.svg)

View File

@@ -54,6 +54,10 @@
margin: 0;
}
moz-radio-group {
display: block;
}
#manage-settings {
display: flex;
align-items: center;

View File

@@ -14,21 +14,28 @@ const l10nMap = new Map([
["viewTabsSidebar", "sidebar-menu-synced-tabs-label"],
["viewBookmarksSidebar", "sidebar-menu-bookmarks-label"],
]);
const VISIBILITY_SETTING_PREF = "sidebar.visibility";
export class SidebarCustomize extends SidebarPage {
constructor() {
super();
this.activeExtIndex = 0;
this.visibility = Services.prefs.getStringPref(
VISIBILITY_SETTING_PREF,
"always-show"
);
}
static properties = {
activeExtIndex: { type: Number },
visibility: { type: String },
};
static queries = {
toolInputs: { all: ".customize-firefox-tools moz-checkbox" },
extensionLinks: { all: ".extension-link" },
positionInputs: { all: ".position-setting" },
visibilityInputs: { all: ".visibility-setting" },
};
connectedCallback() {
@@ -37,6 +44,7 @@ export class SidebarCustomize extends SidebarPage {
this.getWindow().addEventListener("SidebarItemChanged", this);
this.getWindow().addEventListener("SidebarItemRemoved", this);
}
disconnectedCallback() {
super.disconnectedCallback();
this.getWindow().removeEventListener("SidebarItemAdded", this);
@@ -178,10 +186,28 @@ export class SidebarCustomize extends SidebarPage {
</div>
</div>`
)}
<h5 data-l10n-id="sidebar-customize-settings"></h5>
<moz-radio-group
@change=${this.#handleVisibilityChange}
name="visibility"
data-l10n-id="sidebar-customize-settings"
>
<moz-radio
class="visibility-setting"
value="always-show"
?checked=${this.visibility === "always-show"}
iconsrc="chrome://browser/content/sidebar/sidebar-expanded.svg"
data-l10n-id="sidebar-visibility-always-show"
></moz-radio>
<moz-radio
class="visibility-setting"
value="hide-sidebar"
?checked=${this.visibility === "hide-sidebar"}
iconsrc="chrome://browser/content/sidebar/sidebar-hidden.svg"
data-l10n-id="sidebar-visibility-hide-sidebar"
></moz-radio>
</moz-radio-group>
<hr>
<moz-radio-group
class="customize-settings"
@change=${this.reversePosition}
name="position">
<moz-radio
@@ -218,6 +244,11 @@ export class SidebarCustomize extends SidebarPage {
</div>
`;
}
#handleVisibilityChange({ target: { value } }) {
this.visibility = value;
Services.prefs.setStringPref(VISIBILITY_SETTING_PREF, value);
}
}
customElements.define("sidebar-customize", SidebarCustomize);

View File

@@ -83,6 +83,15 @@ export default class SidebarMain extends MozLitElement {
window.removeEventListener("SidebarItemRemoved", this);
}
updated(changedProperties) {
if (
changedProperties.has("expanded") &&
window.SidebarController.toolbarButton
) {
window.SidebarController.toolbarButton.checked = this.expanded;
}
}
onSidebarPopupShowing(event) {
// Store the context menu target which holds the id required for managing sidebar items
this.contextMenuTarget =

View File

@@ -30,7 +30,6 @@ sidebar-search-results-header =
sidebar-customize-firefox-tools =
.label = { -brand-product-name } tools
sidebar-customize-firefox-settings = Manage { -brand-short-name } settings
sidebar-customize-settings = Sidebar settings
sidebar-position-left =
.label = Show on the left
sidebar-position-right =
@@ -81,3 +80,10 @@ sidebar-menu-history-header =
.heading = History
sidebar-menu-syncedtabs-header =
.heading = Tabs from other devices
sidebar-customize-settings =
.label = Sidebar settings
sidebar-visibility-always-show =
.label = Always show
sidebar-visibility-hide-sidebar =
.label = Hide sidebar

View File

@@ -3,6 +3,8 @@
"use strict";
requestLongerTimeout(2);
add_setup(() => SpecialPowers.pushPrefEnv({ set: [["sidebar.revamp", true]] }));
async function showCustomizePanel(win) {
@@ -10,7 +12,7 @@ async function showCustomizePanel(win) {
const document = win.SidebarController.browser.contentDocument;
return TestUtils.waitForCondition(async () => {
const component = document.querySelector("sidebar-customize");
if (!component?.positionInputs) {
if (!component?.positionInputs || !component?.visibilityInputs) {
return false;
}
return component;
@@ -189,3 +191,25 @@ add_task(async function test_customize_position_setting() {
await BrowserTestUtils.closeWindow(newWin);
Services.prefs.clearUserPref("sidebar.position_start");
});
add_task(async function test_customize_visibility_setting() {
const win = await BrowserTestUtils.openNewBrowserWindow();
const panel = await showCustomizePanel(win);
const [showInput, hideInput] = panel.visibilityInputs;
ok(showInput.checked, "Always show is enabled by default.");
EventUtils.synthesizeMouseAtCenter(
hideInput,
{},
win.SidebarController.browser.contentWindow
);
ok(hideInput.checked, "Hide sidebar is enabled.");
const newWin = await BrowserTestUtils.openNewBrowserWindow();
const newPanel = await showCustomizePanel(newWin);
const [, newHideInput] = newPanel.visibilityInputs;
ok(newHideInput.checked, "Visibility setting persists.");
await BrowserTestUtils.closeWindow(win);
await BrowserTestUtils.closeWindow(newWin);
Services.prefs.clearUserPref("sidebar.visibility");
});

View File

@@ -93,3 +93,68 @@ add_task(async function test_toolbar_sidebar_button() {
);
await BrowserTestUtils.closeWindow(win);
});
add_task(async function test_expanded_state_for_always_show() {
const win = await BrowserTestUtils.openNewBrowserWindow();
const {
SidebarController: { sidebarMain, toolbarButton },
} = win;
const checkExpandedState = async (
expanded,
component = sidebarMain,
button = toolbarButton
) => {
await TestUtils.waitForCondition(
() => Boolean(component.expanded) == expanded,
expanded ? "Sidebar is expanded." : "Sidebar is collapsed."
);
await TestUtils.waitForCondition(
() => Boolean(button.checked) == expanded,
expanded
? "Toolbar button is highlighted."
: "Toolbar button is not highlighted."
);
};
info("Check default expanded state.");
await checkExpandedState(false);
info("Toggle expanded state via toolbar button.");
EventUtils.synthesizeMouseAtCenter(toolbarButton, {}, win);
await checkExpandedState(true);
EventUtils.synthesizeMouseAtCenter(toolbarButton, {}, win);
await checkExpandedState(false);
info("Collapse the sidebar by loading a tool.");
sidebarMain.expanded = true;
await sidebarMain.updateComplete;
const toolButton = sidebarMain.toolButtons[0];
EventUtils.synthesizeMouseAtCenter(toolButton, {}, win);
await checkExpandedState(false);
info("Restore the sidebar back to its previous state.");
EventUtils.synthesizeMouseAtCenter(toolButton, {}, win);
await checkExpandedState(true);
info("Load and unload a tool with the sidebar collapsed to begin with.");
sidebarMain.expanded = false;
await sidebarMain.updateComplete;
EventUtils.synthesizeMouseAtCenter(toolButton, {}, win);
await checkExpandedState(false);
EventUtils.synthesizeMouseAtCenter(toolButton, {}, win);
await checkExpandedState(false);
info("Check expanded state on a new window.");
sidebarMain.expanded = true;
await sidebarMain.updateComplete;
const newWin = await BrowserTestUtils.openNewBrowserWindow();
await checkExpandedState(
true,
newWin.SidebarController.sidebarMain,
newWin.SidebarController.toolbarButton
);
await BrowserTestUtils.closeWindow(newWin);
await BrowserTestUtils.closeWindow(win);
});