diff --git a/src/web/App.mjs b/src/web/App.mjs index e84363f8..6696d5f7 100644 --- a/src/web/App.mjs +++ b/src/web/App.mjs @@ -66,6 +66,8 @@ class App { setup() { document.dispatchEvent(this.manager.appstart); + // Splitters are created for desktop; ResponsiveLayoutWaiter destroys them + // immediately when the container is phone/tablet sized. this.initialiseSplitter(); this.loadLocalStorage(); this.manager.options.applyPreferredColorScheme(); @@ -309,14 +311,47 @@ class App { } + /** + * Destroys Split.js instances and removes leftover gutters. + * Used when switching to mobile/tablet layouts. + */ + destroySplitters() { + if (this.columnSplitter) { + this.columnSplitter.destroy(); + this.columnSplitter = null; + } + if (this.ioSplitter) { + this.ioSplitter.destroy(); + this.ioSplitter = null; + } + + document.querySelectorAll("#workspace-wrapper > .gutter, #IO > .gutter").forEach(g => g.remove()); + + // Clear inline sizes Split.js may have left behind + ["operations", "recipe", "IO", "input", "output"].forEach(id => { + const el = document.getElementById(id); + if (el) { + el.style.width = ""; + el.style.height = ""; + el.style.flex = ""; + } + }); + } + + /** * Sets up the adjustable splitter to allow the user to resize areas of the page. * * @param {boolean} [minimise=false] - Set this flag if attempting to minimise frames to 0 width */ initialiseSplitter(minimise=false) { - if (this.columnSplitter) this.columnSplitter.destroy(); - if (this.ioSplitter) this.ioSplitter.destroy(); + this.destroySplitters(); + + // Do not create splitters while in a touch layout — CSS owns the layout. + if (this.manager.responsive && this.manager.responsive.isTouchLayout()) { + this.adjustComponentSizes(); + return; + } this.columnSplitter = Split(["#operations", "#recipe", "#IO"], { sizes: [20, 30, 50], @@ -629,6 +664,10 @@ class App { * Resets the splitter positions to default. */ resetLayout() { + if (!this.columnSplitter || !this.ioSplitter) { + this.adjustComponentSizes(); + return; + } this.columnSplitter.setSizes([20, 30, 50]); this.ioSplitter.setSizes([50, 50]); this.adjustComponentSizes(); diff --git a/src/web/HTMLOperation.mjs b/src/web/HTMLOperation.mjs index 0ba0ffc8..e703c343 100755 --- a/src/web/HTMLOperation.mjs +++ b/src/web/HTMLOperation.mjs @@ -90,6 +90,8 @@ class HTMLOperation { html += `
+ arrow_upward + arrow_downward pause not_interested keyboard_arrow_up diff --git a/src/web/Manager.mjs b/src/web/Manager.mjs index 7cde638d..5ed28df6 100755 --- a/src/web/Manager.mjs +++ b/src/web/Manager.mjs @@ -18,6 +18,7 @@ import BindingsWaiter from "./waiters/BindingsWaiter.mjs"; import BackgroundWorkerWaiter from "./waiters/BackgroundWorkerWaiter.mjs"; import TabWaiter from "./waiters/TabWaiter.mjs"; import TimingWaiter from "./waiters/TimingWaiter.mjs"; +import ResponsiveLayoutWaiter from "./waiters/ResponsiveLayoutWaiter.mjs"; /** @@ -74,6 +75,7 @@ class Manager { this.seasonal = new SeasonalWaiter(this.app, this); this.bindings = new BindingsWaiter(this.app, this); this.background = new BackgroundWorkerWaiter(this.app, this); + this.responsive = new ResponsiveLayoutWaiter(this.app, this); // Object to store dynamic handlers to fire on elements that may not exist yet this.dynamicHandlers = {}; @@ -95,6 +97,7 @@ class Manager { this.bindings.updateKeybList(); this.background.registerChefWorker(); this.seasonal.load(); + this.responsive.setup(); this.confirmWaitersLoaded(); } @@ -148,6 +151,7 @@ class Manager { // Operations this.addMultiEventListener("#search", "keyup paste search", this.ops.searchOperations, this.ops); this.addDynamicListener(".op-list li.operation", "dblclick", this.ops.operationDblclick, this.ops); + this.addDynamicListener(".op-list li.operation", "click", this.ops.operationClick, this.ops); document.getElementById("edit-favourites").addEventListener("click", this.ops.editFavouritesClick.bind(this.ops)); document.getElementById("save-favourites").addEventListener("click", this.ops.saveFavouritesClick.bind(this.ops)); document.getElementById("reset-favourites").addEventListener("click", this.ops.resetFavouritesClick.bind(this.ops)); @@ -160,6 +164,8 @@ class Manager { this.addDynamicListener(".hide-args-icon", "click", this.recipe.hideArgsClick, this.recipe); this.addDynamicListener(".disable-icon", "click", this.recipe.disableClick, this.recipe); this.addDynamicListener(".breakpoint", "click", this.recipe.breakpointClick, this.recipe); + this.addDynamicListener(".op-reorder-up", "click", this.recipe.moveOpUp, this.recipe); + this.addDynamicListener(".op-reorder-down", "click", this.recipe.moveOpDown, this.recipe); this.addDynamicListener("#rec-list li.operation", "dblclick", this.recipe.operationDblclick, this.recipe); this.addDynamicListener("#rec-list li.operation > div", "dblclick", this.recipe.operationChildDblclick, this.recipe); this.addDynamicListener("#rec-list .dropdown-menu.toggle-dropdown a", "click", this.recipe.dropdownToggleClick, this.recipe); diff --git a/src/web/html/index.html b/src/web/html/index.html index 6ce8dd9a..0f53da2d 100755 --- a/src/web/html/index.html +++ b/src/web/html/index.html @@ -24,6 +24,7 @@ CyberChef + @@ -145,7 +146,10 @@ -
+
+
-
+