From 24289831c270cc79a8b39df992b1ced5cc7dd2f0 Mon Sep 17 00:00:00 2001 From: Raymond Hill Date: Sat, 24 Mar 2018 08:01:25 -0400 Subject: [PATCH] polish recipe-related code, user interface --- src/_locales/en/messages.json | 8 ++ src/css/popup.css | 30 ++++-- src/hosts-files.html | 4 +- src/js/messaging.js | 2 +- src/js/popup.js | 17 ++- src/js/recipe-manager.js | 193 +++++++++++++++++++--------------- src/popup.html | 4 +- 7 files changed, 154 insertions(+), 104 deletions(-) diff --git a/src/_locales/en/messages.json b/src/_locales/en/messages.json index da12e7e..cf8a9d8 100644 --- a/src/_locales/en/messages.json +++ b/src/_locales/en/messages.json @@ -155,6 +155,14 @@ "message": "No web page found", "description": "Displays in place of matrix when no data is found for the current page" }, + "matrixRecipeImportTip" : { + "message": "Import rules", + "description": "Used as a tooltip for the recipe import button" + }, + "matrixRecipeSaveTip" : { + "message": "Save rules", + "description": "Used as a tooltip for the recipe padlock button" + }, "statsPageTitle" : { "message": "uMatrix – Statistics", diff --git a/src/css/popup.css b/src/css/popup.css index 3ef899a..b977931 100644 --- a/src/css/popup.css +++ b/src/css/popup.css @@ -159,7 +159,7 @@ body .toolbar button.fa { } .dropdown-menu-capture { - background-color: transparent; + background-color: rgba(0,0,0,0.2); border: 0; bottom: 0; display: none; @@ -171,6 +171,10 @@ body .toolbar button.fa { top: 0; z-index: 300; } +.dropdown-menu-capture.dropdown-menu-centered > .dropdown-menu { + left: 4em; + right: 4em; + } .dropdown-menu-capture.show { display: block; } @@ -211,14 +215,15 @@ body .toolbar button.fa { } button > span.badge { - padding: 1px 1px; - display: inline-block; - font-size: 40%; - position: absolute; - right: 1px; + background-color: rgba(240,240,240,0.75); bottom: 1px; color: #000; - background-color: rgba(240,240,240,0.75) + display: inline-block; + font-size: 40%; + padding: 1px 1px; + pointer-events: none; + position: absolute; + right: 1px; } button.disabled > span.badge { display: none; @@ -238,7 +243,6 @@ button.disabled > span.badge { padding: 0; } .recipe { - cursor: pointer; list-style-type: none; white-space: nowrap; } @@ -266,15 +270,21 @@ button.disabled > span.badge { } .recipe .name { color: #000; + cursor: default; flex-grow: 1; + padding: 0.4em 0; } +.recipe .importer, .recipe .committer { + cursor: pointer; display: none; font-size: 120%; padding: 0.4em; - width: 0.8em; + text-align: center; + width: 1em; } -.recipe.mustCommit .committer { +.recipe.mustImport .importer, +.recipe.mustCommit:not(.mustImport) .committer { display: inline; } .recipe:hover { diff --git a/src/hosts-files.html b/src/hosts-files.html index 61c0af7..9df8e52 100644 --- a/src/hosts-files.html +++ b/src/hosts-files.html @@ -21,7 +21,7 @@
-

+

 

  • diff --git a/src/js/messaging.js b/src/js/messaging.js index 393a329..8a09862 100644 --- a/src/js/messaging.js +++ b/src/js/messaging.js @@ -349,7 +349,7 @@ var onMessage = function(request, sender, callback) { break; case 'fetchRecipeCommitStatuses': - response = µm.recipeManager.commitStatuses(request); + response = µm.recipeManager.statuses(request); break; case 'toggleMatrixSwitch': diff --git a/src/js/popup.js b/src/js/popup.js index 2382924..d661d2a 100644 --- a/src/js/popup.js +++ b/src/js/popup.js @@ -1310,10 +1310,19 @@ let recipeManager = (function() { } function apply(ev) { - if ( ev.target.classList.contains('expander') ) { + if ( + ev.target.classList.contains('expander') || + ev.target.classList.contains('name') + ) { ev.currentTarget.classList.toggle('expanded'); return; } + if ( + ev.target.classList.contains('importer') === false && + ev.target.classList.contains('committer') === false + ) { + return; + } let root = ev.currentTarget; let ruleset = root.querySelector('.ruleset'); let commit = ev.target.classList.contains('committer'); @@ -1326,6 +1335,7 @@ let recipeManager = (function() { }, updateMatrixSnapshot ); + root.classList.remove('mustImport'); if ( commit ) { root.classList.remove('mustCommit'); } @@ -1341,6 +1351,7 @@ let recipeManager = (function() { recipe.ruleset.replace(reScopeAlias, '$1' + details.scope + '$2'), ul ); + li.classList.toggle('mustImport', recipe.mustImport === true); li.classList.toggle('mustCommit', recipe.mustCommit === true); li.addEventListener('click', apply); } @@ -1448,8 +1459,10 @@ function dropDownMenuShow(button) { var menu = menuOverlay.querySelector('.dropdown-menu'); var menuRect = menu.getBoundingClientRect(); var menuLeft = butnNormalLeft * (viewRect.width - menuRect.width); - menu.style.left = menuLeft.toFixed(0) + 'px'; menu.style.top = butnRect.bottom + 'px'; + if ( menuOverlay.classList.contains('dropdown-menu-centered') === false ) { + menu.style.left = menuLeft.toFixed(0) + 'px'; + } } function dropDownMenuHide() { diff --git a/src/js/recipe-manager.js b/src/js/recipe-manager.js index e7813da..213ec6b 100644 --- a/src/js/recipe-manager.js +++ b/src/js/recipe-manager.js @@ -148,99 +148,118 @@ rawRecipes = []; }; - return { - apply: function(details) { - let µm = µMatrix; - let tMatrix = µm.tMatrix; - let pMatrix = µm.pMatrix; - let mustPersist = false; - for ( let rule of details.ruleset.split('\n') ) { - let parts = rule.split(/\s+/); - if ( parts.length < 2 ) { continue; } - let f0 = parts[0]; - let f1 = parts[1]; - // Switch - if ( f0.endsWith(':') ) { - f0 = f0.slice(0, -1); - if ( tMatrix.evaluateSwitchZ(f0, f1) !== false ) { - tMatrix.setSwitchZ(f0, f1, false); - if ( details.commit ) { - pMatrix.setSwitchZ(f0, f1, false); - mustPersist = true; - } - } - continue; - } - // Rule - if ( parts.length < 3 ) { continue; } - let f2 = parts[2]; - let action = tMatrix.evaluateCellZXY(f0, f1, f2); - if ( (action & 3) === 1 ) { - tMatrix.whitelistCell(f0, f1, f2); - } - if ( details.commit !== true ) { continue; } - action = pMatrix.evaluateCellZXY(f0, f1, f2); - if ( (action & 3) === 1 ) { - pMatrix.whitelistCell(f0, f1, f2); - mustPersist = true; - } - } - if ( mustPersist ) { - µm.saveMatrix(); - } - }, - fetch: function(srcHostname, desHostnames, callback) { - fromPendingStrings(); - let out = []; - let fetched = new Set(); - let tokens = getTokens(srcHostname + ' ' + desHostnames.join(' ')); - for ( let token of tokens ) { - let recipes = recipeBook.get(token); - if ( recipes === undefined ) { continue; } - for ( let recipe of recipes ) { - if ( fetched.has(recipe.id) ) { continue; } - if ( - conditionMatch( - recipe.condition, - srcHostname, - desHostnames - ) - ) { - out.push(recipe); - fetched.add(recipe.id); + // true = blocked, false = not blocked + var evaluateRuleParts = function(matrix, scope, parts) { + if ( parts[0].endsWith(':') ) { + return matrix.evaluateSwitchZ(parts[0].slice(0, -1), scope); + } + return matrix.evaluateCellZXY(scope, parts[1], parts[2]) === 1; + }; + + var api = {}; + + api.apply = function(details) { + let µm = µMatrix; + let tMatrix = µm.tMatrix; + let pMatrix = µm.pMatrix; + let mustPersist = false; + for ( let rule of details.ruleset.split('\n') ) { + let parts = rule.split(/\s+/); + if ( parts.length < 2 ) { continue; } + let f0 = parts[0]; + let f1 = parts[1]; + // Switch + if ( f0.endsWith(':') ) { + f0 = f0.slice(0, -1); + if ( tMatrix.evaluateSwitchZ(f0, f1) !== false ) { + tMatrix.setSwitchZ(f0, f1, false); + if ( details.commit ) { + pMatrix.setSwitchZ(f0, f1, false); + mustPersist = true; } } + continue; } - callback(out); - }, - commitStatuses: function(details) { - let matrix = µMatrix.pMatrix; - for ( let recipe of details.recipes ) { - let ruleIter = new µMatrix.LineIterator(recipe.ruleset); - while ( ruleIter.eot() === false ) { - let parts = ruleIter.next().split(/\s+/); - if ( - matrix.evaluateCellZXY( - details.scope, - parts[1], - parts[2] - ) === 1 - ) { - recipe.mustCommit = true; - break; - } - } + // Rule + if ( parts.length < 3 ) { continue; } + let f2 = parts[2]; + let action = tMatrix.evaluateCellZXY(f0, f1, f2); + if ( (action & 3) === 1 ) { + tMatrix.whitelistCell(f0, f1, f2); } - return details; - }, - fromString: function(raw) { - rawRecipes.push(raw); - }, - reset: function() { - rawRecipes.length = 0; - recipeBook.clear(); + if ( details.commit !== true ) { continue; } + action = pMatrix.evaluateCellZXY(f0, f1, f2); + if ( (action & 3) === 1 ) { + pMatrix.whitelistCell(f0, f1, f2); + mustPersist = true; + } + } + if ( mustPersist ) { + µm.saveMatrix(); } }; + + api.fetch = function(srcHostname, desHostnames, callback) { + fromPendingStrings(); + let out = []; + let fetched = new Set(); + let tokens = getTokens(srcHostname + ' ' + desHostnames.join(' ')); + for ( let token of tokens ) { + let recipes = recipeBook.get(token); + if ( recipes === undefined ) { continue; } + for ( let recipe of recipes ) { + if ( fetched.has(recipe.id) ) { continue; } + if ( + conditionMatch( + recipe.condition, + srcHostname, + desHostnames + ) + ) { + out.push(recipe); + fetched.add(recipe.id); + } + } + } + callback(out); + }; + + api.statuses = function(details) { + let pMatrix = µMatrix.pMatrix, + tMatrix = µMatrix.tMatrix; + for ( let recipe of details.recipes ) { + let ruleIter = new µMatrix.LineIterator(recipe.ruleset); + while ( ruleIter.eot() === false ) { + let parts = ruleIter.next().split(/\s+/); + if ( + recipe.mustCommit !== true && + evaluateRuleParts(pMatrix, details.scope, parts) + ) { + recipe.mustCommit = true; + if ( recipe.mustImport ) { break; } + } + if ( + recipe.mustImport !== true && + evaluateRuleParts(tMatrix, details.scope, parts) + ) { + recipe.mustImport = true; + if ( recipe.mustCommit ) { break; } + } + } + } + return details; + }; + + api.fromString = function(raw) { + rawRecipes.push(raw); + }; + + api.reset = function() { + rawRecipes.length = 0; + recipeBook.clear(); + }; + + return api; })(); /******************************************************************************/ diff --git a/src/popup.html b/src/popup.html index ca4a6a0..5e49a47 100644 --- a/src/popup.html +++ b/src/popup.html @@ -74,7 +74,7 @@
-