diff --git a/src/css/fa-icons.css b/src/css/fa-icons.css index adac445f5..639811f2e 100644 --- a/src/css/fa-icons.css +++ b/src/css/fa-icons.css @@ -101,6 +101,9 @@ .fa-icon > .fa-icon_zoom-out { width: calc(1em * 1664 / 1792); } +.fa-icon > .fa-icon_terminal { + width: calc(1em * 1651 / 1792); + } .fa-icon > .fa-icon_magic { width: calc(1em * 1637 / 1792); } diff --git a/src/css/logger-ui-inspector.css b/src/css/logger-ui-inspector.css index 975d90bf9..3d5dc77f1 100644 --- a/src/css/logger-ui-inspector.css +++ b/src/css/logger-ui-inspector.css @@ -1,5 +1,6 @@ #domInspector { display: none; + overflow: hidden; } #inspectors.dom #domInspector { display: flex; diff --git a/src/css/logger-ui.css b/src/css/logger-ui.css index 7ae632e6e..38e434f56 100644 --- a/src/css/logger-ui.css +++ b/src/css/logger-ui.css @@ -3,7 +3,7 @@ body { flex-direction: column; height: 100vh; height: 100svh; - overflow: hidden; + overflow-y: hidden; width: 100vw; } textarea { @@ -63,19 +63,28 @@ textarea { => https://devhints.io/css-system-font-stack */ #inspectors { + display: flex; + flex-direction: column; flex-grow: 1; + flex-wrap: nowrap; font-family: "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif; + overflow: hidden; position: relative; } .inspector { - border-top: 1px solid #ccc; + border-top: 1px solid var(--border-4); display: flex; flex-direction: column; + height: 100%; + } +.inspector .permatoolbar { + border-bottom: 1px solid var(--border-1); } .vscrollable { direction: ltr; flex-grow: 1; font-size: var(--font-size-smaller); + height: 1px; /* necessary for proper space allocation by flex boxes */ overflow-x: hidden; overflow-y: auto; } @@ -106,7 +115,6 @@ textarea { } #netInspector #filterExprGroup { display: flex; - margin: 0 1em; position: relative; } #netInspector #filterButton { @@ -295,7 +303,7 @@ body[dir="rtl"] #netInspector #filterExprPicker { display: inline-block; height: 100%; overflow: hidden; - padding: 0.2em; + padding: 2px; vertical-align: middle; white-space: nowrap; word-break: break-all; @@ -391,7 +399,6 @@ body[dir="rtl"] #vwRenderer .logEntry > .fields > span:first-child { #vwRenderer .logEntry > .fields > span:nth-of-type(8) a { align-items: center; background-color: dimgray; - bottom: 0; color: white; display: none; height: min(100%, 1.5em); @@ -401,6 +408,7 @@ body[dir="rtl"] #vwRenderer .logEntry > .fields > span:first-child { position: absolute; right: 0; text-decoration: none; + top: 0; width: 1.5em; } #netInspector.vExpanded #vwRenderer .logEntry > .fields > span:nth-of-type(8) a { @@ -462,21 +470,13 @@ body[dir="rtl"] #vwRenderer .logEntry > .fields > span:first-child { width: 100%; } -#netInspector .entryTools { +#inspectors .entryTools { background-color: var(--surface-0); - filter: drop-shadow(2px 4px 6px black); - max-width: 640px; - min-width: min(100%, 640px); - position: absolute; - z-index: 2; + flex-basis: 50%; } -#netInspector .entryTools:empty { +#inspectors .entryTools:empty { display: none; } -#netInspector .entryTools .dialogControls { - display: flex; - justify-content: stretch; - } .closeButton { stroke: var(--ink-1); @@ -497,15 +497,28 @@ body[dir="rtl"] .closeButton { .closeButton > * { pointer-events: none; } -.moveBand { - background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAYAAAAECAYAAACtBE5DAAAAFElEQVQI12NgwAfKy8v/M5ANYLoBshgEyQo6H9UAAAAASUVORK5CYII='); - cursor: grab; - flex-grow: 1; - opacity: 0.5; + +#inspectors #infoInspector { + flex-basis: 200%; + } +#inspectors:not(.console) #infoInspector { + display: none; + } +#inspectors #infoInspector .vscrollable { + font-family: monospace; + font-size: small; + } +#inspectors #infoInspector .vscrollable > div { + border-bottom: 1px dotted gray; + padding: 0.2em; + white-space: pre-wrap; + word-break: break-all; + } +#inspectors #infoInspector .vscrollable > div:first-of-type { + } +#inspectors #infoInspector .vscrollable > div[data-type="error"] { + color: var(--cm-negative); } -.moving .moveBand { - cursor: grabbing; -} #popupContainer { background-color: var(--surface-1); @@ -613,9 +626,10 @@ body[dir="rtl"] .closeButton { align-items: center; border-bottom: 1px solid var(--border-4); display: flex; + justify-content: space-between; line-height: 2; } -.netFilteringDialog > .headers > .header { +.netFilteringDialog > .headers .header { border: 1px solid var(--border-2); border-bottom: 1px solid var(--border-4); border-top-left-radius: 4px; @@ -628,9 +642,9 @@ body[dir="rtl"] .closeButton { position: relative; top: 1px; } -.netFilteringDialog[data-pane="details"] > .headers > [data-pane="details"], -.netFilteringDialog[data-pane="dynamic"] > .headers > [data-pane="dynamic"], -.netFilteringDialog[data-pane="static"] > .headers > [data-pane="static"] { +.netFilteringDialog[data-pane="details"] > .headers [data-pane="details"], +.netFilteringDialog[data-pane="dynamic"] > .headers [data-pane="dynamic"], +.netFilteringDialog[data-pane="static"] > .headers [data-pane="static"] { background-color: var(--surface-0); border-color: var(--border-4); border-bottom: 1px solid transparent; @@ -654,11 +668,11 @@ body[dir="rtl"] .closeButton { color: var(--ink-1); fill: var(--ink-1); } -.netFilteringDialog.extendedRealm > .headers > .dynamic, +.netFilteringDialog.extendedRealm > .headers .dynamic, .netFilteringDialog.extendedRealm > .panes > .dynamic { display: none; } -.netFilteringDialog.extendedRealm > .headers > .static, +.netFilteringDialog.extendedRealm > .headers .static, .netFilteringDialog.extendedRealm > .panes > .static { display: none; } @@ -875,8 +889,6 @@ body.dirty .netFilteringDialog > div.panes > .dynamic > .toolbar #saveRules { } .netFilteringDialog > div.panes > div.static textarea { height: 6em; - max-height: 20vh; - min-height: 10vh; word-break: break-all; } .netFilteringDialog > div.panes > div.static > div:nth-of-type(2) { diff --git a/src/img/fontawesome/fontawesome-defs.svg b/src/img/fontawesome/fontawesome-defs.svg index 0113e065c..4e82babbc 100644 --- a/src/img/fontawesome/fontawesome-defs.svg +++ b/src/img/fontawesome/fontawesome-defs.svg @@ -68,6 +68,7 @@ License - https://github.com/FortAwesome/Font-Awesome/tree/a8386aae19e200ddb0f68 + diff --git a/src/js/fa-icons.js b/src/js/fa-icons.js index 5c249b9f9..08fee8557 100644 --- a/src/js/fa-icons.js +++ b/src/js/fa-icons.js @@ -73,6 +73,7 @@ export const faIconsInit = (( ) => { [ 'spinner', { viewBox: '0 0 1664 1728', path: 'm 462,1394 q 0,53 -37.5,90.5 -37.5,37.5 -90.5,37.5 -52,0 -90,-38 -38,-38 -38,-90 0,-53 37.5,-90.5 37.5,-37.5 90.5,-37.5 53,0 90.5,37.5 37.5,37.5 37.5,90.5 z m 498,206 q 0,53 -37.5,90.5 Q 885,1728 832,1728 779,1728 741.5,1690.5 704,1653 704,1600 q 0,-53 37.5,-90.5 37.5,-37.5 90.5,-37.5 53,0 90.5,37.5 Q 960,1547 960,1600 Z M 256,896 q 0,53 -37.5,90.5 Q 181,1024 128,1024 75,1024 37.5,986.5 0,949 0,896 0,843 37.5,805.5 75,768 128,768 q 53,0 90.5,37.5 Q 256,843 256,896 Z m 1202,498 q 0,52 -38,90 -38,38 -90,38 -53,0 -90.5,-37.5 -37.5,-37.5 -37.5,-90.5 0,-53 37.5,-90.5 37.5,-37.5 90.5,-37.5 53,0 90.5,37.5 37.5,37.5 37.5,90.5 z M 494,398 q 0,66 -47,113 -47,47 -113,47 -66,0 -113,-47 -47,-47 -47,-113 0,-66 47,-113 47,-47 113,-47 66,0 113,47 47,47 47,113 z m 1170,498 q 0,53 -37.5,90.5 -37.5,37.5 -90.5,37.5 -53,0 -90.5,-37.5 Q 1408,949 1408,896 q 0,-53 37.5,-90.5 37.5,-37.5 90.5,-37.5 53,0 90.5,37.5 Q 1664,843 1664,896 Z M 1024,192 q 0,80 -56,136 -56,56 -136,56 -80,0 -136,-56 -56,-56 -56,-136 0,-80 56,-136 56,-56 136,-56 80,0 136,56 56,56 56,136 z m 530,206 q 0,93 -66,158.5 -66,65.5 -158,65.5 -93,0 -158.5,-65.5 Q 1106,491 1106,398 q 0,-92 65.5,-158 65.5,-66 158.5,-66 92,0 158,66 66,66 66,158 z' } ], [ 'sun', { viewBox: '0 0 1708 1792', path: 'm 1706,1172.5 c -3,10 -11,17 -20,20 l -292,96 v 306 c 0,10 -5,20 -13,26 -9,6 -19,8 -29,4 l -292,-94 -180,248 c -6,8 -16,13 -26,13 -10,0 -20,-5 -26,-13 l -180,-248 -292,94 c -10,4 -20,2 -29,-4 -8,-6 -13,-16 -13,-26 v -306 l -292,-96 c -9,-3 -17,-10 -20,-20 -3,-10 -2,-21 4,-29 l 180,-248 -180,-248 c -6,-9 -7,-19 -4,-29 3,-10 11,-17 20,-20 l 292,-96 v -306 c 0,-10 5,-20 13,-26 9,-6 19,-8 29,-4 l 292,94 180,-248 c 12,-16 40,-16 52,0 L 1060,260.5 l 292,-94 c 10,-4 20,-2 29,4 8,6 13,16 13,26 v 306 l 292,96 c 9,3 17,10 20,20 3,10 2,20 -4,29 l -180,248 180,248 c 6,8 7,19 4,29 z' } ], [ 'sun-o', { viewBox: '0 0 1708 1792', path: 'm 1430,895.5 c 0,-318 -258,-576 -576,-576 -318,0 -576,258 -576,576 0,318 258,576 576,576 C 1172,1471.5 1430,1213.5 1430,895.5 Z m 276,277 c -3,10 -11,17 -20,20 l -292,96 v 306 c 0,10 -5,20 -13,26 -9,6 -19,8 -29,4 l -292,-94 -180,248 c -6,8 -16,13 -26,13 -10,0 -20,-5 -26,-13 l -180,-248 -292,94 c -10,4 -20,2 -29,-4 -8,-6 -13,-16 -13,-26 v -306 l -292,-96 c -9,-3 -17,-10 -20,-20 -3,-10 -2,-21 4,-29 l 180,-248 -180,-248 c -6,-9 -7,-19 -4,-29 3,-10 11,-17 20,-20 l 292,-96 v -306 c 0,-10 5,-20 13,-26 9,-6 19,-8 29,-4 l 292,94 180,-248 c 12,-16 40,-16 52,0 L 1060,260.5 l 292,-94 c 10,-4 20,-2 29,4 8,6 13,16 13,26 v 306 l 292,96 c 9,3 17,10 20,20 3,10 2,20 -4,29 l -180,248 180,248 c 6,8 7,19 4,29 z' } ], + [ 'terminal', { viewBox: '0 0 1651 1075', path: 'm572 522-466 466q-10 10-23 10t-23-10l-50-50q-10-10-10-23t10-23l393-393-393-393q-10-10-10-23t10-23l50-50q10-10 23-10t23 10l466 466q10 10 10 23t-10 23zm1079 457v64q0 14-9 23t-23 9h-960q-14 0-23-9t-9-23v-64q0-14 9-23t23-9h960q14 0 23 9t9 23z' } ], [ 'times', { viewBox: '0 0 1188 1188', path: 'm 1188,956 q 0,40 -28,68 l -136,136 q -28,28 -68,28 -40,0 -68,-28 L 594,866 300,1160 q -28,28 -68,28 -40,0 -68,-28 L 28,1024 Q 0,996 0,956 0,916 28,888 L 322,594 28,300 Q 0,272 0,232 0,192 28,164 L 164,28 Q 192,0 232,0 272,0 300,28 L 594,322 888,28 q 28,-28 68,-28 40,0 68,28 l 136,136 q 28,28 28,68 0,40 -28,68 l -294,294 294,294 q 28,28 28,68 z' } ], [ 'trash-o', { viewBox: '0 0 1408 1536', path: 'm 512,608 v 576 q 0,14 -9,23 -9,9 -23,9 h -64 q -14,0 -23,-9 -9,-9 -9,-23 V 608 q 0,-14 9,-23 9,-9 23,-9 h 64 q 14,0 23,9 9,9 9,23 z m 256,0 v 576 q 0,14 -9,23 -9,9 -23,9 h -64 q -14,0 -23,-9 -9,-9 -9,-23 V 608 q 0,-14 9,-23 9,-9 23,-9 h 64 q 14,0 23,9 9,9 9,23 z m 256,0 v 576 q 0,14 -9,23 -9,9 -23,9 h -64 q -14,0 -23,-9 -9,-9 -9,-23 V 608 q 0,-14 9,-23 9,-9 23,-9 h 64 q 14,0 23,9 9,9 9,23 z m 128,724 V 384 H 256 v 948 q 0,22 7,40.5 7,18.5 14.5,27 7.5,8.5 10.5,8.5 h 832 q 3,0 10.5,-8.5 7.5,-8.5 14.5,-27 7,-18.5 7,-40.5 z M 480,256 H 928 L 880,139 q -7,-9 -17,-11 H 546 q -10,2 -17,11 z m 928,32 v 64 q 0,14 -9,23 -9,9 -23,9 h -96 v 948 q 0,83 -47,143.5 -47,60.5 -113,60.5 H 288 q -66,0 -113,-58.5 Q 128,1419 128,1336 V 384 H 32 Q 18,384 9,375 0,366 0,352 v -64 q 0,-14 9,-23 9,-9 23,-9 H 341 L 411,89 Q 426,52 465,26 504,0 544,0 h 320 q 40,0 79,26 39,26 54,63 l 70,167 h 309 q 14,0 23,9 9,9 9,23 z' } ], [ 'undo', { viewBox: '0 0 1536 1536', path: 'm 1536,768 q 0,156 -61,298 -61,142 -164,245 -103,103 -245,164 -142,61 -298,61 -172,0 -327,-72.5 Q 286,1391 177,1259 q -7,-10 -6.5,-22.5 0.5,-12.5 8.5,-20.5 l 137,-138 q 10,-9 25,-9 16,2 23,12 73,95 179,147 106,52 225,52 104,0 198.5,-40.5 Q 1061,1199 1130,1130 1199,1061 1239.5,966.5 1280,872 1280,768 1280,664 1239.5,569.5 1199,475 1130,406 1061,337 966.5,296.5 872,256 768,256 670,256 580,291.5 490,327 420,393 l 137,138 q 31,30 14,69 -17,40 -59,40 H 64 Q 38,640 19,621 0,602 0,576 V 128 Q 0,86 40,69 79,52 109,83 L 239,212 Q 346,111 483.5,55.5 621,0 768,0 q 156,0 298,61 142,61 245,164 103,103 164,245 61,142 61,298 z' } ], diff --git a/src/js/logger-ui-inspector.js b/src/js/logger-ui-inspector.js index 092baf888..d90d44a43 100644 --- a/src/js/logger-ui-inspector.js +++ b/src/js/logger-ui-inspector.js @@ -19,10 +19,6 @@ Home: https://github.com/gorhill/uBlock */ -/* globals browser */ - -'use strict'; - import { dom, qs$, qsa$ } from './dom.js'; /******************************************************************************/ @@ -38,7 +34,6 @@ const domTree = qs$('#domTree'); const filterToIdMap = new Map(); let inspectedTabId = 0; -let inspectedURL = ''; let inspectedHostname = ''; let uidGenerator = 1; @@ -112,7 +107,6 @@ const contentInspectorChannel = (( ) => { const onContentMessage = msg => { if ( msg.what === 'domLayoutFull' ) { - inspectedURL = msg.url; inspectedHostname = msg.hostname; renderDOMFull(msg); } else if ( msg.what === 'domLayoutIncremental' ) { @@ -661,9 +655,9 @@ const revert = ( ) => { const toggleOn = ( ) => { dom.cl.add('#inspectors', 'dom'); window.addEventListener('beforeunload', toggleOff); - document.addEventListener('tabIdChanged', onTabIdChanged); - domTree.addEventListener('click', onClicked, true); - domTree.addEventListener('mouseover', onMouseOver, true); + dom.on(document, 'tabIdChanged', onTabIdChanged); + dom.on(domTree, 'click', onClicked, true); + dom.on(domTree, 'mouseover', onMouseOver, true); dom.on('#domInspector .vExpandToggler', 'click', toggleVExpandView); dom.on('#domInspector .vCompactToggler', 'click', toggleVCompactView); dom.on('#domInspector .hCompactToggler', 'click', toggleHCompactView); @@ -680,9 +674,9 @@ const toggleOff = ( ) => { dom.cl.remove('#inspectors', 'dom'); shutdownInspector(); window.removeEventListener('beforeunload', toggleOff); - document.removeEventListener('tabIdChanged', onTabIdChanged); - domTree.removeEventListener('click', onClicked, true); - domTree.removeEventListener('mouseover', onMouseOver, true); + dom.off(document, 'tabIdChanged', onTabIdChanged); + dom.off(domTree, 'click', onClicked, true); + dom.off(domTree, 'mouseover', onMouseOver, true); dom.off('#domInspector .vExpandToggler', 'click', toggleVExpandView); dom.off('#domInspector .vCompactToggler', 'click', toggleVCompactView); dom.off('#domInspector .hCompactToggler', 'click', toggleHCompactView); @@ -700,7 +694,6 @@ const toggle = ( ) => { } else { toggleOff(); } - logger.resize(); }; dom.on(showdomButton, 'click', toggle); diff --git a/src/js/logger-ui.js b/src/js/logger-ui.js index b7aeb8e80..f7752a052 100644 --- a/src/js/logger-ui.js +++ b/src/js/logger-ui.js @@ -19,12 +19,10 @@ Home: https://github.com/gorhill/uBlock */ -'use strict'; - +import { dom, qs$, qsa$ } from './dom.js'; +import { i18n, i18n$ } from './i18n.js'; import { broadcast } from './broadcast.js'; import { hostnameFromURI } from './uri-utils.js'; -import { i18n, i18n$ } from './i18n.js'; -import { dom, qs$, qsa$ } from './dom.js'; /******************************************************************************/ @@ -36,7 +34,6 @@ const logger = self.logger = { ownerId: Date.now() }; const logDate = new Date(); const logDateTimezoneOffset = logDate.getTimezoneOffset() * 60; const loggerEntries = []; -let loggerEntryIdGenerator = 1; const COLUMN_TIMESTAMP = 0; const COLUMN_FILTER = 1; @@ -73,95 +70,12 @@ const tabIdFromAttribute = function(elem) { return isNaN(tabId) ? 0 : tabId; }; +const hasOwnProperty = (o, p) => + Object.prototype.hasOwnProperty.call(o, p); -/******************************************************************************/ -/******************************************************************************/ - -const onStartMovingWidget = (( ) => { - let widget = null; - let ondone = null; - let mx0 = 0, my0 = 0; - let mx1 = 0, my1 = 0; - let l0 = 0, t0 = 0; - let pw = 0, ph = 0; - let cw = 0, ch = 0; - let timer; - - const xyFromEvent = ev => { - if ( ev.type.startsWith('mouse') ) { - return { x: ev.pageX, y: ev.pageY }; - } - const touch = ev.touches[0]; - return { x: touch.pageX, y: touch.pageY }; - }; - - const eatEvent = function(ev) { - ev.stopPropagation(); - if ( ev.touches !== undefined ) { return; } - ev.preventDefault(); - }; - - const move = ( ) => { - timer = undefined; - const l1 = Math.min(Math.max(l0 + mx1 - mx0, 0), Math.max(pw - cw, 0)); - if ( (l1+cw/2) < (pw/2) ) { - widget.style.left = `${l1/pw*100}%`; - widget.style.right = ''; - } else { - widget.style.right = `${(pw-l1-cw)/pw*100}%`; - widget.style.left = ''; - } - const t1 = Math.min(Math.max(t0 + my1 - my0, 0), Math.max(ph - ch, 0)); - widget.style.top = `${t1/ph*100}%`; - widget.style.bottom = ''; - }; - - const moveAsync = ev => { - if ( timer !== undefined ) { return; } - const coord = xyFromEvent(ev); - mx1 = coord.x; my1 = coord.y; - timer = self.requestAnimationFrame(move); - eatEvent(ev); - }; - - const stop = ev => { - if ( timer !== undefined ) { - self.cancelAnimationFrame(timer); - timer = undefined; - } - if ( widget === null ) { return; } - if ( widget.classList.contains('moving') === false ) { return; } - widget.classList.remove('moving'); - self.removeEventListener('mousemove', moveAsync, { capture: true }); - self.removeEventListener('touchmove', moveAsync, { capture: true }); - eatEvent(ev); - widget = null; - if ( ondone !== null ) { - ondone(); - ondone = null; - } - }; - - return function(ev, target, callback) { - if ( dom.cl.has(target, 'moving') ) { return; } - widget = target; - ondone = callback || null; - const coord = xyFromEvent(ev); - mx0 = coord.x; my0 = coord.y; - const widgetParent = widget.parentElement; - const crect = widget.getBoundingClientRect(); - const prect = widgetParent.getBoundingClientRect(); - pw = prect.width; ph = prect.height; - cw = crect.width; ch = crect.height; - l0 = crect.x - prect.x; t0 = crect.y - prect.y; - widget.classList.add('moving'); - self.addEventListener('mousemove', moveAsync, { capture: true }); - self.addEventListener('mouseup', stop, { capture: true, once: true }); - self.addEventListener('touchmove', moveAsync, { capture: true }); - self.addEventListener('touchend', stop, { capture: true, once: true }); - eatEvent(ev); - }; -})(); +const dispatchTabidChange = vAPI.defer.create(( ) => { + document.dispatchEvent(new Event('tabIdChanged')); +}); /******************************************************************************/ /******************************************************************************/ @@ -285,17 +199,17 @@ const nodeFromURL = function(parent, url, re, type) { const a = document.createElement('a'); let href = url; switch ( type ) { - case 'css': - case 'doc': - case 'frame': - case 'object': - case 'other': - case 'script': - case 'xhr': - href = `code-viewer.html?url=${encodeURIComponent(href)}`; - break; - default: - break; + case 'css': + case 'doc': + case 'frame': + case 'object': + case 'other': + case 'script': + case 'xhr': + href = `code-viewer.html?url=${encodeURIComponent(href)}`; + break; + default: + break; } dom.attr(a, 'href', href); dom.attr(a, 'target', '_blank'); @@ -316,45 +230,44 @@ const normalizeToStr = function(s) { /******************************************************************************/ -const LogEntry = function(details) { - if ( details instanceof Object === false ) { return; } - const receiver = LogEntry.prototype; - for ( const prop in receiver ) { - if ( details.hasOwnProperty(prop) === false ) { continue; } - if ( details[prop] === receiver[prop] ) { continue; } - this[prop] = details[prop]; +class LogEntry { + static IdGenerator = 1; + constructor(details) { + this.aliased = false; + this.dead = false; + this.docDomain = ''; + this.docHostname = ''; + this.domain = ''; + this.filter = undefined; + this.id = LogEntry.IdGenerator++; + this.method = ''; + this.realm = ''; + this.tabDomain = ''; + this.tabHostname = ''; + this.tabId = undefined; + this.textContent = ''; + this.tstamp = 0; + this.type = ''; + this.voided = false; + if ( details instanceof Object === false ) { return; } + for ( const prop in this ) { + if ( hasOwnProperty(details, prop) === false ) { continue; } + this[prop] = details[prop]; + } + if ( details.aliasURL !== undefined ) { + this.aliased = true; + } + if ( this.tabDomain === '' ) { + this.tabDomain = this.tabHostname || ''; + } + if ( this.docDomain === '' ) { + this.docDomain = this.docHostname || ''; + } + if ( this.domain === '' ) { + this.domain = details.hostname || ''; + } } - this.id = `${loggerEntryIdGenerator++}`; - if ( details.aliasURL !== undefined ) { - this.aliased = true; - } - if ( this.tabDomain === '' ) { - this.tabDomain = this.tabHostname || ''; - } - if ( this.docDomain === '' ) { - this.docDomain = this.docHostname || ''; - } - if ( this.domain === '' ) { - this.domain = details.hostname || ''; - } -}; -LogEntry.prototype = { - aliased: false, - dead: false, - docDomain: '', - docHostname: '', - domain: '', - filter: undefined, - method: '', - realm: '', - tabDomain: '', - tabHostname: '', - tabId: undefined, - textContent: '', - tstamp: 0, - type: '', - voided: false, -}; +} /******************************************************************************/ @@ -442,10 +355,10 @@ const processLoggerEntries = function(response) { } const addedCount = filteredLoggerEntries.length - previousCount; - if ( addedCount !== 0 ) { - viewPort.updateContent(addedCount); - rowJanitor.inserted(addedCount); - } + if ( addedCount === 0 ) { return; } + viewPort.updateContent(addedCount); + rowJanitor.inserted(addedCount); + consolePane.updateContent(); }; /******************************************************************************/ @@ -716,10 +629,11 @@ const viewPort = (( ) => { }; const resizeTimer = vAPI.defer.create(onLayoutChanged); - const updateLayout = function() { + const updateLayout = ( ) => { resizeTimer.onvsync(1000/8); }; - dom.on(window, 'resize', updateLayout, { passive: true }); + const resizeObserver = new self.ResizeObserver(updateLayout); + resizeObserver.observe(qs$('#netInspector .vscrollable')); updateLayout(); @@ -870,7 +784,7 @@ const viewPort = (( ) => { if ( cells.length > 8 ) { const pos = details.textContent.lastIndexOf('\x1FaliasURL='); if ( pos !== -1 ) { - dom.attr(div, 'data-aliasid', details.id); + div.dataset.aliasid = `${details.id}`; } } @@ -969,7 +883,7 @@ const viewPort = (( ) => { vwScroller.scrollTop = lastTopPix; }; - return { updateContent, updateLayout, }; + return { updateContent, updateLayout }; })(); /******************************************************************************/ @@ -1008,7 +922,7 @@ const synchronizeTabIds = function(newTabIds) { // Mark as "void" all logger entries which are linked to now invalid // tab ids. // When an entry is voided without being removed, we re-create a new entry - // in order to ensure the entry has a new identity. A new identify ensures + // in order to ensure the entry has a new identity. A new identity ensures // that identity-based associations elsewhere are automatically // invalidated. if ( toVoid.size !== 0 ) { @@ -1206,11 +1120,11 @@ const pageSelectorFromURLHash = (( ) => { if ( lastSelectedTabId === selectedTabId ) { return; } rowFilterer.filterAll(); - document.dispatchEvent(new Event('tabIdChanged')); updateCurrentTabTitle(); dom.cl.toggle('.needdom', 'disabled', selectedTabId <= 0); dom.cl.toggle('.needscope', 'disabled', selectedTabId <= 0); lastSelectedTabId = selectedTabId; + dispatchTabidChange.onric({ timeout: 1000 }); }; })(); @@ -1234,18 +1148,18 @@ dom.on(document, 'keydown', ev => { if ( ev.isComposing ) { return; } let bypassCache = false; switch ( ev.key ) { - case 'F5': - bypassCache = ev.ctrlKey || ev.metaKey || ev.shiftKey; - break; - case 'r': - if ( (ev.ctrlKey || ev.metaKey) !== true ) { return; } - break; - case 'R': - if ( (ev.ctrlKey || ev.metaKey) !== true ) { return; } - bypassCache = true; - break; - default: - return; + case 'F5': + bypassCache = ev.ctrlKey || ev.metaKey || ev.shiftKey; + break; + case 'r': + if ( (ev.ctrlKey || ev.metaKey) !== true ) { return; } + break; + case 'R': + if ( (ev.ctrlKey || ev.metaKey) !== true ) { return; } + bypassCache = true; + break; + default: + return; } reloadTab(bypassCache); ev.preventDefault(); @@ -1256,7 +1170,7 @@ dom.on(document, 'keydown', ev => { /******************************************************************************/ (( ) => { - const reRFC3986 = /^([^:\/?#]+:)?(\/\/[^\/?#]*)?([^?#]*)(\?[^#]*)?(#.*)?/; + const reRFC3986 = /^([^:/?#]+:)?(\/\/[^/?#]*)?([^?#]*)(\?[^#]*)?(#.*)?/; const reSchemeOnly = /^[\w-]+:$/; const staticFilterTypes = { 'beacon': 'ping', @@ -1308,7 +1222,7 @@ dom.on(document, 'keydown', ev => { const onColorsReady = function(response) { dom.cl.toggle(dom.body, 'dirty', response.dirty); for ( const url in response.colors ) { - if ( response.colors.hasOwnProperty(url) === false ) { continue; } + if ( hasOwnProperty(response.colors, url) === false ) { continue; } const colorEntry = response.colors[url]; const node = qs$(dialog, `.dynamic .entry .action[data-url="${url}"]`); if ( node === null ) { continue; } @@ -1375,7 +1289,7 @@ dom.on(document, 'keydown', ev => { dom.cl.toggle( qs$(dialog, '#createStaticFilter'), 'disabled', - createdStaticFilters.hasOwnProperty(value) || value === '' + hasOwnProperty(createdStaticFilters, value) || value === '' ); }; @@ -1416,7 +1330,7 @@ dom.on(document, 'keydown', ev => { const value = staticFilterNode().value .replace(/^((?:@@)?\/.+\/)(\$|$)/, '$1*$2'); // Avoid duplicates - if ( createdStaticFilters.hasOwnProperty(value) ) { return; } + if ( hasOwnProperty(createdStaticFilters, value) ) { return; } createdStaticFilters[value] = true; // https://github.com/uBlockOrigin/uBlock-issues/issues/1281#issuecomment-704217175 // TODO: @@ -1624,7 +1538,7 @@ dom.on(document, 'keydown', ev => { const aliasURLFromID = function(id) { if ( id === '' ) { return ''; } for ( const entry of loggerEntries ) { - if ( entry.id !== id ) { continue; } + if ( `${entry.id}` !== id ) { continue; } const match = /\baliasURL=([^\x1F]+)/.exec(entry.textContent); if ( match === null ) { return ''; } return match[1]; @@ -1796,7 +1710,7 @@ dom.on(document, 'keydown', ev => { rows[7].style.display = 'none'; } // Alias URL - text = dom.attr(tr, 'data-aliasid'); + text = tr.dataset.aliasid; const aliasURL = text ? aliasURLFromID(text) : ''; if ( aliasURL !== '' ) { rows[8].children[1].textContent = @@ -1965,22 +1879,6 @@ dom.on(document, 'keydown', ev => { parseStaticInputs(); }; - const moveDialog = ev => { - if ( ev.button !== 0 && ev.touches === undefined ) { return; } - const widget = qs$('#netInspector .entryTools'); - onStartMovingWidget(ev, widget, ( ) => { - vAPI.localStorage.setItem( - 'loggerUI.entryTools', - JSON.stringify({ - bottom: widget.style.bottom, - left: widget.style.left, - right: widget.style.right, - top: widget.style.top, - }) - ); - }); - }; - const fillDialog = function(domains) { dialog = dom.clone('#templates .netFilteringDialog'); dom.cl.toggle( @@ -1998,15 +1896,12 @@ dom.on(document, 'keydown', ev => { dom.on(dialog, 'click', ev => { onClick(ev); }, true); dom.on(dialog, 'change', onSelectChange, true); dom.on(dialog, 'input', onInputChange, true); - const container = qs$('#netInspector .entryTools'); + const container = qs$('#inspectors .entryTools'); if ( container.firstChild ) { container.replaceChild(dialog, container.firstChild); } else { container.append(dialog); } - const moveBand = qs$(dialog, '.moveBand'); - dom.on(moveBand, 'mousedown', moveDialog); - dom.on(moveBand, 'touchstart', moveDialog); }; const toggleOn = async function(ev) { @@ -2036,7 +1931,7 @@ dom.on(document, 'keydown', ev => { }; const toggleOff = function() { - const container = qs$('#netInspector .entryTools'); + const container = qs$('#inspectors .entryTools'); if ( container.firstChild ) { container.firstChild.remove(); } @@ -2046,20 +1941,7 @@ dom.on(document, 'keydown', ev => { }; // Restore position of entry tools dialog - vAPI.localStorage.getItemAsync( - 'loggerUI.entryTools', - ).then(response => { - if ( typeof response !== 'string' ) { return; } - const settings = JSON.parse(response); - const widget = qs$('#netInspector .entryTools'); - widget.style.bottom = ''; - widget.style.left = settings.left || ''; - widget.style.right = settings.right || ''; - widget.style.top = settings.top || ''; - if ( /^-/.test(widget.style.top) ) { - widget.style.top = '0'; - } - }); + vAPI.localStorage.removeItem('loggerUI.entryTools'); // This is to detect text selection, in which case the click won't be // interpreted as a request to open the details of the entry. @@ -2107,6 +1989,145 @@ dom.on(document, 'keydown', ev => { /******************************************************************************/ /******************************************************************************/ +const consolePane = (( ) => { + let on = false; + + const lastInfoEntry = ( ) => { + let j = Number.MAX_SAFE_INTEGER; + let i = loggerEntries.length; + while ( i-- ) { + const entry = loggerEntries[i]; + if ( entry.tabId !== selectedTabId ) { continue; } + if ( entry.realm !== 'message' ) { continue; } + if ( entry.voided ) { continue; } + j = entry.id; + } + return j; + }; + + const filterExpr = { + not: true, + pattern: '', + }; + + const filterExprFromInput = ( ) => { + const raw = qs$('#infoInspector .permatoolbar input').value.trim(); + if ( raw.startsWith('-') ) { + filterExpr.pattern = raw.slice(1); + filterExpr.not = true; + } else { + filterExpr.pattern = raw; + filterExpr.not = false; + } + }; + + const addRows = ( ) => { + const { not, pattern } = filterExpr; + const topRow = qs$('#infoInspector .vscrollable > div'); + const topid = topRow !== null ? parseInt(topRow.dataset.id, 10) : 0; + const fragment = new DocumentFragment(); + for ( const entry of loggerEntries ) { + if ( entry.id <= topid ) { break; } + if ( entry.tabId !== selectedTabId ) { continue; } + if ( entry.realm !== 'message' ) { continue; } + if ( entry.voided ) { continue; } + const fields = entry.textContent.split('\x1F').slice(0, 2); + const textContent = fields.join('\xA0'); + if ( pattern !== '' ) { + if ( textContent.includes(pattern) === not ) { continue; } + } + const div = document.createElement('div'); + div.dataset.id = `${entry.id}`; + div.dataset.type = entry.type; + div.textContent = textContent; + fragment.append(div); + } + const container = qs$('#infoInspector .vscrollable'); + container.prepend(fragment); + } + + const removeRows = (before = 0) => { + if ( before === 0 ) { + before = lastInfoEntry(); + } + const rows = qsa$('#infoInspector .vscrollable > div'); + let i = rows.length; + while ( i-- ) { + const div = rows[i]; + const id = parseInt(div.dataset.id, 10); + if ( id > before ) { break; } + div.remove(); + } + } + + const updateContent = ( ) => { + if ( on === false ) { return; } + removeRows(); + addRows(); + }; + + const onTabIdChanged = ( ) => { + if ( on === false ) { return; } + removeRows(Number.MAX_SAFE_INTEGER); + addRows(); + }; + + const toggleOn = ( ) => { + if ( on ) { return; } + addRows(); + dom.on(document, 'tabIdChanged', onTabIdChanged); + on = true; + }; + + const toggleOff = ( ) => { + removeRows(Number.MAX_SAFE_INTEGER); + dom.off(document, 'tabIdChanged', onTabIdChanged); + on = false; + }; + + const resizeObserver = new self.ResizeObserver(entries => { + if ( entries.length === 0 ) { return; } + const rect = entries[0].contentRect; + if ( rect.width > 0 && rect.height > 0 ) { + toggleOn(); + } else { + toggleOff(); + } + }); + resizeObserver.observe(qs$('#infoInspector')); + + dom.on('button.logConsole', 'click', ev => { + const active = dom.cl.toggle('#inspectors', 'console'); + dom.cl.toggle(ev.currentTarget, 'active', active); + }); + + dom.on('#infoInspector button#clearConsole', 'click', ( ) => { + const ids = []; + qsa$('#infoInspector .vscrollable > div').forEach(div => { + ids.push(parseInt(div.dataset.id, 10)); + }); + rowJanitor.removeSpecificRows(ids); + }); + + dom.on('#infoInspector button#logLevel', 'click', ev => { + const level = dom.cl.toggle(ev.currentTarget, 'active') ? 2 : 1; + broadcast({ what: 'loggerLevelChanged', level }); + }); + + const throttleFilter = vAPI.defer.create(( ) => { + filterExprFromInput(); + updateContent(); + }); + dom.on('#infoInspector .permatoolbar input', 'input', ( ) => { + throttleFilter.offon(517); + }); + + return { updateContent }; +})(); + +/******************************************************************************/ +/******************************************************************************/ + const rowFilterer = (( ) => { const userFilters = []; const builtinFilters = []; @@ -2415,6 +2436,7 @@ const rowJanitor = (( ) => { if ( modified === false ) { return; } rowFilterer.filterAll(); + consolePane.updateContent(); }; const discardAsync = function(deadline) { @@ -2488,11 +2510,25 @@ const rowJanitor = (( ) => { dom.on('#clear', 'click', clear); return { - inserted: function(count) { + inserted(count) { if ( rowIndex !== 0 ) { rowIndex += count; } }, + removeSpecificRows(descendingIds) { + if ( descendingIds.length === 0 ) { return; } + let i = loggerEntries.length; + let id = descendingIds.pop(); + while ( i-- ) { + const entry = loggerEntries[i]; + if ( entry.id !== id ) { continue; } + loggerEntries.splice(i, 1); + if ( descendingIds.length === 0 ) { break; } + id = descendingIds.pop(); + } + rowFilterer.filterAll(); + consolePane.updateContent(); + }, }; })(); @@ -2704,7 +2740,6 @@ const loggerStats = (( ) => { for ( const entry of filteredLoggerEntries ) { const text = entry.textContent; const fields = []; - let i = 0; let beg = text.indexOf('\x1F'); if ( beg === 0 ) { continue; } let timeField = text.slice(0, beg); @@ -2718,7 +2753,6 @@ const loggerStats = (( ) => { if ( end === -1 ) { end = text.length; } fields.push(text.slice(beg, end)); beg = end + 1; - i += 1; } lines.push(fields); } @@ -2800,7 +2834,7 @@ const loggerStats = (( ) => { }; const setRadioButton = function(group, value) { - if ( options.hasOwnProperty(group) === false ) { return; } + if ( hasOwnProperty(options, group) === false ) { return; } const groupEl = qs$(dialog, `[data-radio="${group}"]`); const buttonEls = qsa$(groupEl, '[data-radio-item]'); for ( const buttonEl of buttonEls ) { @@ -2902,7 +2936,7 @@ const loggerSettings = (( ) => { if ( Array.isArray(stored.columns) ) { settings.columns = stored.columns; } - } catch(ex) { + } catch(_) { } }); @@ -2986,36 +3020,6 @@ const loggerSettings = (( ) => { /******************************************************************************/ -logger.resize = (function() { - let timer; - - const resize = function() { - const vrect = dom.body.getBoundingClientRect(); - for ( const elem of qsa$('.vscrollable') ) { - const crect = elem.getBoundingClientRect(); - const dh = crect.bottom - vrect.bottom; - if ( dh === 0 ) { continue; } - elem.style.height = Math.ceil(crect.height - dh) + 'px'; - } - }; - - const resizeAsync = function() { - if ( timer !== undefined ) { return; } - timer = self.requestAnimationFrame(( ) => { - timer = undefined; - resize(); - }); - }; - - resizeAsync(); - - dom.on(window, 'resize', resizeAsync, { passive: true }); - - return resizeAsync; -})(); - -/******************************************************************************/ - const grabView = function() { if ( logger.ownerId === undefined ) { logger.ownerId = Date.now(); @@ -3043,11 +3047,6 @@ dom.on('#pageSelector', 'change', pageSelectorChanged); dom.on('#netInspector .vCompactToggler', 'click', toggleVCompactView); dom.on('#pause', 'click', pauseNetInspector); -dom.on('#logLevel', 'click', ev => { - const level = dom.cl.toggle(ev.currentTarget, 'active') ? 2 : 1; - broadcast({ what: 'loggerLevelChanged', level }); -}); - dom.on('#netInspector #vwContent', 'copy', ev => { const selection = document.getSelection(); const text = selection.toString(); diff --git a/src/js/scriptlets/dom-inspector.js b/src/js/scriptlets/dom-inspector.js index b5317d536..a1be15005 100644 --- a/src/js/scriptlets/dom-inspector.js +++ b/src/js/scriptlets/dom-inspector.js @@ -19,10 +19,6 @@ Home: https://github.com/gorhill/uBlock */ -/* globals browser */ - -'use strict'; - /******************************************************************************/ /******************************************************************************/ @@ -31,7 +27,7 @@ /******************************************************************************/ if ( typeof vAPI !== 'object' ) { return; } -if ( typeof vAPI === null ) { return; } +if ( vAPI === null ) { return; } if ( vAPI.domFilterer instanceof Object === false ) { return; } if ( vAPI.inspectorFrame ) { return; } diff --git a/src/logger-ui.html b/src/logger-ui.html index 8603b916e..9517968fd 100644 --- a/src/logger-ui.html +++ b/src/logger-ui.html @@ -20,13 +20,16 @@