mirror of
https://github.com/zen-browser/desktop.git
synced 2026-04-03 14:19:19 +00:00
no-bug: Implement fast paths and lint
This commit is contained in:
@@ -23,6 +23,7 @@ export class nsZenBoostStyles {
|
||||
* Caches styles to optimize performance.
|
||||
*
|
||||
* @param {object} boostData - The boost configuration data.
|
||||
* @param {string} domain - The domain associated with the boost.
|
||||
* @returns {string} The generated CSS style string.
|
||||
*/
|
||||
getStyleForBoost(boostData, domain) {
|
||||
@@ -59,7 +60,9 @@ export class nsZenBoostStyles {
|
||||
let style = ``;
|
||||
|
||||
const fontFamily =
|
||||
boostData.fontFamily != "" ? `font-family: ${boostData.fontFamily} !important;` : ``;
|
||||
boostData.fontFamily != ""
|
||||
? `font-family: ${boostData.fontFamily} !important;`
|
||||
: ``;
|
||||
const fontCase = `text-transform: ${boostData.textCaseOverride} !important;`;
|
||||
|
||||
let zapBlocks = "";
|
||||
@@ -107,7 +110,6 @@ export class nsZenBoostStyles {
|
||||
*
|
||||
* @param {string} styleUri - The data URI of the CSS style.
|
||||
* @param {string} domain - The domain associated with the boost.
|
||||
* @returns {string} The cached style sheet URI.
|
||||
* @private
|
||||
*/
|
||||
#cacheStyle(styleUri, domain) {
|
||||
|
||||
@@ -46,7 +46,7 @@ export class nsZenBoostEditor {
|
||||
|
||||
this.killOtherEditorInstances();
|
||||
|
||||
nsZenBoostEditor.OBSERVERS.forEach((observe) => {
|
||||
nsZenBoostEditor.OBSERVERS.forEach(observe => {
|
||||
Services.obs.addObserver(this, observe);
|
||||
});
|
||||
|
||||
@@ -60,10 +60,13 @@ export class nsZenBoostEditor {
|
||||
* Initializes the boost editor by setting up event listeners for all UI controls.
|
||||
*/
|
||||
init() {
|
||||
this.editorWindow.addEventListener("unload", () => this.handleClose(), { once: true });
|
||||
this.editorWindow.addEventListener("unload", () => this.handleClose(), {
|
||||
once: true,
|
||||
});
|
||||
|
||||
this.doc.getElementById("zen-boost-editor-root").style.display = "flex";
|
||||
this.doc.getElementById("zen-boost-code-editor-root").style.display = "none";
|
||||
this.doc.getElementById("zen-boost-code-editor-root").style.display =
|
||||
"none";
|
||||
|
||||
this.doc
|
||||
.getElementById("zen-boost-color-contrast")
|
||||
@@ -95,7 +98,7 @@ export class nsZenBoostEditor {
|
||||
.addEventListener("click", this.onToggleInvert.bind(this));
|
||||
this.doc
|
||||
.getElementById("zen-boost-controls")
|
||||
.addEventListener("click", (event) => this.openAdvancedColorOptions(event));
|
||||
.addEventListener("click", event => this.openAdvancedColorOptions(event));
|
||||
this.doc
|
||||
.getElementById("zen-boost-save")
|
||||
.addEventListener("click", this.onSaveBoostClick.bind(this));
|
||||
@@ -118,8 +121,11 @@ export class nsZenBoostEditor {
|
||||
.getElementById("zen-boost-css-inspector")
|
||||
.addEventListener("click", this.onInspectorButtonPressed.bind(this));
|
||||
|
||||
this.doc.addEventListener("keydown", (event) => {
|
||||
if (event.key === "Escape" || (event.key === "w" && (event.ctrlKey || event.metaKey))) {
|
||||
this.doc.addEventListener("keydown", event => {
|
||||
if (
|
||||
event.key === "Escape" ||
|
||||
(event.key === "w" && (event.ctrlKey || event.metaKey))
|
||||
) {
|
||||
this.onClosePressed();
|
||||
}
|
||||
});
|
||||
@@ -133,7 +139,7 @@ export class nsZenBoostEditor {
|
||||
uninit() {
|
||||
this.uninitColorPicker();
|
||||
|
||||
nsZenBoostEditor.OBSERVERS.forEach((observe) => {
|
||||
nsZenBoostEditor.OBSERVERS.forEach(observe => {
|
||||
Services.obs.removeObserver(this, observe);
|
||||
});
|
||||
}
|
||||
@@ -328,7 +334,9 @@ export class nsZenBoostEditor {
|
||||
* @returns {Array<AString>} An array with names of available fonts.
|
||||
*/
|
||||
fetchFontList() {
|
||||
const enumerator = Cc["@mozilla.org/gfx/fontenumerator;1"].createInstance(Ci.nsIFontEnumerator);
|
||||
const enumerator = Cc["@mozilla.org/gfx/fontenumerator;1"].createInstance(
|
||||
Ci.nsIFontEnumerator
|
||||
);
|
||||
|
||||
return enumerator.EnumerateFonts(null, null);
|
||||
}
|
||||
@@ -339,7 +347,8 @@ export class nsZenBoostEditor {
|
||||
onCodeButtonPressed() {
|
||||
const offset = 265;
|
||||
const openRightAligned =
|
||||
this.openerWindow.screenX + this.openerWindow.outerWidth / 2 < this.editorWindow.screenX;
|
||||
this.openerWindow.screenX + this.openerWindow.outerWidth / 2 <
|
||||
this.editorWindow.screenX;
|
||||
const windowElem = this.doc.getElementById("zenBoostWindow");
|
||||
|
||||
if (windowElem.getAttribute("editor") == "code") {
|
||||
@@ -353,13 +362,20 @@ export class nsZenBoostEditor {
|
||||
// being smaller than it should be
|
||||
this._boostEditorWidth = this.editorWindow.outerWidth;
|
||||
|
||||
this.editorWindow.resizeTo(this._codeEditorWidth, this.editorWindow.outerHeight);
|
||||
this.editorWindow.resizeTo(
|
||||
this._codeEditorWidth,
|
||||
this.editorWindow.outerHeight
|
||||
);
|
||||
if (openRightAligned) {
|
||||
this.editorWindow.moveTo(this.editorWindow.screenX - offset, this.editorWindow.screenY);
|
||||
this.editorWindow.moveTo(
|
||||
this.editorWindow.screenX - offset,
|
||||
this.editorWindow.screenY
|
||||
);
|
||||
}
|
||||
|
||||
this.doc.getElementById("zen-boost-editor-root").style.display = "none";
|
||||
this.doc.getElementById("zen-boost-code-editor-root").style.display = "initial";
|
||||
this.doc.getElementById("zen-boost-code-editor-root").style.display =
|
||||
"initial";
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -368,7 +384,8 @@ export class nsZenBoostEditor {
|
||||
onCodeBackButtonPressed() {
|
||||
const offset = 265;
|
||||
const openRightAligned =
|
||||
this.openerWindow.screenX + this.openerWindow.outerWidth / 2 < this.editorWindow.screenX;
|
||||
this.openerWindow.screenX + this.openerWindow.outerWidth / 2 <
|
||||
this.editorWindow.screenX;
|
||||
const windowElem = this.doc.getElementById("zenBoostWindow");
|
||||
|
||||
if (windowElem.getAttribute("editor") == "boost") {
|
||||
@@ -376,13 +393,20 @@ export class nsZenBoostEditor {
|
||||
}
|
||||
windowElem.setAttribute("editor", "boost");
|
||||
|
||||
this.editorWindow.resizeTo(this._boostEditorWidth, this.editorWindow.outerHeight);
|
||||
this.editorWindow.resizeTo(
|
||||
this._boostEditorWidth,
|
||||
this.editorWindow.outerHeight
|
||||
);
|
||||
if (openRightAligned) {
|
||||
this.editorWindow.moveTo(this.editorWindow.screenX + offset, this.editorWindow.screenY);
|
||||
this.editorWindow.moveTo(
|
||||
this.editorWindow.screenX + offset,
|
||||
this.editorWindow.screenY
|
||||
);
|
||||
}
|
||||
|
||||
this.doc.getElementById("zen-boost-editor-root").style.display = "flex";
|
||||
this.doc.getElementById("zen-boost-code-editor-root").style.display = "none";
|
||||
this.doc.getElementById("zen-boost-code-editor-root").style.display =
|
||||
"none";
|
||||
|
||||
// Disable picker mode
|
||||
this.disableAllPickers();
|
||||
@@ -390,7 +414,8 @@ export class nsZenBoostEditor {
|
||||
|
||||
async onZapButtonPressed() {
|
||||
const linkedBrowser = this.openerWindow.gBrowser.selectedTab.linkedBrowser;
|
||||
const actor = linkedBrowser.browsingContext.currentWindowGlobal.getActor("ZenBoosts");
|
||||
const actor =
|
||||
linkedBrowser.browsingContext.currentWindowGlobal.getActor("ZenBoosts");
|
||||
actor.sendQuery("ZenBoost:ToggleZapMode");
|
||||
|
||||
// Focus the parent browser window
|
||||
@@ -399,7 +424,8 @@ export class nsZenBoostEditor {
|
||||
|
||||
async onPickerButtonPressed() {
|
||||
const linkedBrowser = this.openerWindow.gBrowser.selectedTab.linkedBrowser;
|
||||
const actor = linkedBrowser.browsingContext.currentWindowGlobal.getActor("ZenBoosts");
|
||||
const actor =
|
||||
linkedBrowser.browsingContext.currentWindowGlobal.getActor("ZenBoosts");
|
||||
actor.sendQuery("ZenBoost:TogglePickerMode");
|
||||
}
|
||||
|
||||
@@ -425,13 +451,15 @@ ${cssSelector} {
|
||||
|
||||
onInspectorButtonPressed() {
|
||||
const linkedBrowser = this.openerWindow.gBrowser.selectedTab.linkedBrowser;
|
||||
const actor = linkedBrowser.browsingContext.currentWindowGlobal.getActor("ZenBoosts");
|
||||
const actor =
|
||||
linkedBrowser.browsingContext.currentWindowGlobal.getActor("ZenBoosts");
|
||||
actor.sendQuery("ZenBoost:OpenInspector");
|
||||
}
|
||||
|
||||
async onUpdateZapButtonVisual() {
|
||||
const linkedBrowser = this.openerWindow.gBrowser.selectedTab.linkedBrowser;
|
||||
const actor = linkedBrowser.browsingContext.currentWindowGlobal.getActor("ZenBoosts");
|
||||
const actor =
|
||||
linkedBrowser.browsingContext.currentWindowGlobal.getActor("ZenBoosts");
|
||||
const zapButton = this.doc.getElementById("zen-boost-zap");
|
||||
const zapEnabled = await actor.sendQuery("ZenBoost:ZapModeEnabled");
|
||||
|
||||
@@ -440,10 +468,13 @@ ${cssSelector} {
|
||||
|
||||
async onUpdatePickerButtonVisual() {
|
||||
const linkedBrowser = this.openerWindow.gBrowser.selectedTab.linkedBrowser;
|
||||
const actor = linkedBrowser.browsingContext.currentWindowGlobal.getActor("ZenBoosts");
|
||||
const actor =
|
||||
linkedBrowser.browsingContext.currentWindowGlobal.getActor("ZenBoosts");
|
||||
|
||||
const pickerButton = this.doc.getElementById("zen-boost-css-picker");
|
||||
const selectEnabled = await actor.sendQuery("ZenBoost:SelectorPickerModeEnabled");
|
||||
const selectEnabled = await actor.sendQuery(
|
||||
"ZenBoost:SelectorPickerModeEnabled"
|
||||
);
|
||||
|
||||
pickerButton.setAttribute("enabled", selectEnabled ? "true" : "false");
|
||||
}
|
||||
@@ -479,7 +510,9 @@ ${cssSelector} {
|
||||
* interactive color selection on the gradient picker.
|
||||
*/
|
||||
initColorPicker() {
|
||||
const themePicker = this.doc.querySelector(".zen-boost-color-picker-gradient");
|
||||
const themePicker = this.doc.querySelector(
|
||||
".zen-boost-color-picker-gradient"
|
||||
);
|
||||
this._onMouseMove = this.onMouseMove.bind(this);
|
||||
this._onMouseUp = this.onMouseUp.bind(this);
|
||||
this._onMouseDown = this.onMouseDown.bind(this);
|
||||
@@ -494,7 +527,9 @@ ${cssSelector} {
|
||||
* Uninitializes the color picker by removing all mouse event listeners.
|
||||
*/
|
||||
uninitColorPicker() {
|
||||
const themePicker = this.doc.querySelector(".zen-boost-color-picker-gradient");
|
||||
const themePicker = this.doc.querySelector(
|
||||
".zen-boost-color-picker-gradient"
|
||||
);
|
||||
this.doc.removeEventListener("mousemove", this._onMouseMove);
|
||||
this.doc.removeEventListener("mouseup", this._onMouseUp);
|
||||
themePicker.removeEventListener("mousedown", this._onMouseDown);
|
||||
@@ -579,9 +614,15 @@ ${cssSelector} {
|
||||
* and updates the current boost data accordingly.
|
||||
*/
|
||||
onColorOptionChange() {
|
||||
this.currentBoostData.contrast = this.doc.getElementById("zen-boost-color-contrast").value;
|
||||
this.currentBoostData.brightness = this.doc.getElementById("zen-boost-color-brightness").value;
|
||||
this.currentBoostData.saturation = this.doc.getElementById("zen-boost-color-saturation").value;
|
||||
this.currentBoostData.contrast = this.doc.getElementById(
|
||||
"zen-boost-color-contrast"
|
||||
).value;
|
||||
this.currentBoostData.brightness = this.doc.getElementById(
|
||||
"zen-boost-color-brightness"
|
||||
).value;
|
||||
this.currentBoostData.saturation = this.doc.getElementById(
|
||||
"zen-boost-color-saturation"
|
||||
).value;
|
||||
|
||||
this.updateCurrentBoost();
|
||||
}
|
||||
@@ -592,7 +633,9 @@ ${cssSelector} {
|
||||
* @param {Event} event - The click event that triggered this action.
|
||||
*/
|
||||
openAdvancedColorOptions(event) {
|
||||
const panel = this.doc.getElementById("zen-boost-advanced-color-options-panel");
|
||||
const panel = this.doc.getElementById(
|
||||
"zen-boost-advanced-color-options-panel"
|
||||
);
|
||||
panel.openPopup(event.target, "bottomcenter topcenter", 0, 2);
|
||||
}
|
||||
|
||||
@@ -646,7 +689,8 @@ ${cssSelector} {
|
||||
|
||||
if (!animate) {
|
||||
let nDistance = Math.sqrt(
|
||||
(pixelX - this.lastDotSetPos.x) ** 2 + (pixelY - this.lastDotSetPos.y) ** 2
|
||||
(pixelX - this.lastDotSetPos.x) ** 2 +
|
||||
(pixelY - this.lastDotSetPos.y) ** 2
|
||||
);
|
||||
|
||||
if (nDistance > 15) {
|
||||
@@ -667,7 +711,9 @@ ${cssSelector} {
|
||||
this.currentBoostData.dotAngleDeg = 0;
|
||||
this.currentBoostData.dotDistance = 0;
|
||||
} else {
|
||||
let distance = Math.sqrt((pixelX - centerX) ** 2 + (pixelY - centerY) ** 2);
|
||||
let distance = Math.sqrt(
|
||||
(pixelX - centerX) ** 2 + (pixelY - centerY) ** 2
|
||||
);
|
||||
distance = Math.min(distance, radius); // Clamp distance
|
||||
|
||||
const angle = Math.atan2(pixelY - centerY, pixelX - centerX);
|
||||
@@ -677,7 +723,9 @@ ${cssSelector} {
|
||||
|
||||
// Rad to degree
|
||||
this.currentBoostData.dotAngleDeg =
|
||||
((Math.atan2(pixelY - centerY, pixelX - centerX) * 180) / Math.PI + 100) % 360;
|
||||
((Math.atan2(pixelY - centerY, pixelX - centerX) * 180) / Math.PI +
|
||||
100) %
|
||||
360;
|
||||
if (this.currentBoostData.dotAngleDeg < 0) {
|
||||
this.currentBoostData.dotAngleDeg += 360;
|
||||
}
|
||||
@@ -723,6 +771,8 @@ ${cssSelector} {
|
||||
|
||||
/**
|
||||
* Updates the radius of the circle based on the dot's position.
|
||||
*
|
||||
* @param {boolean} animate - Whether to animate the radius change (default: true).
|
||||
*/
|
||||
updateCircleRadius(animate = true) {
|
||||
const gradient = this.doc.querySelector(".zen-boost-color-picker-gradient");
|
||||
@@ -743,7 +793,8 @@ ${cssSelector} {
|
||||
* @param {boolean} userAction - Whether this was triggered by a user action (default: true).
|
||||
*/
|
||||
onToggleDisable(userAction = true) {
|
||||
this.currentBoostData.enableColorBoost = !this.currentBoostData.enableColorBoost;
|
||||
this.currentBoostData.enableColorBoost =
|
||||
!this.currentBoostData.enableColorBoost;
|
||||
|
||||
if (userAction) {
|
||||
this.currentBoostData.changeWasMade = true;
|
||||
@@ -816,7 +867,10 @@ ${cssSelector} {
|
||||
// Give the gradient a grayscale effect
|
||||
// when the color boosting is disabled
|
||||
// or the theme is set automatically
|
||||
if (!this.currentBoostData.enableColorBoost || this.currentBoostData.autoTheme) {
|
||||
if (
|
||||
!this.currentBoostData.enableColorBoost ||
|
||||
this.currentBoostData.autoTheme
|
||||
) {
|
||||
gradient.classList.add("zen-boost-panel-disabled");
|
||||
} else {
|
||||
gradient.classList.remove("zen-boost-panel-disabled");
|
||||
@@ -828,8 +882,12 @@ ${cssSelector} {
|
||||
*/
|
||||
updateColorControlSliderVisuals() {
|
||||
const contrastSlider = this.doc.getElementById("zen-boost-color-contrast");
|
||||
const brightnessSlider = this.doc.getElementById("zen-boost-color-brightness");
|
||||
const saturationSlider = this.doc.getElementById("zen-boost-color-saturation");
|
||||
const brightnessSlider = this.doc.getElementById(
|
||||
"zen-boost-color-brightness"
|
||||
);
|
||||
const saturationSlider = this.doc.getElementById(
|
||||
"zen-boost-color-saturation"
|
||||
);
|
||||
|
||||
contrastSlider.value = this.currentBoostData.contrast;
|
||||
brightnessSlider.value = this.currentBoostData.brightness;
|
||||
@@ -882,7 +940,9 @@ ${cssSelector} {
|
||||
const fontButtonGroup = this.doc.getElementById("zen-boost-font-grid");
|
||||
for (let i = 0; i < fontButtonGroup.children.length; i++) {
|
||||
const fontButton = fontButtonGroup.children[i];
|
||||
if (fontButton.getAttribute("font-data") == this.currentBoostData.fontFamily) {
|
||||
if (
|
||||
fontButton.getAttribute("font-data") == this.currentBoostData.fontFamily
|
||||
) {
|
||||
fontButton.classList.add("zen-boost-font-button-active");
|
||||
} else {
|
||||
fontButton.classList.remove("zen-boost-font-button-active");
|
||||
@@ -904,7 +964,10 @@ ${cssSelector} {
|
||||
* This triggers notifications to observers but does not persist to disk.
|
||||
*/
|
||||
updateCurrentBoost() {
|
||||
const boost = gZenBoostsManager.loadBoostFromStore(this.boostInfo.domain, this.boostInfo.id);
|
||||
const boost = gZenBoostsManager.loadBoostFromStore(
|
||||
this.boostInfo.domain,
|
||||
this.boostInfo.id
|
||||
);
|
||||
boost.boostEntry.boostData = this.currentBoostData;
|
||||
gZenBoostsManager.updateBoost(boost);
|
||||
}
|
||||
@@ -913,7 +976,10 @@ ${cssSelector} {
|
||||
* Deletes the current boost for the domain and closes the editor window.
|
||||
*/
|
||||
deleteBoost() {
|
||||
const boost = gZenBoostsManager.loadBoostFromStore(this.boostInfo.domain, this.boostInfo.id);
|
||||
const boost = gZenBoostsManager.loadBoostFromStore(
|
||||
this.boostInfo.domain,
|
||||
this.boostInfo.id
|
||||
);
|
||||
gZenBoostsManager.deleteBoost(boost);
|
||||
|
||||
this.currentBoostData = null;
|
||||
@@ -954,7 +1020,9 @@ ${cssSelector} {
|
||||
async editBoostName() {
|
||||
const nameText = this.doc.getElementById("zen-boost-name-text");
|
||||
|
||||
const [title] = await this.doc.l10n.formatMessages(["zen-boost-rename-boost-prompt"]);
|
||||
const [title] = await this.doc.l10n.formatMessages([
|
||||
"zen-boost-rename-boost-prompt",
|
||||
]);
|
||||
|
||||
let input = {
|
||||
value: this.currentBoostData.boostName, // Default value and also output
|
||||
@@ -996,11 +1064,16 @@ ${cssSelector} {
|
||||
const loadButton = this.doc.getElementById("zen-boost-save");
|
||||
loadButton.setAttribute("mode", "blue");
|
||||
|
||||
const success = await gZenBoostsManager.exportBoost(this.editorWindow, this.currentBoostData);
|
||||
const success = await gZenBoostsManager.exportBoost(
|
||||
this.editorWindow,
|
||||
this.currentBoostData
|
||||
);
|
||||
|
||||
loadButton.setAttribute("mode", "");
|
||||
if (success) {
|
||||
this.openerWindow.gZenUIManager.showToast("zen-panel-ui-boosts-exported-message");
|
||||
this.openerWindow.gZenUIManager.showToast(
|
||||
"zen-panel-ui-boosts-exported-message"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1074,11 +1147,14 @@ ${cssSelector} {
|
||||
}
|
||||
);
|
||||
|
||||
const anim3 = elementShadow.animate([{ opacity: 0 }, { opacity: 1 }, { opacity: 0 }], {
|
||||
duration: 460,
|
||||
fill: "forwards",
|
||||
easing: "ease-out",
|
||||
});
|
||||
const anim3 = elementShadow.animate(
|
||||
[{ opacity: 0 }, { opacity: 1 }, { opacity: 0 }],
|
||||
{
|
||||
duration: 460,
|
||||
fill: "forwards",
|
||||
easing: "ease-out",
|
||||
}
|
||||
);
|
||||
|
||||
Promise.all([anim1.finished, anim2.finished, anim3.finished]).then(() => {
|
||||
element.remove();
|
||||
@@ -1138,8 +1214,14 @@ ${cssSelector} {
|
||||
this.uninit();
|
||||
if (this.currentBoostData != null && this.currentBoostData.changeWasMade) {
|
||||
this.saveBoost();
|
||||
} else if (this.currentBoostData != null && !this.currentBoostData.changeWasMade) {
|
||||
const boost = gZenBoostsManager.loadBoostFromStore(this.boostInfo.domain, this.boostInfo.id);
|
||||
} else if (
|
||||
this.currentBoostData != null &&
|
||||
!this.currentBoostData.changeWasMade
|
||||
) {
|
||||
const boost = gZenBoostsManager.loadBoostFromStore(
|
||||
this.boostInfo.domain,
|
||||
this.boostInfo.id
|
||||
);
|
||||
gZenBoostsManager.deleteBoost(boost);
|
||||
}
|
||||
|
||||
@@ -1166,13 +1248,19 @@ ${cssSelector} {
|
||||
}
|
||||
|
||||
updateAllVisuals() {
|
||||
this.doc.getElementById("zen-boost-name-text").textContent = this.currentBoostData.boostName;
|
||||
this.doc.getElementById("zen-boost-name-text").textContent =
|
||||
this.currentBoostData.boostName;
|
||||
const dot = this.doc.querySelector(".zen-boost-color-picker-dot");
|
||||
|
||||
if (this.currentBoostData.dotPos.x == null || this.currentBoostData.dotPos.y == null) {
|
||||
if (
|
||||
this.currentBoostData.dotPos.x == null ||
|
||||
this.currentBoostData.dotPos.y == null
|
||||
) {
|
||||
this.resetDotPosition();
|
||||
} else {
|
||||
const gradient = this.doc.querySelector(".zen-boost-color-picker-gradient");
|
||||
const gradient = this.doc.querySelector(
|
||||
".zen-boost-color-picker-gradient"
|
||||
);
|
||||
const rect = gradient.getBoundingClientRect();
|
||||
|
||||
// Test if the stored position is a non-normalized dot position
|
||||
@@ -1183,8 +1271,10 @@ ${cssSelector} {
|
||||
this.currentBoostData.dotPos.y < 0
|
||||
) {
|
||||
// Normalize position
|
||||
this.currentBoostData.dotPos.x = this.currentBoostData.dotPos.x / rect.width;
|
||||
this.currentBoostData.dotPos.y = this.currentBoostData.dotPos.y / rect.height;
|
||||
this.currentBoostData.dotPos.x =
|
||||
this.currentBoostData.dotPos.x / rect.width;
|
||||
this.currentBoostData.dotPos.y =
|
||||
this.currentBoostData.dotPos.y / rect.height;
|
||||
}
|
||||
|
||||
// Convert normalized position to relative position
|
||||
@@ -1215,7 +1305,10 @@ ${cssSelector} {
|
||||
return;
|
||||
}
|
||||
|
||||
const boost = gZenBoostsManager.loadBoostFromStore(this.boostInfo.domain, this.boostInfo.id);
|
||||
const boost = gZenBoostsManager.loadBoostFromStore(
|
||||
this.boostInfo.domain,
|
||||
this.boostInfo.id
|
||||
);
|
||||
boost.boostEntry.boostData = this.currentBoostData;
|
||||
|
||||
gZenBoostsManager.saveBoostToStore(boost);
|
||||
|
||||
@@ -231,7 +231,9 @@ class nsZenBoostsManager {
|
||||
}
|
||||
|
||||
if (domainEntry.boostEntries.has(domainEntry.activeBoostId)) {
|
||||
const boostEntry = domainEntry.boostEntries.get(domainEntry.activeBoostId);
|
||||
const boostEntry = domainEntry.boostEntries.get(
|
||||
domainEntry.activeBoostId
|
||||
);
|
||||
return { id: domainEntry.activeBoostId, domain, boostEntry };
|
||||
}
|
||||
}
|
||||
@@ -323,13 +325,17 @@ class nsZenBoostsManager {
|
||||
if (domainEntry.boostEntries.has(id)) {
|
||||
if (domainEntry.activeBoostId === id) {
|
||||
domainEntry.activeBoostId = null;
|
||||
Services.obs.notifyObservers(null, "zen-boosts-active-change", { id: null });
|
||||
Services.obs.notifyObservers(null, "zen-boosts-active-change", {
|
||||
id: null,
|
||||
});
|
||||
|
||||
this.#stylesManager.invalidateStyleForDomain(domain);
|
||||
this.notify(true);
|
||||
} else {
|
||||
domainEntry.activeBoostId = id;
|
||||
Services.obs.notifyObservers(null, "zen-boosts-active-change", { id });
|
||||
Services.obs.notifyObservers(null, "zen-boosts-active-change", {
|
||||
id,
|
||||
});
|
||||
|
||||
this.#stylesManager.invalidateStyleForDomain(domain);
|
||||
this.notify();
|
||||
@@ -374,6 +380,8 @@ class nsZenBoostsManager {
|
||||
/**
|
||||
* Notifies all observers that boost data has been updated.
|
||||
* This triggers a 'zen-boosts-update' notification event.
|
||||
*
|
||||
* @param {boolean} unloadStyles - Whether to unload styles during the update.
|
||||
*/
|
||||
notify(unloadStyles = false) {
|
||||
Services.obs.notifyObservers(null, "zen-boosts-update", { unloadStyles });
|
||||
@@ -400,7 +408,7 @@ class nsZenBoostsManager {
|
||||
* @private
|
||||
*/
|
||||
#readBoostsFromStore(done) {
|
||||
this.#readFromDisk().then((data) => {
|
||||
this.#readFromDisk().then(data => {
|
||||
this.registeredDomains = data;
|
||||
done();
|
||||
});
|
||||
@@ -587,7 +595,9 @@ class nsZenBoostsManager {
|
||||
*/
|
||||
openBoostWindow(parentWindow, boost, domainUri) {
|
||||
if (!this.canBoostSite(domainUri)) {
|
||||
console.error("[ZenBoostsManager] Cannot open editor for boost with invalid domain.");
|
||||
console.error(
|
||||
"[ZenBoostsManager] Cannot open editor for boost with invalid domain."
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -624,12 +634,16 @@ class nsZenBoostsManager {
|
||||
);
|
||||
|
||||
// Close the editor if the tab is switched
|
||||
parentWindow.gBrowser.tabContainer.addEventListener("TabSelect", editor.close.bind(editor), {
|
||||
once: true,
|
||||
});
|
||||
parentWindow.gBrowser.tabContainer.addEventListener(
|
||||
"TabSelect",
|
||||
editor.close.bind(editor),
|
||||
{
|
||||
once: true,
|
||||
}
|
||||
);
|
||||
|
||||
const progressListener = {
|
||||
onLocationChange: (webProgress) => {
|
||||
onLocationChange: webProgress => {
|
||||
if (webProgress.isTopLevel) {
|
||||
editor.close();
|
||||
parentWindow.gBrowser.removeTabsProgressListener(progressListener);
|
||||
@@ -654,6 +668,7 @@ class nsZenBoostsManager {
|
||||
* Will spawn a file save dialog and export the selected boost
|
||||
*
|
||||
* @param {Window} parentWindow The window that will instance the file picker
|
||||
* @param {object} boostData The data of the boost to be exported
|
||||
* @returns {Promise<void>} Returns a promise which will be resolved after the export action is complete
|
||||
*/
|
||||
exportBoost(parentWindow, boostData) {
|
||||
@@ -693,8 +708,8 @@ class nsZenBoostsManager {
|
||||
fp.defaultExtension = "json";
|
||||
fp.appendFilters(nsIFilePicker.filterAll);
|
||||
|
||||
return new Promise((resolve) => {
|
||||
fp.open(async (result) => {
|
||||
return new Promise(resolve => {
|
||||
fp.open(async result => {
|
||||
if (result === nsIFilePicker.returnOK && fp.file) {
|
||||
try {
|
||||
const boostJSON = JSON.stringify(boostData);
|
||||
@@ -721,12 +736,16 @@ class nsZenBoostsManager {
|
||||
const nsIFilePicker = Ci.nsIFilePicker;
|
||||
const fp = Cc["@mozilla.org/filepicker;1"].createInstance(nsIFilePicker);
|
||||
|
||||
fp.init(parentWindow.browsingContext, "Importing Boost from JSON", nsIFilePicker.modeOpen);
|
||||
fp.init(
|
||||
parentWindow.browsingContext,
|
||||
"Importing Boost from JSON",
|
||||
nsIFilePicker.modeOpen
|
||||
);
|
||||
|
||||
fp.appendFilters(nsIFilePicker.filterAll);
|
||||
|
||||
return new Promise((resolve) => {
|
||||
fp.open(async (result) => {
|
||||
return new Promise(resolve => {
|
||||
fp.open(async result => {
|
||||
if (result === nsIFilePicker.returnOK && fp.file) {
|
||||
try {
|
||||
const fileContent = await IOUtils.readUTF8(fp.file.path);
|
||||
|
||||
@@ -89,13 +89,19 @@ export class SelectorComponent {
|
||||
this.cancelButton.addEventListener("click", this.#cancelSelect.bind(this));
|
||||
|
||||
this.selectThisButton = this.getElementById("select-this");
|
||||
this.selectThisButton.addEventListener("click", this.#handleSelect.bind(this));
|
||||
this.selectThisButton.addEventListener(
|
||||
"click",
|
||||
this.#handleSelect.bind(this)
|
||||
);
|
||||
|
||||
this.selectRelatedSlider = this.getElementById("select-related");
|
||||
this.selectRelatedSlider.addEventListener("click", this.#handleSelect.bind(this));
|
||||
this.selectRelatedSlider.addEventListener(
|
||||
"click",
|
||||
this.#handleSelect.bind(this)
|
||||
);
|
||||
|
||||
// Initialize the related elements button
|
||||
this.selectRelatedSlider.addEventListener("mousemove", (e) => {
|
||||
this.selectRelatedSlider.addEventListener("mousemove", e => {
|
||||
const r = e.currentTarget.getBoundingClientRect();
|
||||
const mouseX = e.clientX;
|
||||
|
||||
@@ -113,7 +119,7 @@ export class SelectorComponent {
|
||||
}
|
||||
});
|
||||
|
||||
this.selectRelatedSlider.addEventListener("mouseout", (e) => {
|
||||
this.selectRelatedSlider.addEventListener("mouseout", e => {
|
||||
e.currentTarget.style.removeProperty("--related-elements-value");
|
||||
|
||||
this.#relatedValueIndex = 0;
|
||||
@@ -159,6 +165,8 @@ export class SelectorComponent {
|
||||
|
||||
/**
|
||||
* Helper for getting an anonymous element by id
|
||||
*
|
||||
* @param {string} id The id of the element
|
||||
*/
|
||||
getElementById(id) {
|
||||
return this.content.root.getElementById(id);
|
||||
@@ -166,9 +174,8 @@ export class SelectorComponent {
|
||||
|
||||
get markup() {
|
||||
// Fetch localizations
|
||||
let [thisElement, relatedElements, cancelAction] = lazy.overlayLocalization.formatMessagesSync(
|
||||
this.#localizationArray
|
||||
);
|
||||
let [thisElement, relatedElements, cancelAction] =
|
||||
lazy.overlayLocalization.formatMessagesSync(this.#localizationArray);
|
||||
|
||||
return `
|
||||
<template>
|
||||
@@ -194,7 +201,10 @@ export class SelectorComponent {
|
||||
if (!this.template) {
|
||||
let parser = new DOMParser();
|
||||
let doc = parser.parseFromString(this.markup, "text/html");
|
||||
this.template = this.document.importNode(doc.querySelector("template"), true);
|
||||
this.template = this.document.importNode(
|
||||
doc.querySelector("template"),
|
||||
true
|
||||
);
|
||||
}
|
||||
let fragment = this.template.content.cloneNode(true);
|
||||
return fragment;
|
||||
@@ -389,12 +399,18 @@ export class SelectorComponent {
|
||||
const top = this.clamp(
|
||||
bounds.top + bounds.height + distance,
|
||||
windowPadding + this.safeAreaPadding.top,
|
||||
windowHeight - zapComponentHeight - windowPadding - this.safeAreaPadding.bottom
|
||||
windowHeight -
|
||||
zapComponentHeight -
|
||||
windowPadding -
|
||||
this.safeAreaPadding.bottom
|
||||
);
|
||||
const left = this.clamp(
|
||||
bounds.left + bounds.width / 2 - zapComponentWidth / 2,
|
||||
windowPadding + this.safeAreaPadding.left,
|
||||
windowWidth - zapComponentWidth - windowPadding - this.safeAreaPadding.right
|
||||
windowWidth -
|
||||
zapComponentWidth -
|
||||
windowPadding -
|
||||
this.safeAreaPadding.right
|
||||
);
|
||||
|
||||
Object.assign(this.selectorComponent.style, {
|
||||
@@ -491,7 +507,10 @@ export class SelectorComponent {
|
||||
this.#hideHoverDiv();
|
||||
}
|
||||
|
||||
if (this.#currentState !== SelectorComponent.STATES.SELECTING || !event.target) {
|
||||
if (
|
||||
this.#currentState !== SelectorComponent.STATES.SELECTING ||
|
||||
!event.target
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -522,7 +541,10 @@ export class SelectorComponent {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.#currentState === SelectorComponent.STATES.SELECTING && !isZenContent) {
|
||||
if (
|
||||
this.#currentState === SelectorComponent.STATES.SELECTING &&
|
||||
!isZenContent
|
||||
) {
|
||||
this.setState(SelectorComponent.STATES.SELECTED, event.target);
|
||||
}
|
||||
}
|
||||
@@ -560,14 +582,18 @@ export class SelectorComponent {
|
||||
/**
|
||||
* Used for retreiving the css path from the selected element and taking
|
||||
* the related objects into account
|
||||
*
|
||||
* @param {Element} document
|
||||
* @param {Element} relatedValueIndex
|
||||
* @param {Element} selectedElement
|
||||
*/
|
||||
getSelectionPath(document, relatedValueIndex, selectedElement) {
|
||||
let path = [];
|
||||
|
||||
const cssescape = (str) => CSS.escape(str);
|
||||
const cssescape = str => CSS.escape(str);
|
||||
|
||||
// Body and Html nodes are not considered valid here
|
||||
const isValidNode = (element) => {
|
||||
const isValidNode = element => {
|
||||
if (!element) {
|
||||
return false;
|
||||
} else if (element.tagName.toLowerCase() === "body") {
|
||||
@@ -578,7 +604,7 @@ export class SelectorComponent {
|
||||
return true;
|
||||
};
|
||||
|
||||
const nthChild = (element) => {
|
||||
const nthChild = element => {
|
||||
if (!element) {
|
||||
return "";
|
||||
}
|
||||
@@ -604,7 +630,7 @@ export class SelectorComponent {
|
||||
const id = specifity < 2 && element.id ? `#${cssescape(element.id)}` : "";
|
||||
const cls =
|
||||
specifity < 1 && element.classList.length
|
||||
? "." + [...element.classList].map((c) => cssescape(c)).join(".")
|
||||
? "." + [...element.classList].map(c => cssescape(c)).join(".")
|
||||
: "";
|
||||
const tag = element.tagName ? element.tagName.toLowerCase() : "";
|
||||
return `${tag}${id}${cls}`;
|
||||
@@ -637,7 +663,7 @@ export class SelectorComponent {
|
||||
}
|
||||
};
|
||||
|
||||
const build = (pathArray) => pathArray.toReversed().join("");
|
||||
const build = pathArray => pathArray.toReversed().join("");
|
||||
|
||||
const findBestExactSelector = (element, doc) => {
|
||||
let buildMap = new Map();
|
||||
@@ -675,7 +701,9 @@ export class SelectorComponent {
|
||||
|
||||
const pathParentElementBuilt = build(parentExactElement);
|
||||
const pathParentElementLength = (
|
||||
pathParentElementBuilt ? doc.querySelectorAll(pathParentElementBuilt) : []
|
||||
pathParentElementBuilt
|
||||
? doc.querySelectorAll(pathParentElementBuilt)
|
||||
: []
|
||||
).length;
|
||||
|
||||
if (!buildMap.has(pathParentElementLength)) {
|
||||
|
||||
@@ -239,10 +239,16 @@ void main() {
|
||||
*/
|
||||
async #createProgram(gl, vertContent, fragContent) {
|
||||
const vertexShader = this.#compileShader(gl, vertContent, gl.VERTEX_SHADER);
|
||||
const fragmentShader = this.#compileShader(gl, fragContent, gl.FRAGMENT_SHADER);
|
||||
const fragmentShader = this.#compileShader(
|
||||
gl,
|
||||
fragContent,
|
||||
gl.FRAGMENT_SHADER
|
||||
);
|
||||
|
||||
if (!vertexShader || !fragmentShader) {
|
||||
console.error("Program creation aborted: One or more shaders failed to compile.");
|
||||
console.error(
|
||||
"Program creation aborted: One or more shaders failed to compile."
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -257,7 +263,10 @@ void main() {
|
||||
gl.deleteShader(fragmentShader);
|
||||
|
||||
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
|
||||
console.error("Shader program initializiation failure:", gl.getProgramInfoLog(program));
|
||||
console.error(
|
||||
"Shader program initializiation failure:",
|
||||
gl.getProgramInfoLog(program)
|
||||
);
|
||||
}
|
||||
|
||||
return program;
|
||||
@@ -292,8 +301,9 @@ void main() {
|
||||
* @returns {ImageData} Image data
|
||||
*/
|
||||
#getImageData(image) {
|
||||
const canvas =
|
||||
this.getElementById("zen-zap-dissolve-canvas").ownerDocument.createElement("canvas");
|
||||
const canvas = this.getElementById(
|
||||
"zen-zap-dissolve-canvas"
|
||||
).ownerDocument.createElement("canvas");
|
||||
canvas.width = image.width;
|
||||
canvas.height = image.height;
|
||||
|
||||
@@ -337,7 +347,12 @@ void main() {
|
||||
this.#webglContext.NEAREST
|
||||
);
|
||||
|
||||
if (image && image instanceof Ci.nsIImageLoadingContent && image.width && image.height) {
|
||||
if (
|
||||
image &&
|
||||
image instanceof Ci.nsIImageLoadingContent &&
|
||||
image.width &&
|
||||
image.height
|
||||
) {
|
||||
this.#webglContext.texImage2D(
|
||||
this.#webglContext.TEXTURE_2D,
|
||||
0,
|
||||
@@ -422,7 +437,7 @@ void main() {
|
||||
* Requests an animation frame
|
||||
*/
|
||||
#requestDraw() {
|
||||
this.#rafId = this.window.requestAnimationFrame((t) => this.#draw(t));
|
||||
this.#rafId = this.window.requestAnimationFrame(t => this.#draw(t));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -487,7 +502,14 @@ void main() {
|
||||
const canvas = this.getElementById("zen-zap-dissolve-canvas");
|
||||
this.#resizeCanvasToClientSize(canvas);
|
||||
|
||||
ctx.drawWindow(this.window, rect.left, rect.top, rect.width, rect.height, "rgba(0,0,0,0)");
|
||||
ctx.drawWindow(
|
||||
this.window,
|
||||
rect.left,
|
||||
rect.top,
|
||||
rect.width,
|
||||
rect.height,
|
||||
"rgba(0,0,0,0)"
|
||||
);
|
||||
|
||||
this.#loadTexture(captureCanvas);
|
||||
this.#bindParameters(element);
|
||||
@@ -505,6 +527,8 @@ void main() {
|
||||
|
||||
/**
|
||||
* Helper for getting an anonymous element by id
|
||||
*
|
||||
* @param {string} id The id of the element
|
||||
*/
|
||||
getElementById(id) {
|
||||
return this.content.root.getElementById(id);
|
||||
@@ -523,7 +547,10 @@ void main() {
|
||||
if (!this.template) {
|
||||
let parser = new DOMParser();
|
||||
let doc = parser.parseFromString(this.markup, "text/html");
|
||||
this.template = this.document.importNode(doc.querySelector("template"), true);
|
||||
this.template = this.document.importNode(
|
||||
doc.querySelector("template"),
|
||||
true
|
||||
);
|
||||
}
|
||||
let fragment = this.template.content.cloneNode(true);
|
||||
return fragment;
|
||||
|
||||
@@ -6,7 +6,8 @@ const lazy = {};
|
||||
|
||||
ChromeUtils.defineESModuleGetters(lazy, {
|
||||
ZapDissolve: "resource:///modules/zen/boosts/ZenZapDissolve.sys.mjs",
|
||||
SelectorComponent: "resource:///modules/zen/boosts/ZenSelectorComponent.sys.mjs",
|
||||
SelectorComponent:
|
||||
"resource:///modules/zen/boosts/ZenSelectorComponent.sys.mjs",
|
||||
});
|
||||
|
||||
ChromeUtils.defineLazyGetter(lazy, "overlayLocalization", () => {
|
||||
@@ -40,7 +41,11 @@ export class ZapOverlay {
|
||||
zenBoostsChild,
|
||||
this.#zapContentIDs,
|
||||
this.handleSelectComponentSelect.bind(this),
|
||||
[{ id: "zen-zap-this" }, { id: "zen-zap-related" }, { id: "zen-zap-cancel" }]
|
||||
[
|
||||
{ id: "zen-zap-this" },
|
||||
{ id: "zen-zap-related" },
|
||||
{ id: "zen-zap-cancel" },
|
||||
]
|
||||
);
|
||||
|
||||
// Remove the bottom unzap bar to the safe area
|
||||
@@ -52,7 +57,9 @@ export class ZapOverlay {
|
||||
*/
|
||||
async initialize() {
|
||||
if (this.#initialized) {
|
||||
console.warn("[ZenZapOverlayChild]: Skipping initialize because initialized.");
|
||||
console.warn(
|
||||
"[ZenZapOverlayChild]: Skipping initialize because initialized."
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -70,7 +77,10 @@ export class ZapOverlay {
|
||||
*/
|
||||
#initializeElements() {
|
||||
this.zapDoneButton = this.getElementById("zap-done");
|
||||
this.zapDoneButton.addEventListener("click", this.#disableZapMode.bind(this));
|
||||
this.zapDoneButton.addEventListener(
|
||||
"click",
|
||||
this.#disableZapMode.bind(this)
|
||||
);
|
||||
|
||||
this.#updateZappedList();
|
||||
}
|
||||
@@ -91,7 +101,8 @@ export class ZapOverlay {
|
||||
|
||||
// Capture current index and increment for next call
|
||||
const returnIndex = this.#currentDissolveIndex;
|
||||
this.#currentDissolveIndex = (this.#currentDissolveIndex + 1) % this.#dissolvePoolSize;
|
||||
this.#currentDissolveIndex =
|
||||
(this.#currentDissolveIndex + 1) % this.#dissolvePoolSize;
|
||||
|
||||
return this.#dissolveEffectPool[returnIndex];
|
||||
}
|
||||
@@ -105,6 +116,8 @@ export class ZapOverlay {
|
||||
|
||||
/**
|
||||
* Helper for getting an anonymous element by id
|
||||
*
|
||||
* @param {string} id The id of the element
|
||||
*/
|
||||
getElementById(id) {
|
||||
return this.content.root.getElementById(id);
|
||||
@@ -112,7 +125,9 @@ export class ZapOverlay {
|
||||
|
||||
get markup() {
|
||||
// Fetch localizations
|
||||
let [done] = lazy.overlayLocalization.formatMessagesSync([{ id: "zen-zap-done" }]);
|
||||
let [done] = lazy.overlayLocalization.formatMessagesSync([
|
||||
{ id: "zen-zap-done" },
|
||||
]);
|
||||
|
||||
return `
|
||||
<template>
|
||||
@@ -131,7 +146,10 @@ export class ZapOverlay {
|
||||
if (!this.template) {
|
||||
let parser = new DOMParser();
|
||||
let doc = parser.parseFromString(this.markup, "text/html");
|
||||
this.template = this.document.importNode(doc.querySelector("template"), true);
|
||||
this.template = this.document.importNode(
|
||||
doc.querySelector("template"),
|
||||
true
|
||||
);
|
||||
}
|
||||
let fragment = this.template.content.cloneNode(true);
|
||||
return fragment;
|
||||
@@ -139,6 +157,8 @@ export class ZapOverlay {
|
||||
|
||||
/**
|
||||
* Handles the onSelect callback from the SelectComponent
|
||||
*
|
||||
* @param {string} cssSelector The CSS selector of the selected element
|
||||
*/
|
||||
handleSelectComponentSelect(cssSelector) {
|
||||
this.#handleZap(cssSelector);
|
||||
@@ -154,20 +174,24 @@ export class ZapOverlay {
|
||||
|
||||
/**
|
||||
* Handles the addition of the given zap selector
|
||||
*
|
||||
* @param {string} cssPath The css selector of the zap
|
||||
*/
|
||||
#handleZap(cssPath) {
|
||||
const useDissolve = Services.prefs.getBoolPref("zen.boosts.dissolve-on-zap");
|
||||
const useDissolve = Services.prefs.getBoolPref(
|
||||
"zen.boosts.dissolve-on-zap"
|
||||
);
|
||||
if (!this.window.gReduceMotion && useDissolve) {
|
||||
const elements = this.document.querySelectorAll(cssPath);
|
||||
|
||||
let counter = 0;
|
||||
elements.forEach(async (element) => {
|
||||
elements.forEach(async element => {
|
||||
if (counter > this.#dissolvePoolSize) {
|
||||
return;
|
||||
}
|
||||
counter++;
|
||||
|
||||
this.#getNextDissolveEffect().then((dissolve) => {
|
||||
this.#getNextDissolveEffect().then(dissolve => {
|
||||
dissolve.dissolve(element);
|
||||
});
|
||||
});
|
||||
@@ -211,7 +235,7 @@ export class ZapOverlay {
|
||||
const boost = await this.zenBoostsChild.getWebsiteBoost();
|
||||
const { boostData } = boost.boostEntry;
|
||||
|
||||
boostData.zapSelectors.forEach((selector) => {
|
||||
boostData.zapSelectors.forEach(selector => {
|
||||
const unzapButton = zapList.ownerDocument.createElement("input");
|
||||
unzapButton.type = "button";
|
||||
unzapButton.id = "zen-zap-unzap";
|
||||
@@ -236,10 +260,11 @@ export class ZapOverlay {
|
||||
});
|
||||
|
||||
// Fetch localizations
|
||||
let [addZapHelper, removeZapHelper] = lazy.overlayLocalization.formatMessagesSync([
|
||||
{ id: "zen-add-zap-helper" },
|
||||
{ id: "zen-remove-zap-helper" },
|
||||
]);
|
||||
let [addZapHelper, removeZapHelper] =
|
||||
lazy.overlayLocalization.formatMessagesSync([
|
||||
{ id: "zen-add-zap-helper" },
|
||||
{ id: "zen-remove-zap-helper" },
|
||||
]);
|
||||
|
||||
if (!boostData.zapSelectors.length) {
|
||||
const addZapHelperText = zapList.ownerDocument.createElement("p");
|
||||
@@ -318,7 +343,7 @@ export class ZapOverlay {
|
||||
this.#selectorComponent.tearDown();
|
||||
this.#selectorComponent = null;
|
||||
|
||||
this.#dissolveEffectPool.forEach((dissolve) => {
|
||||
this.#dissolveEffectPool.forEach(dissolve => {
|
||||
dissolve.tearDown();
|
||||
});
|
||||
|
||||
|
||||
@@ -8,7 +8,8 @@ const lazy = {};
|
||||
|
||||
ChromeUtils.defineESModuleGetters(lazy, {
|
||||
ZapOverlay: "resource:///modules/zen/boosts/ZenZapOverlayChild.sys.mjs",
|
||||
SelectorComponent: "resource:///modules/zen/boosts/ZenSelectorComponent.sys.mjs",
|
||||
SelectorComponent:
|
||||
"resource:///modules/zen/boosts/ZenSelectorComponent.sys.mjs",
|
||||
});
|
||||
|
||||
export class ZenBoostsChild extends JSWindowActorChild {
|
||||
@@ -25,7 +26,14 @@ export class ZenBoostsChild extends JSWindowActorChild {
|
||||
PICKER: "picker",
|
||||
};
|
||||
|
||||
static OVERLAY_EVENTS = ["click", "pointerdown", "pointermove", "pointerup", "scroll", "resize"];
|
||||
static OVERLAY_EVENTS = [
|
||||
"click",
|
||||
"pointerdown",
|
||||
"pointermove",
|
||||
"pointerup",
|
||||
"scroll",
|
||||
"resize",
|
||||
];
|
||||
|
||||
// A list of events that will be prevented from
|
||||
// reaching the document
|
||||
@@ -175,7 +183,10 @@ export class ZenBoostsChild extends JSWindowActorChild {
|
||||
|
||||
handleZapEvent(event) {
|
||||
if (ZenBoostsChild.ALL_EVENTS_SET.has(event.type)) {
|
||||
this.#overlay.handleEvent(event, ZenBoostsChild.PREVENTABLE_SET.has(event.type));
|
||||
this.#overlay.handleEvent(
|
||||
event,
|
||||
ZenBoostsChild.PREVENTABLE_SET.has(event.type)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -263,6 +274,10 @@ export class ZenBoostsChild extends JSWindowActorChild {
|
||||
/**
|
||||
* From ZenGradientGenerator.mjs
|
||||
* Helper function for hslToRgb conversion
|
||||
*
|
||||
* @param {number} p
|
||||
* @param {number} q
|
||||
* @param {number} t
|
||||
*/
|
||||
#hueToRgb(p, q, t) {
|
||||
if (t < 0) {
|
||||
@@ -327,10 +342,16 @@ export class ZenBoostsChild extends JSWindowActorChild {
|
||||
if (boostData.enableColorBoost) {
|
||||
if (boostData.autoTheme) {
|
||||
// Workspace color is converted to the HSL color space
|
||||
let primaryGradientColor = boost.workspaceGradient[0]?.c ?? [0, 0, 0.6];
|
||||
boost.workspaceGradient.forEach((color) => {
|
||||
let primaryGradientColor = boost.workspaceGradient[0]?.c ?? [
|
||||
0, 0, 0.6,
|
||||
];
|
||||
boost.workspaceGradient.forEach(color => {
|
||||
if (color.isPrimary) {
|
||||
primaryGradientColor = this.#rgbToHsl(color.c[0], color.c[1], color.c[2]);
|
||||
primaryGradientColor = this.#rgbToHsl(
|
||||
color.c[0],
|
||||
color.c[1],
|
||||
color.c[2]
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -343,7 +364,10 @@ export class ZenBoostsChild extends JSWindowActorChild {
|
||||
);
|
||||
|
||||
const rgbColor = primaryGradientColor;
|
||||
const nsColor = this.#rgbToNSColor(rgbColor, (1 - boostData.contrast) * 255);
|
||||
const nsColor = this.#rgbToNSColor(
|
||||
rgbColor,
|
||||
(1 - boostData.contrast) * 255
|
||||
);
|
||||
browsingContext.zenBoostsData = nsColor;
|
||||
} else {
|
||||
let colorWheelColor = this.#hslToRgb(
|
||||
@@ -355,7 +379,10 @@ export class ZenBoostsChild extends JSWindowActorChild {
|
||||
);
|
||||
|
||||
const rgbColor = colorWheelColor;
|
||||
const nsColor = this.#rgbToNSColor(rgbColor, (1 - boostData.contrast) * 255);
|
||||
const nsColor = this.#rgbToNSColor(
|
||||
rgbColor,
|
||||
(1 - boostData.contrast) * 255
|
||||
);
|
||||
browsingContext.zenBoostsData = nsColor;
|
||||
}
|
||||
return;
|
||||
@@ -454,7 +481,7 @@ export class ZenBoostsChild extends JSWindowActorChild {
|
||||
}
|
||||
|
||||
async tempShowZappedElement(selector) {
|
||||
this.document.querySelectorAll(selector).forEach((element) => {
|
||||
this.document.querySelectorAll(selector).forEach(element => {
|
||||
element.setAttribute("zen-zap-unhide", "true");
|
||||
});
|
||||
|
||||
@@ -464,8 +491,8 @@ export class ZenBoostsChild extends JSWindowActorChild {
|
||||
}
|
||||
|
||||
async tempHideZappedElement() {
|
||||
this.#zappedElementsTempShown.forEach((selector) => {
|
||||
this.document.querySelectorAll(selector).forEach((element) => {
|
||||
this.#zappedElementsTempShown.forEach(selector => {
|
||||
this.document.querySelectorAll(selector).forEach(element => {
|
||||
element.removeAttribute("zen-zap-unhide");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -24,7 +24,7 @@ export class ZenBoostsParent extends JSWindowActorParent {
|
||||
super();
|
||||
|
||||
this._observe = this.observe.bind(this);
|
||||
ZenBoostsParent.OBSERVERS.forEach((observe) => {
|
||||
ZenBoostsParent.OBSERVERS.forEach(observe => {
|
||||
Services.obs.addObserver(this._observe, observe);
|
||||
});
|
||||
}
|
||||
@@ -33,7 +33,7 @@ export class ZenBoostsParent extends JSWindowActorParent {
|
||||
* Called when the actor is destroyed. Cleans up the observer.
|
||||
*/
|
||||
didDestroy() {
|
||||
ZenBoostsParent.OBSERVERS.forEach((observe) => {
|
||||
ZenBoostsParent.OBSERVERS.forEach(observe => {
|
||||
Services.obs.removeObserver(this._observe, observe);
|
||||
});
|
||||
}
|
||||
@@ -49,7 +49,9 @@ export class ZenBoostsParent extends JSWindowActorParent {
|
||||
switch (topic) {
|
||||
case "zen-boosts-update":
|
||||
case "zen-space-gradient-update":
|
||||
this.sendAsyncMessage("ZenBoost:BoostDataUpdated", { unloadStyles: true });
|
||||
this.sendAsyncMessage("ZenBoost:BoostDataUpdated", {
|
||||
unloadStyles: true,
|
||||
});
|
||||
break;
|
||||
case "zen-boosts-disable-zap":
|
||||
this.sendAsyncMessage("ZenBoost:DisableZapMode");
|
||||
@@ -89,7 +91,11 @@ export class ZenBoostsParent extends JSWindowActorParent {
|
||||
break;
|
||||
}
|
||||
case "ZenBoost:Notify": {
|
||||
Services.obs.notifyObservers(null, message.data.topic, message.data.msg);
|
||||
Services.obs.notifyObservers(
|
||||
null,
|
||||
message.data.topic,
|
||||
message.data.msg
|
||||
);
|
||||
break;
|
||||
}
|
||||
case "ZenBoost:ZapSelector": {
|
||||
@@ -106,9 +112,15 @@ export class ZenBoostsParent extends JSWindowActorParent {
|
||||
}
|
||||
|
||||
if (data.action == "add") {
|
||||
lazy.gZenBoostsManager.addZapSelectorToActive(data.selector, data.domain);
|
||||
lazy.gZenBoostsManager.addZapSelectorToActive(
|
||||
data.selector,
|
||||
data.domain
|
||||
);
|
||||
} else if (data.action == "remove") {
|
||||
lazy.gZenBoostsManager.removeZapSelectorToActive(data.selector, data.domain);
|
||||
lazy.gZenBoostsManager.removeZapSelectorToActive(
|
||||
data.selector,
|
||||
data.domain
|
||||
);
|
||||
} else if (data.action == "clear") {
|
||||
lazy.gZenBoostsManager.clearZapSelectorsForActive(data.domain);
|
||||
}
|
||||
@@ -128,13 +140,15 @@ export class ZenBoostsParent extends JSWindowActorParent {
|
||||
}
|
||||
|
||||
const topWindowIsDarkMode =
|
||||
embedder.ownerGlobal.getComputedStyle(embedder).colorScheme === "dark";
|
||||
embedder.ownerGlobal.getComputedStyle(embedder).colorScheme ===
|
||||
"dark";
|
||||
|
||||
const boost = lazy.gZenBoostsManager.loadActiveBoostFromStore(domain);
|
||||
const currentWorkspace =
|
||||
await this.browsingContext.topChromeWindow.gZenWorkspaces.getActiveWorkspace();
|
||||
|
||||
const styleData = await lazy.gZenBoostsManager.getStyleSheetForBoost(domain);
|
||||
const styleData =
|
||||
await lazy.gZenBoostsManager.getStyleSheetForBoost(domain);
|
||||
|
||||
return {
|
||||
...boost,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# 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/.
|
||||
|
||||
|
||||
content/browser/zen-styles/zen-boosts.css (../../zen/boosts/zen-boosts.css)
|
||||
content/browser/zen-styles/content/zen-zap.css (../../zen/boosts/zen-zap.css)
|
||||
content/browser/zen-styles/content/zen-selector.css (../../zen/boosts/zen-selector.css)
|
||||
|
||||
@@ -25,16 +25,15 @@
|
||||
// serialization/deserialization between parent and content processes.
|
||||
#define NS_GET_CONTRAST(_c) NS_GET_A(_c)
|
||||
|
||||
#define MARK_MEDIA_FEATURE_CHANGED(_pc) \
|
||||
(_pc)->MediaFeatureValuesChanged( \
|
||||
{mozilla::RestyleHint::RecascadeSubtree(), NS_STYLE_HINT_VISUAL, \
|
||||
mozilla::MediaFeatureChangeReason::PreferenceChange}, \
|
||||
#define MARK_MEDIA_FEATURE_CHANGED(_pc) \
|
||||
(_pc)->MediaFeatureValuesChanged( \
|
||||
{mozilla::RestyleHint::RecascadeSubtree(), NS_STYLE_HINT_VISUAL, \
|
||||
mozilla::MediaFeatureChangeReason::PreferenceChange}, \
|
||||
mozilla::MediaFeatureChangePropagation::All);
|
||||
|
||||
#define TRIGGER_PRES_CONTEXT_RESTYLE() \
|
||||
WalkPresContexts([&](nsPresContext* aPc) { \
|
||||
MARK_MEDIA_FEATURE_CHANGED(aPc); \
|
||||
});
|
||||
#define TRIGGER_PRES_CONTEXT_RESTYLE() \
|
||||
WalkPresContexts( \
|
||||
[&](nsPresContext* aPc) { MARK_MEDIA_FEATURE_CHANGED(aPc); });
|
||||
|
||||
using BrowsingContext = mozilla::dom::BrowsingContext;
|
||||
|
||||
@@ -80,47 +79,18 @@ void BrowsingContext::DidSet(FieldIndex<IDX_IsZenBoostsInverted>,
|
||||
}
|
||||
|
||||
namespace zen {
|
||||
|
||||
nsZenAccentOklab nsZenBoostsBackend::mCachedAccent{0};
|
||||
|
||||
namespace {
|
||||
|
||||
/**
|
||||
* Inherited from the Oklab blog
|
||||
* Source: https://bottosson.github.io/posts/oklab/
|
||||
*/
|
||||
struct Lab {
|
||||
float L, a, b;
|
||||
};
|
||||
|
||||
struct Lab {float L; float a; float b;};
|
||||
struct RGB {float r; float g; float b;};
|
||||
|
||||
Lab rgb2oklab(RGB c) {
|
||||
float l = 0.4122214708f * c.r + 0.5363325363f * c.g + 0.0514459929f * c.b;
|
||||
float m = 0.2119034982f * c.r + 0.6806995451f * c.g + 0.1073969566f * c.b;
|
||||
float s = 0.0883024619f * c.r + 0.2817188376f * c.g + 0.6299787005f * c.b;
|
||||
|
||||
float l_ = cbrtf(l);
|
||||
float m_ = cbrtf(m);
|
||||
float s_ = cbrtf(s);
|
||||
|
||||
return {
|
||||
0.2104542553f*l_ + 0.7936177850f*m_ - 0.0040720468f*s_,
|
||||
1.9779984951f*l_ - 2.4285922050f*m_ + 0.4505937099f*s_,
|
||||
0.0259040371f*l_ + 0.7827717662f*m_ - 0.8086757660f*s_,
|
||||
};
|
||||
}
|
||||
|
||||
RGB oklab2rgb(Lab c) {
|
||||
float l_ = c.L + 0.3963377774f * c.a + 0.2158037573f * c.b;
|
||||
float m_ = c.L - 0.1055613458f * c.a - 0.0638541728f * c.b;
|
||||
float s_ = c.L - 0.0894841775f * c.a - 1.2914855480f * c.b;
|
||||
|
||||
float l = l_*l_*l_;
|
||||
float m = m_*m_*m_;
|
||||
float s = s_*s_*s_;
|
||||
|
||||
return {
|
||||
+4.0767416621f * l - 3.3077115913f * m + 0.2309699292f * s,
|
||||
-1.2684380046f * l + 2.6097574011f * m - 0.3413193965f * s,
|
||||
-0.0041960863f * l - 0.7034186147f * m + 1.7076147010f * s,
|
||||
};
|
||||
}
|
||||
struct RGB {
|
||||
float r, g, b;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Clamps a value to the range [0, 255] using branchless operations.
|
||||
@@ -133,6 +103,47 @@ static __inline int32_t clamp255(int32_t v) {
|
||||
return (v | ((255 - v) >> 31)) & 255;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief A fast approximation of the cube root function using bit manipulation
|
||||
* and two Newton-Raphson iterations. This is used to optimize the Oklab color
|
||||
* conversion in the color filtering process.
|
||||
*/
|
||||
inline static float fast_cbrt(float x) {
|
||||
// Bit-level initial approximation (works for positive floats only — fine
|
||||
// here)
|
||||
uint32_t bits;
|
||||
memcpy(&bits, &x, 4);
|
||||
bits = (bits / 3) + 0x2A512400u; // magic constant for cube root
|
||||
float y;
|
||||
memcpy(&y, &bits, 4);
|
||||
// Two Newton-Raphson iterations: y = y - (y³ - x) / (3y²)
|
||||
y = (2.0f / 3.0f) * y + (1.0f / 3.0f) * x / (y * y);
|
||||
y = (2.0f / 3.0f) * y + (1.0f / 3.0f) * x / (y * y);
|
||||
return y;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Converts an Oklab color back to the RGB color space.
|
||||
* @param c The Oklab color to convert.
|
||||
* @return The corresponding RGB color.
|
||||
*/
|
||||
[[nodiscard]]
|
||||
static inline auto oklab2rgb(Lab c) -> RGB {
|
||||
float l_ = c.L + 0.3963377774f * c.a + 0.2158037573f * c.b;
|
||||
float m_ = c.L - 0.1055613458f * c.a - 0.0638541728f * c.b;
|
||||
float s_ = c.L - 0.0894841775f * c.a - 1.2914855480f * c.b;
|
||||
|
||||
// Cubing is just 2 multiplies — no cbrtf needed on the way back
|
||||
return {
|
||||
4.0767416621f * (l_ * l_ * l_) - 3.3077115913f * (m_ * m_ * m_) +
|
||||
0.2309699292f * (s_ * s_ * s_),
|
||||
-1.2684380046f * (l_ * l_ * l_) + 2.6097574011f * (m_ * m_ * m_) -
|
||||
0.3413193965f * (s_ * s_ * s_),
|
||||
-0.0041960863f * (l_ * l_ * l_) - 0.7034186147f * (m_ * m_ * m_) +
|
||||
1.7076147010f * (s_ * s_ * s_),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Applies a color filter to transform an original color toward an accent
|
||||
* color. Preserves the original color's perceived luminance while shifting
|
||||
@@ -143,68 +154,86 @@ static __inline int32_t clamp255(int32_t v) {
|
||||
* contrast value).
|
||||
* @return The filtered color with transformations applied.
|
||||
*/
|
||||
[[nodiscard]]
|
||||
static inline Lab rgb2oklab_fast(RGB c) {
|
||||
float l = 0.4122214708f * c.r + 0.5363325363f * c.g + 0.0514459929f * c.b;
|
||||
float m = 0.2119034982f * c.r + 0.6806995451f * c.g + 0.1073969566f * c.b;
|
||||
float s = 0.0883024619f * c.r + 0.2817188376f * c.g + 0.6299787005f * c.b;
|
||||
float l_ = fast_cbrt(l), m_ = fast_cbrt(m), s_ = fast_cbrt(s);
|
||||
return {
|
||||
0.2104542553f * l_ + 0.7936177850f * m_ - 0.0040720468f * s_,
|
||||
1.9779984951f * l_ - 2.4285922050f * m_ + 0.4505937099f * s_,
|
||||
0.0259040371f * l_ + 0.7827717662f * m_ - 0.8086757660f * s_,
|
||||
};
|
||||
}
|
||||
|
||||
inline static auto zenPrecomputeAccent(nscolor aAccentColor)
|
||||
-> nsZenAccentOklab {
|
||||
constexpr float kInv255 = 1.0f / 255.0f;
|
||||
RGB rgb = {NS_GET_R(aAccentColor) * kInv255, NS_GET_G(aAccentColor) * kInv255,
|
||||
NS_GET_B(aAccentColor) * kInv255};
|
||||
auto lab = rgb2oklab_fast(rgb);
|
||||
float contrast = NS_GET_CONTRAST(aAccentColor);
|
||||
float vibranceBase = 1.0f - ((contrast - 128.0f) * (1.0f / 128.0f));
|
||||
return {lab.L, lab.a, lab.b, vibranceBase, 0.25f + lab.L};
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Applies a color filter to transform an original color toward an accent
|
||||
* color. Preserves the original color's perceived luminance while shifting
|
||||
* hue/chroma toward the accent. Uses the alpha channel of the accent color to
|
||||
* store contrast information.
|
||||
* @param aOriginalColor The original color to filter.
|
||||
* @param aAccentColor The accent color to filter toward (alpha channel contains
|
||||
* contrast value).
|
||||
* @return The filtered color with transformations applied.
|
||||
*/
|
||||
[[nodiscard]]
|
||||
static nscolor zenFilterColorChannel(nscolor aOriginalColor,
|
||||
nscolor aAccentColor) {
|
||||
const auto r1 = NS_GET_R(aOriginalColor);
|
||||
const auto g1 = NS_GET_G(aOriginalColor);
|
||||
const auto b1 = NS_GET_B(aOriginalColor);
|
||||
const auto a1 = NS_GET_A(aOriginalColor);
|
||||
if (a1 == 0) {
|
||||
// Skip processing fully transparent colors since they won't be visible and
|
||||
// we want to avoid unnecessary computations with the accent color's alpha
|
||||
// channel used for contrast information.
|
||||
return aOriginalColor;
|
||||
}
|
||||
const nsZenAccentOklab& aAccent) {
|
||||
const uint8_t a1 = NS_GET_A(aOriginalColor);
|
||||
if (a1 == 0) return aOriginalColor;
|
||||
|
||||
const auto r2 = NS_GET_R(aAccentColor);
|
||||
const auto g2 = NS_GET_G(aAccentColor);
|
||||
const auto b2 = NS_GET_B(aAccentColor);
|
||||
constexpr float kInv255 = 1.0f / 255.0f;
|
||||
constexpr float kTint = 0.6f;
|
||||
constexpr float kInvTint = 1.0f - kTint;
|
||||
|
||||
// It's a bit of a hacky solution, but instead of using alpha as what it is
|
||||
// (opacity), we use it to store contrast information for now.
|
||||
// We do this primarily to avoid having to deal with WebIDL structs and
|
||||
// serialization/deserialization between parent and content processes.
|
||||
const auto contrast = NS_GET_CONTRAST(aAccentColor);
|
||||
RGB orig = {
|
||||
NS_GET_R(aOriginalColor) * kInv255,
|
||||
NS_GET_G(aOriginalColor) * kInv255,
|
||||
NS_GET_B(aOriginalColor) * kInv255,
|
||||
};
|
||||
const auto lab = rgb2oklab_fast(orig);
|
||||
|
||||
RGB originalRgb(r1 / 255.0, g1 / 255.0, b1 / 255.0);
|
||||
const auto originalOklab = rgb2oklab(originalRgb);
|
||||
const float aBlend = kInvTint * lab.a + kTint * aAccent.a;
|
||||
const float bBlend = kInvTint * lab.b + kTint * aAccent.b;
|
||||
|
||||
RGB accentRgb(r2 / 255.0, g2 / 255.0, b2 / 255.0);
|
||||
const auto accentOklab = rgb2oklab(accentRgb);
|
||||
|
||||
double tintStrength = 0.6; // Decides how strongly the accent should influence the original color
|
||||
double aBlend = (1.0 - tintStrength) * originalOklab.a + tintStrength * accentOklab.a;
|
||||
double bBlend = (1.0 - tintStrength) * originalOklab.b + tintStrength * accentOklab.b;
|
||||
// Avoid sqrt: compare squared chroma against squared threshold (0.4^2 = 0.16)
|
||||
// vibranceFactor = chromaMixed/chromaBlend which simplifies to just
|
||||
// vibranceFactor since the sqrt cancels in the normalize+scale round-trip
|
||||
// (see below)
|
||||
const float chromaSq = aBlend * aBlend + bBlend * bBlend;
|
||||
const float saturation =
|
||||
(chromaSq < 0.16f) ? chromaSq * (1.0f / 0.16f) : 1.0f;
|
||||
const float vibranceFactor =
|
||||
1.0f + aAccent.vibranceBase * (1.0f - saturation);
|
||||
|
||||
// Calculating chroma with the length of the vector of (a b)
|
||||
double chromaBlend = sqrt(aBlend * aBlend + bBlend * bBlend);
|
||||
|
||||
// Normalizing against 0.4 since usually Oklab chroma maxes out around there
|
||||
double vibranceAmount = 1 - ((contrast - 128.0) / 128.0);
|
||||
double vibranceFactor = 1.0 + vibranceAmount * (1.0 - std::clamp(chromaBlend / 0.4, 0.0, 1.0));
|
||||
// sqrt cancellation: chromaMixed/chromaBlend =
|
||||
// (chromaBlend*vibranceFactor)/chromaBlend = vibranceFactor, so we multiply
|
||||
// directly with no sqrt needed
|
||||
const float aMixed = aBlend * vibranceFactor;
|
||||
const float bMixed = bBlend * vibranceFactor;
|
||||
|
||||
// Essentially the equivalent of 'hue' for Oklab
|
||||
double chromaMixed = chromaBlend * vibranceFactor;
|
||||
double scale = (chromaBlend > 1e-6) ? (chromaMixed / chromaBlend) : 1.0;
|
||||
float LMixed = 0.5f + (lab.L - 0.5f) * (1.0f + aAccent.vibranceBase * 0.5f);
|
||||
LMixed *= aAccent.accentLOffset;
|
||||
if (LMixed < 0.0f) LMixed = 0.0f;
|
||||
if (LMixed > 1.0f) LMixed = 1.0f;
|
||||
|
||||
double aMixed = aBlend * scale;
|
||||
double bMixed = bBlend * scale;
|
||||
const auto rgb = oklab2rgb({LMixed, aMixed, bMixed});
|
||||
|
||||
// Lightness contrast
|
||||
double contrastFactor = 1.0 + vibranceAmount * 0.5;
|
||||
|
||||
// Lightness factor
|
||||
double LMixed = 0.5 + (originalOklab.L - 0.5) * contrastFactor;
|
||||
LMixed = std::clamp(LMixed * (0.25 + accentOklab.L), 0.0, 1.0);
|
||||
|
||||
Lab tintedOklab(LMixed, aMixed, bMixed);
|
||||
|
||||
auto tintedRgb = oklab2rgb(tintedOklab);
|
||||
const uint8_t fr8 = clamp255(tintedRgb.r * 255);
|
||||
const uint8_t fg8 = clamp255(tintedRgb.g * 255);
|
||||
const uint8_t fb8 = clamp255(tintedRgb.b * 255);
|
||||
|
||||
return NS_RGBA(fr8, fg8, fb8, a1);
|
||||
return NS_RGBA(clamp255((int32_t)(rgb.r * 255.0f + 0.5f)),
|
||||
clamp255((int32_t)(rgb.g * 255.0f + 0.5f)),
|
||||
clamp255((int32_t)(rgb.b * 255.0f + 0.5f)), a1);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -243,9 +272,9 @@ inline static nscolor zenInvertColorChannel(nscolor aColor) {
|
||||
/**
|
||||
* @brief Retrieves the current boost data from the browsing context.
|
||||
*/
|
||||
inline static void GetZenBoostsDataFromBrowsingContext(ZenBoostData* aData,
|
||||
bool* aIsInverted,
|
||||
nsPresContext* aPresContext = nullptr) {
|
||||
inline static void GetZenBoostsDataFromBrowsingContext(
|
||||
ZenBoostData* aData, bool* aIsInverted,
|
||||
nsPresContext* aPresContext = nullptr) {
|
||||
auto zenBoosts = nsZenBoostsBackend::GetInstance();
|
||||
if (!zenBoosts || (zenBoosts->mCurrentFrameIsAnonymousContent)) {
|
||||
return;
|
||||
@@ -257,7 +286,8 @@ inline static void GetZenBoostsDataFromBrowsingContext(ZenBoostData* aData,
|
||||
*aIsInverted = browsingContext->IsZenBoostsInverted();
|
||||
}
|
||||
}
|
||||
} else if (auto currentBrowsingContext = zenBoosts->GetCurrentBrowsingContext()) {
|
||||
} else if (auto currentBrowsingContext =
|
||||
zenBoosts->GetCurrentBrowsingContext()) {
|
||||
*aData = currentBrowsingContext->ZenBoostsData();
|
||||
*aIsInverted = currentBrowsingContext->IsZenBoostsInverted();
|
||||
}
|
||||
@@ -268,8 +298,8 @@ inline static void GetZenBoostsDataFromBrowsingContext(ZenBoostData* aData,
|
||||
auto nsZenBoostsBackend::GetInstance() -> nsZenBoostsBackend* {
|
||||
static nsZenBoostsBackend* zenBoosts;
|
||||
if (!XRE_IsContentProcess()) {
|
||||
// Zen boosts are only supported in content, so if we're in the parent process,
|
||||
// just return null.
|
||||
// Zen boosts are only supported in content, so if we're in the parent
|
||||
// process, just return null.
|
||||
return nullptr;
|
||||
}
|
||||
if (!zenBoosts) {
|
||||
@@ -283,9 +313,8 @@ auto nsZenBoostsBackend::onPresShellEntered(mozilla::dom::Document* aDocument)
|
||||
// Note that aDocument can be null when entering anonymous content frames.
|
||||
// We explicitly do this to prevent applying boosts to anonymous content, such
|
||||
// as devtools or screenshots.
|
||||
mozilla::dom::BrowsingContext* browsingContext = aDocument
|
||||
? aDocument->GetBrowsingContext()
|
||||
: nullptr;
|
||||
mozilla::dom::BrowsingContext* browsingContext =
|
||||
aDocument ? aDocument->GetBrowsingContext() : nullptr;
|
||||
if (!browsingContext) {
|
||||
return;
|
||||
}
|
||||
@@ -293,7 +322,8 @@ auto nsZenBoostsBackend::onPresShellEntered(mozilla::dom::Document* aDocument)
|
||||
}
|
||||
|
||||
auto nsZenBoostsBackend::FilterColorFromPresContext(nscolor aColor,
|
||||
nsPresContext* aPresContext) -> nscolor {
|
||||
nsPresContext* aPresContext)
|
||||
-> nscolor {
|
||||
if (!XRE_IsContentProcess()) {
|
||||
// Zen boosts are only supported in content, so if we somehow end up here
|
||||
// without a prescontext or in the parent process, just return the original
|
||||
@@ -304,13 +334,16 @@ auto nsZenBoostsBackend::FilterColorFromPresContext(nscolor aColor,
|
||||
bool invertColors = false;
|
||||
GetZenBoostsDataFromBrowsingContext(&accentNS, &invertColors, aPresContext);
|
||||
if (accentNS) {
|
||||
if (mCachedAccent.accentNS != accentNS) {
|
||||
mCachedAccent = zenPrecomputeAccent(accentNS);
|
||||
}
|
||||
// Apply a filter-like tint:
|
||||
// - Preserve the original color's perceived luminance
|
||||
// - Map hue/chroma toward the accent by scaling the accent's RGB
|
||||
// to match the original luminance
|
||||
// - Keep the original alpha
|
||||
// Convert both colors to nscolor to access channels
|
||||
aColor = zenFilterColorChannel(aColor, (nscolor)accentNS);
|
||||
aColor = zenFilterColorChannel(aColor, mCachedAccent);
|
||||
}
|
||||
if (invertColors) {
|
||||
aColor = zenInvertColorChannel(aColor);
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
* 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/. */
|
||||
|
||||
#ifndef mozilla_ZenBoostsBackend_h__
|
||||
#define mozilla_ZenBoostsBackend_h__
|
||||
#ifndef mozilla_ZenBoostsBackend_h_
|
||||
#define mozilla_ZenBoostsBackend_h_
|
||||
|
||||
#include "nsColor.h"
|
||||
#include "nsPresContext.h"
|
||||
@@ -16,6 +16,13 @@ using ZenBoostData = nscolor; // For now, Zen boosts data is just a color.
|
||||
|
||||
namespace zen {
|
||||
|
||||
struct nsZenAccentOklab {
|
||||
float L, a, b;
|
||||
float vibranceBase; // 1.0f - ((contrast - 128) / 128)
|
||||
float accentLOffset; // 0.25f + L, precomputed
|
||||
nscolor accentNS; // Used to keep track of the original accent color
|
||||
};
|
||||
|
||||
class nsZenBoostsBackend final {
|
||||
public:
|
||||
explicit nsZenBoostsBackend() = default;
|
||||
@@ -42,8 +49,9 @@ class nsZenBoostsBackend final {
|
||||
* @param aPresContext The presentation context to use for filtering.
|
||||
* @return The filtered color.
|
||||
*/
|
||||
static auto FilterColorFromPresContext(nscolor aColor,
|
||||
nsPresContext* aPresContext = nullptr) -> nscolor;
|
||||
static auto FilterColorFromPresContext(nscolor aColor,
|
||||
nsPresContext* aPresContext = nullptr)
|
||||
-> nscolor;
|
||||
|
||||
/**
|
||||
* @brief Called when a presshell is entered during rendering.
|
||||
@@ -64,6 +72,8 @@ class nsZenBoostsBackend final {
|
||||
*/
|
||||
RefPtr<mozilla::dom::BrowsingContext> mCurrentBrowsingContext;
|
||||
|
||||
static nsZenAccentOklab mCachedAccent;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Get the singleton instance of the ZenBoostsBackend.
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
#filter substitution
|
||||
<?xml version="1.0"?>
|
||||
# -*- Mode: HTML -*-
|
||||
#
|
||||
# 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/.
|
||||
#filter substitution <?xml version="1.0"?> # -*- Mode: HTML -*- # # 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/.
|
||||
|
||||
<!DOCTYPE window>
|
||||
|
||||
@@ -20,132 +17,264 @@
|
||||
scrolling="false"
|
||||
macanimationtype="document"
|
||||
windowsmica="true"
|
||||
data-l10n-sync="true">
|
||||
<head>
|
||||
<link rel="stylesheet" href="chrome://browser/skin/" />
|
||||
<link rel="stylesheet" href="chrome://global/skin/global.css" />
|
||||
data-l10n-sync="true"
|
||||
>
|
||||
<head>
|
||||
<link rel="stylesheet" href="chrome://browser/skin/" />
|
||||
<link rel="stylesheet" href="chrome://global/skin/global.css" />
|
||||
|
||||
<link rel="stylesheet" href="chrome://browser/content/zen-styles/zen-boosts.css" />
|
||||
<link rel="stylesheet" href="chrome://browser/content/zen-styles/zen-buttons.css" />
|
||||
<link rel="stylesheet" href="chrome://browser/content/zen-styles/zen-theme.css" />
|
||||
<link rel="stylesheet" href="chrome://browser/content/zen-styles/zen-animations.css" />
|
||||
<link rel="stylesheet" href="chrome://browser/content/zen-styles/zen-panel-ui.css" />
|
||||
<link rel="stylesheet" href="chrome://browser/skin/zen-icons/icons.css" />
|
||||
<link rel="stylesheet" href="chrome://browser/content/zen-styles/zen-advanced-color-options.css" />
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="chrome://browser/content/zen-styles/zen-boosts.css"
|
||||
/>
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="chrome://browser/content/zen-styles/zen-buttons.css"
|
||||
/>
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="chrome://browser/content/zen-styles/zen-theme.css"
|
||||
/>
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="chrome://browser/content/zen-styles/zen-animations.css"
|
||||
/>
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="chrome://browser/content/zen-styles/zen-panel-ui.css"
|
||||
/>
|
||||
<link rel="stylesheet" href="chrome://browser/skin/zen-icons/icons.css" />
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="chrome://browser/content/zen-styles/zen-advanced-color-options.css"
|
||||
/>
|
||||
|
||||
<link rel="localization" href="browser/zen-boosts.ftl"/>
|
||||
<link rel="localization" href="browser/zen-boosts.ftl" />
|
||||
|
||||
<!-- Loading in the window module -->
|
||||
<script>
|
||||
const { nsZenBoostEditor } = ChromeUtils.importESModule( "resource:///modules/zen/boosts/ZenBoostsEditor.mjs" );
|
||||
window.addEventListener("load", () => {
|
||||
window.boostEditor = new nsZenBoostEditor(document, window.domain, window, window.openerWindow);
|
||||
});
|
||||
</script>
|
||||
</head>
|
||||
<html:body xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
||||
<vbox flex="1" id="zen-boost-editor-root">
|
||||
<hbox id="zen-boost-head-wrapper">
|
||||
<button id="zen-boost-close" class="subviewbutton mod-button title-button"></button>
|
||||
<hbox id="zen-boost-name" flex="1">
|
||||
<hbox id="zen-boost-name-container">
|
||||
<html:p id="zen-boost-name-text"></html:p>
|
||||
<!-- Loading in the window module -->
|
||||
<script>
|
||||
const { nsZenBoostEditor } = ChromeUtils.importESModule(
|
||||
"resource:///modules/zen/boosts/ZenBoostsEditor.mjs"
|
||||
);
|
||||
window.addEventListener("load", () => {
|
||||
window.boostEditor = new nsZenBoostEditor(
|
||||
document,
|
||||
window.domain,
|
||||
window,
|
||||
window.openerWindow
|
||||
);
|
||||
});
|
||||
</script>
|
||||
</head>
|
||||
<html:body
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
>
|
||||
<vbox flex="1" id="zen-boost-editor-root">
|
||||
<hbox id="zen-boost-head-wrapper">
|
||||
<button
|
||||
id="zen-boost-close"
|
||||
class="subviewbutton mod-button title-button"
|
||||
></button>
|
||||
<hbox id="zen-boost-name" flex="1">
|
||||
<hbox id="zen-boost-name-container">
|
||||
<html:p id="zen-boost-name-text"></html:p>
|
||||
</hbox>
|
||||
</hbox>
|
||||
<button
|
||||
data-l10n-id="zen-boost-shuffle"
|
||||
id="zen-boost-shuffle"
|
||||
class="subviewbutton mod-button title-button"
|
||||
></button>
|
||||
</hbox>
|
||||
<button data-l10n-id="zen-boost-shuffle" id="zen-boost-shuffle" class="subviewbutton mod-button title-button"></button>
|
||||
</hbox>
|
||||
<vbox flex="1" id="zen-boost-filter-wrapper">
|
||||
<hbox class="zen-boost-color-picker-gradient zen-boost-panel-disabled">
|
||||
<button data-l10n-id="zen-boost-magic-theme" id="zen-boost-magic-theme" class="subviewbutton mod-button"></button>
|
||||
<html:div class="zen-boost-color-picker-dot"></html:div>
|
||||
<html:div class="zen-boost-color-picker-circle"></html:div>
|
||||
</hbox>
|
||||
|
||||
<hbox flex="1" id="zen-boost-toolbar-wrapper-colors">
|
||||
<button data-l10n-id="zen-boost-invert" id="zen-boost-invert" class="subviewbutton mod-button small"></button>
|
||||
<button data-l10n-id="zen-boost-controls" id="zen-boost-controls" class="subviewbutton mod-button small"></button>
|
||||
<button data-l10n-id="zen-boost-disable" id="zen-boost-disable" class="subviewbutton mod-button small"></button>
|
||||
</hbox>
|
||||
|
||||
<html:div id="zen-boost-font-wrapper">
|
||||
<vbox id="zen-boost-font-grid">
|
||||
<!-- Font buttons will be injected here -->
|
||||
</vbox>
|
||||
<html:div class="visible-separator"></html:div>
|
||||
<hbox flex="1" id="zen-boost-font-toolbar">
|
||||
<html:select name="font" id="zen-boost-font-select" class="mod-button">
|
||||
<!-- Additional font options will be injected here -->
|
||||
</html:select>
|
||||
<button data-l10n-id="zen-boost-text-case-toggle" id="zen-boost-text-case-toggle" class="subviewbutton mod-button"></button>
|
||||
<vbox flex="1" id="zen-boost-filter-wrapper">
|
||||
<hbox class="zen-boost-color-picker-gradient zen-boost-panel-disabled">
|
||||
<button
|
||||
data-l10n-id="zen-boost-magic-theme"
|
||||
id="zen-boost-magic-theme"
|
||||
class="subviewbutton mod-button"
|
||||
></button>
|
||||
<html:div class="zen-boost-color-picker-dot"></html:div>
|
||||
<html:div class="zen-boost-color-picker-circle"></html:div>
|
||||
</hbox>
|
||||
</html:div>
|
||||
|
||||
<button id="zen-boost-zap" class="subviewbutton mod-button big-button toggleable-button">
|
||||
<html:p data-l10n-id="zen-boost-zap" id="zen-boost-zap-text"></html:p>
|
||||
<html:p id="zen-boost-zap-value"></html:p>
|
||||
</button>
|
||||
<hbox flex="1" id="zen-boost-toolbar-wrapper-colors">
|
||||
<button
|
||||
data-l10n-id="zen-boost-invert"
|
||||
id="zen-boost-invert"
|
||||
class="subviewbutton mod-button small"
|
||||
></button>
|
||||
<button
|
||||
data-l10n-id="zen-boost-controls"
|
||||
id="zen-boost-controls"
|
||||
class="subviewbutton mod-button small"
|
||||
></button>
|
||||
<button
|
||||
data-l10n-id="zen-boost-disable"
|
||||
id="zen-boost-disable"
|
||||
class="subviewbutton mod-button small"
|
||||
></button>
|
||||
</hbox>
|
||||
|
||||
<button id="zen-boost-code" class="subviewbutton mod-button big-button">
|
||||
<html:p data-l10n-id="zen-boost-code" id="zen-boost-code-text"></html:p>
|
||||
</button>
|
||||
|
||||
<hbox flex="1" id="zen-boost-toolbar-wrapper">
|
||||
<button data-l10n-id="zen-boost-save" id="zen-boost-save" class="subviewbutton mod-button med"></button>
|
||||
<button data-l10n-id="zen-boost-load" id="zen-boost-load" class="subviewbutton mod-button med"></button>
|
||||
<html:div id="zen-boost-font-wrapper">
|
||||
<vbox id="zen-boost-font-grid">
|
||||
<!-- Font buttons will be injected here -->
|
||||
</vbox>
|
||||
<html:div class="visible-separator"></html:div>
|
||||
<hbox flex="1" id="zen-boost-font-toolbar">
|
||||
<html:select
|
||||
name="font"
|
||||
id="zen-boost-font-select"
|
||||
class="mod-button"
|
||||
>
|
||||
<!-- Additional font options will be injected here -->
|
||||
</html:select>
|
||||
<button
|
||||
data-l10n-id="zen-boost-text-case-toggle"
|
||||
id="zen-boost-text-case-toggle"
|
||||
class="subviewbutton mod-button"
|
||||
></button>
|
||||
</hbox>
|
||||
</html:div>
|
||||
|
||||
<button
|
||||
id="zen-boost-zap"
|
||||
class="subviewbutton mod-button big-button toggleable-button"
|
||||
>
|
||||
<html:p data-l10n-id="zen-boost-zap" id="zen-boost-zap-text"></html:p>
|
||||
<html:p id="zen-boost-zap-value"></html:p>
|
||||
</button>
|
||||
|
||||
<button id="zen-boost-code" class="subviewbutton mod-button big-button">
|
||||
<html:p
|
||||
data-l10n-id="zen-boost-code"
|
||||
id="zen-boost-code-text"
|
||||
></html:p>
|
||||
</button>
|
||||
|
||||
<hbox flex="1" id="zen-boost-toolbar-wrapper">
|
||||
<button
|
||||
data-l10n-id="zen-boost-save"
|
||||
id="zen-boost-save"
|
||||
class="subviewbutton mod-button med"
|
||||
></button>
|
||||
<button
|
||||
data-l10n-id="zen-boost-load"
|
||||
id="zen-boost-load"
|
||||
class="subviewbutton mod-button med"
|
||||
></button>
|
||||
</hbox>
|
||||
</vbox>
|
||||
</vbox>
|
||||
<vbox flex="1" id="zen-boost-code-editor-root">
|
||||
<hbox id="zen-boost-code-top-bar">
|
||||
<button id="zen-boost-back" class="subviewbutton mod-button big-button">
|
||||
<html:p
|
||||
data-l10n-id="zen-boost-back"
|
||||
id="zen-boost-back-text"
|
||||
></html:p>
|
||||
</button>
|
||||
</hbox>
|
||||
|
||||
<vbox flex="1" id="zen-boost-code-editor"> </vbox>
|
||||
|
||||
<hbox id="zen-boost-code-bottom-bar">
|
||||
<button
|
||||
data-l10n-id="zen-boost-css-picker"
|
||||
id="zen-boost-css-picker"
|
||||
class="subviewbutton mod-button big-button toggleable-button"
|
||||
></button>
|
||||
<button
|
||||
data-l10n-id="zen-boost-css-inspector"
|
||||
id="zen-boost-css-inspector"
|
||||
class="subviewbutton mod-button big-button"
|
||||
></button>
|
||||
</hbox>
|
||||
</vbox>
|
||||
</vbox>
|
||||
<vbox flex="1" id="zen-boost-code-editor-root">
|
||||
<hbox id="zen-boost-code-top-bar">
|
||||
<button id="zen-boost-back" class="subviewbutton mod-button big-button">
|
||||
<html:p data-l10n-id="zen-boost-back" id="zen-boost-back-text"></html:p>
|
||||
</button>
|
||||
</hbox>
|
||||
|
||||
<vbox flex="1" id="zen-boost-code-editor">
|
||||
</vbox>
|
||||
|
||||
<hbox id="zen-boost-code-bottom-bar">
|
||||
<button data-l10n-id="zen-boost-css-picker" id="zen-boost-css-picker" class="subviewbutton mod-button big-button toggleable-button"></button>
|
||||
<button data-l10n-id="zen-boost-css-inspector" id="zen-boost-css-inspector" class="subviewbutton mod-button big-button"></button>
|
||||
</hbox>
|
||||
</vbox>
|
||||
<popupset id="mainPopupSet">
|
||||
<panel
|
||||
type="arrow"
|
||||
popupalign="topmiddle"
|
||||
id="zen-boost-advanced-color-options-panel"
|
||||
>
|
||||
<html:div flex="1" id="zen-boost-advanced-color-options-container">
|
||||
<p data-l10n-id="zen-bootst-color-contrast"></p>
|
||||
<html:input
|
||||
id="zen-boost-color-contrast"
|
||||
type="range"
|
||||
min="0"
|
||||
max="1"
|
||||
value="0.5"
|
||||
step="0.01"
|
||||
/>
|
||||
<separator />
|
||||
<p data-l10n-id="zen-bootst-color-brightness"></p>
|
||||
<html:input
|
||||
id="zen-boost-color-brightness"
|
||||
type="range"
|
||||
min="0"
|
||||
max="1"
|
||||
value="0.5"
|
||||
step="0.01"
|
||||
/>
|
||||
<separator />
|
||||
<p data-l10n-id="zen-bootst-color-original-saturation"></p>
|
||||
<html:input
|
||||
id="zen-boost-color-saturation"
|
||||
type="range"
|
||||
min="0"
|
||||
max="1"
|
||||
value="0.5"
|
||||
step="0.01"
|
||||
/>
|
||||
</html:div>
|
||||
</panel>
|
||||
</popupset>
|
||||
|
||||
<popupset id="mainPopupSet">
|
||||
<panel type="arrow" popupalign="topmiddle" id="zen-boost-advanced-color-options-panel">
|
||||
<html:div flex="1" id="zen-boost-advanced-color-options-container">
|
||||
<p data-l10n-id="zen-bootst-color-contrast"></p>
|
||||
<html:input id="zen-boost-color-contrast" type="range" min="0" max="1" value="0.5" step="0.01"/>
|
||||
<separator />
|
||||
<p data-l10n-id="zen-bootst-color-brightness"></p>
|
||||
<html:input id="zen-boost-color-brightness" type="range" min="0" max="1" value="0.5" step="0.01"/>
|
||||
<separator />
|
||||
<p data-l10n-id="zen-bootst-color-original-saturation"></p>
|
||||
<html:input id="zen-boost-color-saturation" type="range" min="0" max="1" value="0.5" step="0.01"/>
|
||||
</html:div>
|
||||
</panel>
|
||||
</popupset>
|
||||
<menupopup id="zenBoostContextMenu">
|
||||
<menuitem
|
||||
data-l10n-id="zen-boost-edit-rename"
|
||||
id="zen-boost-edit-rename"
|
||||
command="cmd_zenBoostEditName"
|
||||
/>
|
||||
<menuitem
|
||||
data-l10n-id="zen-boost-edit-shuffle"
|
||||
id="zen-boost-edit-shuffle"
|
||||
command="cmd_zenBoostShuffle"
|
||||
/>
|
||||
<menuitem
|
||||
data-l10n-id="zen-boost-edit-reset"
|
||||
id="zen-boost-edit-reset"
|
||||
command="cmd_zenBoostReset"
|
||||
/>
|
||||
<menuseparator />
|
||||
<menuitem
|
||||
data-l10n-id="zen-boost-edit-delete"
|
||||
id="zen-boost-edit-delete"
|
||||
command="cmd_zenBoostDelete"
|
||||
/>
|
||||
</menupopup>
|
||||
|
||||
<menupopup id="zenBoostContextMenu">
|
||||
<menuitem data-l10n-id="zen-boost-edit-rename" id="zen-boost-edit-rename" command="cmd_zenBoostEditName" />
|
||||
<menuitem data-l10n-id="zen-boost-edit-shuffle" id="zen-boost-edit-shuffle" command="cmd_zenBoostShuffle" />
|
||||
<menuitem data-l10n-id="zen-boost-edit-reset" id="zen-boost-edit-reset" command="cmd_zenBoostReset" />
|
||||
<menuseparator/>
|
||||
<menuitem data-l10n-id="zen-boost-edit-delete" id="zen-boost-edit-delete" command="cmd_zenBoostDelete" />
|
||||
</menupopup>
|
||||
<commandset id="zenBoostCommandSet">
|
||||
<command
|
||||
id="cmd_zenBoostEditName"
|
||||
oncommand="window.boostEditor.editBoostName()"
|
||||
/>
|
||||
|
||||
<commandset id="zenBoostCommandSet">
|
||||
<command id="cmd_zenBoostEditName"
|
||||
oncommand="window.boostEditor.editBoostName();" />
|
||||
<command
|
||||
id="cmd_zenBoostShuffle"
|
||||
oncommand="window.boostEditor.shuffleBoost()"
|
||||
/>
|
||||
|
||||
<command id="cmd_zenBoostShuffle"
|
||||
oncommand="window.boostEditor.shuffleBoost();" />
|
||||
<command
|
||||
id="cmd_zenBoostReset"
|
||||
oncommand="window.boostEditor.resetBoost()"
|
||||
/>
|
||||
|
||||
<command id="cmd_zenBoostReset"
|
||||
oncommand="window.boostEditor.resetBoost();" />
|
||||
|
||||
<command id="cmd_zenBoostDelete"
|
||||
oncommand="window.boostEditor.deleteBoost();" />
|
||||
</commandset>
|
||||
</html:body>
|
||||
<command
|
||||
id="cmd_zenBoostDelete"
|
||||
oncommand="window.boostEditor.deleteBoost()"
|
||||
/>
|
||||
</commandset>
|
||||
</html:body>
|
||||
</html>
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
background-color: #f6f6f8c0;
|
||||
}
|
||||
|
||||
border: solid 0px #ededef;
|
||||
border: solid 0 #ededef;
|
||||
border-bottom-width: 1px;
|
||||
}
|
||||
|
||||
@@ -70,7 +70,7 @@
|
||||
background-color: #f6f6f8c0;
|
||||
}
|
||||
|
||||
border: solid 0px #ededef;
|
||||
border: solid 0 #ededef;
|
||||
border-top-width: 1px;
|
||||
|
||||
display: flex;
|
||||
@@ -100,8 +100,8 @@ body {
|
||||
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding: 0px;
|
||||
margin: 0px;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
|
||||
& button {
|
||||
border-radius: 6px;
|
||||
@@ -216,7 +216,7 @@ body {
|
||||
#zen-boost-font-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(5, 1fr);
|
||||
gap: 0px;
|
||||
gap: 0;
|
||||
width: 100%;
|
||||
|
||||
padding: 2px;
|
||||
@@ -299,7 +299,7 @@ body {
|
||||
list-style-type: none;
|
||||
|
||||
& hbox {
|
||||
margin-right: 0px;
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -375,20 +375,20 @@ body {
|
||||
}
|
||||
|
||||
#zen-boost-close {
|
||||
margin-left: 0px;
|
||||
margin-left: 0;
|
||||
margin-right: 6px;
|
||||
@media (-moz-platform: macos) {
|
||||
margin-left: 6px;
|
||||
margin-right: 0px;
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
#zen-boost-shuffle {
|
||||
margin-right: 0px;
|
||||
margin-right: 0;
|
||||
margin-left: 4px;
|
||||
@media (-moz-platform: macos) {
|
||||
margin-right: 10px;
|
||||
margin-left: 0px;
|
||||
margin-left: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -415,7 +415,7 @@ body {
|
||||
margin-top: 12px;
|
||||
|
||||
z-index: 4;
|
||||
box-shadow: 0px 2px 4px #00000010;
|
||||
box-shadow: 0 2px 4px #00000010;
|
||||
|
||||
position: relative;
|
||||
margin-left: auto;
|
||||
@@ -456,12 +456,11 @@ body {
|
||||
transition: 0.4s opacity cubic-bezier(0.075, 0.82, 0.165, 1) !important;
|
||||
|
||||
color: #727272;
|
||||
background-color: transparent;
|
||||
background: none;
|
||||
|
||||
font-size: 9pt;
|
||||
|
||||
padding: 0px;
|
||||
padding: 0;
|
||||
text-indent: 2px;
|
||||
|
||||
margin-left: 8px;
|
||||
@@ -492,7 +491,7 @@ body {
|
||||
}
|
||||
|
||||
#zen-boost-font-wrapper {
|
||||
box-shadow: 0px 2px 8px #00000010;
|
||||
box-shadow: 0 2px 8px #00000010;
|
||||
background-color: #ffffff;
|
||||
|
||||
border-radius: 6px;
|
||||
@@ -659,10 +658,10 @@ body {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
border-radius: 16px;
|
||||
box-shadow: 0px 4px 12px #00000021;
|
||||
box-shadow: 0 4px 12px #00000021;
|
||||
width: 100%;
|
||||
aspect-ratio: 1 /1;
|
||||
margin: 10px 0px 4px 0px;
|
||||
margin: 10px 0 4px 0;
|
||||
|
||||
min-height: calc(var(--panel-width) - var(--panel-padding) * 2 - 2px);
|
||||
|
||||
@@ -687,7 +686,7 @@ body {
|
||||
}
|
||||
|
||||
& .zen-boost-color-picker-dot {
|
||||
box-shadow: 0px 2px 4px #00000022;
|
||||
box-shadow: 0 2px 4px #00000022;
|
||||
position: absolute;
|
||||
z-index: 4;
|
||||
width: 24px;
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
border-radius: 24px;
|
||||
}
|
||||
|
||||
box-shadow: 0px 0px 20px#00000050;
|
||||
box-shadow: 0 0 20px#00000050;
|
||||
|
||||
scale: 1;
|
||||
opacity: 1;
|
||||
@@ -130,16 +130,16 @@
|
||||
|
||||
border: none;
|
||||
color: #dadada;
|
||||
box-shadow: 0px 0px 15px #00000052;
|
||||
box-shadow: 0 0 15px #00000052;
|
||||
|
||||
&:hover {
|
||||
box-shadow: 0px 0px 14px #00000066;
|
||||
box-shadow: 0 0 14px #00000066;
|
||||
background:
|
||||
linear-gradient(to right, transparent var(--related-elements-value), gray var(--related-elements-value)),
|
||||
linear-gradient(to top, rgb(247, 66, 0), rgb(245, 134, 86));
|
||||
|
||||
@media not (-moz-platform: windows) {
|
||||
box-shadow: 0px 0px 20px #00000077;
|
||||
box-shadow: 0 0 20px #00000077;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -151,7 +151,7 @@
|
||||
border: none;
|
||||
color: #dadada;
|
||||
|
||||
box-shadow: 0px 0px 15px #00000052;
|
||||
box-shadow: 0 0 15px #00000052;
|
||||
}
|
||||
|
||||
#select-cancel {
|
||||
@@ -165,7 +165,7 @@
|
||||
border: none;
|
||||
color: #dadada;
|
||||
|
||||
box-shadow: 0px 0px 15px #00000052;
|
||||
box-shadow: 0 0 15px #00000052;
|
||||
}
|
||||
|
||||
#selector-preview {
|
||||
|
||||
@@ -16,10 +16,10 @@
|
||||
|
||||
@keyframes zap-border-in {
|
||||
0% {
|
||||
left: 0px;
|
||||
top: 0px;
|
||||
bottom: 0px;
|
||||
right: 0px;
|
||||
left: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
100% {
|
||||
|
||||
@@ -8,8 +8,7 @@
|
||||
#include "nsIZenDragAndDrop.h"
|
||||
#include "nsCOMPtr.h"
|
||||
|
||||
#define ZEN_DND_MANAGER_CONTRACTID \
|
||||
"@mozilla.org/zen/drag-and-drop;1"
|
||||
#define ZEN_DND_MANAGER_CONTRACTID "@mozilla.org/zen/drag-and-drop;1"
|
||||
|
||||
namespace zen {
|
||||
|
||||
|
||||
@@ -33,7 +33,8 @@ nsZenModsBackend::nsZenModsBackend() { (void)CheckEnabled(); }
|
||||
auto nsZenModsBackend::CheckEnabled() -> void {
|
||||
// Check if the mods backend is enabled based on the preference.
|
||||
bool inSafeMode = false;
|
||||
if (nsCOMPtr<nsIXULRuntime> appInfo = do_GetService("@mozilla.org/xre/app-info;1")) {
|
||||
if (nsCOMPtr<nsIXULRuntime> appInfo =
|
||||
do_GetService("@mozilla.org/xre/app-info;1")) {
|
||||
appInfo->GetInSafeMode(&inSafeMode);
|
||||
}
|
||||
mEnabled = !inSafeMode &&
|
||||
|
||||
@@ -23,7 +23,10 @@ add_task(async function test_getSelectionPath_basic() {
|
||||
|
||||
for (let i = 0; i <= 7; i++) {
|
||||
const path = component.getSelectionPath(doc, i, child2);
|
||||
ok(path, `getSelectionPath should return a path for relatedValueIndex=${i}`);
|
||||
ok(
|
||||
path,
|
||||
`getSelectionPath should return a path for relatedValueIndex=${i}`
|
||||
);
|
||||
|
||||
const selectedElements = doc.querySelectorAll(path);
|
||||
|
||||
@@ -33,6 +36,9 @@ add_task(async function test_getSelectionPath_basic() {
|
||||
"For relatedValueIndex=1 there should be exactly one queried element"
|
||||
);
|
||||
|
||||
ok(selectedElements.length >= 1, "CSS path should select at least one element");
|
||||
ok(
|
||||
selectedElements.length >= 1,
|
||||
"CSS path should select at least one element"
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -8,7 +8,11 @@ add_task(async function test_getSelectionPath_invalidNode() {
|
||||
const component = new SelectorComponent(doc, null, [], () => {});
|
||||
|
||||
// Null element
|
||||
Assert.equal(component.getSelectionPath(doc, 0, null), null, "Null element should return null");
|
||||
Assert.equal(
|
||||
component.getSelectionPath(doc, 0, null),
|
||||
null,
|
||||
"Null element should return null"
|
||||
);
|
||||
|
||||
// Body element
|
||||
Assert.equal(
|
||||
|
||||
@@ -34,6 +34,10 @@ add_task(async function test_getSelectionPath_nthchild() {
|
||||
"Selector must include the selected node"
|
||||
);
|
||||
|
||||
Assert.equal(selectedElements.length, 1, "Selector should uniquely identify the element");
|
||||
Assert.equal(
|
||||
selectedElements.length,
|
||||
1,
|
||||
"Selector should uniquely identify the element"
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -101,7 +101,7 @@ export class nsZenSiteDataPanel {
|
||||
#initBrowserListeners() {
|
||||
Services.obs.addObserver(this, "zen-boosts-update");
|
||||
this.window.gBrowser.addProgressListener({
|
||||
onLocationChange: (aWebProgress) => {
|
||||
onLocationChange: aWebProgress => {
|
||||
if (aWebProgress.isTopLevel) {
|
||||
this.checkIfTabIsBoosted();
|
||||
}
|
||||
@@ -266,7 +266,7 @@ export class nsZenSiteDataPanel {
|
||||
|
||||
if (boosts) {
|
||||
const activeBoostId = lazy.gZenBoostsManager.getActiveBoostId(domain);
|
||||
boosts.forEach((boost) => {
|
||||
boosts.forEach(boost => {
|
||||
const boostData = boost.boostEntry.boostData;
|
||||
if (!boostData.changeWasMade) {
|
||||
return;
|
||||
@@ -296,7 +296,14 @@ export class nsZenSiteDataPanel {
|
||||
this.#setSiteBoost();
|
||||
}
|
||||
|
||||
#createBoostPanelItem(iconClass, title, description, actionId, boost = null, enabled = false) {
|
||||
#createBoostPanelItem(
|
||||
iconClass,
|
||||
title,
|
||||
description,
|
||||
actionId,
|
||||
boost = null,
|
||||
enabled = false
|
||||
) {
|
||||
const container = this.document.createXULElement("hbox");
|
||||
container.classList.add("permission-popup-boost-item");
|
||||
|
||||
@@ -311,7 +318,10 @@ export class nsZenSiteDataPanel {
|
||||
}
|
||||
|
||||
const img = this.document.createXULElement("toolbarbutton");
|
||||
img.classList.add("permission-popup-boost-icon", "zen-site-data-boost-icon");
|
||||
img.classList.add(
|
||||
"permission-popup-boost-icon",
|
||||
"zen-site-data-boost-icon"
|
||||
);
|
||||
img.setAttribute("closemenu", "none");
|
||||
img.classList.add(iconClass);
|
||||
|
||||
@@ -341,7 +351,7 @@ export class nsZenSiteDataPanel {
|
||||
editorButton.classList.add("zen-permission-popup-boost-editor-button");
|
||||
container.appendChild(editorButton);
|
||||
|
||||
editorButton.addEventListener("click", (event) => {
|
||||
editorButton.addEventListener("click", event => {
|
||||
event.stopPropagation(); // Prevents the container event
|
||||
this.#onBoostClick(event);
|
||||
});
|
||||
@@ -425,7 +435,9 @@ export class nsZenSiteDataPanel {
|
||||
}
|
||||
|
||||
#resetSiteOptionsList() {
|
||||
const settingsList = this.document.getElementById("zen-site-data-settings-list");
|
||||
const settingsList = this.document.getElementById(
|
||||
"zen-site-data-settings-list"
|
||||
);
|
||||
settingsList.innerHTML = "";
|
||||
const boostList = this.document.getElementById("zen-site-data-boost-list");
|
||||
boostList.innerHTML = "";
|
||||
@@ -865,7 +877,10 @@ export class nsZenSiteDataPanel {
|
||||
case "zen-site-data-edit-boost": {
|
||||
const boostId = target.getAttribute("data-boost-id");
|
||||
const uri = this.window.gBrowser.currentURI;
|
||||
const boost = lazy.gZenBoostsManager.loadBoostFromStore(domain, boostId);
|
||||
const boost = lazy.gZenBoostsManager.loadBoostFromStore(
|
||||
domain,
|
||||
boostId
|
||||
);
|
||||
lazy.gZenBoostsManager.openBoostWindow(this.window, boost, uri);
|
||||
this.unifiedPanel.hidePopup();
|
||||
break;
|
||||
|
||||
Reference in New Issue
Block a user