diff --git a/src/web/App.mjs b/src/web/App.mjs
index a3556aa1..b0cbeba4 100755
--- a/src/web/App.mjs
+++ b/src/web/App.mjs
@@ -63,6 +63,7 @@ class App {
this.setCompileMessage();
this.loadLocalStorage();
this.populateOperationsList();
+ this.manager.recipe.updateSelectedOperations();
this.manager.setup();
this.manager.output.saveBombe();
this.uriParams = this.getURIParams();
@@ -329,6 +330,8 @@ class App {
});
this.adjustComponentSizes();
+
+ // @TODO: handle sortable, draggable, popovers functionality etc.
}
/**
@@ -801,7 +804,7 @@ class App {
/**
- * Handler for CyerChef statechange events.
+ * Handler for CyberChef statechange events.
* Fires whenever the input or recipe changes in any way.
*
* @listens Manager#statechange
diff --git a/src/web/TODO.md b/src/web/TODO.md
index 8d27c2b1..23454d96 100644
--- a/src/web/TODO.md
+++ b/src/web/TODO.md
@@ -4,9 +4,8 @@
---
#### Mobile UI ( on real device ):
-- OperationsWaiter operationDblClick: class 'selected' needs to be removed once it is deleted from recipe list, through any type of event
- How to add operations to favourites since drag and drop is now disabled on mobile ( maybe a star icon...? )
-- 'name' in recipe waiter > addOperation is whatever instead of a plain title..
+- 'name' in recipe waiter > addOperation is whatever instead of a plain data-name, updateSelectedOperations not working for search results because of that
- Recipe list on mobile panel is too small to comfortably scroll and change order of recipes
- test *thoroughly* with keyboard popping up because that messes with view-heights on mobile probably and might make it a very frustrating experience
diff --git a/src/web/waiters/OperationsWaiter.mjs b/src/web/waiters/OperationsWaiter.mjs
index cec9e909..504a1ad6 100755
--- a/src/web/waiters/OperationsWaiter.mjs
+++ b/src/web/waiters/OperationsWaiter.mjs
@@ -236,7 +236,6 @@ class OperationsWaiter {
*/
operationDblclick(e) {
const li = e.target;
- e.target.classList.add("selected");
this.manager.recipe.addOperation(li.getAttribute("data-name"));
}
@@ -340,6 +339,7 @@ class OperationsWaiter {
this.app.saveFavourites(favouritesList);
this.app.loadFavourites();
this.app.populateOperationsList();
+ this.manager.recipe.updateSelectedOperations();
this.manager.recipe.initialiseOperationDragNDrop();
}
diff --git a/src/web/waiters/RecipeWaiter.mjs b/src/web/waiters/RecipeWaiter.mjs
index 7e29a558..3b957c12 100755
--- a/src/web/waiters/RecipeWaiter.mjs
+++ b/src/web/waiters/RecipeWaiter.mjs
@@ -388,7 +388,8 @@ class RecipeWaiter {
/**
- * Adds the specified operation to the recipe.
+ * Adds the specified operation to the recipe and
+ * adds a checkmark to the operation in Operations op-list
*
* @fires Manager#operationadd
* @param {string} name - The name of the operation to add
@@ -396,6 +397,7 @@ class RecipeWaiter {
*/
addOperation(name) {
const item = document.createElement("li");
+ item.setAttribute("data-name", name);
item.classList.add("operation");
item.innerText = name;
@@ -404,6 +406,8 @@ class RecipeWaiter {
$(item).find("[data-toggle='tooltip']").tooltip();
+ this.updateSelectedOperations();
+
item.dispatchEvent(this.manager.operationadd);
return item;
}
@@ -419,6 +423,7 @@ class RecipeWaiter {
while (recList.firstChild) {
recList.removeChild(recList.firstChild);
}
+ this.clearAllSelectedClasses();
recList.dispatchEvent(this.manager.operationremove);
}
@@ -466,8 +471,8 @@ class RecipeWaiter {
* @param {event} e
*/
opAdd(e) {
- log.debug(`'${e.target.querySelector(".op-title").textContent}' added to recipe`);
-
+ log.debug(`'${e.target.getAttribute("data-name")}' added to recipe`);
+ this.updateSelectedOperations();
this.triggerArgEvents(e.target);
window.dispatchEvent(this.manager.statechange);
}
@@ -482,6 +487,7 @@ class RecipeWaiter {
*/
opRemove(e) {
log.debug("Operation removed from recipe");
+ this.updateSelectedOperations();
window.dispatchEvent(this.manager.statechange);
}
@@ -605,6 +611,70 @@ class RecipeWaiter {
controlsContent.style.transform = `scale(${scale})`;
}
+
+ /**
+ * Remove all "selected" classes for op-list list items at once
+ *
+ * This hides all the checkmark icons of previously added ( selected )
+ * operations to the recipe list
+ */
+ clearAllSelectedClasses(){
+ const list = document.querySelectorAll(".operation.selected");
+
+ // check if any operations are selected at all to prevent errors
+ if (list.length){
+ list.forEach((item) => {
+ item.classList.remove("selected");
+ })
+ }
+ }
+
+ /**
+ * Add "selected" to the operation that is added to the recipe
+ *
+ * This displays a checkmark icon to the operation in the op-list
+ *
+ * @param {string} opDataName the data-name of the target operation
+ */
+ addSelectedClass(opDataName){
+ const list = document.querySelectorAll(".operation");
+ const item = Array.from(list).find((item) => item.getAttribute("data-name") === opDataName );
+
+ item.classList.add("selected");
+ }
+
+ /**
+ * Update which items are selected in op-list.
+ *
+ * First, all selected classes are removed from op-list, then we get the current
+ * recipe-list ingredient names and add 'selected' back to the matching operations.
+ *
+ * Note: It seems a little overkill, but with the current tightly coupled code this is
+ * a reliable way to make sure the 'selected' operations are always in sync with
+ * the recipe list ( I think this is preferable to complicating a lot of existing
+ * code ), I'd recommend to refactor this at one point, but that will mean a huge code
+ * overhaul for another time / issue.
+ */
+ updateSelectedOperations(){
+ let recipeList, operations;
+
+ recipeList = document.querySelectorAll("#rec-list > li");
+ operations = document.querySelectorAll(".operation");
+
+ this.clearAllSelectedClasses();
+
+ if ( recipeList.length ){
+ recipeList.forEach((ingredient) => {
+ const ingredientName = ingredient.getAttribute("data-name");
+
+ operations.forEach((operation) => {
+ if ( ingredientName === operation.getAttribute("data-name")){
+ this.addSelectedClass(ingredientName);
+ }
+ })
+ })
+ }
+ }
}
export default RecipeWaiter;
diff --git a/src/web/waiters/WindowWaiter.mjs b/src/web/waiters/WindowWaiter.mjs
index 29cfbccf..f5d6042c 100755
--- a/src/web/waiters/WindowWaiter.mjs
+++ b/src/web/waiters/WindowWaiter.mjs
@@ -27,16 +27,13 @@ class WindowWaiter {
* continuous resetting).
*/
windowResize() {
- debounce(this.app.adjustComponentSizes, 200, "windowResize", this.app, [])();
-
if ( window.innerWidth >= this.app.breakpoint ) {
- this.app.setDesktopLayout(false);
+ this.app.setDesktopLayout(false); //@TODO: use setDesktopUI() func
} else {
- this.app.setMobileLayout();
+ this.app.setMobileLayout(); //@TODO: use mobileUI() if needed
}
- // we must repopulate the op lists to handle sortable, draggable, popovers etc.
- debounce(this.app.populateOperationsList, 200, "windowResize", this.app, [])();
+ debounce(this.app.adjustComponentSizes, 200, "windowResize", this.app, [])();
}