Cache element picker's optimized candidates for reuse

Optimized candidates computed for each depth are now
cached for reuse. This reduces the amount of work
done when moving the depth slider.
This commit is contained in:
Raymond Hill 2020-10-20 05:37:07 -04:00
parent 5de0ce9757
commit ee059540f7
No known key found for this signature in database
GPG Key ID: 25E1490B761470C2
4 changed files with 37 additions and 16 deletions

View File

@ -32,10 +32,6 @@ html#ublock0-epicker,
#ublock0-epicker #toolbar { #ublock0-epicker #toolbar {
cursor: grab; cursor: grab;
display: flex; display: flex;
justify-content: space-between;
}
#ublock0-epicker aside.moving #toolbar {
cursor: grabbing;
} }
#ublock0-epicker ul { #ublock0-epicker ul {
margin: 0.25em 0 0 0; margin: 0.25em 0 0 0;
@ -67,6 +63,13 @@ html#ublock0-epicker,
background-color: var(--button-preferred-surface); background-color: var(--button-preferred-surface);
color: var(--button-preferred-ink); color: var(--button-preferred-ink);
} }
#ublock0-epicker #move {
cursor: grab;
flex-grow: 1;
}
#ublock0-epicker aside.moving #move {
cursor: grabbing;
}
#ublock0-epicker section { #ublock0-epicker section {
border: 0; border: 0;
box-sizing: border-box; box-sizing: border-box;
@ -117,12 +120,14 @@ html#ublock0-epicker,
} }
.resultsetModifier > span { .resultsetModifier > span {
align-items: flex-end; align-items: flex-end;
border-bottom: 2px solid white;
display: flex; display: flex;
height: 100%; height: 100%;
pointer-events: none; pointer-events: none;
width: 100%; width: 100%;
} }
.resultsetModifier > span > span {
margin: 2px 0;
}
.resultsetModifier > span > span:nth-of-type(1) { .resultsetModifier > span > span:nth-of-type(1) {
background-color: var(--checkbox-checked-ink); background-color: var(--checkbox-checked-ink);
border-inline-end: 1px solid #aaa; border-inline-end: 1px solid #aaa;

View File

@ -63,7 +63,7 @@ let netFilterCandidates = [];
let cosmeticFilterCandidates = []; let cosmeticFilterCandidates = [];
let computedCandidateSlot = 0; let computedCandidateSlot = 0;
let computedCandidate = ''; let computedCandidate = '';
let computedSpecificityCandidates = []; const computedSpecificityCandidates = new Map();
let needBody = false; let needBody = false;
/******************************************************************************/ /******************************************************************************/
@ -201,6 +201,16 @@ const candidateFromFilterChoice = function(filterChoice) {
/******************************************************************************/ /******************************************************************************/
const cosmeticCandidatesFromFilterChoice = function(filterChoice) { const cosmeticCandidatesFromFilterChoice = function(filterChoice) {
let { slot, filters } = filterChoice;
renderRange('resultsetDepth', slot, true);
renderRange('resultsetSpecificity');
if ( computedSpecificityCandidates.has(slot) ) {
onCandidatesOptimized({ slot });
return;
}
const specificities = [ const specificities = [
0b0000, // remove hierarchy; remove id, nth-of-type, attribute values 0b0000, // remove hierarchy; remove id, nth-of-type, attribute values
0b0010, // remove hierarchy; remove id, nth-of-type 0b0010, // remove hierarchy; remove id, nth-of-type
@ -214,7 +224,6 @@ const cosmeticCandidatesFromFilterChoice = function(filterChoice) {
const candidates = []; const candidates = [];
let { slot, filters } = filterChoice;
let filter = filters[slot]; let filter = filters[slot];
for ( const specificity of specificities ) { for ( const specificity of specificities ) {
@ -288,12 +297,10 @@ const cosmeticCandidatesFromFilterChoice = function(filterChoice) {
candidates.push(paths); candidates.push(paths);
} }
renderRange('resultsetDepth', slot, true);
renderRange('resultsetSpecificity');
vAPI.MessagingConnection.sendTo(epickerConnectionId, { vAPI.MessagingConnection.sendTo(epickerConnectionId, {
what: 'optimizeCandidates', what: 'optimizeCandidates',
candidates, candidates,
slot,
}); });
}; };
@ -302,8 +309,11 @@ const cosmeticCandidatesFromFilterChoice = function(filterChoice) {
const onCandidatesOptimized = function(details) { const onCandidatesOptimized = function(details) {
$id('resultsetModifiers').classList.remove('hide'); $id('resultsetModifiers').classList.remove('hide');
const i = parseInt($stor('#resultsetSpecificity input').value, 10); const i = parseInt($stor('#resultsetSpecificity input').value, 10);
computedSpecificityCandidates = details.candidates; if ( Array.isArray(details.candidates) ) {
computedCandidate = computedSpecificityCandidates[i]; computedSpecificityCandidates.set(details.slot, details.candidates);
}
const candidates = computedSpecificityCandidates.get(details.slot);
computedCandidate = candidates[i];
cmEditor.setValue(computedCandidate); cmEditor.setValue(computedCandidate);
cmEditor.clearHistory(); cmEditor.clearHistory();
onCandidateChanged(); onCandidateChanged();
@ -521,8 +531,11 @@ const onDepthChanged = function() {
const onSpecificityChanged = function() { const onSpecificityChanged = function() {
renderRange('resultsetSpecificity'); renderRange('resultsetSpecificity');
if ( rawFilterFromTextarea() !== computedCandidate ) { return; } if ( rawFilterFromTextarea() !== computedCandidate ) { return; }
const depthInput = $stor('#resultsetDepth input');
const slot = parseInt(depthInput.max, 10) - parseInt(depthInput.value, 10);
const i = parseInt($stor('#resultsetSpecificity input').value, 10); const i = parseInt($stor('#resultsetSpecificity input').value, 10);
computedCandidate = computedSpecificityCandidates[i]; const candidates = computedSpecificityCandidates.get(slot);
computedCandidate = candidates[i];
cmEditor.setValue(computedCandidate); cmEditor.setValue(computedCandidate);
cmEditor.clearHistory(); cmEditor.clearHistory();
onCandidateChanged(); onCandidateChanged();
@ -614,7 +627,7 @@ const onStartMoving = (( ) => {
}; };
return function(ev) { return function(ev) {
const target = dialog.querySelector('#toolbar'); const target = dialog.querySelector('#move');
if ( ev.target !== target ) { return; } if ( ev.target !== target ) { return; }
if ( dialog.classList.contains('moving') ) { return; } if ( dialog.classList.contains('moving') ) { return; }
isTouch = ev.type.startsWith('touch'); isTouch = ev.type.startsWith('touch');
@ -735,6 +748,7 @@ const showDialog = function(details) {
populateCandidates(netFilters, '#netFilters'); populateCandidates(netFilters, '#netFilters');
populateCandidates(cosmeticFilters, '#cosmeticFilters'); populateCandidates(cosmeticFilters, '#cosmeticFilters');
computedSpecificityCandidates.clear();
const depthInput = $stor('#resultsetDepth input'); const depthInput = $stor('#resultsetDepth input');
depthInput.max = cosmeticFilters.length - 1; depthInput.max = cosmeticFilters.length - 1;
@ -805,8 +819,8 @@ const startPicker = function() {
$id('create').addEventListener('click', onCreateClicked); $id('create').addEventListener('click', onCreateClicked);
$id('pick').addEventListener('click', onPickClicked); $id('pick').addEventListener('click', onPickClicked);
$id('quit').addEventListener('click', onQuitClicked); $id('quit').addEventListener('click', onQuitClicked);
$id('toolbar').addEventListener('mousedown', onStartMoving); $id('move').addEventListener('mousedown', onStartMoving);
$id('toolbar').addEventListener('touchstart', onStartMoving); $id('move').addEventListener('touchstart', onStartMoving);
$id('candidateFilters').addEventListener('click', onCandidateClicked); $id('candidateFilters').addEventListener('click', onCandidateClicked);
$stor('#resultsetDepth input').addEventListener('input', onDepthChanged); $stor('#resultsetDepth input').addEventListener('input', onDepthChanged);
$stor('#resultsetSpecificity input').addEventListener('input', onSpecificityChanged); $stor('#resultsetSpecificity input').addEventListener('input', onSpecificityChanged);

View File

@ -847,6 +847,7 @@ const onOptmizeCandidates = function(details) {
vAPI.MessagingConnection.sendTo(epickerConnectionId, { vAPI.MessagingConnection.sendTo(epickerConnectionId, {
what: 'candidatesOptimized', what: 'candidatesOptimized',
candidates: results.map(a => a.selector), candidates: results.map(a => a.selector),
slot: details.slot,
}); });
}; };

View File

@ -35,6 +35,7 @@
<div> <div>
<button id="preview" type="button" data-i18n="pickerPreview"></button> <button id="preview" type="button" data-i18n="pickerPreview"></button>
</div> </div>
<div id="move"></div>
<div> <div>
<button id="create" type="button" disabled data-i18n="pickerCreate"></button> <button id="create" type="button" disabled data-i18n="pickerCreate"></button>
<button id="pick" type="button" data-i18n="pickerPick"></button> <button id="pick" type="button" data-i18n="pickerPick"></button>