|
|
@@ -28,24 +28,25 @@ this.singlefile.extension.ui.content.main = this.singlefile.extension.ui.content
|
|
|
const SELECTED_CONTENT_ATTRIBUTE_NAME = this.singlefile.lib.helper.SELECTED_CONTENT_ATTRIBUTE_NAME;
|
|
|
|
|
|
const MASK_TAGNAME = "singlefile-mask";
|
|
|
- const PROGRESS_BAR_TAGNAME = "singlefile-progress-bar";
|
|
|
- const PROGRESS_CURSOR_TAGNAME = "singlefile-progress-cursor";
|
|
|
+ const MASK_CONTENT_CLASSNAME = "singlefile-mask-content";
|
|
|
+ const PROGRESSBAR_CLASSNAME = "singlefile-progress-bar";
|
|
|
+ const PROGRESSBAR_CONTENT_CLASSNAME = "singlefile-progress-bar-content";
|
|
|
const SELECTION_ZONE_TAGNAME = "single-file-selection-zone";
|
|
|
const LOGS_WINDOW_TAGNAME = "singlefile-logs-window";
|
|
|
- const LOGS_LINE_TAGNAME = "singlefile-logs-line";
|
|
|
- const LOGS_LINE_ELEMENT_TAGNAME = "singlefile-logs-element";
|
|
|
+ const LOGS_CLASSNAME = "singlefile-logs";
|
|
|
+ const LOGS_LINE_CLASSNAME = "singlefile-logs-line";
|
|
|
+ const LOGS_LINE_TEXT_ELEMENT_CLASSNAME = "singlefile-logs-line-text";
|
|
|
+ const LOGS_LINE_STATUS_ELEMENT_CLASSNAME = "singlefile-logs-line-icon";
|
|
|
const SINGLE_FILE_UI_ELEMENT_CLASS = "single-file-ui-element";
|
|
|
const SELECT_PX_THRESHOLD = 8;
|
|
|
const LOG_PANEL_DEFERRED_IMAGES_MESSAGE = browser.i18n.getMessage("logPanelDeferredImages");
|
|
|
const LOG_PANEL_FRAME_CONTENTS_MESSAGE = browser.i18n.getMessage("logPanelFrameContents");
|
|
|
const LOG_PANEL_STEP_MESSAGE = browser.i18n.getMessage("logPanelStep");
|
|
|
const LOG_PANEL_WIDTH = browser.i18n.getMessage("logPanelWidth");
|
|
|
+ const CSS_PROPERTIES = new Set(Array.from(getComputedStyle(document.body)));
|
|
|
|
|
|
- let selectedAreaElement;
|
|
|
-
|
|
|
- let logsWindowElement = createLogsWindowElement();
|
|
|
- const allProperties = new Set();
|
|
|
- Array.from(getComputedStyle(document.body)).forEach(property => allProperties.add(property));
|
|
|
+ let selectedAreaElement, logsWindowElement;
|
|
|
+ createLogsWindowElement();
|
|
|
|
|
|
return {
|
|
|
getSelectedLinks,
|
|
|
@@ -58,7 +59,6 @@ this.singlefile.extension.ui.content.main = this.singlefile.extension.ui.content
|
|
|
let maskElement = document.querySelector(MASK_TAGNAME);
|
|
|
if (!maskElement) {
|
|
|
if (options.logsEnabled) {
|
|
|
- setLogsWindowStyle();
|
|
|
document.body.appendChild(logsWindowElement);
|
|
|
}
|
|
|
if (options.shadowEnabled) {
|
|
|
@@ -66,9 +66,6 @@ this.singlefile.extension.ui.content.main = this.singlefile.extension.ui.content
|
|
|
if (options.progressBarEnabled) {
|
|
|
createProgressBarElement(maskElement);
|
|
|
}
|
|
|
- maskElement.offsetWidth;
|
|
|
- maskElement.style.setProperty("background-color", "black", "important");
|
|
|
- maskElement.style.setProperty("opacity", .3, "important");
|
|
|
}
|
|
|
}
|
|
|
},
|
|
|
@@ -77,17 +74,20 @@ this.singlefile.extension.ui.content.main = this.singlefile.extension.ui.content
|
|
|
if (maskElement) {
|
|
|
maskElement.remove();
|
|
|
}
|
|
|
-
|
|
|
logsWindowElement.remove();
|
|
|
clearLogs();
|
|
|
},
|
|
|
onLoadResource(index, maxIndex, options) {
|
|
|
if (options.shadowEnabled && options.progressBarEnabled) {
|
|
|
- const progressBarElement = document.querySelector(PROGRESS_BAR_TAGNAME);
|
|
|
- if (progressBarElement && maxIndex) {
|
|
|
- const width = Math.floor((index / maxIndex) * 100) + "%";
|
|
|
- if (progressBarElement.style.getPropertyValue("width") != width) {
|
|
|
- requestAnimationFrame(() => progressBarElement.style.setProperty("width", Math.floor((index / maxIndex) * 100) + "%", "important"));
|
|
|
+ const maskElement = document.querySelector(MASK_TAGNAME);
|
|
|
+ if (maskElement) {
|
|
|
+ const progressBarElement = maskElement.shadowRoot.querySelector("." + PROGRESSBAR_CLASSNAME);
|
|
|
+ if (progressBarElement && maxIndex) {
|
|
|
+ const width = Math.floor((index / maxIndex) * 100) + "%";
|
|
|
+ if (progressBarElement.style.getPropertyValue("width") != width) {
|
|
|
+ progressBarElement.style.setProperty("width", width);
|
|
|
+ progressBarElement.offsetWidth;
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
@@ -377,104 +377,151 @@ this.singlefile.extension.ui.content.main = this.singlefile.extension.ui.content
|
|
|
function createMaskElement() {
|
|
|
let maskElement = document.querySelector(MASK_TAGNAME);
|
|
|
if (!maskElement) {
|
|
|
- maskElement = createElement(MASK_TAGNAME);
|
|
|
- maskElement.style.setProperty("opacity", 0, "important");
|
|
|
- maskElement.style.setProperty("background-color", "transparent", "important");
|
|
|
- maskElement.style.setProperty("position", "fixed", "important");
|
|
|
- maskElement.style.setProperty("top", "0", "important");
|
|
|
- maskElement.style.setProperty("left", "0", "important");
|
|
|
- maskElement.style.setProperty("width", "100%", "important");
|
|
|
- maskElement.style.setProperty("height", "100%", "important");
|
|
|
- maskElement.style.setProperty("z-index", 2147483646, "important");
|
|
|
- maskElement.style.setProperty("transition", "opacity 250ms", "important");
|
|
|
- document.body.appendChild(maskElement);
|
|
|
+ maskElement = createElement(MASK_TAGNAME, document.body);
|
|
|
+ const shadowRoot = maskElement.attachShadow({ mode: "open" });
|
|
|
+ const styleElement = document.createElement("style");
|
|
|
+ styleElement.textContent = `
|
|
|
+ @keyframes single-file-progress {
|
|
|
+ 0% {
|
|
|
+ left: -50px;
|
|
|
+ }
|
|
|
+ 100% {
|
|
|
+ left: 0;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .${PROGRESSBAR_CLASSNAME} {
|
|
|
+ position: fixed;
|
|
|
+ top: 0;
|
|
|
+ left: 0;
|
|
|
+ width: 0;
|
|
|
+ height: 8px;
|
|
|
+ z-index: 2147483646;
|
|
|
+ opacity: .5;
|
|
|
+ overflow: hidden;
|
|
|
+ transition: width 200ms ease-in-out;
|
|
|
+ }
|
|
|
+ .${PROGRESSBAR_CONTENT_CLASSNAME} {
|
|
|
+ position: absolute;
|
|
|
+ left: 0;
|
|
|
+ animation: single-file-progress 3s linear infinite reverse;
|
|
|
+ background:
|
|
|
+ white
|
|
|
+ linear-gradient(-45deg, rgba(0, 0, 0, 0.075) 25%,
|
|
|
+ transparent 25%,
|
|
|
+ transparent 50%,
|
|
|
+ rgba(0, 0, 0, 0.075) 50%,
|
|
|
+ rgba(0, 0, 0, 0.075) 75%,
|
|
|
+ transparent 75%, transparent)
|
|
|
+ repeat scroll 0% 0% / 50px 50px padding-box border-box;
|
|
|
+ width: calc(100% + 50px);
|
|
|
+ height: 100%;
|
|
|
+ }
|
|
|
+ .${MASK_CONTENT_CLASSNAME} {
|
|
|
+ position: fixed;
|
|
|
+ top: 0;
|
|
|
+ left: 0;
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+ z-index: 2147483646;
|
|
|
+ opacity: 0;
|
|
|
+ background-color: black;
|
|
|
+ transition: opacity 250ms;
|
|
|
+ }
|
|
|
+ `;
|
|
|
+ shadowRoot.appendChild(styleElement);
|
|
|
+ let maskElementContent = document.createElement("div");
|
|
|
+ maskElementContent.classList.add(MASK_CONTENT_CLASSNAME);
|
|
|
+ shadowRoot.appendChild(maskElementContent);
|
|
|
+ maskElement.offsetWidth;
|
|
|
+ maskElementContent.style.setProperty("opacity", .3);
|
|
|
maskElement.offsetWidth;
|
|
|
}
|
|
|
return maskElement;
|
|
|
}
|
|
|
|
|
|
function createProgressBarElement(maskElement) {
|
|
|
- let progressBarElementContainer = document.querySelector(PROGRESS_BAR_TAGNAME);
|
|
|
- if (!progressBarElementContainer) {
|
|
|
- progressBarElementContainer = createElement(PROGRESS_BAR_TAGNAME, maskElement);
|
|
|
- const styleElement = document.createElement("style");
|
|
|
- styleElement.textContent = "@keyframes single-file-progress { 0% { left: -50px } 100% { left: 0 }";
|
|
|
- maskElement.appendChild(styleElement);
|
|
|
- progressBarElementContainer.style.setProperty("position", "fixed", "important");
|
|
|
- progressBarElementContainer.style.setProperty("top", "0", "important");
|
|
|
- progressBarElementContainer.style.setProperty("left", "0", "important");
|
|
|
- progressBarElementContainer.style.setProperty("width", "0", "important");
|
|
|
- progressBarElementContainer.style.setProperty("height", "8px", "important");
|
|
|
- progressBarElementContainer.style.setProperty("overflow", "hidden", "important");
|
|
|
- progressBarElementContainer.style.setProperty("transition", "width 200ms", "important");
|
|
|
- progressBarElementContainer.style.setProperty("will-change", "width", "important");
|
|
|
- const progressBarElement = createElement(PROGRESS_CURSOR_TAGNAME, progressBarElementContainer);
|
|
|
- progressBarElement.style.setProperty("position", "absolute", "important");
|
|
|
- progressBarElement.style.setProperty("left", "0");
|
|
|
- progressBarElement.style.setProperty("animation", "single-file-progress 5s linear infinite reverse", "important");
|
|
|
- progressBarElement.style.setProperty("background", "white linear-gradient(-45deg, rgba(0, 0, 0, 0.1) 25%, transparent 25%, transparent 50%, rgba(0, 0, 0, 0.1) 50%, rgba(0, 0, 0, 0.1) 75%, transparent 75%, transparent) repeat scroll 0% 0% / 50px 50px padding-box border-box", "important");
|
|
|
- progressBarElement.style.setProperty("width", "calc(100% + 50px)", "important");
|
|
|
- progressBarElement.style.setProperty("height", "100%", "important");
|
|
|
- progressBarElement.style.setProperty("inset-inline-start", "auto");
|
|
|
+ let progressBarElement = maskElement.shadowRoot.querySelector("." + PROGRESSBAR_CLASSNAME);
|
|
|
+ if (!progressBarElement) {
|
|
|
+ let progressBarContent = document.createElement("div");
|
|
|
+ progressBarContent.classList.add(PROGRESSBAR_CLASSNAME);
|
|
|
+ maskElement.shadowRoot.appendChild(progressBarContent);
|
|
|
+ const progressBarContentElement = document.createElement("div");
|
|
|
+ progressBarContentElement.classList.add(PROGRESSBAR_CONTENT_CLASSNAME);
|
|
|
+ progressBarContent.appendChild(progressBarContentElement);
|
|
|
}
|
|
|
- return progressBarElementContainer;
|
|
|
}
|
|
|
|
|
|
function createLogsWindowElement() {
|
|
|
- let logsWindowElement = document.querySelector(LOGS_WINDOW_TAGNAME);
|
|
|
+ logsWindowElement = document.querySelector(LOGS_WINDOW_TAGNAME);
|
|
|
if (!logsWindowElement) {
|
|
|
- logsWindowElement = document.createElement(LOGS_WINDOW_TAGNAME);
|
|
|
- logsWindowElement.className = SINGLE_FILE_UI_ELEMENT_CLASS;
|
|
|
+ logsWindowElement = createElement(LOGS_WINDOW_TAGNAME);
|
|
|
+ const shadowRoot = logsWindowElement.attachShadow({ mode: "open" });
|
|
|
+ const styleElement = document.createElement("style");
|
|
|
+ styleElement.textContent = `
|
|
|
+ @keyframes single-file-pulse {
|
|
|
+ 0% {
|
|
|
+ opacity: .25;
|
|
|
+ }
|
|
|
+ 100% {
|
|
|
+ opacity: 1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .${LOGS_CLASSNAME} {
|
|
|
+ position: fixed;
|
|
|
+ bottom: 24px;
|
|
|
+ left: 8px;
|
|
|
+ z-index: 2147483647;
|
|
|
+ opacity: 0.9;
|
|
|
+ padding: 4px;
|
|
|
+ background-color: white;
|
|
|
+ min-width: ${LOG_PANEL_WIDTH}px;
|
|
|
+ min-height: 16px;
|
|
|
+ transition: height 100ms;
|
|
|
+ }
|
|
|
+ .${LOGS_LINE_CLASSNAME} {
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ padding: 2px;
|
|
|
+ font-family: arial, sans-serif;
|
|
|
+ color: black;
|
|
|
+ background-color: white;
|
|
|
+ }
|
|
|
+ .${LOGS_LINE_TEXT_ELEMENT_CLASSNAME} {
|
|
|
+ font-size: 13px;
|
|
|
+ opacity: 1;
|
|
|
+ transition: opacity 200ms;
|
|
|
+ }
|
|
|
+ .${LOGS_LINE_STATUS_ELEMENT_CLASSNAME} {
|
|
|
+ font-size: 11px;
|
|
|
+ min-width: 15px;
|
|
|
+ text-align: center;
|
|
|
+ position: relative;
|
|
|
+ top: 1px;
|
|
|
+ }
|
|
|
+ `;
|
|
|
+ shadowRoot.appendChild(styleElement);
|
|
|
+ const logsContentElement = document.createElement("div");
|
|
|
+ logsContentElement.classList.add(LOGS_CLASSNAME);
|
|
|
+ shadowRoot.appendChild(logsContentElement);
|
|
|
}
|
|
|
- const styleElement = document.createElement("style");
|
|
|
- logsWindowElement.appendChild(styleElement);
|
|
|
- styleElement.textContent = "@keyframes single-file-pulse { 0% { opacity: .5 } 100% { opacity: 1 }";
|
|
|
- return logsWindowElement;
|
|
|
- }
|
|
|
-
|
|
|
- function setLogsWindowStyle() {
|
|
|
- initStyle(logsWindowElement);
|
|
|
- logsWindowElement.style.setProperty("opacity", "0.9", "important");
|
|
|
- logsWindowElement.style.setProperty("padding", "4px", "important");
|
|
|
- logsWindowElement.style.setProperty("position", "fixed", "important");
|
|
|
- logsWindowElement.style.setProperty("bottom", "24px", "important");
|
|
|
- logsWindowElement.style.setProperty("left", "8px", "important");
|
|
|
- logsWindowElement.style.setProperty("z-index", 2147483647, "important");
|
|
|
- logsWindowElement.style.setProperty("background-color", "white", "important");
|
|
|
- logsWindowElement.style.setProperty("min-width", LOG_PANEL_WIDTH + "px", "important");
|
|
|
- logsWindowElement.style.setProperty("min-height", "16px", "important");
|
|
|
- logsWindowElement.style.setProperty("transition", "height 100ms", "important");
|
|
|
- logsWindowElement.style.setProperty("will-change", "height", "important");
|
|
|
- logsWindowElement.style.setProperty("inset-block", "auto");
|
|
|
}
|
|
|
|
|
|
function updateLog(id, textContent, textStatus, options) {
|
|
|
if (options.logsEnabled) {
|
|
|
- let lineElement = logsWindowElement.querySelector("[data-id='" + id + "']");
|
|
|
+ const logsContentElement = logsWindowElement.shadowRoot.querySelector("." + LOGS_CLASSNAME);
|
|
|
+ let lineElement = logsContentElement.querySelector("[data-id='" + id + "']");
|
|
|
if (!lineElement) {
|
|
|
- lineElement = createElement(LOGS_LINE_TAGNAME, logsWindowElement);
|
|
|
+ lineElement = document.createElement("div");
|
|
|
+ lineElement.classList.add(LOGS_LINE_CLASSNAME);
|
|
|
+ logsContentElement.appendChild(lineElement);
|
|
|
lineElement.setAttribute("data-id", id);
|
|
|
- lineElement.style.setProperty("display", "flex", "important");
|
|
|
- lineElement.style.setProperty("justify-content", "space-between", "important");
|
|
|
- lineElement.style.setProperty("padding", "2px", "important");
|
|
|
- const textElement = createElement(LOGS_LINE_ELEMENT_TAGNAME, lineElement);
|
|
|
- textElement.style.setProperty("font-size", "13px", "important");
|
|
|
- textElement.style.setProperty("font-family", "arial, sans-serif", "important");
|
|
|
- textElement.style.setProperty("color", "black", "important");
|
|
|
- textElement.style.setProperty("background-color", "white", "important");
|
|
|
- textElement.style.setProperty("opacity", "1", "important");
|
|
|
- textElement.style.setProperty("transition", "opacity 200ms", "important");
|
|
|
+ const textElement = document.createElement("div");
|
|
|
+ textElement.classList.add(LOGS_LINE_TEXT_ELEMENT_CLASSNAME);
|
|
|
+ lineElement.appendChild(textElement);
|
|
|
textElement.textContent = textContent;
|
|
|
- const statusElement = createElement(LOGS_LINE_ELEMENT_TAGNAME, lineElement);
|
|
|
- statusElement.style.setProperty("font-size", "11px", "important");
|
|
|
- statusElement.style.setProperty("font-family", "arial, sans-serif", "important");
|
|
|
- statusElement.style.setProperty("color", "black", "important");
|
|
|
- statusElement.style.setProperty("background-color", "white", "important");
|
|
|
- statusElement.style.setProperty("min-width", "15px", "important");
|
|
|
- statusElement.style.setProperty("text-align", "center", "important");
|
|
|
- statusElement.style.setProperty("position", "relative", "important");
|
|
|
- statusElement.style.setProperty("top", "1px", "important");
|
|
|
- statusElement.style.setProperty("will-change", "opacity", "important");
|
|
|
+ const statusElement = document.createElement("div");
|
|
|
+ statusElement.classList.add(LOGS_LINE_STATUS_ELEMENT_CLASSNAME);
|
|
|
+ lineElement.appendChild(statusElement);
|
|
|
}
|
|
|
updateLogLine(lineElement, textContent, textStatus);
|
|
|
}
|
|
|
@@ -484,19 +531,19 @@ this.singlefile.extension.ui.content.main = this.singlefile.extension.ui.content
|
|
|
const textElement = lineElement.childNodes[0];
|
|
|
const statusElement = lineElement.childNodes[1];
|
|
|
textElement.textContent = textContent;
|
|
|
- statusElement.style.setProperty("color", textStatus == "✓" ? "#055000" : "black", "important");
|
|
|
+ statusElement.style.setProperty("color", textStatus == "✓" ? "#055000" : "black");
|
|
|
if (textStatus == "✓") {
|
|
|
- textElement.style.setProperty("opacity", ".5", "important");
|
|
|
- statusElement.style.setProperty("animation", "none", "important");
|
|
|
+ textElement.style.setProperty("opacity", ".5");
|
|
|
+ statusElement.style.setProperty("opacity", ".5");
|
|
|
+ statusElement.style.setProperty("animation", "none");
|
|
|
} else {
|
|
|
- statusElement.style.setProperty("opacity", ".5", "important");
|
|
|
- statusElement.style.setProperty("animation", "single-file-pulse 1s linear infinite alternate", "important");
|
|
|
+ statusElement.style.setProperty("animation", "1s ease-in-out 0s infinite alternate none running single-file-pulse");
|
|
|
}
|
|
|
statusElement.textContent = textStatus;
|
|
|
}
|
|
|
|
|
|
function clearLogs() {
|
|
|
- logsWindowElement = createLogsWindowElement();
|
|
|
+ createLogsWindowElement();
|
|
|
}
|
|
|
|
|
|
function getMatchedParents(target, property) {
|
|
|
@@ -533,12 +580,8 @@ this.singlefile.extension.ui.content.main = this.singlefile.extension.ui.content
|
|
|
if (parentElement) {
|
|
|
parentElement.appendChild(element);
|
|
|
}
|
|
|
- initStyle(element);
|
|
|
+ CSS_PROPERTIES.forEach(property => element.style.setProperty(property, "initial", "important"));
|
|
|
return element;
|
|
|
}
|
|
|
|
|
|
- function initStyle(element) {
|
|
|
- allProperties.forEach(property => element.style.setProperty(property, "initial", "important"));
|
|
|
- }
|
|
|
-
|
|
|
})();
|