From 6e0b7927cdee2006c9b2bc55dbd34885b2ae80cc Mon Sep 17 00:00:00 2001
From: anapnoe <124302297+anapnoe@users.noreply.github.com>
Date: Fri, 3 Mar 2023 17:30:42 +0200
Subject: [PATCH] extra networks aside menu alternative
---
html/svg/stack-line.svg | 1 +
javascript/ui.js | 223 +++++++++++++++++++++++-----------------
modules/shared.py | 1 +
modules/ui.py | 1 +
style.css | 127 +++++++++++++++++++++--
5 files changed, 249 insertions(+), 104 deletions(-)
create mode 100644 html/svg/stack-line.svg
diff --git a/html/svg/stack-line.svg b/html/svg/stack-line.svg
new file mode 100644
index 00000000..1bd316f6
--- /dev/null
+++ b/html/svg/stack-line.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/javascript/ui.js b/javascript/ui.js
index 5f7820ea..4cf1cb43 100644
--- a/javascript/ui.js
+++ b/javascript/ui.js
@@ -385,6 +385,59 @@ onUiUpdate(function(){
})
+ let selectedTabItemId = "tab_txt2img";
+ let net_container = gradioApp().querySelector('#txt2img_extra_networks_row');
+ let net_menu_open = false;
+ const net_menu = gradioApp().querySelector('#extra_networks_menu');
+
+ /* switch tab item from instance button, this is the only method that works i havent found a workaround yet */
+ const Observe = (sel, opt, cb) => {
+ const Obs = new MutationObserver((m) => [...m].forEach(cb));
+ gradioApp().querySelectorAll(sel).forEach(el => Obs.observe(el, opt));
+ }
+ Observe("#tabs > div.tabitem", {
+ attributesList: ["style"], attributeOldValue: true, }, (m) => {
+ if(m.target.style.display === 'block'){
+ let idx = parseInt(m.target.getAttribute("tab-item"));
+ selectedTabItemId = m.target.id;
+ tabItemChanged(idx);
+ }
+ })
+
+ function tabItemChanged(idx){
+ gradioApp().querySelectorAll('#tabs > div > button.bg-white, #nav_menu_header_tabs > button.bg-white').forEach(function (tab){
+ tab.classList.remove("bg-white");
+ })
+
+ gradioApp().querySelectorAll('#tabs > div > button:nth-child('+(idx+1)+'), #nav_menu_header_tabs > button:nth-child('+(idx+1)+')').forEach(function (tab){
+ tab.classList.add("bg-white");
+ })
+ //gardio removes listeners and attributes from tab buttons we add them again here
+ gradioApp().querySelectorAll('#tabs > div > button').forEach(function (tab, index){
+ tab.setAttribute("tab-id", index);
+ tab.removeEventListener('mouseup', navTabClicked);
+ tab.addEventListener('mouseup', navTabClicked);
+ })
+
+ netMenuVisibility();
+ }
+
+ function netMenuVisibility(){
+ if(selectedTabItemId.indexOf("2img") != -1){
+ net_menu.style.display = "block";
+ let nid = selectedTabItemId.split("_")[1];
+ net_container = gradioApp().querySelector('#'+nid+'_extra_networks_row');
+ if(net_container.classList.contains("aside")){
+ toggleMenu(net_menu_open, net_menu, net_container, null);
+ net_menu.style.display = "block";
+ }else{
+ net_menu.style.display = "none";
+ }
+ }else{
+ net_menu.style.display = "none";
+ }
+ }
+
// menu
function disableScroll() {
scrollTop = window.pageYOffset || document.documentElement.scrollTop;
@@ -398,8 +451,12 @@ onUiUpdate(function(){
function enableScroll() {
window.onscroll = function() {}
- }
+ }
+ function getPos(el) {
+ let rect=el.getBoundingClientRect();
+ return {x:rect.left,y:rect.top};
+ }
function toggleMenu(isopen, icon, panel, func) {
if(isopen){
@@ -414,27 +471,16 @@ onUiUpdate(function(){
enableScroll();
}
}
-
- function getPos(el) {
- let rect=el.getBoundingClientRect();
- return {x:rect.left,y:rect.top};
- }
-
+
// mobile nav menu
const tabs_menu = gradioApp().querySelector('#tabs > div:first-child');
- const nav_menu = gradioApp().querySelector('#nav_menu');
+ const nav_menu = gradioApp().querySelector('#nav_menu');
const header = gradioApp().querySelector('#header-top');
let menu_open = false;
- let z_menu = nav_menu.cloneNode(true);
-/* let pos = getPos(nav_menu);
- clone.style.position = 'fixed';
- clone.style.left = pos.x+'px';
- clone.style.top = pos.y+'px';
- clone.style.zIndex = 99999; */
+ const z_menu = nav_menu.cloneNode(true);
z_menu.id = "clone_nav_menu";
- header.parentElement.append(z_menu);
- function toggleNavMenu(e) {
- //e.preventDefault();
+ header.parentElement.append(z_menu);
+ function toggleNavMenu(e) {
e.stopPropagation();
menu_open = !menu_open;
toggleMenu(menu_open, nav_menu, tabs_menu, toggleNavMenu);
@@ -458,6 +504,18 @@ onUiUpdate(function(){
}
quick_menu.addEventListener('click', toggleQuickMenu);
+ function toggleNetMenu(e) {
+ net_menu_open = !net_menu_open;
+ e.preventDefault();
+ e.stopPropagation();
+ toggleMenu(net_menu_open, net_menu, net_container, null);
+
+ }
+ net_menu.addEventListener('click', toggleNetMenu);
+ gradioApp().querySelectorAll('button[id$="2img_extra_networks"]').forEach((elem) => {
+ elem.addEventListener('click', toggleNetMenu);
+ })
+
// additional ui styles
let styleobj = {};
@@ -500,7 +558,6 @@ onUiUpdate(function(){
})
viewportOrder(opts.ui_views_order.toLowerCase());
-
// sd max resolution output
function sdMaxOutputResolution(value) {
gradioApp().querySelectorAll('[id$="2img_width"] input,[id$="2img_height"] input').forEach((elem) => {
@@ -514,14 +571,13 @@ onUiUpdate(function(){
})
sdMaxOutputResolution(opts.sd_max_resolution);
-
function extra_networks_visibility(value){
- gradioApp().querySelectorAll('[id$="2img_extra_networks_row"]').forEach((elem) => {
+ gradioApp().querySelectorAll('[id$="2img_extra_networks_row"]').forEach((elem) => {
if(value){
elem.classList.remove("!hidden");
}else{
elem.classList.add("!hidden");
- }
+ }
})
}
gradioApp().querySelector("#setting_extra_networks_default_visibility input").addEventListener('click', function (e) {
@@ -550,8 +606,24 @@ onUiUpdate(function(){
})
})
extra_networks_cards_visible_rows(opts.extra_networks_cards_visible_rows);
+
+ function extra_networks_aside(value){
+ gradioApp().querySelectorAll('[id$="2img_extra_networks_row"]').forEach((elem) => {
+ if(value){
+ elem.classList.add("aside");
+ }else{
+ elem.classList.remove("aside");
+ }
+ netMenuVisibility();
+ })
+ }
+ gradioApp().querySelector("#setting_extra_networks_aside input").addEventListener('click', function (e) {
+ extra_networks_aside(e.target.checked);
+ })
+ extra_networks_aside(opts.extra_networks_aside);
+
- //hidden ui tabs
+ // hidden - header ui tabs
let radio_hidden_html="";
let radio_header_html="";
let hiddentabs={};
@@ -563,8 +635,7 @@ onUiUpdate(function(){
setting_ui_header_tabs.style.display = "none";
const maintabs = gradioApp().querySelectorAll('#tabs > div:first-child > button');
- const tabitem = gradioApp().querySelectorAll('#tabs > div.tabitem');
-
+ const tabitems = gradioApp().querySelectorAll('#tabs > div.tabitem');
function tabOpsSave(setting){
const iEvent = new Event("input");
@@ -584,13 +655,10 @@ onUiUpdate(function(){
styleobj[key] = "#tabs > div:first-child > button:nth-child("+(index+1)+"){display:block;}";
}
})
-
-
+
tabOpsSave(setting_ui_hidden_tabs);
tabsHeaderChange();
-
- }
-
+ }
function tabsHeaderChange() {
const keys = Object.keys(headertabs);
setting_ui_header_tabs.value = "";
@@ -609,39 +677,24 @@ onUiUpdate(function(){
}
- const Observe = (sel, opt, cb) => {
- const Obs = new MutationObserver((m) => [...m].forEach(cb));
- gradioApp().querySelectorAll(sel).forEach(el => Obs.observe(el, opt));
- }
-
- Observe("#tabs > div.tabitem", {
- attributesList: ["style"], attributeOldValue: true, }, (m) => {
- if(m.target.style.display === 'block'){
- let idx = parseInt(m.target.getAttribute("tab-item"));
- tabSelected(idx);
- }
- })
-
- function tabSelected(idx){
-
- gradioApp().querySelectorAll('#tabs > div > button.bg-white, #nav_menu_header_tabs > button.bg-white').forEach(function (tab){
- tab.classList.remove("bg-white");
- })
-
- gradioApp().querySelectorAll('#tabs > div > button:nth-child('+(idx+1)+'), #nav_menu_header_tabs > button:nth-child('+(idx+1)+')').forEach(function (tab){
- tab.classList.add("bg-white");
- })
- }
-
- function navigate2Tab(idx){
+ function navigate2TabItem(idx){
gradioApp().querySelectorAll('#tabs > div.tabitem').forEach(function (tabitem, index){
if(idx == index){
tabitem.style.display = "block";
+ //tabitem.classList.add("wtf");
}else{
tabitem.style.display = "none";
+ //tabitem.classList.remove("wtf");
}
})
}
+
+ function navTabClicked(e){
+ const idx = parseInt(e.currentTarget.getAttribute("tab-id"));
+ console.log(idx);
+ navigate2TabItem(idx);
+ }
+
maintabs.forEach(function (elem, index) {
let tabvalue = elem.innerText.replaceAll(" ", "");
@@ -660,21 +713,17 @@ onUiUpdate(function(){
radio_hidden_html += '';
radio_header_html += '';
- tabitem[index].setAttribute("tab-item", index);
+ tabitems[index].setAttribute("tab-item", index);
+ elem.setAttribute("tab-id", index);
let clonetab = elem.cloneNode(true);
clonetab.id = tabvalue+"_clone";
- parent_header_tabs.append(clonetab);
- clonetab.setAttribute("tab-id", index);
-
- clonetab.addEventListener('click', function (e) {
- const idx = parseInt(e.currentTarget.getAttribute("tab-id"));
- navigate2Tab(idx);
- })
+ parent_header_tabs.append(clonetab);
+ clonetab.addEventListener('click', navTabClicked);
+
})
-
let div = document.createElement("div");
div.id = "hidden_radio_tabs_container";
div.classList.add("flex", "flex-wrap", "gap-2");
@@ -687,7 +736,6 @@ onUiUpdate(function(){
div.innerHTML = radio_header_html;
setting_ui_header_tabs.parentElement.appendChild(div);
-
// hidden tabs
gradioApp().querySelector("#hidden_radio_tabs_container").addEventListener('click', function (e) {
if (e.target && e.target.matches("input[type='checkbox']")) {
@@ -709,7 +757,7 @@ onUiUpdate(function(){
tabsHiddenChange();
- // add to quick settings
+ // add - remove quicksettings
const settings_submit = gradioApp().querySelector('#settings_submit');
const quick_parent = gradioApp().querySelector("#quicksettings_overflow_container");
@@ -752,9 +800,19 @@ onUiUpdate(function(){
})
-
+ // draggable reordable quicksettings
const container = gradioApp().querySelector("#quicksettings_overflow_container");
let draggables;
+ let lastElemAfter;
+ let islastChild;
+ let timeout;
+
+ function preventBehavior(e){
+ e.stopPropagation();
+ e.preventDefault();
+ return false;
+ }
+
// function that gets the element next of cursor/touch
function getElementAfter(container, y){
return draggables.reduce((closest, child) => {
@@ -768,18 +826,6 @@ onUiUpdate(function(){
}, { offset: Number.NEGATIVE_INFINITY } ).element;
}
-
- let lastElemAfter;
- let islastChild;
- let timeout;
-
- function preventBehavior(e){
- e.stopPropagation();
- e.preventDefault();
- return false;
- }
-
-
function dragOrderChange(elementAfter, isComplete, delem) {
if(lastElemAfter !== elementAfter || islastChild){
@@ -832,7 +878,6 @@ onUiUpdate(function(){
let elementAfter = getElementAfter(container, y);
dragOrderChange(elementAfter);
}
-
function touchstart(e){
e.currentTarget.draggable = "false";
let target = e.currentTarget;
@@ -846,8 +891,7 @@ onUiUpdate(function(){
target.addEventListener('touchend', touchend);
target.addEventListener('touchcancel', touchcancel);
- }
-
+ }
function touchend(e){
e.currentTarget.draggable = "true";
clearTimeout(timeout);
@@ -857,7 +901,6 @@ onUiUpdate(function(){
let elementAfter = getElementAfter(container, y);
dragOrderChange(elementAfter, true, e.currentTarget);
}
-
function touchcancel(e){
e.currentTarget.draggable = "true";
clearTimeout(timeout);
@@ -870,7 +913,6 @@ onUiUpdate(function(){
e.currentTarget.draggable = "false";
e.currentTarget.classList.add("dragging");
}
-
function dragend(e){
e.stopPropagation();
e.preventDefault();
@@ -879,7 +921,6 @@ onUiUpdate(function(){
let elementAfter = getElementAfter(container, y);
dragOrderChange(elementAfter, true, e.currentTarget);
}
-
function dragOver(e) {
e.preventDefault();
let y = e.clientY;
@@ -887,10 +928,7 @@ onUiUpdate(function(){
dragOrderChange(elementAfter);
}
-
- function actionQuickSettingsDraggable(checked){
-
-
+ function actionQuickSettingsDraggable(checked){
if(checked){
draggables = Array.from(gradioApp().querySelectorAll('#quicksettings_overflow_container > div:not(.dragging)'));
gradioApp().addEventListener('drop', preventBehavior);
@@ -898,12 +936,8 @@ onUiUpdate(function(){
gradioApp().removeEventListener('drop', preventBehavior);
}
-
gradioApp().querySelectorAll('#quicksettings_overflow_container > div').forEach(function (elem){
-
- //elem.setAttribute("draggable", checked);
elem.draggable = checked;
-
if(checked){
elem.addEventListener('touchstart', touchstart);
@@ -920,12 +954,10 @@ onUiUpdate(function(){
elem.removeEventListener('dragstart', dragstart, false);
elem.removeEventListener('dragend', dragend, false);
elem.removeEventListener('dragover', dragOver, false);
-
}
})
}
-
gradioApp().querySelector('#quicksettings_draggable').addEventListener('click', function (e) {
if (e.target && e.target.matches("input[type='checkbox']")) {
actionQuickSettingsDraggable(e.target.checked);
@@ -933,9 +965,8 @@ onUiUpdate(function(){
})
-
updateOpStyles();
-
+
/* anapnoe ui end */
diff --git a/modules/shared.py b/modules/shared.py
index 5e3de28c..b131faf5 100644
--- a/modules/shared.py
+++ b/modules/shared.py
@@ -445,6 +445,7 @@ options_templates.update(options_section(('extra_networks', "Extra Networks"), {
"extra_networks_default_visibility": OptionInfo(True, "Extra Networks default visibility"),
"extra_networks_cards_size": OptionInfo(1, "Card size for extra networks", gr.Slider, {"minimum": 0.8, "maximum": 2, "step": 0.1}),
"extra_networks_cards_visible_rows": OptionInfo(1, "Visible card rows for extra networks", gr.Slider, {"minimum": 1, "maximum": 3, "step": 1}),
+ "extra_networks_aside": OptionInfo(True, "Extra Networks aside view"),
}))
diff --git a/modules/ui.py b/modules/ui.py
index 8d1a5416..e5a6d53d 100644
--- a/modules/ui.py
+++ b/modules/ui.py
@@ -1733,6 +1733,7 @@ def create_ui():
component = create_setting_component(k, item.section[0], is_quicksettings=True)
component_dict[k] = component
+ gr.Row(elem_id="extra_networks_menu")
gr.Row(elem_id="quick_menu")
parameters_copypaste.connect_paste_params_buttons()
diff --git a/style.css b/style.css
index 465d3e68..fbeddae3 100644
--- a/style.css
+++ b/style.css
@@ -14,6 +14,7 @@ License: GNU General Public License
--extra-networks-height: calc((var(--extra-networks-card-real-size) * var(--extra-networks-visible-rows)) + ( var(--inside-padding-size) * 2 ) );
--extra-networks-name-size: calc(var(--extra-networks-card-size) * 1em);
+ --top-header-padding-top:1rem;
--top-header-height:60px;
@@ -47,6 +48,7 @@ body {
/* padding: 10px; */
padding-left: 1rem;
padding-right: 1rem;
+ padding-top: var(--top-header-padding-top);
}
@@ -73,6 +75,7 @@ body {
right: 0;
}
+#extra_networks_menu,
#quick_menu {
z-index: 9999;
background-color: var(--input-bg-color);
@@ -441,8 +444,8 @@ body {
[id$="2img_extra_networks"]::before
{
- -webkit-mask: url(./file=html/svg/pantone-line.svg) no-repeat 50% 50%;
- mask: url(./file=html/svg/pantone-line.svg) no-repeat 50% 50%;
+ -webkit-mask: url(./file=html/svg/stack-line.svg) no-repeat 50% 50%;
+ mask: url(./file=html/svg/stack-line.svg) no-repeat 50% 50%;
}
#img2img_actions_column [id$="interrogate"]::before
@@ -514,9 +517,15 @@ body {
-
-
-
+/*
+.tabitem.wtf
+{
+ display:block !important;
+}
+.tabitem:not(.wtf){
+ display:none !important;
+}
+*/
.livePreview > img,
#img2img_gallery .overflow-y-auto,
@@ -716,7 +725,7 @@ body {
position:fixed;
z-index:10000;
left:1rem;
- top: calc((var(--top-header-height) - 38px) / 2);
+ top: calc((var(--top-header-padding-top) + var(--top-header-height) - 38px) / 2);
}
/* offcanvas quicksettings menu */
@@ -779,7 +788,7 @@ min-height: 34px;
}
-
+#extra_networks_menu::before,
#quick_menu::before {
content: ' ';
display: inline-block;
@@ -797,10 +806,17 @@ min-height: 34px;
transform: translate(-50%, -50%) scale(1.0);
}
-
+#extra_networks_menu::before{
+ -webkit-mask: url(./file=html/svg/stack-line.svg) no-repeat 50% 50%;
+ mask: url(./file=html/svg/stack-line.svg) no-repeat 50% 50%;
+}
+#extra_networks_menu.fixed,
+#extra_networks_menu:hover,
#quick_menu:hover {
background-color: var(--primary-color);
}
+#extra_networks_menu.fixed::before,
+#extra_networks_menu:hover::before,
#quick_menu:hover::before {
background-color: var(--main-bg-color);
}
@@ -2295,6 +2311,89 @@ ul.list-none {
/******************/
/* extra-network-cards */
/******************/
+/*
+#quicksettings_overflow {
+ position: fixed;
+ z-index: 9999;
+ display: block;
+ width: 90%;
+ background-color: var(--main-bg-color) !important;
+ top: var(--top-header-height);
+ bottom: 0px;
+ padding: 16px;
+
+ right: 0;
+ max-width: 480px;
+ transform: translateX(100%);
+ transition: all 0.25s ease 0s;
+ box-shadow: rgba(0,0,0,0) -30px 0 30px -30px;
+ overflow: hidden;
+
+}
+
+#quicksettings_overflow_container {
+ overflow-y: auto;
+ height: calc(100% - 45px);
+}
+
+#quicksettings_overflow.open {
+ transform: translateX(0);
+ box-shadow: rgba(0,0,0,0.4) -30px 0 30px -30px;
+}
+
+#quicksettings_overflow > div {
+ margin-bottom: var(--outside-gap-size);
+}
+*/
+
+[id$="2img_extra_networks_row"].aside
+{
+ position: fixed;
+ top: var(--top-header-height);
+ width: 90%;
+ right: 0;
+ height: calc(100% - var(--top-header-height));
+ max-width: 480px;
+ z-index: 9999;
+ transform: translateX(100%);
+ transition: all 0.25s ease 0s;
+ box-shadow: rgba(0,0,0,0) -30px 0 30px -30px;
+ padding: calc(1rem - var(--outside-gap-size));
+ background-color: var(--main-bg-color) !important;
+}
+
+[id$="2img_extra_networks_row"].aside.open
+{
+ transform: translateX(0);
+ box-shadow: rgba(0,0,0,0.4) -30px 0 30px -30px;
+}
+
+
+
+[id$="2img_extra_networks_row"].aside > div:first-child
+{
+ border: 0 !important;
+}
+
+[id$="2img_extra_networks_row"].aside > div:first-child > div:first-child
+{
+ display: none;
+ border: 0;
+}
+[id$="2img_extra_networks_row"].aside.\!hidden,
+[id$="2img_extra_networks_row"].aside > div:first-child > div:last-child
+{
+ display: block !important;
+}
+[id$="2img_extra_close"]{
+ display:none;
+}
+
+[id$="2img_checkpoints_subdirs"] button{
+ max-height:34px;
+ margin-bottom: var(--inside-padding-size);
+}
+
.extra-network-cards .nocards,
.extra-network-thumbs .nocards {
@@ -2362,6 +2461,18 @@ ul.list-none {
scroll-snap-type: x mandatory;
}
+[id$="2img_extra_networks_row"].aside .extra-network-cards
+{
+ /*grid-template-columns: repeat(auto-fill, var(--extra-networks-card-real-size)); */
+ /*grid-template-columns: repeat(calc( var(--extra-networks-card-size) * 4), calc( var(--extra-networks-card-size) * 25%));*/
+ grid-template-columns: repeat(auto-fit, minmax(calc(var(--extra-networks-card-size) * 25%), 1fr));
+ overflow-y: auto;
+ scroll-snap-type: y mandatory;
+ overflow-x: hidden;
+ grid-template-rows: auto;
+ grid-auto-flow: row;
+ max-height: calc(100vh - 216px);
+}
.extra-network-cards .card {