diff --git a/webextensions/common/Tab.js b/webextensions/common/Tab.js
index 1b4fae0ce..948109c39 100644
--- a/webextensions/common/Tab.js
+++ b/webextensions/common/Tab.js
@@ -14,6 +14,7 @@ import {
mapAndFilter,
mapAndFilterUniq,
toLines,
+ sanitizeForHTMLText,
sanitizeForRegExpSource,
isNewTabCommandTab,
isFirefoxViewTab,
@@ -608,6 +609,34 @@ export default class Tab {
return tooltip.join('\n');
}
+ generateTooltipHtml() {
+ return this.cookieStoreName ?
+ `${sanitizeForHTMLText(this.tab.title)}${sanitizeForHTMLText(this.cookieStoreName)}` :
+ `${sanitizeForHTMLText(this.tab.title)}`;
+ }
+
+ generateTooltipHtmlWithDescendants() {
+ return `
${this.generateTooltipHtmlWithDescendantsInternal()}
`;
+ }
+ generateTooltipHtmlWithDescendantsInternal() {
+ let tooltip = `${this.generateTooltipHtml()}`;
+ const children = [];
+ for (const child of this.children) {
+ if (!child)
+ continue;
+ children.push(child.$TST.generateTooltipHtmlWithDescendantsInternal());
+ }
+ if (children.length > 0)
+ tooltip += ``;
+ return `${tooltip}`;
+ }
+
registerTooltipText(ownerId, text, isHighPriority = false) {
if (isHighPriority) {
this.highPriorityTooltipTexts.set(ownerId, text);
diff --git a/webextensions/resources/tab-preview-frame.js b/webextensions/resources/tab-preview-frame.js
index 59d0183b2..e5eb32a9d 100644
--- a/webextensions/resources/tab-preview-frame.js
+++ b/webextensions/resources/tab-preview-frame.js
@@ -178,6 +178,33 @@ try{
.updating {
visibility: hidden;
}
+
+
+ /* tree */
+ .tab-preview-tooltip-text ul,
+ .tab-preview-tooltip-text ul ul {
+ margin: 0 0 0 1em;
+ padding: 0;
+ list-style: disc;
+ }
+
+ .tab-preview-tooltip-text .title-line {
+ display: flex;
+ flex-direction: row;
+ max-width: 100%;
+ white-space: nowrap;
+ }
+ .tab-preview-tooltip-text .title-line .title {
+ overflow: hidden;
+ text-overflow: ellipsis;
+ }
+ .tab-preview-tooltip-text .title-line .cookieStoreName {
+ display: flex;
+ margin-left: 1ch;
+ }
+ .tab-preview-tooltip-text .title-line .cookieStoreName::before {
+ content: "- ";
+ }
`;
document.head.appendChild(style);
@@ -270,7 +297,7 @@ function createPanel() {
return panel;
}
-function updatePanel({ tabId, title, url, tooltipText, hasPreview, previewURL, tabRect, offsetTop, align, scale } = {}) {
+function updatePanel({ tabId, title, url, tooltipText, tooltipHtml, hasPreview, previewURL, tabRect, offsetTop, align, scale } = {}) {
if (!panel)
return;
@@ -297,12 +324,12 @@ function updatePanel({ tabId, title, url, tooltipText, hasPreview, previewURL, t
const titleElement = panel.querySelector('.tab-preview-title');
const urlElement = panel.querySelector('.tab-preview-url');
const tooltipTextElement = panel.querySelector('.tab-preview-tooltip-text');
- if (typeof tooltipText == 'string') {
+ if (typeof tooltipHtml == 'string') {
if (typeof title == 'string' &&
tooltipText != title) {
titleElement.classList.add('hidden');
urlElement.classList.add('hidden');
- tooltipTextElement.textContent = tooltipText;
+ tooltipTextElement.innerHTML = tooltipHtml;
tooltipTextElement.classList.remove('hidden');
panel.classList.add('extended');
}
diff --git a/webextensions/sidebar/components/TabElement.js b/webextensions/sidebar/components/TabElement.js
index 238d19b74..8a22a778c 100644
--- a/webextensions/sidebar/components/TabElement.js
+++ b/webextensions/sidebar/components/TabElement.js
@@ -5,7 +5,8 @@
*/
import {
- configs
+ configs,
+ sanitizeForHTMLText,
} from '/common/common.js';
import * as Constants from '/common/constants.js';
import * as TabsStore from '/common/tabs-store.js';
@@ -409,6 +410,8 @@ windowId = ${tab.windowId}
this.tooltip = this.$TST.generateTooltipText();
this.tooltipWithDescendants = this.$TST.generateTooltipTextWithDescendants();
+ this.tooltipHtml = this.$TST.generateTooltipHtml();
+ this.tooltipHtmlWithDescendants = this.$TST.generateTooltipHtmlWithDescendants();
const tooltipText = configs.tabPreviewTooltip ?
null :
@@ -429,7 +432,7 @@ windowId = ${tab.windowId}
const highPriorityTooltipText = this.$TST.getHighPriorityTooltipText();
if (typeof highPriorityTooltipText == 'string') {
if (highPriorityTooltipText)
- return this.tooltip;
+ return highPriorityTooltipText;
return null;
}
@@ -455,6 +458,42 @@ windowId = ${tab.windowId}
return tooltip;
}
+ get appliedTooltipHtml() {
+ if (configs.showCollapsedDescendantsByTooltip &&
+ this.$TST.subtreeCollapsed &&
+ this.$TST.hasChild) {
+ return this.tooltipHtmlWithDescendants;
+ }
+
+ const highPriorityTooltipText = this.$TST.getHighPriorityTooltipText();
+ if (typeof highPriorityTooltipText == 'string') {
+ if (highPriorityTooltipText)
+ return sanitizeForHTMLText(highPriorityTooltipText);
+
+ return null;
+ }
+
+ let tooltip = null;
+
+ const tab = this.$TST.tab;
+ if (this.classList.contains('faviconized') ||
+ this.overflow ||
+ this.tooltip != tab.title)
+ tooltip = this.tooltipHtml;
+ else
+ tooltip = null;
+
+ const lowPriorityTooltipText = this.$TST.getLowPriorityTooltipText();
+ if (typeof lowPriorityTooltipText == 'string' &&
+ !this.getAttribute('title')) {
+ if (lowPriorityTooltipText)
+ tooltip = sanitizeForHTMLText(lowPriorityTooltipText);
+ else
+ tooltip = null;
+ }
+ return tooltip;
+ }
+
_initExtraItemsContainers() {
if (!this.extraItemsContainerIndentRoot) {
this.extraItemsContainerIndentRoot = this.querySelector(`.${Constants.kEXTRA_ITEMS_CONTAINER}.indent`).attachShadow({ mode: 'open' });
diff --git a/webextensions/sidebar/tab-preview-tooltip.js b/webextensions/sidebar/tab-preview-tooltip.js
index f81a10667..16ca9faca 100644
--- a/webextensions/sidebar/tab-preview-tooltip.js
+++ b/webextensions/sidebar/tab-preview-tooltip.js
@@ -303,6 +303,7 @@ async function onTabSubstanceEnter(event) {
hoveringTabIds.add(event.target.tab.id);
const tooltipText = event.target.appliedTooltipText;
+ const tooltipHtml = event.target.appliedTooltipHtml;
const targetTabId = CUSTOM_PANEL_AVAILABLE_URLS_MATCHER.test(activeTab.url) ?
activeTab.id :
@@ -349,6 +350,7 @@ async function onTabSubstanceEnter(event) {
title: event.target.tab.title,
url,
tooltipText,
+ tooltipHtml,
hasPreview,
timestamp: startAt, // Don't call Date.now() here, because it can become larger than the timestamp on mouseleave.
canRetry: !!targetTabId,