Remember presentation state of "My rules" pane

Related feedback:
https://old.reddit.com/r/uBlockOrigin/comments/198ohgi/
This commit is contained in:
Raymond Hill 2024-01-17 10:36:23 -05:00
parent 588468821c
commit 3d1b100646
No known key found for this signature in database
GPG Key ID: 25E1490B761470C2
1 changed files with 83 additions and 52 deletions

View File

@ -69,7 +69,6 @@ const thePanes = {
let cleanEditToken = 0; let cleanEditToken = 0;
let cleanEditText = ''; let cleanEditText = '';
let isCollapsed = false;
/******************************************************************************/ /******************************************************************************/
@ -104,7 +103,6 @@ let isCollapsed = false;
qs$('.CodeMirror-merge-copybuttons-left'), qs$('.CodeMirror-merge-copybuttons-left'),
{ attributes: true, attributeFilter: [ 'title' ], subtree: true } { attributes: true, attributeFilter: [ 'title' ], subtree: true }
); );
} }
/******************************************************************************/ /******************************************************************************/
@ -142,14 +140,34 @@ const updateOverlay = (( ) => {
stream.skipToEnd(); stream.skipToEnd();
} }
}; };
return function(filter) { return function() {
reFilter = typeof filter === 'string' && filter !== '' ? const f = presentationState.filter;
new RegExp(filter.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), 'gi') : reFilter = typeof f === 'string' && f !== ''
undefined; ? new RegExp(f.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), 'gi')
: undefined;
return mode; return mode;
}; };
})(); })();
const toggleOverlay = (( ) => {
let overlay = null;
return function() {
if ( overlay !== null ) {
mergeView.leftOriginal().removeOverlay(overlay);
mergeView.editor().removeOverlay(overlay);
overlay = null;
}
if ( presentationState.filter !== '' ) {
overlay = updateOverlay();
mergeView.leftOriginal().addOverlay(overlay);
mergeView.editor().addOverlay(overlay);
}
rulesToDoc(true);
savePresentationState();
};
})();
/******************************************************************************/ /******************************************************************************/
// Incrementally update text in a CodeMirror editor for best user experience: // Incrementally update text in a CodeMirror editor for best user experience:
@ -210,7 +228,7 @@ const rulesToDoc = function(clearHistory) {
if ( mark.uboEllipsis !== true ) { continue; } if ( mark.uboEllipsis !== true ) { continue; }
mark.clear(); mark.clear();
} }
if ( isCollapsed ) { if ( presentationState.isCollapsed ) {
for ( let iline = 0, n = edit.lineCount(); iline < n; iline++ ) { for ( let iline = 0, n = edit.lineCount(); iline < n; iline++ ) {
if ( edit.getLine(iline) !== '...' ) { continue; } if ( edit.getLine(iline) !== '...' ) { continue; }
const mark = edit.markText( const mark = edit.markText(
@ -353,41 +371,25 @@ function exportUserRulesToFile() {
/******************************************************************************/ /******************************************************************************/
const onFilterChanged = (( ) => { {
let timer; let timer;
let overlay = null;
let last = '';
const process = function() { dom.on('#ruleFilter input', 'input', ( ) => {
if ( timer !== undefined ) { self.cancelIdleCallback(timer); }
timer = self.requestIdleCallback(( ) => {
timer = undefined; timer = undefined;
if ( mergeView.editor().isClean(cleanEditToken) === false ) { return; } if ( mergeView.editor().isClean(cleanEditToken) === false ) { return; }
const filter = qs$('#ruleFilter input').value; const filter = qs$('#ruleFilter input').value;
if ( filter === last ) { return; } if ( filter === presentationState.filter ) { return; }
last = filter; presentationState.filter = filter;
if ( overlay !== null ) { toggleOverlay();
mergeView.leftOriginal().removeOverlay(overlay); }, { timeout: 773 });
mergeView.editor().removeOverlay(overlay); });
overlay = null; }
}
if ( filter !== '' ) {
overlay = updateOverlay(filter);
mergeView.leftOriginal().addOverlay(overlay);
mergeView.editor().addOverlay(overlay);
}
rulesToDoc(true);
};
return function() {
if ( timer !== undefined ) { self.cancelIdleCallback(timer); }
timer = self.requestIdleCallback(process, { timeout: 773 });
};
})();
/******************************************************************************/ /******************************************************************************/
const onPresentationChanged = (( ) => { const onPresentationChanged = (( ) => {
let sortType = 1;
const reSwRule = /^([^/]+): ([^/ ]+) ([^ ]+)/; const reSwRule = /^([^/]+): ([^/ ]+) ([^ ]+)/;
const reRule = /^([^ ]+) ([^/ ]+) ([^ ]+ [^ ]+)/; const reRule = /^([^ ]+) ([^/ ]+) ([^ ]+ [^ ]+)/;
const reUrlRule = /^([^ ]+) ([^ ]+) ([^ ]+ [^ ]+)/; const reUrlRule = /^([^ ]+) ([^ ]+) ([^ ]+ [^ ]+)/;
@ -431,10 +433,10 @@ const onPresentationChanged = (( ) => {
desHn = sortNormalizeHn(hostnameFromURI(match[2])); desHn = sortNormalizeHn(hostnameFromURI(match[2]));
extra = match[3]; extra = match[3];
} }
if ( sortType === 0 ) { if ( presentationState.sortType === 0 ) {
return { rule, token: `${type} ${srcHn} ${desHn} ${extra}` }; return { rule, token: `${type} ${srcHn} ${desHn} ${extra}` };
} }
if ( sortType === 1 ) { if ( presentationState.sortType === 1 ) {
return { rule, token: `${srcHn} ${type} ${desHn} ${extra}` }; return { rule, token: `${srcHn} ${type} ${desHn} ${extra}` };
} }
return { rule, token: `${desHn} ${type} ${srcHn} ${extra}` }; return { rule, token: `${desHn} ${type} ${srcHn} ${extra}` };
@ -452,7 +454,7 @@ const onPresentationChanged = (( ) => {
}; };
const collapse = ( ) => { const collapse = ( ) => {
if ( isCollapsed !== true ) { return; } if ( presentationState.isCollapsed !== true ) { return; }
const diffs = getDiffer().diff_main( const diffs = getDiffer().diff_main(
thePanes.orig.modified.join('\n'), thePanes.orig.modified.join('\n'),
thePanes.edit.modified.join('\n') thePanes.edit.modified.join('\n')
@ -491,23 +493,31 @@ const onPresentationChanged = (( ) => {
thePanes.edit.modified = rr; thePanes.edit.modified = rr;
}; };
return function(clearHistory) { dom.on('#ruleFilter select', 'input', ev => {
presentationState.sortType = parseInt(ev.target.value, 10) || 0;
savePresentationState();
onPresentationChanged(true);
});
dom.on('#ruleFilter #diffCollapse', 'click', ev => {
presentationState.isCollapsed = dom.cl.toggle(ev.target, 'active');
savePresentationState();
onPresentationChanged(true);
});
return function onPresentationChanged(clearHistory) {
const origPane = thePanes.orig; const origPane = thePanes.orig;
const editPane = thePanes.edit; const editPane = thePanes.edit;
origPane.modified = origPane.original.slice(); origPane.modified = origPane.original.slice();
editPane.modified = editPane.original.slice(); editPane.modified = editPane.original.slice();
const select = qs$('#ruleFilter select');
sortType = parseInt(select.value, 10);
if ( isNaN(sortType) ) { sortType = 1; }
{ {
const mode = origPane.doc.getMode(); const mode = origPane.doc.getMode();
mode.sortType = sortType; mode.sortType = presentationState.sortType;
mode.setHostnameToDomainMap(hostnameToDomainMap); mode.setHostnameToDomainMap(hostnameToDomainMap);
mode.setPSL(publicSuffixList); mode.setPSL(publicSuffixList);
} }
{ {
const mode = editPane.doc.getMode(); const mode = editPane.doc.getMode();
mode.sortType = sortType; mode.sortType = presentationState.sortType;
mode.setHostnameToDomainMap(hostnameToDomainMap); mode.setHostnameToDomainMap(hostnameToDomainMap);
mode.setPSL(publicSuffixList); mode.setPSL(publicSuffixList);
} }
@ -644,6 +654,35 @@ self.hasUnsavedData = function() {
/******************************************************************************/ /******************************************************************************/
const presentationState = {
sortType: 0,
isCollapsed: false,
filter: '',
};
const savePresentationState = ( ) => {
vAPI.localStorage.setItem('dynaRulesPresentationState', presentationState);
};
vAPI.localStorage.getItemAsync('dynaRulesPresentationState').then(details => {
if ( details instanceof Object === false ) { return; }
if ( typeof details.sortType === 'number' ) {
presentationState.sortType = details.sortType;
qs$('#ruleFilter select').value = `${details.sortType}`;
}
if ( typeof details.isCollapsed === 'boolean' ) {
presentationState.isCollapsed = details.isCollapsed;
dom.cl.toggle('#ruleFilter #diffCollapse', 'active', details.isCollapsed);
}
if ( typeof details.filter === 'string' ) {
presentationState.filter = details.filter;
qs$('#ruleFilter input').value = details.filter;
toggleOverlay();
}
});
/******************************************************************************/
vAPI.messaging.send('dashboard', { vAPI.messaging.send('dashboard', {
what: 'getRules', what: 'getRules',
}).then(details => { }).then(details => {
@ -660,14 +699,6 @@ dom.on('#exportButton', 'click', exportUserRulesToFile);
dom.on('#revertButton', 'click', revertAllHandler); dom.on('#revertButton', 'click', revertAllHandler);
dom.on('#commitButton', 'click', commitAllHandler); dom.on('#commitButton', 'click', commitAllHandler);
dom.on('#editSaveButton', 'click', editSaveHandler); dom.on('#editSaveButton', 'click', editSaveHandler);
dom.on('#ruleFilter input', 'input', onFilterChanged);
dom.on('#ruleFilter select', 'input', ( ) => {
onPresentationChanged(true);
});
dom.on('#ruleFilter #diffCollapse', 'click', ev => {
isCollapsed = dom.cl.toggle(ev.target, 'active');
onPresentationChanged(true);
});
// https://groups.google.com/forum/#!topic/codemirror/UQkTrt078Vs // https://groups.google.com/forum/#!topic/codemirror/UQkTrt078Vs
mergeView.editor().on('updateDiff', ( ) => { mergeView.editor().on('updateDiff', ( ) => {