- Changed the resize system of the n-sidebar (it can now be resized directly from its sides NOTE: the top side wilL only move the bar)

- Added the ability to directly download CIVITAI models into chosen folders (this includes Checkpoint, Textual Inversion, Hypernetwork, Aesthetic Gradient, LORA, LoCon, DoRA, Controlnet, Upscaler, Motion Module, VAE, Poses, Wildcards, Workflows). [More Info](#assets-downloader).
  - Added the ability to import/export your settings.
  - EXPERIMENTAL: You can now embed ComfyUI's native bar within the n-sidebar
  - EXPERIMENTAL: Added a small console (useful if you don’t have direct access to the machine). If you want to remove this feature, simply delete the `terminal` folder within `ComfyUI-N-Sidebar/app/panels`
  - EXPERIMENTAL: Added the ability to edit the layout of the bar, this functionality is highly unstable and its use may lead to unexpected behaviors
  - Redesigned configuration menu
  - Fixed some bugs
This commit is contained in:
nuked88
2024-09-04 16:10:41 +02:00
parent 563f49c8e2
commit 2c08bb7617
33 changed files with 5474 additions and 826 deletions
Vendored
BIN
View File
Binary file not shown.
+2 -1
View File
@@ -1,7 +1,8 @@
# Config file
app/settings.json
app/settings.json.bak
app/views/views_backup.json
metadata/*
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
+22 -2
View File
@@ -10,8 +10,19 @@ A simple sidebar for ComfyUI.
For what i know nobody did it, so i did it.
Maybe you don't need it. I need it >.<
# Updates
- 04-09-2024
- Changed the resize system of the n-sidebar (it can now be resized directly from its sides NOTE: the top side wilL only move the bar)
- Added the ability to directly download CIVITAI models into chosen folders (this includes Checkpoint, Textual Inversion, Hypernetwork, Aesthetic Gradient, LORA, LoCon, DoRA, Controlnet, Upscaler, Motion Module, VAE, Poses, Wildcards, Workflows). [More Info](#assets-downloader).
- Added the ability to import/export your settings.
- EXPERIMENTAL: You can now embed ComfyUI's native bar within the n-sidebar
- EXPERIMENTAL: Added a small console (useful if you don’t have direct access to the machine). If you want to remove this feature, simply delete the `terminal` folder within `ComfyUI-N-Sidebar/app/panels`
- EXPERIMENTAL: Added the ability to edit the layout of the bar, this functionality is highly unstable and its use may lead to unexpected behaviors
- Redesigned configuration menu
- Fixed some bugs
- 01-08-2024
- A lot of people are having trouble with the CSS class change in the last update because of a browser cache issue: the old CSS file keeps loading from disk instead of the new one with the latest changes (thanks, modern browsers!). To fix this, I've changed the name of the CSS file, which SHOULD force browsers to load the new one. If this doesn't fix the issue, I'm not sure what will 😭.
- Added the new option `Show at Startup` in the settings. This lets you have the sidebar open at startup (if it's not in fixed mode).
@@ -171,7 +182,16 @@ This feature is enabled by default, you can disable it in the settings. I've use
### 🎨 New Settings Panel 🎨
![ComfyUI Settings](./images/settings.png)
PS: Workflow Path
### ASSETS DOWNLOADER
![ComfyUI Assets](./images/assets.gif)
This new panel allows you to download CIVITAI models (Checkpoint, TextualInversion, Hypernetwork, AestheticGradient, LORA, LoCon, DoRA, Controlnet, Upscaler, MotionModule, VAE, Poses, Wildcards, Workflows).
The various models will be downloaded into the folders set in the settings.
There is also the option to rebuild the "My Library" section (the dots at the top right corner):
once the reference folders are set in the settings, by launching the rebuild, the already existing models will be identified and added to the library (if they exist in the CivitAI database).
NOTE: you can set your own API key for models that are not publicly available.
@@ -184,8 +204,8 @@ PS: Workflow Path
- [x] Custom Categories!!
- [x] Workflows
- [x] Templates
- [x] Export and Import Settings
- [ ] Custom Shortcuts
- [ ] Export and Import Settings
- [ ] Touch Support
+1121 -12
View File
File diff suppressed because it is too large Load Diff
BIN
View File
Binary file not shown.
+555 -44
View File
@@ -5,6 +5,11 @@
z-index: 100 !important;
}
:root {
--n-sidebar-width: 30px;
--sidebar-menu-item-width: 24px;
--main-menubar-height:35px;
}
.sidebar {
position: absolute;
@@ -21,11 +26,16 @@
user-select: none;
box-sizing: content-box;
display: flex;
flex-direction: row;
justify-content: space-around;
align-items: flex-start;
}
sidebar * {
box-sizing: revert; /* o qualsiasi valore tu voglia usare */
box-sizing: revert;
}
.sidebar ul {
@@ -45,6 +55,7 @@
cursor: pointer;
user-select: none;
color: var(--input-text);
margin-left: 4px;
}
.content_sidebar {
@@ -56,20 +67,43 @@
float: left;
backdrop-filter: blur(5px);
width: calc(100% - 45px);
}
.dragHandle {
position: relative;
float: left;
right: 0;
right: 5;
top: 0;
height: 100%;
width: 5px;
cursor: ew-resize;
background: rgb(62, 62, 62);
background: linear-gradient(90deg, rgb(62 62 62 / 46%) 0%, rgb(39 39 39 / 47%) 50%, rgb(28 28 28 / 31%) 100%);
background: rgb(119 111 111 / 0%);
/*background: linear-gradient(90deg, rgb(62 62 62 / 46%) 0%, rgb(39 39 39 / 47%) 50%, rgb(28 28 28 / 31%) 100%);*/
}
.dragHandleTB {
background: #ffffff00;
height: 10px;
width: calc(100% - 10px);
position: absolute;
cursor: n-resize;
}
#dragHandleV {
bottom: -5px;
}
#dragHandleT {
top: 15px;
z-index: 999999;
}
#searchInputSB {
box-sizing: border-box;
width: 100%;
@@ -88,10 +122,12 @@
width: calc(100% - 75px);
margin-top: 5px;
margin-bottom: 10px;
margin-left: 44px;
margin-left: var(--n-sidebar-width);
z-index: 400;
width: calc(100% - 60px);
margin-top: 5px;
left: 11px;
}
.clearIcon, .searchCategoryIcon, .clearIconCustomCategory, .searchCategoryIconCustomCategory, .clearIconCustomTemplate, .searchTemplateIconCustomTemplate, .clearIconCustomWorkflow, .searchWorkflowIconCustomWorkflow {
@@ -99,12 +135,21 @@
padding: 5px;
right: 30px;
color: var(--input-text);
font-size: x-large;
font-size: larger;
cursor: pointer;
opacity: 0.5;
user-select: none;
line-height: 1.4;
line-height: 1.6;
top: 0;
display: flex;
align-content: center;
justify-content: center;
align-items: center;
height: -moz-available; /* WebKit-based browsers will ignore this. */
height: -webkit-fill-available; /* Mozilla-based browsers will ignore this. */
height: fill-available;
}
@@ -112,21 +157,31 @@
opacity: 1.0;
}
.clearIcon,.clearIconCustomTemplate,.clearIconCustomWorkflow {
line-height: 1.25 !important
line-height: 1.6 !important
}
.searchCategoryIcon, .searchCategoryIconCustomCategory, .searchTemplateIconCustomTemplate, .searchWorkflowIconCustomWorkflow {
right: 0px;
padding: 3px;
padding: 6px;
font-size: larger;
background: var(--border-color);
color: var(--drag-text);
margin: 4px;
border-radius: 5px;
width: 18px;
text-align: center;
top: 0;
box-sizing: content-box;
/* text-align: center; */
height: -moz-available; /* WebKit-based browsers will ignore this. */
height: -webkit-fill-available; /* Mozilla-based browsers will ignore this. */
height: fill-available;
/* top: 0; */
/* box-sizing: content-box; */
display: flex;
align-content: center;
justify-content: center;
line-height: 1;
align-items: center;
}
@@ -200,29 +255,46 @@
width: 100%;
text-overflow: ellipsis;
overflow: hidden;
overflow: hidden;
}
/* Firefox-specific styles */
@-moz-document url-prefix() {
.content_sidebar,#settingsContainer {
scrollbar-width: thin; /* Scrollbar thickness */
scrollbar-color: hsla(0, 0%, 50%, .8) transparent; /* Thumb and track colors */
}
#settingsContainer::-moz-scrollbar-thumb:hover,
.content_sidebar::-moz-scrollbar-thumb:hover {
background-color: rgba(150, 150, 150, 1); /* Thumb color on hover */
}
#settingsContainer::-moz-scrollbar-thumb,
.content_sidebar::-moz-scrollbar-thumb {
background-color: hsla(0, 0%, 50%, .8); /* Thumb color */
border-radius: 9px;
}
}
#settingsContainer::-webkit-scrollbar,
.content_sidebar::-webkit-scrollbar {
margin-top: 0.5rem;
height: 1rem;
width: .5rem;
top: 10px;
}
#settingsContainer::-webkit-scrollbar:horizontal,
.content_sidebar::-webkit-scrollbar:horizontal {
height: .5rem;
width: 1rem
}
#settingsContainer::-webkit-scrollbar-track,
.content_sidebar::-webkit-scrollbar-track {
background-color: transparent;
background-color: transparent !important;
border-radius: 9999px
}
#settingsContainer::-webkit-scrollbar-thumb,
.content_sidebar::-webkit-scrollbar-thumb {
--tw-border-opacity: 1;
background-color: hsla(0, 0%, 50%, .8);
@@ -231,6 +303,7 @@
border-width: 1px
}
#settingsContainer::-webkit-scrollbar-thumb:hover,
.content_sidebar::-webkit-scrollbar-thumb:hover {
--tw-bg-opacity: 1;
@@ -247,19 +320,32 @@
float: unset;
cursor: pointer;
user-select: none;
padding: 5px;
padding: 5px 0 5px;
font-size: 20px;
background-color: var(--comfy-input-bg);
/*background-color: var(--comfy-input-bg);*/
opacity: 0.7;
border-radius: 5px;
/*border-radius: 5px;*/
margin-top:2px;
box-sizing: content-box;
display: flex;
justify-content: center;
align-items: center;
height: var(--sidebar-menu-item-width);
/*border-right: 2px solid var(--content-bg);*/
border-color: var(--content-bg);
}
.view_button:hover {
opacity: 1.0;
}
.sb_button_active {
border-color: var(--content-hover-fg);
color: var(--content-hover-fg);
}
#sidebar_views {
position: relative;
float: left;
@@ -269,16 +355,16 @@
user-select: none;
padding: 0px 2px 2px 2px;
font-size: 20px;
border-bottom-right-radius: 5px;
border-top-right-radius: 5px;
height: 100%;
width: 30px;
width: var(--n-sidebar-width);
border: 0;
border-left: 2px rgb(from var(--comfy-menu-bg) r g b / 100%);
border-style: solid;
padding-bottom: 0px;
backdrop-filter: blur(16px) !important;
background: rgb(from var(--comfy-menu-bg) r g b / 100%);
z-index: 99999;
}
@@ -364,11 +450,14 @@
#sidebarBookmarks .sidebarItem {
margin-left: 10px;
margin-right: 29px;
margin-left: 0px;
margin-right: 0px;
}
#sidebarBookmarks {
width: calc(100% - 16px);
margin-left: 3px;
}
.sb_label {
font-family: 'Open Sans', sans-serif;
position: relative;
@@ -380,14 +469,20 @@
padding-left: 6px;
padding-right: 6px;
display: block;
display: flex;
width: calc(100% - 20px);
text-align: center;
user-select: none;
cursor: pointer;
align-items: center;
height: 28px;
justify-content: center;
padding-top: 1px;
}
.expand_node, .pin_node {
position: absolute;
position: absolute !important;
right: 5px;
background: transparent;
border: 0;
@@ -497,9 +592,9 @@
display: grid;
grid-column-gap: 10px;
/* Spazio tra le colonne */
width: 100%;
/* Imposta la larghezza della tabella al 100% del contenitore */
}
.sb_row {
@@ -661,13 +756,16 @@
#switch_settings{
bottom: 5px;
position: absolute;
width: 19px;
width: -moz-available; /* WebKit-based browsers will ignore this. */
width: -webkit-fill-available; /* Mozilla-based browsers will ignore this. */
width: fill-available;
height: 20px;
border: 0 !important;
line-height: 1;
box-sizing: content-box;
}
#sb_settingsDiv{
#sb_settingsDiv,#sb_settingsDiv_export, #sb_settingsDiv_import {
outline: 0;
border: 0;
border-radius: 6px;
@@ -675,6 +773,7 @@
color: var(--input-text);
box-shadow: inset 1px 1px 0px rgba(255, 255, 255, 0.05), inset -1px -1px 0px rgba(0, 0, 0, 0.5), 2px 2px 20px rgb(0, 0, 0);
max-width: 800px;
width: 650px;
box-sizing: border-box;
font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
font-size: 0.8rem;
@@ -687,9 +786,13 @@
text-transform: uppercase;
font-weight: bold;
}
#sb_settingsDiv_export, #sb_settingsDiv_import {
z-index: 1005;
width: 30vh;
}
#sb_settingsDiv .setting{
height: 28px;
width: 450px;
width: 100%;
margin-bottom: 7px;
}
#sb_settingsDiv .setting input[type="range"]{
@@ -702,8 +805,8 @@
color: var(--drag-text);
padding: 5px;
float: right;
width: 129px;
margin-right: 47px;
width: 60%;
margin-right: 0px;
border-radius: 5px;
border: solid 1px var(--descrip-text);
}
@@ -717,12 +820,16 @@
margin-right: 47px;
border-radius: 5px;
border: solid 1px var(--descrip-text);
margin-bottom: 20px;
}
#sb_settingsDiv .setting input[type="checkbox"]{
#sb_settingsDiv .setting input[type="checkbox"], #sb_settingsDiv_export .setting input[type="checkbox"], #sb_settingsDiv_import .setting input[type="checkbox"]{
width: 18px;
height: 18px;
}
#sb_settingsDiv .setting input{
#sb_settingsDiv_export .setting, #sb_settingsDiv_import .setting{
height: 36px;
}
#sb_settingsDiv .setting input, #sb_settingsDiv_export .setting input , #sb_settingsDiv_import .setting input{
float: right;
}
#sb_settingsDiv .setting label{
@@ -738,7 +845,12 @@
margin: 5px auto;
}
#sb_settingsDiv h1{
#sb_settingsDiv_export h1, #sb_settingsDiv_import h1{
font-size: medium;
}
#sb_settingsDiv h1,#sb_settingsDiv_export h1, #sb_settingsDiv_import h1{
margin: 0 0 20px 0;
padding: 0 0 5px 0;
text-align: center;
@@ -746,7 +858,7 @@
text-transform: uppercase;
}
#sb_settingsDiv button{
#settingsContainer button{
padding: 9px;
/* position: absolute; */
@@ -761,9 +873,53 @@
text-transform: uppercase;
font-weight: bold;
}
#sb_settingsDiv button:hover{
#settingsContainer button:hover{
filter: brightness(120%);
}
#settingsContainer{
height: 50vh;
overflow-x: hidden;
overflow-y: auto;
margin-right: -10px;
padding-right: 10px;
}
#sb_buttonsContainer {
display: grid;
grid-template-columns: repeat(2, 1fr); /* Due colonne, larghezza uguale */
grid-template-rows: auto; /* Le righe si adattano all'altezza degli elementi */
gap: 5px; /* Spaziatura tra i bottoni */
width: 100%; /* Si adatta alla larghezza del contenitore padre */
margin-bottom: 8px;
}
#sb_buttonsContainer button, #sb_buttonsContainerCustomize button {
padding: 9px;
width: 100%; /* Il bottone si adatta alla colonna */
background: var(--comfy-menu-bg);
color: var(--input-text);
border: 1px solid var(--border-color);
margin: 0 0 0px 0;
border-radius: 5px;
cursor: pointer;
text-transform: uppercase;
font-weight: bold;
box-sizing: border-box; /* Include il padding e il bordo nel calcolo della larghezza */
}
#sb_buttonsContainer #sb_runExportButton{
width: 200%;
}
#sb_buttonsContainerCustomize{
display: grid;
grid-template-columns: repeat(3, 1fr); /* Due colonne, larghezza uguale */
grid-template-rows: auto; /* Le righe si adattano all'altezza degli elementi */
gap: 5px; /* Spaziatura tra i bottoni */
width: 100%; /* Si adatta alla larghezza del contenitore padre */
margin-bottom: 8px;
}
#sb_settingsDiv i{
margin-left: 4px;
@@ -772,6 +928,12 @@
font-size: larger;
}
.remove-section-btn{
padding: 5px;
position: static;
float: right;
right: 25px;
}
/* MODALS */
.sb-modal-title{
position: absolute;
@@ -818,11 +980,11 @@
#switch_home,#switch_custom_view{
/*#switch_home,#switch_custom_view{
width: 1.3rem;
height: 1.3rem;
}
}*/
#switch_sidebar{
@@ -832,4 +994,353 @@
#sbModal{
display: none;
z-index: 9999;
}
.full_rounded{
border-radius: 5px;
}
.p-button {
overflow: visible !important;
}
/*************/
/*ALPHA: INGLOBE SIDEBAR */
.splitter-overlay{
/*width: 486px !important;*/
z-index: 100 !important;
}
#official_button{
display: flex;
flex-direction: column;
position: absolute;
height: auto;
bottom: 50%;
}
#official_button button{
width: var(--n-sidebar-width);
height: var(--n-sidebar-width);
}
#official_button i {
font-size: 20px !important;
}
/* setup tooltips */
#openModalButton{
z-index: 1000 !important;
}
[data-tooltip] {
--arrow-size: 5px;
position: relative;
/*z-index: 10;*/
}
/* Positioning and visibility settings of the tooltip */
[data-tooltip]:before,
[data-tooltip]:after {
position: absolute;
visibility: hidden;
opacity: 0;
left: 50%;
bottom: calc(100% + var(--arrow-size));
pointer-events: none;
transition: 0.2s;
will-change: transform;
}
/* The actual tooltip with a dynamic width */
[data-tooltip]:before {
content: attr(data-tooltip);
padding: 10px 18px;
min-width: 50px;
max-width: 350px;
width: max-content;
width: -moz-max-content;
border-radius: 6px;
font-size: 14px;
background-color: var(--border-color);;
background-image: linear-gradient(30deg,
rgba(59, 72, 80, 0.44),
rgba(59, 68, 75, 0.44),
rgba(60, 82, 88, 0.44));
box-shadow: 0px 0px 24px rgba(0, 0, 0, 0.2);
color: #fff;
white-space: pre-wrap;
transform: translate(-50%, calc(0px - var(--arrow-size))) scale(0.5);
z-index: 10;
}
/* Tooltip arrow */
[data-tooltip]:after {
content: '';
border-style: solid;
border-width: var(--arrow-size) var(--arrow-size) 0px var(--arrow-size); /* CSS triangle */
border-color: var(--border-color) transparent transparent transparent;
transition-duration: 0s; /* If the mouse leaves the element,
the transition effects for the
tooltip arrow are "turned off" */
transform-origin: top; /* Orientation setting for the
slide-down effect */
transform: translateX(-50%) scaleY(0);
}
/* Tooltip becomes visible at hover */
[data-tooltip]:hover:before,
[data-tooltip]:hover:after {
visibility: visible;
opacity: 1;
}
/* Scales from 0.5 to 1 -> grow effect */
[data-tooltip]:hover:before {
transition-delay: 0.8s;
transform: translate(-50%, calc(0px - var(--arrow-size))) scale(1);
}
/*
Arrow slide down effect only on mouseenter (NOT on mouseleave)
*/
[data-tooltip]:hover:after {
transition-delay: 0.8s; /* Starting after the grow effect */
transition-duration: 0.2s;
transform: translateX(-50%) scaleY(1);
}
/*
That's it for the basic tooltip.
If you want some adjustability
here are some orientation settings you can use:
*/
/* LEFT */
/* Tooltip + arrow */
.left:before,
.left:after {
left: auto;
right: calc(100% + var(--arrow-size));
bottom: 50%;
}
/* Tooltip */
.left:before {
transform: translate(calc(0px - var(--arrow-size)), 50%) scale(0.5);
}
.left:hover:before {
transform: translate(calc(0px - var(--arrow-size)), 50%) scale(1);
}
/* Arrow */
.left:after {
border-width: var(--arrow-size) 0px var(--arrow-size) var(--arrow-size);
border-color: transparent transparent transparent var(--border-color);;
transform-origin: left;
transform: translateY(50%) scaleX(0);
}
.left:hover:after {
transform: translateY(50%) scaleX(1);
}
/* RIGHT */
.right:before,
.right:after {
left: calc(100% + var(--arrow-size));
bottom: 50%;
}
.right:before {
transform: translate(var(--arrow-size), 50%) scale(0.5);
}
.right:hover:before {
transform: translate(var(--arrow-size), 50%) scale(1);
}
.right:after {
border-width: var(--arrow-size) var(--arrow-size) var(--arrow-size) 0px;
border-color: transparent var(--border-color) transparent transparent;
transform-origin: right;
transform: translateY(50%) scaleX(0);
}
.right:hover:after {
transform: translateY(50%) scaleX(1);
}
/* BOTTOM */
[data-tooltip-location="bottom"]:before,
[data-tooltip-location="bottom"]:after {
top: calc(100% + var(--arrow-size));
bottom: auto;
}
[data-tooltip-location="bottom"]:before {
transform: translate(-50%, var(--arrow-size)) scale(0.5);
}
[data-tooltip-location="bottom"]:hover:before {
transform: translate(-50%, var(--arrow-size)) scale(1);
}
[data-tooltip-location="bottom"]:after {
border-width: 0px var(--arrow-size) var(--arrow-size) var(--arrow-size);
border-color: transparent transparent var(--border-color) transparent;
transform-origin: bottom;
}
/* Settings that make the pen look nicer */
@keyframes moveFocus {
0% { background-position: 0% 100% }
100% { background-position: 100% 0% }
}
@media (max-height: 450px) {
main {
margin: 2rem 0;
}
}
@media (max-width: 800px) {
html {
font-size: 0.9em;
}
}
/*SETTINGS TAB&CUSTOMIZE*/
.n-sb-tab-container {
margin-bottom: 1rem;
display: grid;
grid-template-columns: repeat(2, 1fr);
grid-template-rows: auto;
gap: 5px;
width: 100%;
margin-bottom: 8px;
}
.n-sb-tab {
padding: 10px 20px;
cursor: pointer;
margin-right: 5px;
border-bottom: 3px solid rgb(255, 255, 255);
text-align: center;
}
.n-sb-tab.n-sb-active {
border-color: #0075ff;
}
.n-sb-tab-content {
display: none;
height: 50vh;
overflow-y: auto;
}
.n-sb-active {
display: block !important;
}
.sb_hidden {
display: none;
}
.n-sb-tab-container .n-sb-tab {
padding: 9px;
width: 100%;
color: var(--input-text);
margin: 0 0 0px 0;
cursor: pointer;
text-transform: uppercase;
font-weight: bold;
box-sizing: border-box;
font-size: medium;
}
.n-sb-section {
display: flex;
flex-direction: column;
margin-bottom: 20px;
padding: 10px;
border-radius: 5px;
background-color: var(--comfy-menu-bg);
}
.n-sb-section-header {
display: flex;
align-items: center;
margin-bottom: 10px;
}
.n-sb-section-header input {
margin-left: 10px;
height: 23px;
}
.n-sb-section-panels {
margin-bottom: 10px;
}
.n-sb-section-panels .add-panel-btn{
padding: 5px;
float: right;
}
.draggable {
cursor: move;
}
.panel-list {
list-style-type: none;
padding: 0;
}
.panel-list li {
margin-bottom: 5px;
margin-right: 5px;
padding: 5px !important;
background: var(--bg-color);
}
.panel-select{
margin-left: 9px !important;
width: 70% !important;
float: left !important;
}
.remove-panel {
bottom: 0;
float: right;
background: var(--comfy-menu-bg);
color: var(--input-text);
border: 1px solid var(--border-color);
border-radius: 5px;
cursor: pointer;
text-transform: uppercase;
font-weight: bold;
}
.n-sb-section-header label {
padding: 0 0 0px 10px;
}
.icon-input{
width: 20px;
text-align: center;
}
+99 -20
View File
@@ -1,28 +1,23 @@
<div class="sidebar" id="sidebar" style="width:{{sidebar_width}};">
<div class="dragHandleTB" id="dragHandleT"></div>
<div class="sidebar-header" id="sidebar-header" data-content="panel_head_home">
<input type="text" id="searchInputSB" placeholder="Search..." autocomplete="off">
<span class="clearIcon">&times;</span>
<span class="searchCategoryIcon">C</span>
<span class="searchCategoryIcon" title="Category Only">C</span>
</div>
<div id="sidebar_views">
<div class="view_button" id="switch_sidebar" title="Toggle Sidebar">☰</div>
<div class="view_button" id="switch_home" data-content="home" title="Home"><svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" x="0px" y="0px" viewBox="0 0 100 100"
style="enable-background:new 0 0 100 100; fill:var(--input-text);" xml:space="preserve">
<g>
<path
d="M29,82h13V63.1c0-1.7,1.3-3,3-3h10.3c1.7,0,3,1.3,3,3V82H71c1.7,0,3-1.3,3-3V43.2c0-0.8-0.3-1.6-0.9-2.1l-21-21 c-1.2-1.2-3.1-1.2-4.2,0l-21,21c-0.6,0.6-0.9,1.3-0.9,2.1V79C26,80.7,27.3,82,29,82z" />
</g>
</svg></div>
<div class="view_button" id="switch_settings" title="Settings">⚙</div>
<div class="view_button right" id="switch_sidebar" data-tooltip="Toggle Sidebar"><i class="pi pi-bars"></i></div>
<div class="view_button right" id="switch_home" data-content="home" data-tooltip="Home"><i class="pi pi-home"></i></div>
<div class="view_button" id="official_button"></div>
<div class="view_button right" id="switch_settings" data-tooltip="Settings">⚙</div>
</div>
<div class="content_sidebar" id="content_sidebar_home" data-expanded="false" data-content="panel_content_home">
<div class="content_sidebar" id="panel_home" data-expanded="false" data-content="panel_content_home">
<div id="spacer"></div>
<label class="sb_label" id="sb_label_pinned">PINNED</label>
<ul id="sidebarBookmarks"></ul>
<label class="sb_label" id="sb_label_custom">CUSTOM NODES<button class="expand_node" title="Expand/Collapse">
<label class="sb_label" id="sb_label_custom">CUSTOM NODES<button class="expand_node left" data-tooltip="Expand/Collapse">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 52 52" enable-background="new 0 0 52 52"
xml:space="preserve">
<path
@@ -38,15 +33,98 @@
<ul id="sidebarCustomNodes"></ul>
</div>
<div class="dragHandle" id="dragHandle"></div>
<div id="previewDiv"></div>
<!-- settings -->
<div id="sb-modal-backdrop-settings" class="sb-modal-backdrop-settings sb_hidden"></div>
<div id="sb_settingsDiv" class="sb_hidden">
<h1>SideBar Settings</h1>
<button id="sb_resetButton">Soft Reset</button>
<button id="sb_factoryResetButton">Factory Reset</button>
<div id="sb_settingsDiv_export" class="sb_hidden">
<h1>Export Settings</h1>
<div class="setting"><label>Pinned Nodes</label><input type="checkbox" checked></div>
<div class="setting"><label>Custom Categories</label><input type="checkbox" checked></div>
<div class="setting"><label>Workflows Categories</label><input type="checkbox" checked></div>
<div class="setting"><label>Templates Categories</label><input type="checkbox" checked></div>
<div class="setting"><label>CivitAI API KEY</label><input type="checkbox" checked></div>
<div class="setting"><label>Model Templates</label><input type="checkbox" checked></div>
<div class="setting"><label>Other Settings</label><input type="checkbox" checked></div>
<div id="sb_buttonsContainer"><button id="sb_runExportButton">Export</button></div>
</div>
<div id="sb_settingsDiv_import" class="sb_hidden">
<h1>Import Settings</h1>
<div class="setting"><label>Pinned Nodes</label><input type="checkbox" checked></div>
<div class="setting"><label>Custom Categories</label><input type="checkbox" checked></div>
<div class="setting"><label>Workflows Categories</label><input type="checkbox" checked></div>
<div class="setting"><label>Templates Categories</label><input type="checkbox" checked></div>
<div class="setting"><label>CivitAI API KEY</label><input type="checkbox" checked></div>
<div class="setting"><label>Model Templates</label><input type="checkbox" checked></div>
<div class="setting"><label>Other Settings</label><input type="checkbox" checked></div>
<div id="sb_buttonsContainer">
<button id="sb_selectFileButton">Select File</button>
<input type="file" id="importFileInput" style="display: none;">
<button id="sb_runImportButton">Import</button>
</div>
</div>
<style>
#g_section, #w_section, #t_section, #m_section {
margin-top: 3vh;
height: auto;
background: var(--bg-color);
}
#g_section h3, #w_section h3, #t_section h3, #m_section h3 {
font-size: 12px;
line-height: 27px;
font-weight: 600;
text-align: center;
color: var(--content-fg);
border-bottom: 2px solid var(--border-color);
}
</style>
<div id="sb_settingsDiv" class="sb_hidden">
<div id="tabContainer" class="n-sb-tab-container">
<div id="tabSettings" class="n-sb-tab n-sb-active">SideBar Settings</div>
<div id="tabCustomize" class="n-sb-tab">Customize</div>
</div>
<!-- SideBar Settings Content -->
<div id="settingsContainer" class="n-sb-tab-content n-sb-active">
<div id="sb_buttonsContainer">
<button id="sb_resetButton">Soft Reset</button>
<button id="sb_factoryResetButton">Factory Reset</button>
<button id="sb_exportButton">Export Config</button>
<button id="sb_importButton">Import Config</button>
</div>
<div id="g_section"><h3>General Settings</h3></div>
<div id="w_section"><h3>Workflow Panel</h3></div>
<div id="m_section"><h3>Assets Downloader Panel</h3></div>
</div>
<!-- Customize Content -->
<div id="sbCustomizeContainer" class="n-sb-tab-content">
<center style="color:red">NOTE: THIS SECTION IS UNDER DEVELOPMENT, PLEASE USE AT YOUR OWN RISK.</center>
<div id="n-sb-section-list">
<!-- Le sezioni verranno inserite qui dinamicamente -->
</div>
<div id="sb_buttonsContainerCustomize">
<button id="add-section-btn">Add Section</button>
<button id="save-btn">Save Layout</button>
<button id="restore-btn">Restore Layout</button>
</div>
<!-- Add your customize settings UI here -->
</div>
</div>
<!-- end settings -->
<a href="#" id="sb_scrollToTopButton">
<svg fill="#000000" height="800px" width="800px" version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 330 330" xml:space="preserve">
@@ -59,4 +137,5 @@
<div id="customMenu" class="custom-menu">
<ul> </ul>
</div>
<div class="dragHandleTB" id="dragHandleV"></div>
</div>
+178 -16
View File
@@ -22,19 +22,18 @@ function sidebarAddNode(name, text, x, y) {
}
}
function sdExpandAll(forceExpand=0) {
function sdExpandAll(forceExpand = 0) {
const categoryItems = document.querySelectorAll(".content_sidebar .sidebarCategory");
const side_bar_status = document.querySelector(".content_sidebar").dataset.expanded;
const expand_node = document.getElementsByClassName("expand_node")[0];
const expand_nodes = document.querySelectorAll(".expand_node");
let display_value = "true";
if (side_bar_status === "true" && forceExpand === 0) {
display_value = "none";
expand_node.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg"
expand_nodes.forEach(node => {
if (node.tagName.toLowerCase() === "button") {
node.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 52 52" enable-background="new 0 0 52 52" xml:space="preserve">
<path d="M48,9.5C48,8.7,47.3,8,46.5,8h-41C4.7,8,4,8.7,4,9.5v3C4,13.3,4.7,14,5.5,14h41c0.8,0,1.5-0.7,1.5-1.5V9.5z"
/>
@@ -45,12 +44,15 @@ function sdExpandAll(forceExpand=0) {
c0,0.8,0.7,1.5,1.5,1.5h3c0.8,0,1.5-0.7,1.5-1.5V30C29,29.4,29.4,29,30,29z"/>
<rect class="expand_node" style="opacity:0" x="0" y="0" width="52" height="52" />
</svg>`;
}
});
document.querySelector(".content_sidebar").dataset.expanded = "false";
} else {
display_value = "block";
expand_node.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 52 52" enable-background="new 0 0 52 52" xml:space="preserve" >
expand_nodes.forEach(node => {
if (node.tagName.toLowerCase() === "button") {
node.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 52 52" enable-background="new 0 0 52 52" xml:space="preserve" >
<path d="M48,9.5C48,8.7,47.3,8,46.5,8h-41C4.7,8,4,8.7,4,9.5v3C4,13.3,4.7,14,5.5,14h41c0.8,0,1.5-0.7,1.5-1.5V9.5z"></path>
<path d="M48,39.5c0-0.8-0.7-1.5-1.5-1.5h-41C4.7,38,4,38.7,4,39.5v3C4,43.3,4.7,44,5.5,44h41c0.8,0,1.5-0.7,1.5-1.5
V39.5z"></path>
@@ -59,24 +61,22 @@ function sdExpandAll(forceExpand=0) {
<rect class="expand_node" style="opacity:0" x="0" y="0" width="52" height="52" />
</svg>`;
}
});
document.querySelector(".content_sidebar").dataset.expanded = "true";
}
categoryItems.forEach(function (categoryItem) {
const displayNamesList = categoryItem.querySelector("ul");
if (expand_node) {
if (displayNamesList) {
displayNamesList.style.display = display_value;
}
});
}
function handleSearch(categorySearchToggle,searchSection,searchIdInput) {
@@ -331,30 +331,101 @@ return [`<div class="sb_table">
}
async function getPreview(item, previewDiv, sidebad_view_width, contentFunction, configFunction = null) {
try {
item.addEventListener('mouseover', async function () {
let shouldShowPreview = true;
if (configFunction) {
shouldShowPreview = await configFunction();
}
if (shouldShowPreview && this.classList.contains('sidebarItem') && this.tagName === 'LI') {
let descriptionDiv = "";
const itemPosition = getElementPosition(this);
let previewDivTop = 0;
// Usa la funzione contentFunction per ottenere il contenuto del preview
const [previewContent, node_description] = await contentFunction(item);
if (node_description) {
descriptionDiv = "<div class='sb_description'>" + node_description + "</div>";
}
previewDiv.innerHTML = previewContent + descriptionDiv;
previewDiv.style.display = 'block';
const correction_offset = 45;
let sbtop = calcSBTop();
if (itemPosition.top - this.offsetHeight >= 0 && itemPosition.top + previewDiv.offsetHeight < document.body.offsetHeight) {
previewDivTop = itemPosition.top - this.offsetHeight - sbtop;
} else if (itemPosition.top - this.offsetHeight - previewDiv.offsetHeight <= 0) {
previewDivTop = 0 + correction_offset - sbtop;
} else {
previewDivTop = (itemPosition.top + this.offsetHeight) - previewDiv.offsetHeight - sbtop;
}
let sidebar_width = parseInt(getVar("sidebarWidth")) || 500;
previewDiv.style.top = `${previewDivTop}px`;
const previewDivLeft = sidebar_width - sidebad_view_width + correction_offset;
if (sbPosition == "left") {
previewDiv.style.left = `${previewDivLeft}px`;
} else {
previewDiv.style.right = `${previewDivLeft}px`;
}
}
});
item.addEventListener('mouseout', function () {
previewDiv.style.display = 'none';
});
} catch (error) {
console.log(error);
}
}
//change view
function switchTab(tabId) {
if (tabId != null) {
const tabContents = document.querySelectorAll('.content_sidebar');
const tabHead = document.querySelectorAll('.sidebar-header');
let switch_id= tabId.replace("panel", "switch");
const switchButton = document.getElementById(switch_id);
if (tabId=="content_sidebar_home"){
if (tabId=="panel_home"){
const tabIdHead = document.getElementById("sidebar-header");
tabIdHead.classList.remove('sb_hidden');
document.getElementById("switch_home").classList.add('sb_button_active');
}
else{
tabHead.forEach(content => {
content.classList.add('sb_hidden');
})
}
// Hide all tabs
tabContents.forEach(content => {
content.classList.add('sb_hidden');
let switch_id_disbled= content.id.replace("panel", "switch");
const switchButtonDisbled = document.getElementById(switch_id_disbled);
switchButtonDisbled.classList.remove('sb_button_active');
});
// Show the content of the clicked tab
document.getElementById(tabId).classList.remove('sb_hidden');
switchButton.classList.add('sb_button_active');
setVar('sb_current_tab', tabId);
}
@@ -402,4 +473,95 @@ function migrationSettings() {
}
})
// updateConfiguration('sb_pinnedItems',pinnedItemsString) ;
}
}
function toggleSHSB(force = undefined) {
const side_bars = document.querySelectorAll(".content_sidebar");
const main_sidebar = document.getElementById('sidebar');
const search_bar = document.getElementById('searchInputSB');
const scrollToTopButton = document.getElementById("sb_scrollToTopButton");
const clearIcon = document.querySelector(".clearIcon");
const searchCategoryIcon = document.querySelector(".searchCategoryIcon");
const switch_sidebar = document.getElementById('switch_sidebar');
const sidebar_views = document.getElementById("sidebar_views");
//search_bar.classList.toggle('closed',force);
side_bars.forEach(side_bar => {
//side_bar.classList.toggle('closed',force);
if (force !== undefined) {
if (force) {
side_bar.classList.add('closed');
clearIcon.classList.add('closed');
searchCategoryIcon.classList.add('closed');
search_bar.classList.add('closed');
scrollToTopButton.classList.add('closed');
sidebar_views.classList.add('full_rounded');
} else {
side_bar.classList.remove('closed');
clearIcon.classList.remove('closed');
searchCategoryIcon.classList.remove('closed');
search_bar.classList.remove('closed');
scrollToTopButton.classList.remove('closed');
sidebar_views.classList.remove('full_rounded');
setVar("sb_minimized", "true");
}
} else {
if (side_bar.classList.contains('closed')) {
side_bar.classList.remove('closed');
clearIcon.classList.remove('closed');
searchCategoryIcon.classList.remove('closed');
search_bar.classList.remove('closed');
sidebar_views.classList.remove('full_rounded');
scrollToTopButton.classList.remove('closed');
//fix for keyboard shortcuts
if (getVar("sb_minimized") == "true") {
switch_sidebar.style.filter = "brightness(0.8)";
}
} else {
if (getVar("sb_minimized") == "false") {
side_bar.classList.add('closed');
clearIcon.classList.add('closed');
searchCategoryIcon.classList.add('closed');
search_bar.classList.add('closed');
scrollToTopButton.classList.add('closed');
sidebar_views.classList.add('full_rounded');
switch_sidebar.style.filter = "brightness(1.0)";
} else {
switch_sidebar.style.filter = "brightness(0.8)";
}
}
}
});
if (getVar("sb_minimized") == "false") {
if (force == undefined) {
setVar("sb_minimized", true);
}
main_sidebar.style.width = '45px';
} else {
if (force == undefined) {
setVar("sb_minimized", false);
main_sidebar.style.width = getVar("sidebarWidth") + 'px' || '300px';
} else if (force == true) {
main_sidebar.style.width = '45px';
} else {
main_sidebar.style.width = getVar("sidebarWidth") + 'px' || '300px';
}
}
}
File diff suppressed because it is too large Load Diff
+44 -7
View File
@@ -69,7 +69,24 @@
var response = await api.fetchApi(url, { cache: "no-store" })
return await response.json()
}
function getDynamicCSSRule(selector, property) {
const styleId = 'dynamic-styles';
const customStyle = document.getElementById(styleId);
if (!customStyle) {
return null;
}
const existingRule = Array.from(customStyle.sheet.cssRules).find(rule => rule.selectorText === selector);
if (existingRule) {
return existingRule.style.getPropertyValue(property);
}
return null;
}
function addDynamicCSSRule(selector, property, value) {
const styleId = 'dynamic-styles';
let customStyle = document.getElementById(styleId);
@@ -83,7 +100,7 @@
const existingRule = Array.from(customStyle.sheet.cssRules).find(rule => rule.selectorText === selector);
if (existingRule) {
existingRule.style[property] = value;
existingRule.style.setProperty(property, value, 'important');
} else {
customStyle.sheet.insertRule(`${selector} { ${property}: ${value} !important; }`, customStyle.sheet.cssRules.length);
@@ -189,8 +206,17 @@ function cleanText(text) {
return cleanedText;
}
function calcSBTop() {
let sb = document.getElementById('sidebar');
let sbtop = window.getComputedStyle(sb).getPropertyValue('top').replace('px', '');
if (getVar('Comfy.Settings.Comfy.UseNewMenu') === '"Top"') {
return parseInt(sbtop) + 35;
}
else{
return sbtop;
}
}
//CONTEXT MENU
function createContextMenu(event, subMenus,settingsData) {
event.preventDefault();
@@ -247,7 +273,9 @@ function createContextMenu(event, subMenus,settingsData) {
// Show context menu
sbcontextMenu.style.display = 'block';
sbcontextMenu.style.top = event.clientY + 'px';
let sbtop = calcSBTop();
sbcontextMenu.style.top = (event.clientY - sbtop) + 'px';
if (sbPosition === "left") {
sbcontextMenu.style.left = event.clientX + 'px';
@@ -374,7 +402,7 @@ async function setContextMenu(settingsData,class_menu_item,main=0,exluded_class=
}
const sidebarItems = document.querySelectorAll(class_menu_item);
//const sb =document.getElementById('content_sidebar_home');
//const sb =document.getElementById('panel_home');
for (const sidebarItem of sidebarItems) {
@@ -428,7 +456,7 @@ async function reloadCtxMenu() {
const response3 = await fetch(cnPath +'settings.json');
const settingsData = await response3.json();
setContextMenu(settingsData,"#content_sidebar_home .sidebarItem",1);
setContextMenu(settingsData,"#panel_home .sidebarItem",1);
}
@@ -462,7 +490,7 @@ function setModalContext(addon=null) {
<h2 class="sb-modal-title">Add New Category</h2>
<form id="sb-category-form" action="javascript:void(0);">
<input type="text" autocomplete="off" class="sb-input" id="sb-categoryName" name="sb-categoryName" placeholder="Category Name" required>
<button type="submit" class="sb-button" onclick="addCategory()">Add Category</button>
<button type="submit" class="sb-button" onclick="custom_categories.addCategory()">Add Category</button>
</form>
<button id="closeModalButton" class="sb-button">X</button>
`;
@@ -568,6 +596,15 @@ function showSettings() {
sb_modal_backdrop.classList.remove('sb_hidden');
}
function showIESettings(operation) {
const sb_settingsDiv = document.getElementById("sb_settingsDiv_"+operation);
sb_settingsDiv.classList.remove('sb_hidden');
}
function isBottomEdgeVisible(el) {
var rect = el.getBoundingClientRect();
+224 -289
View File
@@ -11,13 +11,17 @@ console.time('execution time');
const cnPath = "../extensions/ComfyUI-N-Sidebar/"
function jsloader(url) {
return new Promise((resolve, reject) => {
try{
const script = document.createElement("script");
const timestamp = new Date().getTime();
script.src = `${url}?v=${timestamp}`;
script.type = "text/javascript";
script.onload = () => resolve(script);
script.onerror = () => reject(new Error(`Failed to load script: ${url}`));
//script.onerror = () => reject(new Error(`Failed to load script: ${url}`));
document.head.appendChild(script);
}catch(err){
console.log(err)
}
});
}
@@ -85,42 +89,9 @@ function postPinned() {
}
});
item.addEventListener('mouseover', function () {
if (this.classList.contains('sidebarItem') && this.tagName === 'LI') {
let descriptionDiv = "";
const itemPosition = getElementPosition(this);
let previewDivTop = 0;
const [previewContent, node_description] = createNodePreview(item.id);
if (node_description) {
descriptionDiv = "<div class='sb_description'>" + node_description + "</div>";
}
previewDiv.innerHTML = previewContent + descriptionDiv;
previewDiv.style.display = 'block';
const correction_offset = 45;
if (itemPosition.top - this.offsetHeight >= 0 && itemPosition.top + previewDiv.offsetHeight < document.body.offsetHeight) {
previewDivTop = itemPosition.top - this.offsetHeight;
} else if (itemPosition.top - this.offsetHeight - previewDiv.offsetHeight <= 0) {
previewDivTop = 0 + correction_offset;
} else {
previewDivTop = (itemPosition.top + this.offsetHeight) - previewDiv.offsetHeight;
}
let sidebar_width = parseInt(getVar("sidebarWidth")) || 500;
previewDiv.style.top = `${previewDivTop}px`;
const previewDivLeft = sidebar_width - sidebad_view_width + correction_offset;
if (sbPosition == "left") {
previewDiv.style.left = `${previewDivLeft}px`;
} else {
previewDiv.style.right = `${previewDivLeft}px`;
}
}
});
item.addEventListener('mouseout', function () {
previewDiv.style.display = 'none';
});
getPreview(item, previewDiv,sidebad_view_width,(item) => {
return createNodePreview(item.id);
});
reloadCtxMenu();
});
@@ -141,9 +112,30 @@ function postPinned() {
}
function saveSidebarWidth(sideb) {
const width = sideb.style.width;
document.cookie = setVar("sidebarWidth", width);
function saveSidebarPosition(sideb) {
const width = sideb.style.width.replace('px', '');
//const top = sideb.style.top.replace('px', '');
const top = getDynamicCSSRule(".sidebar", 'top').replace('%', '');
const height = getDynamicCSSRule(".sidebar", 'height').replace('%', '');
if (width > 50) {
setVar("sidebarWidth", width);
addDynamicCSSRule('.side-bar-panel', 'min-width', 'calc('+width+'px - 35px)');
}
if (parseInt(top) > 0 ) {
setVar("sb_bartop", top);
}
else {
setVar("sb_bartop", 0);
}
if (height > 0) {
setVar("sb_barbottom", height);
}
}
@@ -287,7 +279,7 @@ async function createCategoryList() {
// defaultSearchToggle = await getConfiguration("sb_search_type")
if (defaultSearchToggle == "original" && itemSearchInput.value != "") {
//search in all .sidebarItem
handleSearch(categorySearchToggle, "#content_sidebar_home", "searchInputSB")
handleSearch(categorySearchToggle, "#panel_home", "searchInputSB")
}
else {
updateList();
@@ -535,7 +527,7 @@ async function createCategoryList() {
}
// APPLY THE COLOR, IF ANY
if (color) {
displayNameItem.style = `background: ${color}`;
displayNameItem.style = `background: ${color} !important;`;
}
//
@@ -597,60 +589,16 @@ async function createCategoryList() {
loadPinnedItemsAndAddToBookmarks();
/* preview */
/* PREVIEW */
const sidebarItems_cat = document.querySelectorAll('.sidebarItem');
const previewDiv = document.getElementById('previewDiv');
let sidebad_view_width = document.getElementById("sidebar_views").offsetWidth;
sidebarItems_cat.forEach(item => {
item.addEventListener('mouseover', function () {
if (this.classList.contains('sidebarItem') && this.tagName === 'LI') {
let descriptionDiv = "";
const itemPosition = getElementPosition(this);
let previewDivTop = 0;
const [previewContent, node_description] = createNodePreview(item.id);
if (node_description) {
descriptionDiv = "<div class='sb_description'>" + node_description + "</div>";
}
previewDiv.innerHTML = previewContent + descriptionDiv;
previewDiv.style.display = 'block';
const correction_offset = 45;
if (itemPosition.top - this.offsetHeight >= 0 && itemPosition.top + previewDiv.offsetHeight < document.body.offsetHeight) {
previewDivTop = itemPosition.top - this.offsetHeight
} else if (itemPosition.top - this.offsetHeight - previewDiv.offsetHeight <= 0) {
previewDivTop = 0 + correction_offset;
}
else {
previewDivTop = (itemPosition.top + this.offsetHeight) - previewDiv.offsetHeight;
}
let sidebar_width = parseInt(getVar("sidebarWidth")) || 500;
previewDiv.style.top = `${previewDivTop}px`;
const previewDivLeft = sidebar_width - sidebad_view_width + correction_offset;
if (sbPosition == "left") {
previewDiv.style.left = `${previewDivLeft}px`;
} else {
previewDiv.style.right = `${previewDivLeft}px`;
}
}
});
item.addEventListener('mouseout', function () {
previewDiv.style.display = 'none';
})
getPreview(item,previewDiv,sidebad_view_width,(item) => {
return createNodePreview(item.id);
});
});
@@ -666,8 +614,10 @@ async function createCategoryList() {
}
});
/* END PREVIEW */
const categoryItems = document.querySelectorAll("#content_sidebar_home .sidebarCategory");
const categoryItems = document.querySelectorAll("#panel_home .sidebarCategory");
categoryItems.forEach(function (folderItem) {
folderItem.addEventListener("click", function (event) {
@@ -693,50 +643,105 @@ async function createCategoryList() {
let udata = await updateList();
/* RESIZE */
const dragHandles = {
"dragHandle": "width",
"dragHandleT": "top",
"dragHandleV": "height",
"sidebar_views": "top" // Condizione per altKey più avanti
};
let dragging = null;
let startX, startY, startValue;
const containerHeight = window.innerHeight;
Object.keys(dragHandles).forEach(handleId => {
const element = document.getElementById(handleId);
if (!element) return;
const dragHandle = document.getElementById("dragHandle");
let isDragging = false;
let startX;
let startWidth;
// Funzioni per gestire gli eventi del mouse
dragHandle.addEventListener("mousedown", function (event) {
isDragging = true;
startX = event.clientX;
startWidth = parseInt(window.getComputedStyle(sidebar_main).width);
});
document.addEventListener("mouseup", function () {
if (isDragging) {
isDragging = false;
saveSidebarWidth(sidebar_main);
element.addEventListener("mousedown", function (event) {
if (handleId === "sidebar_views") {
if (!event.altKey) return; // Gestisci l'eccezione altKey per sidebar_views
element.style.cursor = 'n-resize'; // Cambia cursore quando alt è premuto
} else if (handleId === "dragHandle" && localStorage.getItem("sb_minimized") === "true") {
return; // Gestisci l'eccezione minimized
} else {
element.style.cursor = ''; // Cambia cursore per gli altri handle
}
dragging = dragHandles[handleId];
startX = event.clientX;
startY = event.clientY;
if (dragging === "width") {
startValue = parseInt(window.getComputedStyle(sidebar_main).width);
} else if (dragging === "top") {
startValue = (parseInt(window.getComputedStyle(sidebar_main).top)/ containerHeight) * 100;
} else if (dragging === "height") {
startValue = (parseFloat(window.getComputedStyle(sidebar_main).height) / containerHeight) * 100;
}
event.preventDefault(); // Evita il comportamento predefinito del browser (ad esempio, selezione di testo)
});
document.addEventListener("mousemove", function (event) {
if (!isDragging) return;
});
document.addEventListener("mouseup", function () {
if (dragging) {
saveSidebarPosition(sidebar_main);
dragging = null;
// Ripristina il cursore
Object.keys(dragHandles).forEach(handleId => {
const element = document.getElementById(handleId);
if (element) {
element.style.cursor = ''; // Reset del cursore a default
}
});
}
});
document.addEventListener("mousemove", function (event) {
if (!dragging) return;
if (dragging === "width") {
const delta = event.clientX - startX;
if (sbPosition === "left") {
sidebar_main.style.width = (startWidth + delta) + "px";
sidebar_main.style.width = (startValue + delta) + "px";
} else {
sidebar_main.style.width = (startWidth - delta) + "px";
sidebar_main.style.width = (startValue - delta) + "px";
}
});
} else if (dragging === "top") {
const deltaV = event.clientY - startY;
const newTopPercent = ((startValue * containerHeight / 100) + deltaV) / containerHeight * 100;
addDynamicCSSRule('.sidebar', 'top', newTopPercent + '%');
} else if (dragging === "height") {
const deltaV = event.clientY - startY;
const newHeightPercent = ((startValue * containerHeight / 100) + deltaV) / containerHeight * 100;
//sidebar_main.style.setProperty("height", newHeightPercent + "%", "important");
addDynamicCSSRule('.sidebar', 'height', newHeightPercent+ '%');
}
});
// Funzioni per gestire gli eventi touch
dragHandle.addEventListener("touchstart", function (event) {
if (localStorage.getItem("sb_minimized")==="false")
{
isDragging = true;
startX = event.touches[0].clientX;
startWidth = parseInt(window.getComputedStyle(sidebar_main).width);
}
});
document.addEventListener("touchend", function () {
if (isDragging) {
isDragging = false;
saveSidebarWidth(sidebar_main);
saveSidebarPosition(sidebar_main);
}
});
@@ -752,6 +757,7 @@ async function createCategoryList() {
});
/* END RESIZE */
}
@@ -765,8 +771,9 @@ async function addSidebar() {
const timestamp = new Date().getTime();
const response = await fetch(cnPath + 'html/sidebar.html?v=' + timestamp);
let html = await response.text();
html = html.replace(/{{sidebar_width}}/g, sidebar_width);
//addDynamicCSSRule('.splitter-overlay', 'width', sidebar_width);
html = html.replace(/{{sidebar_width}}/g, sidebar_width+"px");
html = html.replace(/{{node_path}}/g, cnPath);
const canvas = $el("sidebar", {
parent: document.body,
@@ -777,7 +784,7 @@ async function addSidebar() {
document.getElementById("content_sidebar_home").addEventListener("click", async function (event) {
document.getElementById("panel_home").addEventListener("click", async function (event) {
const clickedElement = event.target;
const pinnedItems = await loadPinnedItems();
const pinButton = clickedElement.tagName;
@@ -926,94 +933,6 @@ async function addSidebar() {
SidebarPostBoot();
}
function toggleSHSB(force = undefined) {
const side_bars = document.querySelectorAll(".content_sidebar");
const main_sidebar = document.getElementById('sidebar');
const search_bar = document.getElementById('searchInputSB');
const scrollToTopButton = document.getElementById("sb_scrollToTopButton");
const clearIcon = document.querySelector(".clearIcon");
const searchCategoryIcon = document.querySelector(".searchCategoryIcon");
const switch_sidebar = document.getElementById('switch_sidebar');
//search_bar.classList.toggle('closed',force);
side_bars.forEach(side_bar => {
//side_bar.classList.toggle('closed',force);
if (force !== undefined) {
if (force) {
side_bar.classList.add('closed');
clearIcon.classList.add('closed');
searchCategoryIcon.classList.add('closed');
search_bar.classList.add('closed');
scrollToTopButton.classList.add('closed');
} else {
side_bar.classList.remove('closed');
clearIcon.classList.remove('closed');
searchCategoryIcon.classList.remove('closed');
search_bar.classList.remove('closed');
scrollToTopButton.classList.remove('closed');
setVar("sb_minimized", "true");
}
} else {
if (side_bar.classList.contains('closed')) {
side_bar.classList.remove('closed');
clearIcon.classList.remove('closed');
searchCategoryIcon.classList.remove('closed');
search_bar.classList.remove('closed');
//fix for keyboard shortcuts
if (getVar("sb_minimized") == "true") {
switch_sidebar.style.filter = "brightness(0.8)";
}
} else {
if (getVar("sb_minimized") == "false") {
side_bar.classList.add('closed');
clearIcon.classList.add('closed');
searchCategoryIcon.classList.add('closed');
search_bar.classList.add('closed');
scrollToTopButton.classList.add('closed');
switch_sidebar.style.filter = "brightness(1.0)";
} else {
switch_sidebar.style.filter = "brightness(0.8)";
}
}
}
});
if (getVar("sb_minimized") == "false") {
if (force == undefined) {
setVar("sb_minimized", true);
}
main_sidebar.style.width = '45px';
} else {
if (force == undefined) {
setVar("sb_minimized", false);
main_sidebar.style.width = getVar("sidebarWidth") || '300px';
} else if (force == true) {
main_sidebar.style.width = '45px';
} else {
main_sidebar.style.width = getVar("sidebarWidth") || '300px';
}
}
}
//option: disable auto-hide when minimized
//Shortcuts
function handleKeyPress(event) {
@@ -1021,7 +940,7 @@ function handleKeyPress(event) {
// Per la combinazione Alt + X
if (event.altKey && (event.key.toLowerCase() === "x" || event.keyCode === 88)) {
// Toggle sidebar if it's closed
const side_bar = document.getElementById('content_sidebar_home');
const side_bar = document.getElementById('panel_home');
if (side_bar.classList.contains('closed')) {
toggleSHSB();
}
@@ -1044,12 +963,12 @@ function handleKeyPress(event) {
// Custom Node View
function processViews(viewsData, settingsData) {
async function processViews(viewsData, settingsData) {
const sb = document.getElementById('sidebar');
const sbv = document.getElementById('sidebar_views');
const promises = viewsData.map(async (view) => {
// Funzione per caricare un singolo view
const loadView = async (view) => {
const icon = view.icon;
if (!icon) {
return;
@@ -1060,15 +979,10 @@ function processViews(viewsData, settingsData) {
div_view.classList = "content_sidebar sb_hidden";
div_view.id = "panel_" + view.id;
div_view.dataset.content = view.id;
const bsb = document.getElementById('content_sidebar_home');
// add button to sidebarviews
const bsb = document.getElementById('panel_home');
bsb.insertAdjacentElement('afterend', div_view);
//console.log('Icon:', icon);
//console.log('Descr:', description);
//console.log('Panel:', view.panels);
//console.log('-------------------');
// Caricamento dei pannelli
await Promise.all(view.panels.map(async (panel) => {
try {
const timestamp = new Date().getTime();
@@ -1076,7 +990,6 @@ function processViews(viewsData, settingsData) {
const html = await response.text();
if (html !== "404: Not Found") {
//inherit width from bsb
const div_panel = document.createElement('div');
div_panel.classList = "panel_sidebar";
div_panel.id = "panel_" + panel;
@@ -1085,11 +998,7 @@ function processViews(viewsData, settingsData) {
div_panel_title.classList = "panel_sidebar_title sb_label";
div_panel_title.id = "panel_title_" + panel;
div_panel_title.innerHTML = view.id.replace("_", " ");
div_panel_title.innerHTML = panel.replace("_", " ");
div_panel.appendChild(div_panel_title);
const canvas = $el("div", {
@@ -1097,10 +1006,8 @@ function processViews(viewsData, settingsData) {
innerHTML: html,
});
div_view.insertAdjacentElement('beforeend', div_panel);
jsloader(`${cnPath}panels/${panel}/${panel}.jsb`);
//window.custom_templates();
console.log("LOADING " + cnPath + `panels/${panel}/${panel}.js`)
}
} catch (error) {
@@ -1108,69 +1015,60 @@ function processViews(viewsData, settingsData) {
}
}));
//sidebar menu
// Creazione del pulsante per la vista
const div_button = document.createElement('div');
div_button.classList = "view_button";
div_button.classList = "view_button right";
div_button.id = "switch_" + view.id;
//inherit width from bsb
div_button.dataset.tab = view.id;
div_button.title = description;
div_button.dataset.tooltip = description;
div_button.innerHTML += view.icon;
div_button.addEventListener('click', function () {
const tabId = "panel_" + this.getAttribute('data-tab');
switchTab(tabId)
switchTab(tabId);
if (getVar("sb_auto_hide") == "false" && getVar("sb_minimized") == "true") {
toggleSHSB(false);
toggleSHSB(false);
}
});
sbv.appendChild(div_button);
});
return Promise.all(promises).then(() => {
};
setTimeout(() => {
// Gestione degli ordini dei viewData
await viewsData.reduce(async (prevPromise, view) => {
await prevPromise;
return loadView(view);
}, Promise.resolve());
settingsSetup(app, $el)
setContextMenu(settingsData, "#content_sidebar_home .sidebarItem", 1);
switchTab(getVar('sb_current_tab'));
const sidebar_view = document.getElementById('sidebar_views');
const sidebar = document.getElementById('sidebar');
setTimeout(() => {
settingsSetup(app, $el);
setContextMenu(settingsData, "#panel_home .sidebarItem", 1);
switchTab(getVar('sb_current_tab'));
const sidebar_view = document.getElementById('sidebar_views');
const sidebar = document.getElementById('sidebar');
sidebar_view.addEventListener('mouseover', function () {
if (getVar('sb_auto_hide') == "true") {
if (getVar('sb_minimized') == "true") {
toggleSHSB(false);
}
sidebar_view.addEventListener('mouseover', function () {
if (getVar('sb_auto_hide') == "true") {
if (getVar('sb_minimized') == "true") {
toggleSHSB(false);
}
});
document.addEventListener('click', function (event) {
//if click is outside sidebar id element
if (!sidebar.contains(event.target)) {
if (getVar('sb_minimized') == "true") {
toggleSHSB(true);
}
}
});
document.addEventListener('click', function (event) {
if (!sidebar.contains(event.target)) {
if (getVar('sb_minimized') == "true") {
toggleSHSB(true);
}
});
}, 100);
});
}
});
}, 100);
}
async function loadData() {
try {
@@ -1195,14 +1093,11 @@ async function loadData() {
async function SidebarPostBoot() {
console.log('SidebarPostBoot');
const switch_home = document.getElementById("switch_home");
//only for home
switch_home.addEventListener('click', function () {
switchTab("content_sidebar_home", 1)
switchTab("panel_home", 1)
if (getVar("sb_auto_hide") == "false" && getVar("sb_minimized") == "true") {
toggleSHSB(false);
}
@@ -1210,8 +1105,6 @@ async function SidebarPostBoot() {
});
if (getVar("sb_minimized") == "false") {
const switch_sidebar = document.getElementById('switch_sidebar');
switch_sidebar.style.filter = "brightness(0.8)";
@@ -1225,7 +1118,7 @@ async function SidebarPostBoot() {
document.addEventListener("keydown", handleKeyPress);
const sb = document.getElementById('content_sidebar_home');
const sb = document.getElementById('panel_home');
const scrollToTopButton = document.getElementById("sb_scrollToTopButton");
scrollToTopButton.addEventListener("click", function () {
sb.scrollTo({
@@ -1254,18 +1147,56 @@ async function SidebarPostBoot() {
sidebarCustomNodes.style.display = getVar('sb_custom_collapsed');
}
loadData();
/*
const sidebar_views = document.getElementById("sidebar_views");
const sidebar = document.getElementById("sidebar");
//if is hover sidebar_views
sidebar_views.addEventListener("mouseover", function() {
toggleSHSB();
})
//if is not hover sidebar_views
sidebar.addEventListener("mouseout", function() {
toggleSHSB();
})
*/
try{
//BETA
if (getVar('Comfy.Settings.Comfy.UseNewMenu') != '"Disabled"') {
const sidebar = document.getElementById('sidebar');
const dragHandleT = document.getElementById('dragHandleT');
if (getVar('Comfy.Settings.Comfy.UseNewMenu') === '"Top"') {
sidebar.style.marginTop = '35px';
sidebar.style.paddingTop = '0px';
dragHandleT.style.top = '-6px';
}
else{
sidebar.style.marginTop = '0px';
sidebar.style.marginBottom = '35px';
sidebar.style.paddingTop = '0px';
sidebar.style.paddingBottom = '0px';
dragHandleT.style.top = '0px';
}
}
if (getVar('sb_embed_osb') == 'true') {
// Seleziona il contenitore .sidebar
const sidebarContainer = document.getElementById('official_button');
// Seleziona tutti i bottoni all'interno della nav
const navContainer = document.querySelector('.side-tool-bar-container');
const buttons = navContainer.querySelectorAll('button');
// Sposta ogni bottone dalla nav alla sidebar
buttons.forEach(button => {
if (!(button.classList.contains('node-library-tab-button') && getVar('sb_embed_osb_nodes') === 'false')) {
sidebarContainer.appendChild(button);
}
});
navContainer.style.display = "none";
}
}catch(e){
}
}
@@ -1274,9 +1205,13 @@ function SidebarBoot() {
if (Object.keys(LiteGraph.registered_node_types).length > 10) {
// Execute the function when the element is not an empty object
//
try {
//MIGRATION
migrationSettings()
}
catch(e){
console.log(e);
}
addSidebarStyles("css/base_style_sb.css");
addSidebar();
BIN
View File
Binary file not shown.
@@ -0,0 +1,128 @@
<div id="tabContainer" class="n-sb-tab-container">
<div id="tabSettings2" class="n-sb-tab n-sb-active">Explore</div>
<div id="tabCustomize2" class="n-sb-tab" onclick="assets_downloader.loadLibrary();">My Library</div>
</div>
<div id="t1" class="n-sb-active">
<div id="assets_downloader_header">
<div class="h-header" id="h_search" data-content="panel_head_home">
<!-- Search Input -->
<div class="search-row">
<input type="text" id="searchTemplateInput" class="n-sb-searchmodels"
oninput="assets_downloader.searchT()" placeholder="Search..." autocomplete="off" class="">
</div>
<div class="filters-row">
<!-- NSFW Filter -->
<select id="nsfwFilter" onchange="assets_downloader.searchT()">
<option value="true">NSFW</option>
<option value="false" selected>SFW</option>
</select>
<!-- Type Filter -->
<select id="typeFilter" data-placeholder="Type(s)" multiple data-multi-select>
<option value="Checkpoint">Checkpoint</option>
<option value="TextualInversion">TextualInversion</option>
<option value="Hypernetwork">Hypernetwork</option>
<option value="AestheticGradient">AestheticGradient</option>
<option value="LORA">LORA</option>
<option value="LoCon">LoCon</option>
<option value="DoRA">DoRA</option>
<option value="Controlnet">Controlnet</option>
<option value="Upscaler">Upscaler</option>
<option value="MotionModule">MotionModule</option>
<option value="VAE">VAE</option>
<option value="Poses">Poses</option>
<option value="Wildcards">Wildcards</option>
<option value="Workflows">Workflows</option>
<option value="Other">Other</option>
</select>
<!-- Sort Option -->
<select id="sortOption" onchange="assets_downloader.searchT()">
<option value="">Sort By</option>
<option value="Highest Rated">Rates</option>
<option value="Most Downloaded">Downloads</option>
<option value="Newest">Newest</option>
</select>
<!-- Period Option -->
<select id="periodOption" onchange="assets_downloader.searchT()">
<option value="">All Time</option>
<option value="Year">Year</option>
<option value="Month">Month</option>
<option value="Week">Week</option>
<option value="Day">Day</option>
</select>
</div>
</div>
</div>
<div id="assets_downloader_main">
<div class="result-container" id="results-container">
<!-- Results will be injected here -->
</div>
</div>
</div>
<div id="t2">
<div class="sb-mymodels">
<div id="assets_downloader_header">
<div class="h-header" id="h_search" data-content="panel_head_home">
<!-- Search Input -->
<div class="search-row">
<input type="text" id="searchLibraryInput" class="n-sb-searchmodels"
oninput="assets_downloader.searchInLibrary()" placeholder="Search..." autocomplete="off"
class="">
<div class="sb-kebab-menu">
<div class="sb-kebab-icon" onclick="toggleMenu()">⋮</div>
<ul id="sb-menu" class="sb-menu">
<li id="sb-rebuild" onclick="assets_downloader.rebuildLibrary(0)">Rebuild Library</li>
<li id="sb-rebuild" onclick="assets_downloader.rebuildLibrary(1)">Rebuild Library From Zero</li>
</ul>
</div>
</div>
<div class="search-row">
<div class="sb-rebuild-bg-pgs">
<label>Building library...</label>
<div class="sb-rebuild-pgs"></div>
</div>
</div>
<div class="filters-row">
<!-- NSFW Filter -->
<select id="nsfwFilterLibrary" onchange="assets_downloader.searchInLibrary()">
<option value="true">NSFW</option>
<option value="false" selected>SFW</option>
</select>
<!-- Type Filter -->
<select id="typeFilterLibrary" data-placeholder="Type(s)" multiple data-library-multi-select>
<option value="Checkpoint">Checkpoint</option>
<option value="TextualInversion">TextualInversion</option>
<option value="Hypernetwork">Hypernetwork</option>
<option value="AestheticGradient">AestheticGradient</option>
<option value="LORA">LORA</option>
<option value="LoCon">LoCon</option>
<option value="DoRA">DoRA</option>
<option value="Controlnet">Controlnet</option>
<option value="Upscaler">Upscaler</option>
<option value="MotionModule">MotionModule</option>
<option value="VAE">VAE</option>
<option value="Poses">Poses</option>
<option value="Wildcards">Wildcards</option>
<option value="Workflows">Workflows</option>
<option value="Other">Other</option>
</select>
<!-- Sort Option -->
<select id="sortOptionLibrary" onchange="assets_downloader.searchInLibrary()">
<option value="">Sort By</option>
<option value="az">A-z</option>
<option value="za">Z-a</option>
<option value="Newest">Newest</option>
</select>
</div>
</div>
</div>
<div id="library-container"></div>
</div>
</div>
File diff suppressed because it is too large Load Diff
+761
View File
@@ -0,0 +1,761 @@
#assets_downloader_main,#assets_downloader_header,.sb-mymodels {
justify-content: center;
align-items: center;
height: 44px;
margin: 0;
}
#assets_downloader_main, .sb-mymodels {
height: auto;
padding-top: 0px;
padding-bottom: 150px;
}
#assets_downloader_header {
margin: 10px 0px;
font-size: 16px;
}
/* General styles for the header */
#assets_downloader_header {
display: flex;
align-items: center;
padding: 10px;
}
#assets_downloader_header .h-header {
display: flex;
align-items: center;
flex: 1;
position: relative;
width: 100%;
flex-direction: column;
}
.n-sb-searchmodels {
box-sizing: border-box;
width: 100%;
border-radius: 5px;
padding: 10px;
border: none;
user-select: none;
background: var(--comfy-input-bg);
color: var(--input-text);
line-height: 1.4;
border: 1px solid var(--border-color);
padding: 10px;
font-size: 16px;
border-radius: 4px;
margin-right: 10px;
}
#assets_downloader_header select {
padding: 10px;
font-size: 16px;
width : 145px;
border-radius: 4px;
border-color: var(--comfy-input-bg);
background: var(--comfy-input-bg);
}
/* Main container styles */
#assets_downloader_main {
padding: 4px;
}
/* Styles for the results container */
#results-container {
display: flex;
justify-content: center; /* Center horizontally */
align-items: center; /* Center vertically */
height: 100%; /* Ensure the container has defined height */
min-height: 200px; /* Minimum height for the container, adjust if needed */
position: relative;
}
/* Styles for the loading icon */
.pi-spinner-dotted {
font-size: 2rem; /* Size of the loading icon */
}
.result-container,#library-container {
display: flex;
flex-wrap: wrap;
gap: 10px;
justify-content: center;
}
.result-card {
background-color: var(--bg-color);
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
width: 287px;
padding: 8px;
height: 372px;
text-align: center;
position: relative;
}
.result-card img,
.result-card video {
max-width: 100%;
min-width: 100%;
height: 60%;
width: 100%;
border-radius: 8px;
/* height: auto; */
object-fit: cover;
object-position: center center;
transition: transform 400ms;
}
.result-card h3 {
margin: 10px 0;
font-size: 18px;
}
.result-card p {
color: #555;
margin: 5px 0;
}
.result-card .username {
font-weight: bold;
color: #007bff;
}
.download-button {
display: inline-block;
margin-top: 10px;
padding: 10px 20px;
background-color: #007bff;
color: #fff;
text-decoration: none;
border-radius: 5px;
font-size: 16px;
cursor: pointer;
}
.download-button:hover {
background-color: #0056b3;
}
/* multiselect from: https://codeshack.io/multi-select-dropdown-html-javascript/ */
.multi-select {
display: flex;
box-sizing: border-box;
flex-direction: column;
position: relative;
width: 100%;
user-select: none;
}
.multi-select .multi-select-header {
border: 1px solid #dee2e6;
padding: 7px 30px 7px 12px;
overflow: hidden;
gap: 7px;
min-height: 43px;
}
.multi-select .multi-select-header::after {
content: "";
display: block;
position: absolute;
top: 50%;
right: 15px;
transform: translateY(-50%);
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23949ba3' viewBox='0 0 16 16'%3E%3Cpath d='M8 13.1l-8-8 2.1-2.2 5.9 5.9 5.9-5.9 2.1 2.2z'/%3E%3C/svg%3E");
height: 12px;
width: 12px;
}
.multi-select .multi-select-header.multi-select-header-active {
border-color: var(--comfy-input-bg);
background: var(--comfy-input-bg);
}
.multi-select .multi-select-header.multi-select-header-active::after {
transform: translateY(-50%) rotate(180deg);
}
.multi-select .multi-select-header.multi-select-header-active + .multi-select-options {
display: flex;
}
.multi-select .multi-select-header .multi-select-header-placeholder {
color: var(--content-fg);
}
.multi-select .multi-select-header .multi-select-header-option {
display: inline-flex;
align-items: center;
background-color: var(--comfy-menu-bg);
font-size: 14px;
padding: 3px 8px;
border-radius: 4px;
text-wrap: nowrap;
}
.multi-select .multi-select-header .multi-select-header-max {
font-size: 14px;
color: var(--content-fg);
}
.multi-select .multi-select-options {
display: none;
box-sizing: border-box;
flex-flow: wrap;
position: absolute;
top: 100%;
/* left: 0; */
right: 0;
z-index: 999;
margin-top: 5px;
/* padding: 5px; */
background-color: var(--bg-color);
border-radius: 5px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
/* max-height: 200px; */
overflow-y: auto;
overflow-x: hidden;
width: fit-content;
}
.multi-select .multi-select-options::-webkit-scrollbar {
width: 5px;
}
.multi-select .multi-select-options::-webkit-scrollbar-track {
background: #f0f1f3;
}
.multi-select .multi-select-options::-webkit-scrollbar-thumb {
background: #cdcfd1;
}
.multi-select .multi-select-options::-webkit-scrollbar-thumb:hover {
background: #b2b6b9;
}
.multi-select .multi-select-options .multi-select-option, .multi-select .multi-select-options .multi-select-all {
padding: 4px 12px;
height: 42px;
}
.multi-select .multi-select-options .multi-select-option .multi-select-option-radio, .multi-select .multi-select-options .multi-select-all .multi-select-option-radio {
margin-right: 14px;
height: 16px;
width: 16px;
border: 1px solid #ced4da;
border-radius: 4px;
}
.multi-select .multi-select-options .multi-select-option .multi-select-option-text, .multi-select .multi-select-options .multi-select-all .multi-select-option-text {
box-sizing: border-box;
flex: 1;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
color: inherit;
font-size: 16px;
line-height: 20px;
}
.multi-select .multi-select-options .multi-select-option.multi-select-selected .multi-select-option-radio, .multi-select .multi-select-options .multi-select-all.multi-select-selected .multi-select-option-radio {
border-color: var(--border-color);
background-color: var(--bg-color);
}
.multi-select .multi-select-options .multi-select-option.multi-select-selected .multi-select-option-radio::after, .multi-select .multi-select-options .multi-select-all.multi-select-selected .multi-select-option-radio::after {
content: "";
display: block;
width: 3px;
height: 7px;
margin: 0.12em 0 0 0.27em;
border: solid #fff;
border-width: 0 0.15em 0.15em 0;
transform: rotate(45deg);
}
.multi-select .multi-select-options .multi-select-option.multi-select-selected .multi-select-option-text, .multi-select .multi-select-options .multi-select-all.multi-select-selected .multi-select-option-text {
color: var(--content-fg);
}
.multi-select .multi-select-options .multi-select-option:hover, .multi-select .multi-select-options .multi-select-option:active, .multi-select .multi-select-options .multi-select-all:hover, .multi-select .multi-select-options .multi-select-all:active {
background-color: var(--content-bg);
border-radius: 0;
}
.multi-select .multi-select-options .multi-select-all {
border-bottom: 1px solid #f1f3f5;
border-radius: 0;
}
.multi-select .multi-select-options .multi-select-search {
padding: 7px 10px;
border: 1px solid #dee2e6;
border-radius: 5px;
margin: 10px 10px 5px 10px;
width: 100%;
outline: none;
font-size: 16px;
}
.multi-select .multi-select-options .multi-select-search::placeholder {
color: #b2b5b9;
}
.multi-select .multi-select-header, .multi-select .multi-select-option, .multi-select .multi-select-all {
display: flex;
flex-wrap: wrap;
box-sizing: border-box;
align-items: center;
border-radius: 5px;
cursor: pointer;
display: flex;
align-items: center;
width: 100%;
font-size: 16px;
color: var(--content-fg);
border-color: var(--comfy-input-bg);
background: var(--comfy-input-bg);
min-width: max-content;
}
#t1, #t2{
display: none;
}
#assets_downloader_header {
display: flex;
flex: 1;
position: relative;
width: calc(100% - 5px);
flex-direction: column;
justify-content: space-between;
align-items: center;
height: auto;
margin-top: 10px;
}
#assets_downloader_header input:focus, #assets_downloader_header select:focus, .multi-select .multi-select-header:active {
outline: var(--border-color) solid 2px;
}
#assets_downloader_main a, .sb-mymodels a {
text-decoration: none;
color: #fff;
}
.search-row {
width: 100%;
display: flex;
justify-content: center;
}
.n-sb-searchmodels {
padding: 10px;
font-size: 16px;
border-radius: 4px;
width: 100%; /* Usa tutta la larghezza disponibile nella riga */
max-width: 100%; /* Nessun limite alla larghezza massima */
}
.type-checkpoint {
position: absolute;
top: 0;
right: 0px;
padding: 5px;
background: var(--content-fg);
border-radius: 5px;
margin: 10px 10px 0px 0px !important;
opacity: 0.7;
text-transform: uppercase;
font-weight: bold;
font-size: smaller;
}
#assets_downloader_main .stats, .sb-mymodels .stats {
position: absolute;
bottom: 0;
background: #404040;
padding: 5px;
border-radius: 5px;
color: var(--content-fg);
right: 3px;
}
#assets_downloader_main .username, .sb-mymodels .username {
position: absolute;
bottom: 0px;
right: 0;
margin: 5px;
background: var(--comfy-menu-bg);
padding: 6px;
border-radius: 5px;
}
/* Filtri */
.filters-row {
width: 100%;
max-width: 600px;
display: flex;
flex-wrap: wrap;
justify-content: center;
gap: 3px;
margin-right: 15px;
}
#t1 .filters-row > * {
flex: 1 1 22%;
/* min-width: 120px; */
}
/* Stili per le selezioni */
#assets_downloader_header select {
padding: 10px;
font-size: 16px;
border-radius: 4px;
width: 100%;
max-width: 150px;
height: 42px;
margin-top: 10px;
}
/* Multi-select */
#assets_downloader_header .multi-select {
width: 145px; /* Larghezza massima per il multi-select */
margin-top: 10px;
}
/* Adattamento responsive */
@media (max-width: 768px) {
.filters-row {
flex-direction: column; /* I filtri si dispongono in colonna su schermi più piccoli */
align-items: center; /* Centratura orizzontale dei filtri su schermi più piccoli */
}
select, .multi-select,.n-sb-searchmodels {
width: 100%; /* Usa tutta la larghezza disponibile */
max-width: 100%; /* Nessun limite alla larghezza massima */
}
}
.sb-kebab-menu {
position: relative;
display: inline-block;
color: var(--content-fg);
margin-right: 10px;
display: flex;
align-items: center;
}
.sb-kebab-icon {
font-size: 24px;
cursor: pointer;
}
.sb-menu {
display: none;
position: absolute;
right: 0;
background-color:var(--bg-color);
box-shadow: 0px 8px 16px rgba(0,0,0,0.2);
list-style-type: none;
padding: 10px 0;
margin: 0;
border-radius: 4px;
z-index: 1;
width: max-content !important;
}
.sb-menu li {
padding: 8px 16px;
cursor: pointer;
}
.sb-menu li:hover {
background-color: var(--comfy-menu-bg);
}
.sb-rebuild-bg-pgs {
text-align: left;
width: inherit;
padding-right: 28px;
display: none;
}
.sb-rebuild-bg-pgs label {
font-size: 0.6rem;
line-height: 1.6;
position: absolute;
padding-left: 5px;
}
.sb-rebuild-pgs {
width: 0%;
background: #1da874a6;
border-radius: 1px;
height: 16px;
font-size: 0.7vh;
text-align: center;
animation: pulsate 1.5s ease-in-out infinite;
}
@keyframes pulsate {
0% {
background-color: #1da874a6; /* Colore iniziale */
}
50% {
background-color: #28a745; /* Colore più brillante o diverso */
}
100% {
background-color: #1da874a6; /* Torna al colore iniziale */
}
}
#assets_downloader_main .card, .sb-mymodels .card {
position: relative;
width: 220px;
height: 340px;
overflow: hidden;
border-radius: 10px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
background-size: cover;
background-position: center;
/*box-shadow: 0 0 7px 0px rgb(170 133 32 / 70%); */
cursor: pointer;
}
#assets_downloader_main .card img , .sb-mymodels .card img {
position: absolute;
width: 100%;
height: 100%;
object-fit: cover;
z-index: 1;
}
#assets_downloader_main .header,#assets_downloader_main .footer , .sb-mymodels .header, .sb-mymodels .footer {
position: absolute;
width: 100%;
left: 0;
z-index: 2;
text-align: left;
color: white;
padding: 10px;
}
#assets_downloader_main .header, .sb-mymodels .header {
top: 0;
text-align: left;
width: -moz-available;
width: -webkit-fill-available;
}
#assets_downloader_main .footer, .sb-mymodels .footer {
bottom: 0;
}
#assets_downloader_main .content, .sb-mymodels .content {
/*position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: 2;
text-align: center;*/
color: white;
}
#assets_downloader_main .card .header .main-stripe, .sb-mymodels .card .header .main-stripe {
box-sizing: border-box;
-webkit-box-flex: 0;
}
#assets_downloader_main .card .header .sub-stripe, .sb-mymodels .card .header .sub-stripe, #assets_downloader_main .card .footer .sub-stripe, .sb-mymodels .card .footer .sub-stripe {
display: inline-flex;
-webkit-box-align: center;
align-items: center;
-webkit-box-pack: center;
justify-content: center;
width: auto;
text-transform: uppercase;
font-weight: 700;
letter-spacing: 0.25px;
cursor: inherit;
text-overflow: ellipsis;
overflow: hidden;
background: rgba(0, 0, 0, 0.51);
border: 1px solid transparent;
color: rgb(254, 254, 254);
border-radius: 32px;
height: 26px;
font-size: 9px;
line-height: 18px;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji";
text-decoration: none;
padding: 0px 10.6667px;
box-sizing: border-box;
}
#assets_downloader_main .card .header .main-stripe .separator, .sb-mymodels .card .header .sub-stripe .separator {
margin: -4px 8px;
border-left-color: rgba(255, 255, 255, 0.31);
border-right: 1px solid rgba(0, 0, 0, 0.2);
border-left-width: 1px;
border-left-style: solid;
}
#assets_downloader_main .card .card-main-text, .sb-mymodels .card .card-main-text {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji";
-webkit-tap-highlight-color: transparent;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
color: inherit;
font-size: 1.5vh;
text-decoration: none;
font-weight: 700;
filter: drop-shadow(rgba(0, 0, 0, 0.8) 1px 1px 1px);
line-height: 1.2;
margin-bottom: 5px;
}
#assets_downloader_main .stats-section, .sb-mymodels .stats-section{
-webkit-tap-highlight-color: transparent;
font-size: 11px;
line-height: 18px;
text-decoration: none;
padding: 0px 10.6667px;
box-sizing: border-box;
display: inline-flex;
-webkit-box-align: center;
align-items: center;
width: auto;
font-weight: 700;
letter-spacing: 0.25px;
cursor: inherit;
text-overflow: ellipsis;
overflow: hidden;
background: rgb(0 0 0 / 45%);
border: 1px solid transparent;
align-self: flex-start;
color: rgb(254, 254, 254);
border-radius: 32px;
height: 26px;
}
#assets_downloader_main .card .creator-name, .sb-mymodels .card .creator-name{
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji";
-webkit-tap-highlight-color: transparent;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 1;
-webkit-box-orient: vertical;
color: #ffffff;
font-size: 0.70vw;
line-height: 1.55;
/* text-decoration: none; */
font-weight: 500;
/* background-clip: text; */
/* -webkit-text-fill-color: transparent; */
vertical-align: middle;
filter: drop-shadow(rgba(0, 0, 0, 0.8) 3px 1px 0px);
text-align: left;
padding: 0;
margin: 0px;
}
.card .model-image {
transition: transform 0.3s ease-in-out;
}
/* .card img:hover, .image-overlay:hover{
transform: scale(1.05);
}*/
.card .stat-item i {
padding: 0 5px;
}
/* Overlay con effetto vetro */
.card .image-overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: linear-gradient(to bottom, rgb(14 14 14 / 0%) 0%, rgb(47 47 58 / 79%) 100%);
display: flex;
justify-content: center;
align-items: center;
color: white;
font-size: 24px;
text-align: center;
z-index: 99;
}
.card .progress-container {
width: 100%;
height: 100%;
background-color: #e0e0e0;
position: relative;
}
.card .progress-bar {
z-index: 98;
height: 100%;
background-color: #76c7c04f;
width: 0%;
transition: width 0.3s;
position: absolute;
}
.card .sub-stripe-status{
font-size: 1rem;
background: #00000073;
padding: 3px 10px;
border-radius: 11px;
display: none;
}
.sub-stripe-manager {
display: flex;
flex-direction: column; /* I div figli saranno disposti verticalmente */
align-items: flex-start; /* Allineamento a sinistra */
}
.sub-stripe-manager div {
padding: 2px 9px;
transition: filter 0.3s ease;
}
.sub-stripe-manager div:hover {
filter: brightness(180%); /* Aumenta la luminosità del 10% */
}
.sub-stripe-manager{
position: absolute;
right: 28px;
top: 0;
right: 0;
}
.card .sub-stripe-dw{
background: #ff4141;
border-bottom-left-radius: 6px;
}
.card .sub-stripe-ps{
background: #ff6720;
display: none;
filter: brightness(80%);
}
.card .sub-stripe-cn{
background: #ff4141;
border-bottom-left-radius: 6px;
display: none;
filter: brightness(80%);
}
.card .sub-stripe-complete{
background: #00c027;
display: none;
}
.card .sub-stripe-delete{
background: #ff4141;
border-bottom-left-radius: 6px;
display: none;
}
.sb-pi-toast-center {
padding-top: 5px;
}
@@ -1,26 +1,11 @@
<style>
</style>
<script>
</script>
<div id ="custom_categories_header">
<div class="h-header" id="h_search" data-content="panel_head_home">
<input type="text" id="searchInputCn" oninput="searchT(this)" placeholder="Search..." autocomplete="off" class="">
<input type="text" id="searchInputCn" oninput="custom_categories.searchT(this)" placeholder="Search..." autocomplete="off" class="">
<span class="clearIconCustomCategory">×</span>
<span class="searchCategoryIconCustomCategory" title="Category Only">C</span>
</div>
<button id="openModalButton" onclick="openModal()" title="Add New Category">+</button>
</div>
<button id="openModalButton" onclick="custom_categories.openModal()" class="left" data-tooltip="Add New Category" >+</button>
</div>
<div id="custom_categories_main" >
</div>
@@ -1,5 +1,5 @@
//console.log(LiteGraph.registered_node_types);
var custom_categories = (function () {
let currentElement = null;
function createCustomHtml(type, name, elem = null) {
@@ -7,7 +7,7 @@ function createCustomHtml(type, name, elem = null) {
return `<h2 class="sb-modal-title">Rename Category</h2>
<form id="sb-category-form" action="javascript:void(0);">
<input type="text" autocomplete="off" class="sb-input" id="sb-categoryName" value="${name}" name="sb-categoryName" required>
<button type="submit" class="sb-button" onclick="renameCategory('${name}',document.getElementById('sb-categoryName').value)">Rename Category</button>
<button type="submit" class="sb-button" onclick="custom_categories.renameCategory('${name}',document.getElementById('sb-categoryName').value)">Rename Category</button>
</form>
<button id="closeModalButton" class="sb-button">X</button>
@@ -16,10 +16,10 @@ function createCustomHtml(type, name, elem = null) {
currentElement = elem;
return `<h2 class="sb-modal-title">Color ${name}</h2>
<div class="colorBlob">
<input class="colorBlobPicker" type="color" oninput="colorCategory('${name}',this.value)" value="${rgbToHex(elem.style.backgroundColor)}" id="colorPicker">
<input class="colorBlobPicker" type="color" oninput="custom_categories.colorCategory('${name}',this.value)" value="${rgbToHex(elem.style.backgroundColor)}" id="colorPicker">
</div>
<button type="button" class="sb-button" onclick="resetColorCategory('${name}')">Reset Color</button>
<button type="button" class="sb-button" onclick="removeKeyConfig('sb_ColorCustomCategories') ">Reset All Colors</button>
<button type="button" class="sb-button" onclick="custom_categories.resetColorCategory('${name}')">Reset Color</button>
<button type="button" class="sb-button" onclick="custom_categories.removeKeyConfig('sb_ColorCustomCategories') ">Reset All Colors</button>
<button id="closeModalButton" class="sb-button">X</button>
`
@@ -87,9 +87,9 @@ function afterRender() {
]
],
"menuctx_opt_callback": [
"renameCategoryCallback",
"deleteCategory",
"colorCategoryCallback"
"custom_categories.renameCategoryCallback",
"custom_categories.deleteCategory",
"custom_categories.colorCategoryCallback"
],
"menuctx_sub_opt_callback": [
@@ -111,7 +111,7 @@ function afterRender() {
]
],
"menuctx_opt_callback": [
"removeNodeFromCategoryCallback"
"custom_categories.removeNodeFromCategoryCallback"
],
"menuctx_sub_opt_callback": [
@@ -232,8 +232,9 @@ async function renderList(elementID) {
const value_perc = await getConfiguration("sb_opacity") || "1.0";
const rgbColor = hexToRgb(currentColor);
categoryItem.style.setProperty('background-color', `rgba(${rgbColor}, ${value_perc})`, 'important');
categoryItem.style.backgroundColor = `rgba(${rgbColor}, ${value_perc})`;
//categoryItem.style.backgroundColor = `rgba(${rgbColor}, ${value_perc})`;
}
@@ -337,56 +338,10 @@ async function renderList(elementID) {
sidebarItems_cat.forEach(item => {
item.addEventListener('mouseover', function () {
if (this.classList.contains('sidebarItem') && this.tagName === 'LI') {
let descriptionDiv = "";
const itemPosition = getElementPosition(this);
let previewDivTop = 0;
const [previewContent, node_description] = createNodePreview(item.dataset.type);
if (node_description) {
descriptionDiv = "<div class='sb_description'>" + node_description + "</div>";
}
previewDiv.innerHTML = previewContent + descriptionDiv;
previewDiv.style.display = 'block';
const correction_offset = 45;
if (itemPosition.top - this.offsetHeight >= 0 && itemPosition.top + previewDiv.offsetHeight < document.body.offsetHeight) {
previewDivTop = itemPosition.top - this.offsetHeight
} else if (itemPosition.top - this.offsetHeight - previewDiv.offsetHeight <= 0) {
previewDivTop = 0 + correction_offset;
}
else {
previewDivTop = (itemPosition.top + this.offsetHeight) - previewDiv.offsetHeight;
}
let sidebar_width = parseInt(getVar("sidebarWidth")) || 300;
previewDiv.style.top = `${previewDivTop}px`;
const previewDivLeft = sidebar_width - sidebad_view_width + correction_offset;
if (sbPosition == "left") {
previewDiv.style.left = `${previewDivLeft}px`;
}else {
previewDiv.style.right = `${previewDivLeft}px`;
}
}
getPreview(item,previewDiv,sidebad_view_width,(item) => {
return createNodePreview(item.id);
});
item.addEventListener('mouseout', function () {
previewDiv.style.display = 'none';
})
});
@@ -406,10 +361,6 @@ async function renderList(elementID) {
const categoryItems = document.querySelectorAll("#custom_categories_main .sidebarCategory");
categoryItems.forEach(function (categoryItem) {
categoryItem.addEventListener("click", function (event) {
@@ -579,12 +530,12 @@ async function deleteCategory(e) {
removeNodeMapCategory(name);
createContextualMenu();
removeKeyFromConfig("sb_ColorCustomCategories", name)
reloadCtxMenu()
setTimeout(() => {
renderList("custom_categories_main");
},200)
reloadCtxMenu()
},300)
} else {
alert("Category not found!");
}
@@ -766,8 +717,8 @@ async function colorCategory(name, value) {
const value_perc = await getConfiguration("sb_opacity") || "1.0";
const rgbColor = hexToRgb(value);
currentElement.style.backgroundColor = `rgba(${rgbColor}, ${value_perc})`;
currentElement.style.setProperty('background-color', `rgba(${rgbColor}, ${value_perc})`, 'important');
assignValueToConfig("sb_ColorCustomCategories", name, value)
}
@@ -795,7 +746,7 @@ async function createContextualMenu() {
category_menu = await readCategories();
callback_menu = [];
for (let i = 0; i < category_menu.length; i++) {
callback_menu.push("assignNodeToCategoryCallback");
callback_menu.push("custom_categories.assignNodeToCategoryCallback");
}
new_submenu_options.push(category_menu);
@@ -837,7 +788,30 @@ searchCategoryIconCustomCategory.addEventListener("click", async function () {
console.error("Error occurred during search:", error);
}
});
return {
openModal,
addSidebarStyles,
createContextualMenu,
renderList,
renameCategory,
colorCategory,
removeKeyConfig,
searchT,
deleteCategory,
addCategory,
editNodeCategory,
removeNodeMapCategory,
reorderNodeInCategory,
removeNodeFromCategoryCallback,
assignNodeToCategoryCallback,
renameCategoryCallback,
renameCategoryCallback,
colorCategoryCallback,
resetColorCategory
};
addSidebarStyles("panels/custom_categories/style.css");
createContextualMenu()
renderList("custom_categories_main");
})();
custom_categories.addSidebarStyles("panels/custom_categories/style.css");
custom_categories.createContextualMenu()
custom_categories.renderList("custom_categories_main");
+1
View File
@@ -37,6 +37,7 @@ float: right;
position: relative;
margin: 3px 2px 2px 8px;
cursor: pointer;
z-index: 999;
}
#custom_categories_header button:hover {border: 2px solid var(--descrip-text);
@@ -6,8 +6,8 @@
<span class="searchTemplateIconCustomTemplate" title="Category Only">C</span>
</div>
<button id="openModalButton" onclick="custom_templates.openModal()" title="Add New Template">+</button>
<button id="refreshlButton" onclick="custom_templates.renderList('custom_templates_main')" title="Refresh">↻</button>
<button id="openModalButton" onclick="custom_templates.openModal()" class="left" data-tooltip="Add New Template">+</button>
<button id="refreshlButton" onclick="custom_templates.renderList('custom_templates_main')" class="left" data-tooltip="Refresh">↻</button>
</div>
<div id="custom_templates_main">
</div>
@@ -253,10 +253,10 @@ var custom_templates = (function () {
customMenuItemJSONOut = JSON.parse(customMenuTemplateItemOut);
setContextMenu(customMenuJSON, "#custom_templates_main .sidebarCategory", 0, "sidebarItem", "sidebarCategory");
//setContextMenu(customMenuItemJSONOut, "#custom_templates_main .sidebarItem");
setContextMenu(customMenuItemJSON, "#custom_templates_main .displayNamesList .sidebarItem");
// ORDER CUSTOM CATEGORIES
const custom_templates_main = document.getElementById("custom_templates_main");
@@ -286,7 +286,9 @@ var custom_templates = (function () {
item.addEventListener("dragstart", handleTemplateDragStart);
});
}
// handler
function handleTemplateDragStart(event) {
dragItem = event.target;
}
@@ -447,8 +449,8 @@ var custom_templates = (function () {
const value_perc = await getConfiguration("sb_opacity") || "1.0";
const rgbColor = hexToRgb(currentColor);
templateItem.style.backgroundColor = `rgba(${rgbColor}, ${value_perc})`;
templateItem.style.setProperty('background-color', `rgba(${rgbColor}, ${value_perc})`, 'important');
}
@@ -476,9 +478,6 @@ var custom_templates = (function () {
displayNameItem.draggable = true;
exclusion_list.push(displayName);
@@ -552,6 +551,7 @@ var custom_templates = (function () {
}
@@ -562,95 +562,41 @@ var custom_templates = (function () {
const sidebarItems_cat = document.querySelectorAll('#' + elementID + ' .sidebarItem');
const previewDiv = document.getElementById('previewDiv');
let sidebad_view_width = document.getElementById("sidebar_views").offsetWidth;
const previewFunction = (item) => {
const previewContent = createTemplatePreview(item.dataset.nametemplate, item.dataset.data);
return [previewContent, null];
};
sidebarItems_cat.forEach(item => {
item.addEventListener('mouseover', function () {
if (this.classList.contains('sidebarItem') && this.tagName === 'LI') {
let descriptionDiv = "";
const itemPosition = getElementPosition(this);
let previewDivTop = 0;
const previewContent = createTemplatePreview(item.dataset.nametemplate, item.dataset.data);
previewDiv.innerHTML = previewContent + descriptionDiv;
previewDiv.style.display = 'block';
const correction_offset = 45;
if (itemPosition.top - this.offsetHeight >= 0 && itemPosition.top + previewDiv.offsetHeight < document.body.offsetHeight) {
previewDivTop = itemPosition.top - this.offsetHeight
} else if (itemPosition.top - this.offsetHeight - previewDiv.offsetHeight <= 0) {
previewDivTop = 0 + correction_offset;
}
else {
previewDivTop = (itemPosition.top + this.offsetHeight) - previewDiv.offsetHeight;
}
let sidebar_width = parseInt(getVar("sidebarWidth")) || 500;
previewDiv.style.top = `${previewDivTop}px`;
const previewDivLeft = sidebar_width - sidebad_view_width+correction_offset;
if (sbPosition == "left") {
previewDiv.style.left = `${previewDivLeft}px`;
} else {
previewDiv.style.right = `${previewDivLeft}px`;
}
sidebarItems_cat.forEach(item => {
getPreview(item,previewDiv,sidebad_view_width,previewFunction);
});
window.addEventListener('click', function (event) {
if (!event.target.classList.contains('sidebarItem')) {
previewDiv.style.display = 'none';
}
});
item.addEventListener('mouseout', function () {
previewDiv.style.display = 'none';
})
});
const templateItems = document.querySelectorAll("#custom_templates_main .sidebarCategory");
templateItems.forEach(function (templateItem) {
templateItem.addEventListener("click", function (event) {
if (event.target === event.currentTarget) {
const displayNamesList = event.target.querySelector("ul");
displayNamesList.style.display = displayNamesList.style.display === "none" ? "block" : "none";
window.addEventListener('click', function (event) {
if (!event.target.classList.contains('sidebarItem')) {
previewDiv.style.display = 'none';
setNodeStatus('sb_templateNodeStatus',displayNamesList.parentElement.dataset.nametemplate, displayNamesList.style.display)
}
});
const templateItems = document.querySelectorAll("#custom_templates_main .sidebarCategory");
templateItems.forEach(function (templateItem) {
templateItem.addEventListener("click", function (event) {
if (event.target === event.currentTarget) {
const displayNamesList = event.target.querySelector("ul");
displayNamesList.style.display = displayNamesList.style.display === "none" ? "block" : "none";
setNodeStatus('sb_templateNodeStatus',displayNamesList.parentElement.dataset.nametemplate, displayNamesList.style.display)
}
});
});
resolve(afterRender);
});
resolve(afterRender);
@@ -1162,7 +1108,7 @@ var custom_templates = (function () {
const value_perc = await getConfiguration("sb_opacity") || "1.0";
const rgbColor = hexToRgb(value);
currentElement.style.backgroundColor = `rgba(${rgbColor}, ${value_perc})`;
currentElement.style.setProperty('background-color', `rgba(${rgbColor}, ${value_perc})`, 'important');
assignValueToConfig("sb_ColorCustomTemplates", name, value)
@@ -1181,12 +1127,12 @@ var custom_templates = (function () {
//const menuOptions = document.getElementById('menu-options');
//new_menu_options_callback = [];
//for each template
template_menu = await readTemplates();
/*template_menu = await readTemplates();
callback_menu = [];
for (let i = 0; i < template_menu.length; i++) {
callback_menu.push("assignNodeToTemplateCallback");
}
}*/
console.log("custom template panel loaded")
+2 -1
View File
@@ -6,7 +6,7 @@
margin: 0;
}
#custom_templates_main{
height: auto;
padding-top: 0px;
padding-bottom: 150px;
}
@@ -37,6 +37,7 @@ float: right;
position: relative;
margin: 3px 2px 2px 2px;
cursor: pointer;
z-index: 999;
}
#custom_templates_header button:hover {
@@ -6,8 +6,8 @@
<span class="searchWorkflowIconCustomWorkflow" title="Category Only">C</span>
</div>
<button id="openModalButton" onclick="custom_workflows.openModal()" title="Add New Workflow">+</button>
<button id="refreshlButton" onclick="custom_workflows.renderList('custom_workflows_main')" title="Refresh">↻</button>
<button id="openModalButton" onclick="custom_workflows.openModal()" data-tooltip="Add New Workflow">+</button>
<button id="refreshlButton" onclick="custom_workflows.renderList('custom_workflows_main')" data-tooltip="Refresh">↻</button>
</div>
<div id="custom_workflows_main">
<div></div>
@@ -593,7 +593,8 @@ var custom_workflows = (function () {
const rgbColor = hexToRgb(currentColor);
workflowItem.style.backgroundColor = `rgba(${rgbColor}, ${value_perc})`;
workflowItem.style.setProperty('background-color', `rgba(${rgbColor}, ${value_perc})`, 'important');
}
@@ -689,76 +690,32 @@ var custom_workflows = (function () {
const previewDiv = document.getElementById('previewDiv');
let sidebad_view_width = document.getElementById("sidebar_views").offsetWidth;
sidebarItems_cat.forEach(item => {
item.addEventListener('mouseover', async function () {
const preview = JSON.parse(await getConfiguration('sb_workflow_preview', true))
const configFunction = async () => {
const preview = JSON.parse(await getConfiguration('sb_workflow_preview', true));
return preview;
};
const previewFunction = async (item) => {
const previewContent = await createWorkflowPreview(item.dataset.nameworkflow, item.dataset.data);
return [previewContent, null];
};
const preview = JSON.parse(await getConfiguration('sb_workflow_preview', true))
// Preview
if (preview) {
if (this.classList.contains('sidebarItem') && this.tagName === 'LI') {
let descriptionDiv = "";
const itemPosition = getElementPosition(this);
let previewDivTop = 0;
const previewContent = await createWorkflowPreview(item.dataset.nameworkflow, item.dataset.data);
sidebarItems_cat.forEach(item => {
if (preview) {
getPreview(item,previewDiv,sidebad_view_width, previewFunction, configFunction);
}
});
previewDiv.innerHTML = previewContent + descriptionDiv;
previewDiv.style.display = 'block';
const correction_offset = 45;
window.addEventListener('click', function (event) {
if (itemPosition.top - this.offsetHeight >= 0 && itemPosition.top + previewDiv.offsetHeight < document.body.offsetHeight) {
previewDivTop = itemPosition.top - this.offsetHeight
if (!event.target.classList.contains('sidebarItem')) {
previewDiv.style.display = 'none';
} else if (itemPosition.top - this.offsetHeight - previewDiv.offsetHeight <= 0) {
previewDivTop = 0 + correction_offset;
}
else {
previewDivTop = (itemPosition.top + this.offsetHeight) - previewDiv.offsetHeight;
}
let sidebar_width = parseInt(getVar("sidebarWidth")) || 500;
previewDiv.style.top = `${previewDivTop}px`;
const previewDivLeft = sidebar_width - sidebad_view_width+correction_offset;
if (sbPosition == "left") {
previewDiv.style.left = `${previewDivLeft}px`;
} else {
previewDiv.style.right = `${previewDivLeft}px`;
}
}
}
});
item.addEventListener('mouseout', function () {
previewDiv.style.display = 'none';
})
});
window.addEventListener('click', function (event) {
if (!event.target.classList.contains('sidebarItem')) {
previewDiv.style.display = 'none';
}
});
}
});
@@ -1016,7 +973,7 @@ var custom_workflows = (function () {
renameWorkflowNode("sb_workflowNodeMap", oldWorkflowNameHash, newWorkflowNameHash)
const element = document.getElementById('panel_workflows');
const element = document.getElementById('custom_workflows_main');
let position = element.scrollTop;
closeModal()
renderList("custom_workflows_main");
@@ -1182,7 +1139,8 @@ var custom_workflows = (function () {
workflowNodeMap[workflowName].push(nodeName);
});
updateConfiguration('sb_workflowNodeMap', JSON.stringify(workflowNodeMap));
const element = document.getElementById('panel_workflows');
const element = document.getElementById('custom_workflows_main');
let position = element.scrollTop;
renderList("custom_workflows_main");
@@ -1307,7 +1265,7 @@ var custom_workflows = (function () {
const value_perc = await getConfiguration("sb_opacity") || "1.0";
const rgbColor = hexToRgb(value);
currentElement.style.backgroundColor = `rgba(${rgbColor}, ${value_perc})`;
currentElement.style.setProperty('background-color', `rgba(${rgbColor}, ${value_perc})`, 'important');
assignValueToConfig("sb_ColorCustomWorkflows", name, value)
@@ -1323,18 +1281,6 @@ var custom_workflows = (function () {
async function createContextualMenu() {
//const menuOptions = document.getElementById('menu-options');
//new_menu_options_callback = [];
//for each workflow
//workflow_menu = await readWorkflows();
//callback_menu = [];
//for (let i = 0; i < workflow_menu.length; i++) {
// callback_menu.push("assignNodeToWorkflowCallback");
//}
console.log("custom workflow panel loaded")
}
+1
View File
@@ -37,6 +37,7 @@ float: right;
position: relative;
margin: 3px 2px 2px 2px;
cursor: pointer;
z-index: 999;
}
#custom_workflows_header button:hover {
+25
View File
@@ -0,0 +1,25 @@
.terminal {
width: 100%;
height: 400px;
background-color: #000;
padding: 10px;
overflow-y: auto;
white-space: pre-wrap; /* Maintains spaces and line breaks */
}
.input-area {
display: flex;
}
.input-field {
flex: 1;
background-color: #333;
color: #fff;
border: none;
padding: 5px;
}
.submit-btn {
background-color: #007bff;
color: #fff;
padding: 5px 10px;
border: none;
cursor: pointer;
}
+13
View File
@@ -0,0 +1,13 @@
<div id="custom_example_header">
</div>
<div id="custom_example_main">
<div class="terminal" id="terminal-output">
</div>
<div class="input-area">
<input type="text" id="terminal-input" class="input-field" placeholder="Enter command...">
<button class="submit-btn" onclick="custom_example.sendCommand()">Send</button>
</div>
</div>
+87
View File
@@ -0,0 +1,87 @@
var custom_example= (function () {
let history = [];
let historyIndex = -1;
function escapeHtml(html) {
const text = document.createTextNode(html);
const p = document.createElement('p');
p.appendChild(text);
return p.innerHTML;
}
function sendCommand() {
const inputField = document.getElementById('terminal-input');
const command = inputField.value;
if (command.trim() === '') return;
// Add command to terminal
document.getElementById('terminal-output').innerHTML += `<div>> ${escapeHtml(command)}</div>`;
// Send command to backend
fetch('/sidebar/execute', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ command }),
})
.then(response => response.json())
.then(data => {
// Display output
const output = data.output;//.replace(/\n/g, '<br>'); // Convert line breaks to <br>
document.getElementById('terminal-output').innerHTML += `<div>${escapeHtml(output)}</div>`;
// Scroll to the bottom
const terminal = document.getElementById('terminal-output');
terminal.scrollTop = terminal.scrollHeight;
})
.catch(error => {
document.getElementById('terminal-output').innerHTML += `<div>Error: ${escapeHtml(error.message)}</div>`;
// Scroll to the bottom
const terminal = document.getElementById('terminal-output');
terminal.scrollTop = terminal.scrollHeight;
});
// Add command to history and clear input field
if (history.length === 0 || history[history.length - 1] !== command) {
history.push(command);
}
historyIndex = history.length;
inputField.value = '';
}
function handleKeyDown(event) {
const inputField = document.getElementById('terminal-input');
if (event.key === 'Enter') {
event.preventDefault(); // Prevent the default action (form submission or newline)
sendCommand();
} else if (event.key === 'ArrowUp') {
event.preventDefault();
if (historyIndex > 0) {
historyIndex--;
inputField.value = history[historyIndex];
}
} else if (event.key === 'ArrowDown') {
event.preventDefault();
if (historyIndex < history.length - 1) {
historyIndex++;
inputField.value = history[historyIndex];
} else {
historyIndex = history.length;
inputField.value = '';
}
}
}
// Add event listener for Enter key and Arrow keys
document.getElementById('terminal-input').addEventListener('keydown', handleKeyDown);
return {
sendCommand
};
})();
addSidebarStyles("panels/terminal/style.css?v=3421");
+42 -31
View File
@@ -1,31 +1,42 @@
[
{
"id": "custom_categories",
"icon": "⌬",
"description": "Custom Node Categories",
"panels": [
"custom_categories"
]
},
{
"id": "templates",
"icon": "Τ",
"description": "Templates list",
"panels": [
"custom_templates"
]
},
{
"id": "workflows",
"icon": "W",
"description": "Workflows list",
"panels": [
"custom_workflows"
]
}
]
[
{
"id": "custom_categories",
"description": "Custom Node Categories",
"icon": "⌬",
"panels": [
"custom_categories"
]
},
{
"id": "custom_templates",
"description": "Templates list",
"icon": "Τ",
"panels": [
"custom_templates"
]
},
{
"id": "custom_workflows",
"description": "Workflows list",
"icon": "W",
"panels": [
"custom_workflows"
]
},
{
"id": "section_-281285428",
"description": "Assets Downloader",
"icon": "A",
"panels": [
"assets_downloader"
]
},
{
"id": "section_-1116604772",
"description": "Terminal",
"icon": ">",
"panels": [
"terminal"
]
}
]
+42
View File
@@ -0,0 +1,42 @@
[
{
"id": "custom_categories",
"description": "Custom Node Categories",
"icon": "⌬",
"panels": [
"custom_categories"
]
},
{
"id": "custom_templates",
"description": "Templates list",
"icon": "Τ",
"panels": [
"custom_templates"
]
},
{
"id": "custom_workflows",
"description": "Workflows list",
"icon": "W",
"panels": [
"custom_workflows"
]
},
{
"id": "assets_downloader",
"description": "Assets Downloader",
"icon": "A",
"panels": [
"assets_downloader"
]
},
{
"id": "section_terminal",
"description": "Terminal",
"icon": ">",
"panels": [
"terminal"
]
}
]
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 MiB

+1 -1
View File
@@ -1,7 +1,7 @@
[project]
name = "comfyui-n-sidebar"
description = "A simple sidebar for ComfyUI."
version = "1.2.8"
version = "1.5.0"
license = { file = "LICENSE" }
[project.urls]
+1
View File
@@ -0,0 +1 @@
aiofiles