mirror of
https://github.com/gorhill/uBlock.git
synced 2024-11-09 12:22:33 +01:00
Add ability to sort rules in _My rules_ pane
Related issue: - https://github.com/uBlockOrigin/uBlock-issues/issues/1055
This commit is contained in:
parent
6284eca351
commit
dd655473f6
@ -48,6 +48,23 @@
|
|||||||
.cm-staticnetAllow { color: #004f00; }
|
.cm-staticnetAllow { color: #004f00; }
|
||||||
.cm-staticOpt { background-color: #ddd; font-weight: bold; }
|
.cm-staticOpt { background-color: #ddd; font-weight: bold; }
|
||||||
|
|
||||||
|
/* Rules */
|
||||||
|
.cm-s-default .cm-allowrule {
|
||||||
|
color: green;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.cm-s-default .cm-blockrule {
|
||||||
|
color: red;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.cm-s-default .cm-nooprule {
|
||||||
|
color: darkslategray;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.cm-s-default .cm-sortkey {
|
||||||
|
color: #708;
|
||||||
|
}
|
||||||
|
|
||||||
div.CodeMirror span.CodeMirror-matchingbracket {
|
div.CodeMirror span.CodeMirror-matchingbracket {
|
||||||
color: unset;
|
color: unset;
|
||||||
}
|
}
|
||||||
@ -111,11 +128,9 @@ div.CodeMirror span.CodeMirror-matchingbracket {
|
|||||||
|
|
||||||
.CodeMirror-merge-l-deleted {
|
.CodeMirror-merge-l-deleted {
|
||||||
background-image: none;
|
background-image: none;
|
||||||
font-weight: bold;
|
|
||||||
}
|
}
|
||||||
.CodeMirror-merge-l-inserted {
|
.CodeMirror-merge-l-inserted {
|
||||||
background-image: none;
|
background-image: none;
|
||||||
font-weight: bold;
|
|
||||||
}
|
}
|
||||||
/* This probably needs to be added to CodeMirror repo */
|
/* This probably needs to be added to CodeMirror repo */
|
||||||
.CodeMirror-merge-gap {
|
.CodeMirror-merge-gap {
|
||||||
|
@ -34,7 +34,9 @@
|
|||||||
<button type="button" class="iconifiable" id="importButton"><span class="fa"></span><span data-i18n="rulesImport"></span></button>
|
<button type="button" class="iconifiable" id="importButton"><span class="fa"></span><span data-i18n="rulesImport"></span></button>
|
||||||
<button type="button" class="iconifiable important disabled" id="editSaveButton"><span class="fa"></span><span data-i18n="rulesEditSave"></span></button>
|
<button type="button" class="iconifiable important disabled" id="editSaveButton"><span class="fa"></span><span data-i18n="rulesEditSave"></span></button>
|
||||||
</div>
|
</div>
|
||||||
<div id="ruleFilter"><span class="fa"></span> <input type="search" size="20"></div>
|
<div id="ruleFilter">
|
||||||
|
<span><span class="fa-icon">filter</span> <input type="search" size="20"></span> Sort: <select><option value="0">Rule type<option value="1" selected>Source<option value="2">Destination</select>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -57,7 +57,10 @@ CodeMirror.defineMode('ubo-dynamic-filtering', ( ) => {
|
|||||||
'noop',
|
'noop',
|
||||||
]);
|
]);
|
||||||
const reIsNotHostname = /[:/#?*]/;
|
const reIsNotHostname = /[:/#?*]/;
|
||||||
|
const slices = [];
|
||||||
|
let sliceIndex = 0;
|
||||||
const tokens = [];
|
const tokens = [];
|
||||||
|
let tokenIndex = 0;
|
||||||
|
|
||||||
const isSwitchRule = ( ) => {
|
const isSwitchRule = ( ) => {
|
||||||
const token = tokens[0];
|
const token = tokens[0];
|
||||||
@ -73,35 +76,54 @@ CodeMirror.defineMode('ubo-dynamic-filtering', ( ) => {
|
|||||||
return style;
|
return style;
|
||||||
};
|
};
|
||||||
|
|
||||||
const token = stream => {
|
const token = function(stream) {
|
||||||
if ( stream.sol() ) { tokens.length = 0; }
|
if ( stream.sol() ) {
|
||||||
stream.eatSpace();
|
slices.length = 0;
|
||||||
const match = stream.match(/\S+/);
|
tokens.length = 0;
|
||||||
if ( Array.isArray(match) === false ) {
|
const reTokens = /\S+/g;
|
||||||
return skipToEnd(stream);
|
for (;;) {
|
||||||
|
const lastIndex = reTokens.lastIndex;
|
||||||
|
const match = reTokens.exec(stream.string);
|
||||||
|
if ( match === null ) { break; }
|
||||||
|
const l = match.index;
|
||||||
|
const r = reTokens.lastIndex;
|
||||||
|
if ( l !== lastIndex ) {
|
||||||
|
slices.push({ t: false, l: lastIndex, r: l });
|
||||||
}
|
}
|
||||||
if ( tokens.length === 4 ) {
|
slices.push({ t: true, l, r });
|
||||||
return skipToEnd(stream, 'error');
|
tokens.push(stream.string.slice(l, r));
|
||||||
}
|
}
|
||||||
const token = match[0];
|
sliceIndex = tokenIndex = 0;
|
||||||
tokens.push(token);
|
}
|
||||||
|
if ( sliceIndex >= slices.length ) {
|
||||||
|
return stream.skipToEnd(stream);
|
||||||
|
}
|
||||||
|
const slice = slices[sliceIndex++];
|
||||||
|
stream.pos = slice.r;
|
||||||
|
if ( slice.t !== true ) { return null; }
|
||||||
|
const token = tokens[tokenIndex++];
|
||||||
// Field 1: per-site switch or hostname
|
// Field 1: per-site switch or hostname
|
||||||
if ( tokens.length === 1 ) {
|
if ( tokenIndex === 1 ) {
|
||||||
if ( isSwitchRule(token) ) {
|
if ( isSwitchRule(token) ) {
|
||||||
if ( validSwitches.has(token) === false ) {
|
if ( validSwitches.has(token) === false ) {
|
||||||
return skipToEnd(stream, 'error');
|
return skipToEnd(stream, 'error');
|
||||||
}
|
}
|
||||||
} else if ( reIsNotHostname.test(token) && token !== '*' ) {
|
if ( this.sortType === 0 ) { return 'sortkey'; }
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if ( reIsNotHostname.test(token) && token !== '*' ) {
|
||||||
return skipToEnd(stream, 'error');
|
return skipToEnd(stream, 'error');
|
||||||
}
|
}
|
||||||
|
if ( this.sortType === 1 ) { return 'sortkey'; }
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
// Field 2: hostname or url
|
// Field 2: hostname or url
|
||||||
if ( tokens.length === 2 ) {
|
if ( tokenIndex === 2 ) {
|
||||||
if ( isSwitchRule(tokens[0]) ) {
|
if ( isSwitchRule(tokens[0]) ) {
|
||||||
if ( reIsNotHostname.test(token) && token !== '*' ) {
|
if ( reIsNotHostname.test(token) && token !== '*' ) {
|
||||||
return skipToEnd(stream, 'error');
|
return skipToEnd(stream, 'error');
|
||||||
}
|
}
|
||||||
|
if ( this.sortType === 1 ) { return 'sortkey'; }
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
reIsNotHostname.test(token) &&
|
reIsNotHostname.test(token) &&
|
||||||
@ -110,15 +132,18 @@ CodeMirror.defineMode('ubo-dynamic-filtering', ( ) => {
|
|||||||
) {
|
) {
|
||||||
return skipToEnd(stream, 'error');
|
return skipToEnd(stream, 'error');
|
||||||
}
|
}
|
||||||
|
if ( this.sortType === 2 ) { return 'sortkey'; }
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
// Field 3
|
// Field 3
|
||||||
if ( tokens.length === 3 ) {
|
if ( tokenIndex === 3 ) {
|
||||||
// Switch rule
|
// Switch rule
|
||||||
if ( isSwitchRule(tokens[0]) ) {
|
if ( isSwitchRule(tokens[0]) ) {
|
||||||
if ( validSwitcheStates.has(token) === false ) {
|
if ( validSwitcheStates.has(token) === false ) {
|
||||||
return skipToEnd(stream, 'error');
|
return skipToEnd(stream, 'error');
|
||||||
}
|
}
|
||||||
|
if ( token === 'true' ) { return 'blockrule'; }
|
||||||
|
if ( token === 'false' ) { return 'allowrule'; }
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
// Hostname rule
|
// Hostname rule
|
||||||
@ -141,61 +166,19 @@ CodeMirror.defineMode('ubo-dynamic-filtering', ( ) => {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
// Field 4
|
// Field 4
|
||||||
if ( tokens.length === 4 ) {
|
if ( tokenIndex === 4 ) {
|
||||||
if (
|
if (
|
||||||
isSwitchRule(tokens[0]) ||
|
isSwitchRule(tokens[0]) ||
|
||||||
validActions.has(token) === false
|
validActions.has(token) === false
|
||||||
) {
|
) {
|
||||||
return skipToEnd(stream, 'error');
|
return skipToEnd(stream, 'error');
|
||||||
}
|
}
|
||||||
return null;
|
if ( token === 'allow' ) { return 'allowrule'; }
|
||||||
|
if ( token === 'block' ) { return 'blockrule'; }
|
||||||
|
return 'nooprule';
|
||||||
}
|
}
|
||||||
return skipToEnd(stream);
|
return skipToEnd(stream);
|
||||||
};
|
};
|
||||||
|
|
||||||
return { token };
|
return { token, sortType: 1 };
|
||||||
});
|
});
|
||||||
|
|
||||||
/*
|
|
||||||
Code below is to address
|
|
||||||
https://github.com/uBlockOrigin/uMatrix-issues/issues/128
|
|
||||||
|
|
||||||
But this needs fixing because glitchiness in some cases.
|
|
||||||
I may end up having to create a custom merge view rather
|
|
||||||
than using the existing CodeMirror one.
|
|
||||||
|
|
||||||
CodeMirror.registerHelper('fold', 'ubo-dynamic-filtering', (cm, start) => {
|
|
||||||
function isHeader(lineNo) {
|
|
||||||
const tokentype = cm.getTokenTypeAt(CodeMirror.Pos(lineNo, 0));
|
|
||||||
return tokentype && /\bheader\b/.test(tokentype);
|
|
||||||
}
|
|
||||||
|
|
||||||
function headerLevel(lineNo, line, nextLine) {
|
|
||||||
let match = line && line.match(/^#+/);
|
|
||||||
if (match && isHeader(lineNo)) return match[0].length;
|
|
||||||
match = nextLine && nextLine.match(/^[=\-]+\s*$/);
|
|
||||||
if (match && isHeader(lineNo + 1)) return nextLine[0] === '=' ? 1 : 2;
|
|
||||||
return 100;
|
|
||||||
}
|
|
||||||
|
|
||||||
const firstLine = cm.getLine(start.line);
|
|
||||||
let nextLine = cm.getLine(start.line + 1);
|
|
||||||
const level = headerLevel(start.line, firstLine, nextLine);
|
|
||||||
if ( level === 100 ) { return; }
|
|
||||||
|
|
||||||
const lastLineNo = cm.lastLine();
|
|
||||||
let end = start.line,
|
|
||||||
nextNextLine = cm.getLine(end + 2);
|
|
||||||
while ( end < lastLineNo ) {
|
|
||||||
if ( headerLevel(end + 1, nextLine, nextNextLine) <= level ) { break; }
|
|
||||||
++end;
|
|
||||||
nextLine = nextNextLine;
|
|
||||||
nextNextLine = cm.getLine(end + 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
from: CodeMirror.Pos(start.line, firstLine.length),
|
|
||||||
to: CodeMirror.Pos(end, cm.getLine(end).length),
|
|
||||||
};
|
|
||||||
});
|
|
||||||
*/
|
|
||||||
|
@ -101,7 +101,7 @@ let differ;
|
|||||||
// https://github.com/codemirror/CodeMirror/blob/3e1bb5fff682f8f6cbfaef0e56c61d62403d4798/addon/search/search.js#L22
|
// https://github.com/codemirror/CodeMirror/blob/3e1bb5fff682f8f6cbfaef0e56c61d62403d4798/addon/search/search.js#L22
|
||||||
// ... and modified as needed.
|
// ... and modified as needed.
|
||||||
|
|
||||||
const updateOverlay = (function() {
|
const updateOverlay = (( ) => {
|
||||||
let reFilter;
|
let reFilter;
|
||||||
const mode = {
|
const mode = {
|
||||||
token: function(stream) {
|
token: function(stream) {
|
||||||
@ -135,11 +135,16 @@ const updateOverlay = (function() {
|
|||||||
// - Minimum amount of text updated
|
// - Minimum amount of text updated
|
||||||
|
|
||||||
const rulesToDoc = function(clearHistory) {
|
const rulesToDoc = function(clearHistory) {
|
||||||
|
const orig = unfilteredRules.orig.doc;
|
||||||
|
const edit = unfilteredRules.edit.doc;
|
||||||
|
orig.startOperation();
|
||||||
|
edit.startOperation();
|
||||||
for ( const key in unfilteredRules ) {
|
for ( const key in unfilteredRules ) {
|
||||||
if ( unfilteredRules.hasOwnProperty(key) === false ) { continue; }
|
if ( unfilteredRules.hasOwnProperty(key) === false ) { continue; }
|
||||||
const doc = unfilteredRules[key].doc;
|
const doc = unfilteredRules[key].doc;
|
||||||
const rules = filterRules(key);
|
const rules = filterRules(key);
|
||||||
if (
|
if (
|
||||||
|
clearHistory ||
|
||||||
doc.lineCount() === 1 && doc.getValue() === '' ||
|
doc.lineCount() === 1 && doc.getValue() === '' ||
|
||||||
rules.length === 0
|
rules.length === 0
|
||||||
) {
|
) {
|
||||||
@ -157,27 +162,27 @@ const rulesToDoc = function(clearHistory) {
|
|||||||
let afterText = rules.join('\n').trim();
|
let afterText = rules.join('\n').trim();
|
||||||
if ( afterText !== '' ) { afterText += '\n'; }
|
if ( afterText !== '' ) { afterText += '\n'; }
|
||||||
const diffs = differ.diff_main(beforeText, afterText);
|
const diffs = differ.diff_main(beforeText, afterText);
|
||||||
doc.startOperation();
|
let i = diffs.length;
|
||||||
let i = diffs.length,
|
let iedit = beforeText.length;
|
||||||
iedit = beforeText.length;
|
|
||||||
while ( i-- ) {
|
while ( i-- ) {
|
||||||
let diff = diffs[i];
|
const diff = diffs[i];
|
||||||
if ( diff[0] === 0 ) {
|
if ( diff[0] === 0 ) {
|
||||||
iedit -= diff[1].length;
|
iedit -= diff[1].length;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let end = doc.posFromIndex(iedit);
|
const end = doc.posFromIndex(iedit);
|
||||||
if ( diff[0] === 1 ) {
|
if ( diff[0] === 1 ) {
|
||||||
doc.replaceRange(diff[1], end, end);
|
doc.replaceRange(diff[1], end, end);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
/* diff[0] === -1 */
|
/* diff[0] === -1 */
|
||||||
iedit -= diff[1].length;
|
iedit -= diff[1].length;
|
||||||
let beg = doc.posFromIndex(iedit);
|
const beg = doc.posFromIndex(iedit);
|
||||||
doc.replaceRange('', beg, end);
|
doc.replaceRange('', beg, end);
|
||||||
}
|
}
|
||||||
doc.endOperation();
|
|
||||||
}
|
}
|
||||||
|
orig.endOperation();
|
||||||
|
edit.endOperation();
|
||||||
cleanEditText = mergeView.editor().getValue().trim();
|
cleanEditText = mergeView.editor().getValue().trim();
|
||||||
cleanEditToken = mergeView.editor().changeGeneration();
|
cleanEditToken = mergeView.editor().changeGeneration();
|
||||||
if ( clearHistory ) {
|
if ( clearHistory ) {
|
||||||
@ -205,27 +210,75 @@ const filterRules = function(key) {
|
|||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
const renderRules = (( ) => {
|
const renderRules = (( ) => {
|
||||||
const reIsSwitchRule = /^[a-z-]+: /;
|
|
||||||
let firstVisit = true;
|
let firstVisit = true;
|
||||||
|
let sortType = 1;
|
||||||
|
|
||||||
// Switches always listed at the top.
|
const reSwRule = /^([^/]+): ([^/ ]+) ([^ ]+)/;
|
||||||
const customSort = (a, b) => {
|
const reRule = /^([^ ]+) ([^/ ]+) ([^ ]+ [^ ]+)/;
|
||||||
const aIsSwitch = reIsSwitchRule.test(a);
|
const reUrlRule = /^([^ ]+) ([^ ]+) ([^ ]+ [^ ]+)/;
|
||||||
if ( reIsSwitchRule.test(b) === aIsSwitch ) {
|
|
||||||
return a.localeCompare(b);
|
const reverseHn = function(hn) {
|
||||||
}
|
return hn.split('.').reverse().join('.');
|
||||||
return aIsSwitch ? -1 : 1;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return function(details) {
|
const slotFromRule = function(rule) {
|
||||||
details.permanentRules.sort(customSort);
|
let type, srcHn, desHn, extra = '';
|
||||||
details.sessionRules.sort(customSort);
|
let match = reSwRule.exec(rule);
|
||||||
unfilteredRules.orig.rules = details.permanentRules;
|
if ( match !== null ) {
|
||||||
unfilteredRules.edit.rules = details.sessionRules;
|
type = ' ' + match[1];
|
||||||
rulesToDoc(firstVisit);
|
srcHn = reverseHn(match[2]);
|
||||||
if ( firstVisit ) {
|
desHn = srcHn;
|
||||||
|
} else if ( (match = reRule.exec(rule)) !== null ) {
|
||||||
|
type = '\x10FFFE';
|
||||||
|
srcHn = reverseHn(match[1]);
|
||||||
|
desHn = reverseHn(match[2]);
|
||||||
|
} else if ( (match = reUrlRule.exec(rule)) !== null ) {
|
||||||
|
type = '\x10FFFF';
|
||||||
|
srcHn = reverseHn(match[1]);
|
||||||
|
desHn = reverseHn(vAPI.hostnameFromURI(match[2]));
|
||||||
|
extra = rule;
|
||||||
|
}
|
||||||
|
if ( sortType === 0 ) {
|
||||||
|
return { rule, token: `${type} ${srcHn} ${desHn} ${extra}` };
|
||||||
|
}
|
||||||
|
if ( sortType === 1 ) {
|
||||||
|
return { rule, token: `${srcHn} ${type} ${desHn} ${extra}` };
|
||||||
|
}
|
||||||
|
return { rule, token: `${desHn} ${type} ${srcHn} ${extra}` };
|
||||||
|
};
|
||||||
|
|
||||||
|
const sort = rules => {
|
||||||
|
const slots = [];
|
||||||
|
for ( let i = 0; i < rules.length; i++ ) {
|
||||||
|
slots.push(slotFromRule(rules[i], 1));
|
||||||
|
}
|
||||||
|
slots.sort((a, b) => a.token.localeCompare(b.token));
|
||||||
|
for ( let i = 0; i < rules.length; i++ ) {
|
||||||
|
rules[i] = slots[i].rule;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return function(clearHistory = false) {
|
||||||
|
const select = document.querySelector('#ruleFilter select');
|
||||||
|
sortType = parseInt(select.value, 10) || 1;
|
||||||
|
unfilteredRules.orig.doc.getMode().sortType = sortType;
|
||||||
|
unfilteredRules.edit.doc.getMode().sortType = sortType;
|
||||||
|
sort(unfilteredRules.orig.rules);
|
||||||
|
sort(unfilteredRules.edit.rules);
|
||||||
|
rulesToDoc(firstVisit || clearHistory);
|
||||||
|
if ( firstVisit || clearHistory ) {
|
||||||
firstVisit = false;
|
firstVisit = false;
|
||||||
mergeView.editor().execCommand('goNextDiff');
|
const chunks = mergeView.leftChunks();
|
||||||
|
if ( chunks.length !== 0 ) {
|
||||||
|
const ldoc = unfilteredRules.orig.doc;
|
||||||
|
const { clientHeight } = ldoc.getScrollInfo();
|
||||||
|
const line = Math.min(chunks[0].editFrom, chunks[0].origFrom);
|
||||||
|
ldoc.setCursor(line, 0);
|
||||||
|
ldoc.scrollIntoView(
|
||||||
|
{ line, ch: 0 },
|
||||||
|
(clientHeight - ldoc.defaultTextHeight()) / 2
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
onTextChanged(true);
|
onTextChanged(true);
|
||||||
};
|
};
|
||||||
@ -240,7 +293,9 @@ const applyDiff = async function(permanent, toAdd, toRemove) {
|
|||||||
toAdd: toAdd,
|
toAdd: toAdd,
|
||||||
toRemove: toRemove,
|
toRemove: toRemove,
|
||||||
});
|
});
|
||||||
renderRules(details);
|
unfilteredRules.orig.rules = details.permanentRules;
|
||||||
|
unfilteredRules.edit.rules = details.sessionRules;
|
||||||
|
renderRules();
|
||||||
};
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
@ -326,10 +381,10 @@ function exportUserRulesToFile() {
|
|||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
const onFilterChanged = (function() {
|
const onFilterChanged = (( ) => {
|
||||||
let timer,
|
let timer;
|
||||||
overlay = null,
|
let overlay = null;
|
||||||
last = '';
|
let last = '';
|
||||||
|
|
||||||
const process = function() {
|
const process = function() {
|
||||||
timer = undefined;
|
timer = undefined;
|
||||||
@ -351,22 +406,28 @@ const onFilterChanged = (function() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return function() {
|
return function() {
|
||||||
if ( timer !== undefined ) { clearTimeout(timer); }
|
if ( timer !== undefined ) { self.cancelIdleCallback(timer); }
|
||||||
timer = vAPI.setTimeout(process, 773);
|
timer = self.requestIdleCallback(process, { timeout: 773 });
|
||||||
};
|
};
|
||||||
})();
|
})();
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
|
const onSortChanged = function() {
|
||||||
|
renderRules(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
const onTextChanged = (( ) => {
|
const onTextChanged = (( ) => {
|
||||||
let timer;
|
let timer;
|
||||||
|
|
||||||
const process = now => {
|
const process = details => {
|
||||||
timer = undefined;
|
timer = undefined;
|
||||||
const diff = document.getElementById('diff');
|
const diff = document.getElementById('diff');
|
||||||
let isClean = mergeView.editor().isClean(cleanEditToken);
|
let isClean = mergeView.editor().isClean(cleanEditToken);
|
||||||
if (
|
if (
|
||||||
now &&
|
details === undefined &&
|
||||||
isClean === false &&
|
isClean === false &&
|
||||||
mergeView.editor().getValue().trim() === cleanEditText
|
mergeView.editor().getValue().trim() === cleanEditText
|
||||||
) {
|
) {
|
||||||
@ -388,8 +449,8 @@ const onTextChanged = (( ) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return function(now) {
|
return function(now) {
|
||||||
if ( timer !== undefined ) { clearTimeout(timer); }
|
if ( timer !== undefined ) { self.cancelIdleCallback(timer); }
|
||||||
timer = now ? process(now) : vAPI.setTimeout(process, 57);
|
timer = now ? process() : self.requestIdleCallback(process, { timeout: 57 });
|
||||||
};
|
};
|
||||||
})();
|
})();
|
||||||
|
|
||||||
@ -483,7 +544,9 @@ self.hasUnsavedData = function() {
|
|||||||
vAPI.messaging.send('dashboard', {
|
vAPI.messaging.send('dashboard', {
|
||||||
what: 'getRules',
|
what: 'getRules',
|
||||||
}).then(details => {
|
}).then(details => {
|
||||||
renderRules(details);
|
unfilteredRules.orig.rules = details.permanentRules;
|
||||||
|
unfilteredRules.edit.rules = details.sessionRules;
|
||||||
|
renderRules();
|
||||||
});
|
});
|
||||||
|
|
||||||
// Handle user interaction
|
// Handle user interaction
|
||||||
@ -494,9 +557,10 @@ uDom('#revertButton').on('click', revertAllHandler);
|
|||||||
uDom('#commitButton').on('click', commitAllHandler);
|
uDom('#commitButton').on('click', commitAllHandler);
|
||||||
uDom('#editSaveButton').on('click', editSaveHandler);
|
uDom('#editSaveButton').on('click', editSaveHandler);
|
||||||
uDom('#ruleFilter input').on('input', onFilterChanged);
|
uDom('#ruleFilter input').on('input', onFilterChanged);
|
||||||
|
uDom('#ruleFilter select').on('input', onSortChanged);
|
||||||
|
|
||||||
// https://groups.google.com/forum/#!topic/codemirror/UQkTrt078Vs
|
// https://groups.google.com/forum/#!topic/codemirror/UQkTrt078Vs
|
||||||
mergeView.editor().on('updateDiff', function() { onTextChanged(); });
|
mergeView.editor().on('updateDiff', ( ) => { onTextChanged(); });
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user