summaryrefslogtreecommitdiffstats
path: root/src/js/logger-ui.js
diff options
context:
space:
mode:
Diffstat (limited to 'src/js/logger-ui.js')
-rw-r--r--src/js/logger-ui.js124
1 files changed, 80 insertions, 44 deletions
diff --git a/src/js/logger-ui.js b/src/js/logger-ui.js
index 177632e..b7aeb8e 100644
--- a/src/js/logger-ui.js
+++ b/src/js/logger-ui.js
@@ -21,6 +21,7 @@
'use strict';
+import { broadcast } from './broadcast.js';
import { hostnameFromURI } from './uri-utils.js';
import { i18n, i18n$ } from './i18n.js';
import { dom, qs$, qsa$ } from './dom.js';
@@ -33,8 +34,9 @@ import { dom, qs$, qsa$ } from './dom.js';
const messaging = vAPI.messaging;
const logger = self.logger = { ownerId: Date.now() };
const logDate = new Date();
-const logDateTimezoneOffset = logDate.getTimezoneOffset() * 60000;
+const logDateTimezoneOffset = logDate.getTimezoneOffset() * 60;
const loggerEntries = [];
+let loggerEntryIdGenerator = 1;
const COLUMN_TIMESTAMP = 0;
const COLUMN_FILTER = 1;
@@ -318,13 +320,11 @@ const LogEntry = function(details) {
if ( details instanceof Object === false ) { return; }
const receiver = LogEntry.prototype;
for ( const prop in receiver ) {
- if (
- details.hasOwnProperty(prop) &&
- details[prop] !== receiver[prop]
- ) {
- this[prop] = details[prop];
- }
+ if ( details.hasOwnProperty(prop) === false ) { continue; }
+ if ( details[prop] === receiver[prop] ) { continue; }
+ this[prop] = details[prop];
}
+ this.id = `${loggerEntryIdGenerator++}`;
if ( details.aliasURL !== undefined ) {
this.aliased = true;
}
@@ -345,7 +345,6 @@ LogEntry.prototype = {
docHostname: '',
domain: '',
filter: undefined,
- id: '',
method: '',
realm: '',
tabDomain: '',
@@ -368,7 +367,7 @@ const createLogSeparator = function(details, text) {
separator.textContent = '';
const textContent = [];
- logDate.setTime(separator.tstamp - logDateTimezoneOffset);
+ logDate.setTime((separator.tstamp - logDateTimezoneOffset) * 1000);
textContent.push(
// cell 0
padTo2(logDate.getUTCHours()) + ':' +
@@ -377,7 +376,7 @@ const createLogSeparator = function(details, text) {
// cell 1
text
);
- separator.textContent = textContent.join('\t');
+ separator.textContent = textContent.join('\x1F');
if ( details.voided ) {
separator.voided = true;
@@ -464,7 +463,7 @@ const parseLogEntry = function(details) {
const textContent = [];
// Cell 0
- logDate.setTime(details.tstamp - logDateTimezoneOffset);
+ logDate.setTime((details.tstamp - logDateTimezoneOffset) * 1000);
textContent.push(
padTo2(logDate.getUTCHours()) + ':' +
padTo2(logDate.getUTCMinutes()) + ':' +
@@ -474,7 +473,13 @@ const parseLogEntry = function(details) {
// Cell 1
if ( details.realm === 'message' ) {
textContent.push(details.text);
- entry.textContent = textContent.join('\t');
+ if ( details.type ) {
+ textContent.push(details.type);
+ }
+ if ( details.keywords ) {
+ textContent.push(...details.keywords);
+ }
+ entry.textContent = textContent.join('\x1F') + '\x1F';
return entry;
}
@@ -545,7 +550,7 @@ const parseLogEntry = function(details) {
textContent.push(`aliasURL=${details.aliasURL}`);
}
- entry.textContent = textContent.join('\t');
+ entry.textContent = textContent.join('\x1F');
return entry;
};
@@ -744,7 +749,7 @@ const viewPort = (( ) => {
vwEntry.logEntry = details;
- const cells = details.textContent.split('\t');
+ const cells = details.textContent.split('\x1F');
const div = dom.clone(vwLogEntryTemplate);
const divcl = div.classList;
let span;
@@ -863,7 +868,7 @@ const viewPort = (( ) => {
// Alias URL (CNAME, etc.)
if ( cells.length > 8 ) {
- const pos = details.textContent.lastIndexOf('\taliasURL=');
+ const pos = details.textContent.lastIndexOf('\x1FaliasURL=');
if ( pos !== -1 ) {
dom.attr(div, 'data-aliasid', details.id);
}
@@ -1336,9 +1341,7 @@ dom.on(document, 'keydown', ev => {
if ( reSchemeOnly.test(value) ) {
value = `|${value}`;
} else {
- if ( value.endsWith('/') ) {
- value += '*';
- } else if ( /[/?]/.test(value) === false ) {
+ if ( /[/?]/.test(value) === false ) {
value += '^';
}
value = `||${value}`;
@@ -1410,7 +1413,8 @@ dom.on(document, 'keydown', ev => {
// Create static filter
if ( target.id === 'createStaticFilter' ) {
ev.stopPropagation();
- const value = staticFilterNode().value;
+ const value = staticFilterNode().value
+ .replace(/^((?:@@)?\/.+\/)(\$|$)/, '$1*$2');
// Avoid duplicates
if ( createdStaticFilters.hasOwnProperty(value) ) { return; }
createdStaticFilters[value] = true;
@@ -1620,9 +1624,10 @@ dom.on(document, 'keydown', ev => {
const aliasURLFromID = function(id) {
if ( id === '' ) { return ''; }
for ( const entry of loggerEntries ) {
- if ( entry.id !== id || entry.aliased ) { continue; }
- const fields = entry.textContent.split('\t');
- return fields[COLUMN_URL] || '';
+ if ( entry.id !== id ) { continue; }
+ const match = /\baliasURL=([^\x1F]+)/.exec(entry.textContent);
+ if ( match === null ) { return ''; }
+ return match[1];
}
return '';
};
@@ -2005,8 +2010,12 @@ dom.on(document, 'keydown', ev => {
};
const toggleOn = async function(ev) {
- targetRow = ev.target.closest('.canDetails');
- if ( targetRow === null ) { return; }
+ const clickedRow = ev.target.closest('.canDetails');
+ if ( clickedRow === null ) { return; }
+ if ( clickedRow === targetRow ) {
+ return toggleOff();
+ }
+ targetRow = clickedRow;
ev.stopPropagation();
targetTabId = tabIdFromAttribute(targetRow);
targetType = targetRow.children[COLUMN_TYPE].textContent.trim() || '';
@@ -2052,12 +2061,30 @@ dom.on(document, 'keydown', ev => {
}
});
- dom.on(
- '#netInspector',
- 'click',
- '.canDetails > span:not(:nth-of-type(4)):not(:nth-of-type(8))',
- ev => { toggleOn(ev); }
- );
+ // 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.
+ let selectionAtMouseDown;
+ let selectionAtTimer;
+ dom.on('#netInspector', 'mousedown', '.canDetails *', ev => {
+ if ( ev.button !== 0 ) { return; }
+ if ( selectionAtMouseDown !== undefined ) { return; }
+ selectionAtMouseDown = document.getSelection().toString();
+ });
+
+ dom.on('#netInspector', 'click', '.canDetails *', ev => {
+ if ( ev.button !== 0 ) { return; }
+ if ( selectionAtTimer !== undefined ) {
+ clearTimeout(selectionAtTimer);
+ }
+ selectionAtTimer = setTimeout(( ) => {
+ selectionAtTimer = undefined;
+ const selectionAsOfNow = document.getSelection().toString();
+ const selectionHasChanged = selectionAsOfNow !== selectionAtMouseDown;
+ selectionAtMouseDown = undefined;
+ if ( selectionHasChanged && selectionAsOfNow !== '' ) { return; }
+ toggleOn(ev);
+ }, 333);
+ });
dom.on(
'#netInspector',
@@ -2149,16 +2176,12 @@ const rowFilterer = (( ) => {
filters = builtinFilters.concat(userFilters);
};
- const filterOne = function(logEntry) {
- if (
- logEntry.dead ||
- selectedTabId !== 0 &&
- (
- logEntry.tabId === undefined ||
- logEntry.tabId > 0 && logEntry.tabId !== selectedTabId
- )
- ) {
- return false;
+ const filterOne = logEntry => {
+ if ( logEntry.dead ) { return false; }
+ if ( selectedTabId !== 0 ) {
+ if ( logEntry.tabId !== undefined && logEntry.tabId > 0 ) {
+ if (logEntry.tabId !== selectedTabId ) { return false; }
+ }
}
if ( masterFilterSwitch === false || filters.length === 0 ) {
@@ -2303,7 +2326,7 @@ const rowJanitor = (( ) => {
? opts.maxEntryCount
: 0;
const obsolete = typeof opts.maxAge === 'number'
- ? Date.now() - opts.maxAge * 60000
+ ? Date.now() / 1000 - opts.maxAge * 60
: 0;
let i = rowIndex;
@@ -2682,16 +2705,16 @@ const loggerStats = (( ) => {
const text = entry.textContent;
const fields = [];
let i = 0;
- let beg = text.indexOf('\t');
+ let beg = text.indexOf('\x1F');
if ( beg === 0 ) { continue; }
let timeField = text.slice(0, beg);
if ( options.time === 'anonymous' ) {
- timeField = '+' + Math.round((entry.tstamp - t0) / 1000).toString();
+ timeField = '+' + Math.round(entry.tstamp - t0).toString();
}
fields.push(timeField);
beg += 1;
while ( beg < text.length ) {
- let end = text.indexOf('\t', beg);
+ let end = text.indexOf('\x1F', beg);
if ( end === -1 ) { end = text.length; }
fields.push(text.slice(beg, end));
beg = end + 1;
@@ -3020,6 +3043,19 @@ 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();
+ if ( /\x1F|\u200B/.test(text) === false ) { return; }
+ ev.clipboardData.setData('text/plain', text.replace(/\x1F|\u200B/g, '\t'));
+ ev.preventDefault();
+});
+
// https://github.com/gorhill/uBlock/issues/507
// Ensure tab selector is in sync with URL hash
pageSelectorFromURLHash();