Bug 381821 - Add a preference to allow horizontal scrolling on table view. r=tobyp,darktrojan

### How to test

- Use table view
- Resize columns until the elastic style pushed them back
- Access `Settings` > `General` > `Reading & Display`
- Toggle `Allow horizontal scroll` on

The message list should now have horizontal scrolling enabled
and only the columns that haven't been previously manually resized
should expand. The last column also should be resizable, allowing
more control on the layout.

Differential Revision: https://phabricator.services.mozilla.com/D222886

--HG--
extra : amend_source : da2b8055924e754f3c581982ff932685a6c6180b
This commit is contained in:
Alessandro Castellani 2024-09-26 22:37:51 +00:00
Родитель c4e2c7da8b
Коммит 6396ab509c
11 изменённых файлов: 232 добавлений и 25 удалений

Просмотреть файл

@ -356,6 +356,9 @@ pref("mail.threadpane.padding.bottom_percent", 10);
// Use correspondents column instead of from/recipient columns.
pref("mail.threadpane.use_correspondents", true);
// Allow horizontal scroll and last column resize on the thread pane.
pref("mail.threadpane.table.horizontal_scroll", false);
// To allow images to be inserted into a composition with an auth prompt, we
// need the following two.
pref("network.auth.subresource-img-cross-origin-http-auth-allow", true);

Просмотреть файл

@ -4247,6 +4247,7 @@ var threadPane = {
this.setUpTagStyles();
Services.prefs.addObserver("mailnews.tags.", this);
Services.prefs.addObserver("mail.threadpane.table.horizontal_scroll", this);
Services.obs.addObserver(this, "addrbook-displayname-changed");
Services.obs.addObserver(this, "custom-column-added");
@ -4256,6 +4257,11 @@ var threadPane = {
threadTree = document.getElementById("threadTree");
this.treeTable = threadTree.table;
this.treeTable.editable = true;
this.treeTable.isHorizontalScroll = Services.prefs.getBoolPref(
"mail.threadpane.table.horizontal_scroll",
false
);
this.treeTable.setPopupMenuTemplates([
"threadPaneApplyColumnMenu",
"threadPaneApplyViewMenu",
@ -4359,6 +4365,10 @@ var threadPane = {
uninit() {
Services.prefs.removeObserver("mailnews.tags.", this);
Services.prefs.removeObserver(
"mail.threadpane.table.horizontal_scroll",
this
);
Services.obs.removeObserver(this, "addrbook-displayname-changed");
Services.obs.removeObserver(this, "custom-column-added");
Services.obs.removeObserver(this, "custom-column-removed");
@ -4433,7 +4443,20 @@ var threadPane = {
observe(subject, topic, data) {
switch (topic) {
case "nsPref:changed":
this.setUpTagStyles();
if (data == "mail.threadpane.table.horizontal_scroll") {
this.treeTable.isHorizontalScroll = Services.prefs.getBoolPref(
"mail.threadpane.table.horizontal_scroll",
false
);
// Only call a columns refresh if a folder is selected. We can skip
// this since we already set the isHorizontalScroll variable and it
// will be used next time the user selects a folder.
if (gFolder) {
this.treeTable.updateColumns(this.columns);
}
} else if (data.startsWith("mailnews.tags.")) {
this.setUpTagStyles();
}
break;
case "addrbook-displayname-changed":
// This runs the when mail.displayname.version preference observer is

Просмотреть файл

@ -1754,6 +1754,13 @@ class TreeViewTable extends HTMLTableElement {
*/
popupMenuTemplates = [];
/**
* If the widget implementing the tree view table requires horizontal scroll.
*
* @type {boolean}
*/
isHorizontalScroll = false;
connectedCallback() {
if (this.hasConnected) {
return;
@ -1924,7 +1931,8 @@ class TreeViewTable extends HTMLTableElement {
continue;
}
headerCell.resizable = column != lastResizableColumn;
headerCell.resizable =
this.isHorizontalScroll || column != lastResizableColumn;
if (column.width) {
headerCell.style.setProperty(
`--${column.id}Splitter-width`,

Просмотреть файл

@ -78,6 +78,7 @@ skip-if = os == 'mac'
[browser_tagsMenusAndKeys.js]
skip-if = os == 'mac' && debug # Frequently hangs. Bug 1884033.
[browser_tagsMode.js]
[browser_threadHorizontal.js]
[browser_threads.js]
[browser_threadTreeDeleting.js]
[browser_threadTreeQuirks.js]

Просмотреть файл

@ -0,0 +1,139 @@
/* 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/. */
const { MessageGenerator } = ChromeUtils.importESModule(
"resource://testing-common/mailnews/MessageGenerator.sys.mjs"
);
const { click_through_appmenu } = ChromeUtils.importESModule(
"resource://testing-common/mail/WindowHelpers.sys.mjs"
);
const tabmail = document.getElementById("tabmail");
const about3Pane = tabmail.currentAbout3Pane;
const { threadTree } = about3Pane;
add_setup(async function () {
const account = MailServices.accounts.createLocalMailAccount();
account.addIdentity(MailServices.accounts.createIdentity());
const rootFolder = account.incomingServer.rootFolder.QueryInterface(
Ci.nsIMsgLocalMailFolder
);
const testFolder = rootFolder
.createLocalSubfolder("horizontalScroll")
.QueryInterface(Ci.nsIMsgLocalMailFolder);
const generator = new MessageGenerator();
testFolder.addMessageBatch(
generator
.makeMessages({ count: 5 })
.map(message => message.toMessageString())
);
about3Pane.displayFolder(testFolder.URI);
registerCleanupFunction(() => {
MailServices.accounts.removeAccount(account, false);
Services.prefs.clearUserPref("mail.threadpane.table.horizontal_scroll");
Services.xulStore.removeDocument(
"chrome://messenger/content/messenger.xhtml"
);
about3Pane.folderTree.focus();
});
});
add_task(async function testHorizontalScroll() {
const displayContext = about3Pane.document.getElementById(
"threadPaneDisplayContext"
);
const displayButton = about3Pane.document.getElementById(
"threadPaneDisplayButton"
);
const shownPromise = BrowserTestUtils.waitForEvent(
displayContext,
"popupshown"
);
EventUtils.synthesizeMouseAtCenter(displayButton, {}, about3Pane);
await shownPromise;
const hiddenPromise = BrowserTestUtils.waitForEvent(
displayContext,
"popuphidden"
);
displayContext.activateItem(
displayContext.querySelector("#threadPaneTableView")
);
await BrowserTestUtils.waitForCondition(
() => threadTree.getAttribute("rows") == "thread-row",
"The tree view switched to a table layout"
);
EventUtils.synthesizeKey("KEY_Escape", {});
await hiddenPromise;
const threadPane = about3Pane.document.getElementById("threadPane");
Assert.equal(
threadPane.getBoundingClientRect().width,
threadTree.table.getBoundingClientRect().width,
"The tree table and the parent container should have the same width"
);
Assert.ok(
about3Pane.document.getElementById("dateCol").dataset.resizable == "false",
"The last column shouldn't be resizable"
);
Assert.ok(
about3Pane.document.getElementById("dateColSplitter").isDisabled,
"The last column's splitter should be disabled"
);
Services.prefs.setBoolPref("mail.threadpane.table.horizontal_scroll", true);
// Simulate the resize of some columns by hardcoding a width value so we can
// force a situation in which the user wants columns to be wider than the
// available space offered by the threadPane.
for (const col of ["subjectCol", "correspondentCol", "dateCol"]) {
const element = about3Pane.document.getElementById(col);
element.style = "";
element.width = "400px";
}
await BrowserTestUtils.waitForCondition(
() =>
threadTree.table.getBoundingClientRect().width >
threadPane.getBoundingClientRect().width,
"Waiting for the tree table to grow past its parent"
);
Assert.greater(
threadTree.table.getBoundingClientRect().width,
threadPane.getBoundingClientRect().width,
"The tree table should grow past its parent width"
);
Assert.ok(
about3Pane.document.getElementById("dateCol").dataset.resizable == "true",
"The last column should be resizable"
);
Assert.ok(
!about3Pane.document.getElementById("dateColSplitter").isDisabled,
"The last column's splitter shouldn't be disabled"
);
Services.prefs.setBoolPref("mail.threadpane.table.horizontal_scroll", false);
await BrowserTestUtils.waitForCondition(
() =>
threadTree.table.getBoundingClientRect().width ==
threadPane.getBoundingClientRect().width,
"Waiting for the tree table to shrink within the boundaries of its parent"
);
Assert.equal(
threadPane.getBoundingClientRect().width,
threadTree.table.getBoundingClientRect().width,
"The tree table and the parent container should have the same width"
);
about3Pane.folderTree.focus();
});

Просмотреть файл

@ -1185,6 +1185,7 @@ function reportPreferences() {
"mail.purge.ask",
"mail.addressDisplayFormat",
"mail.showCondensedAddresses",
"mail.threadpane.table.horizontal_scroll",
"mailnews.database.global.indexer.enabled",
"mailnews.mark_message_read.auto",
"mailnews.mark_message_read.delay",

Просмотреть файл

@ -703,29 +703,46 @@
</hbox>
</vbox>
<hbox>
<html:legend data-l10n-id="address-display-legend"></html:legend>
</hbox>
<description flex="1" data-l10n-id="address-display-description"/>
<radiogroup id="changeAddressDisplayFormat"
class="indent"
preference="mail.addressDisplayFormat">
<radio id="displayFull"
value="0"
data-l10n-id="address-display-full"/>
<radio id="displayEmail"
value="1"
data-l10n-id="address-display-email"/>
<radio id="displayName"
value="2"
data-l10n-id="address-display-name"/>
</radiogroup>
<separator class="thin"/>
<hbox>
<checkbox id="showCondensedAddresses"
data-l10n-id="condensed-addresses-label"
preference="mail.showCondensedAddresses"/>
</hbox>
<separator/>
<vbox>
<hbox>
<html:legend data-l10n-id="address-display-legend"></html:legend>
</hbox>
<description flex="1" data-l10n-id="address-display-description"/>
<radiogroup id="changeAddressDisplayFormat"
class="indent"
preference="mail.addressDisplayFormat">
<radio id="displayFull"
value="0"
data-l10n-id="address-display-full"/>
<radio id="displayEmail"
value="1"
data-l10n-id="address-display-email"/>
<radio id="displayName"
value="2"
data-l10n-id="address-display-name"/>
</radiogroup>
<separator class="thin"/>
<hbox>
<checkbox id="showCondensedAddresses"
data-l10n-id="condensed-addresses-label"
preference="mail.showCondensedAddresses"/>
</hbox>
</vbox>
<separator/>
<vbox>
<hbox>
<html:legend data-l10n-id="table-layout-legend"></html:legend>
</hbox>
<hbox>
<checkbox id="tableHorizontalScroll"
data-l10n-id="table-layout-horizontal-scroll-label"
preference="mail.threadpane.table.horizontal_scroll"/>
</hbox>
</vbox>
<separator class="thin"/>

Просмотреть файл

@ -84,6 +84,7 @@ Preferences.addAll([
{ id: "mailnews.labels.color.5", type: "string" },
{ id: "mail.addressDisplayFormat", type: "int" },
{ id: "mail.showCondensedAddresses", type: "bool" },
{ id: "mail.threadpane.table.horizontal_scroll", type: "bool" },
{ id: "mailnews.mark_message_read.auto", type: "bool" },
{ id: "mailnews.mark_message_read.delay", type: "bool" },
{ id: "mailnews.mark_message_read.delay.interval", type: "int" },

Просмотреть файл

@ -149,6 +149,10 @@ add_task(async () => {
{
checkboxID: "showCondensedAddresses",
pref: "mail.showCondensedAddresses",
},
{
checkboxID: "tableHorizontalScroll",
pref: "mail.threadpane.table.horizontal_scroll",
}
);
});

Просмотреть файл

@ -534,6 +534,12 @@ condensed-addresses-label =
.label = Show only display name for people in my address book
.accesskey = S
table-layout-legend = Table View
table-layout-horizontal-scroll-label =
.label = Allow horizontal scroll
.accesskey = h
## Compose Tab
forward-label =

Просмотреть файл

@ -389,6 +389,10 @@ table[is="tree-view-table"] {
line-height: 1;
font-size: 1rem;
color: var(--tree-view-color);
@media (-moz-bool-pref: "mail.threadpane.table.horizontal_scroll") {
flex-basis: auto;
}
}
thead[is="tree-view-table-header"] {