Răsfoiți Sursa

Finish base layout. Fix bugs. Need to test for stability and clean up.

Sj-Si 1 an în urmă
părinte
comite
0726a6e12e

+ 4 - 1
extensions-builtin/Lora/ui_extra_networks_lora.py

@@ -24,13 +24,16 @@ class ExtraNetworksPageLora(ui_extra_networks.ExtraNetworksPage):
 
 
         alias = lora_on_disk.get_alias()
         alias = lora_on_disk.get_alias()
 
 
+        search_terms = [self.search_terms_from_path(lora_on_disk.filename)]
+        if lora_on_disk.hash:
+            search_terms.append(lora_on_disk.hash)
         item = {
         item = {
             "name": name,
             "name": name,
             "filename": lora_on_disk.filename,
             "filename": lora_on_disk.filename,
             "shorthash": lora_on_disk.shorthash,
             "shorthash": lora_on_disk.shorthash,
             "preview": self.find_preview(path),
             "preview": self.find_preview(path),
             "description": self.find_description(path),
             "description": self.find_description(path),
-            "search_term": self.search_terms_from_path(lora_on_disk.filename) + " " + (lora_on_disk.hash or ""),
+            "search_terms": search_terms,
             "local_preview": f"{path}.{shared.opts.samples_format}",
             "local_preview": f"{path}.{shared.opts.samples_format}",
             "metadata": lora_on_disk.metadata,
             "metadata": lora_on_disk.metadata,
             "sort_keys": {'default': index, **self.get_sort_keys(lora_on_disk.filename)},
             "sort_keys": {'default': index, **self.get_sort_keys(lora_on_disk.filename)},

+ 1 - 3
html/extra-networks-card.html

@@ -6,9 +6,7 @@
 		{edit_button}
 		{edit_button}
 	</div>
 	</div>
 	<div class='actions'>
 	<div class='actions'>
-		<div class='additional'>
-			<span style="display:none" class='search_term{search_only}'>{search_term}</span>
-		</div>
+		<div class='additional'>{search_terms}</div>
 		<span class='name'>{name}</span>
 		<span class='name'>{name}</span>
 		<span class='description'>{description}</span>
 		<span class='description'>{description}</span>
 	</div>
 	</div>

+ 0 - 3
html/extra-networks-pane.html

@@ -1,6 +1,3 @@
-<div id='{tabname}_{network_type_id}_subdirs' class='extra-network-subdirs extra-network-subdirs-cards'>
-    {subdirs_html}
-</div>
 <div id='{tabname}_{network_type_id}_pane' class='extra-network-pane'>
 <div id='{tabname}_{network_type_id}_pane' class='extra-network-pane'>
     <div id='{tabname}_{network_type_id}_tree' class='extra-network-tree'>
     <div id='{tabname}_{network_type_id}_tree' class='extra-network-tree'>
         {tree_html}
         {tree_html}

+ 23 - 25
javascript/extraNetworks.js

@@ -24,8 +24,6 @@ function setupExtraNetworksForTab(tabname) {
     var sort = gradioApp().getElementById(tabname + '_extra_sort');
     var sort = gradioApp().getElementById(tabname + '_extra_sort');
     var sortOrder = gradioApp().getElementById(tabname + '_extra_sortorder');
     var sortOrder = gradioApp().getElementById(tabname + '_extra_sortorder');
     var refresh = gradioApp().getElementById(tabname + '_extra_refresh');
     var refresh = gradioApp().getElementById(tabname + '_extra_refresh');
-    var showDirsDiv = gradioApp().getElementById(tabname + '_extra_show_dirs');
-    var showDirs = gradioApp().querySelector('#' + tabname + '_extra_show_dirs input');
     var promptContainer = gradioApp().querySelector('.prompt-container-compact#' + tabname + '_prompt_container');
     var promptContainer = gradioApp().querySelector('.prompt-container-compact#' + tabname + '_prompt_container');
     var negativePrompt = gradioApp().querySelector('#' + tabname + '_neg_prompt');
     var negativePrompt = gradioApp().querySelector('#' + tabname + '_neg_prompt');
 
 
@@ -33,14 +31,14 @@ function setupExtraNetworksForTab(tabname) {
     tabs.appendChild(sort);
     tabs.appendChild(sort);
     tabs.appendChild(sortOrder);
     tabs.appendChild(sortOrder);
     tabs.appendChild(refresh);
     tabs.appendChild(refresh);
-    tabs.appendChild(showDirsDiv);
 
 
     var applyFilter = function() {
     var applyFilter = function() {
         var searchTerm = search.value.toLowerCase();
         var searchTerm = search.value.toLowerCase();
 
 
         gradioApp().querySelectorAll('#' + tabname + '_extra_tabs div.card').forEach(function(elem) {
         gradioApp().querySelectorAll('#' + tabname + '_extra_tabs div.card').forEach(function(elem) {
             var searchOnly = elem.querySelector('.search_only');
             var searchOnly = elem.querySelector('.search_only');
-            var text = elem.querySelector('.name').textContent.toLowerCase() + " " + elem.querySelector('.search_term').textContent.toLowerCase();
+
+            var text = Array.prototype.map.call(elem.querySelectorAll('.search_terms'), function(t) { return t.textContent.toLowerCase() }).join(" ");
 
 
             var visible = text.indexOf(searchTerm) != -1;
             var visible = text.indexOf(searchTerm) != -1;
 
 
@@ -100,15 +98,6 @@ function setupExtraNetworksForTab(tabname) {
 
 
     extraNetworksApplySort[tabname] = applySort;
     extraNetworksApplySort[tabname] = applySort;
     extraNetworksApplyFilter[tabname] = applyFilter;
     extraNetworksApplyFilter[tabname] = applyFilter;
-
-    var showDirsUpdate = function() {
-        var css = '#' + tabname + '_extra_tabs .extra-network-subdirs { display: none; }';
-        toggleCss(tabname + '_extra_show_dirs_style', css, !showDirs.checked);
-        localSet('extra-networks-show-dirs', showDirs.checked ? 1 : 0);
-    };
-    showDirs.checked = localGet('extra-networks-show-dirs', 1) == 1;
-    showDirs.addEventListener("change", showDirsUpdate);
-    showDirsUpdate();
 }
 }
 
 
 function extraNetworksMovePromptToTab(tabname, id, showPrompt, showNegativePrompt) {
 function extraNetworksMovePromptToTab(tabname, id, showPrompt, showNegativePrompt) {
@@ -136,14 +125,23 @@ function extraNetworksMovePromptToTab(tabname, id, showPrompt, showNegativePromp
     }
     }
 }
 }
 
 
+function clearSearch(tabname) {
+    // Clear search box.
+    var tab_id = tabname + "_extra_search";
+    var searchTextarea = gradioApp().querySelector("#" + tab_id + ' > label > textarea');
+    searchTextarea.value = "";
+    updateInput(searchTextarea);
+}
+
 
 
-function extraNetworksUrelatedTabSelected(tabname) { // called from python when user selects an unrelated tab (generate)
+function extraNetworksUnrelatedTabSelected(tabname) { // called from python when user selects an unrelated tab (generate)
     extraNetworksMovePromptToTab(tabname, '', false, false);
     extraNetworksMovePromptToTab(tabname, '', false, false);
+    clearSearch(tabname);
 }
 }
 
 
 function extraNetworksTabSelected(tabname, id, showPrompt, showNegativePrompt) { // called from python when user selects an extra networks tab
 function extraNetworksTabSelected(tabname, id, showPrompt, showNegativePrompt) { // called from python when user selects an extra networks tab
     extraNetworksMovePromptToTab(tabname, id, showPrompt, showNegativePrompt);
     extraNetworksMovePromptToTab(tabname, id, showPrompt, showNegativePrompt);
-
+    clearSearch(tabname);
 }
 }
 
 
 function applyExtraNetworkFilter(tabname) {
 function applyExtraNetworkFilter(tabname) {
@@ -254,6 +252,15 @@ function saveCardPreview(event, tabname, filename) {
 }
 }
 
 
 function extraNetworksFolderClick(event, tabs_id) {
 function extraNetworksFolderClick(event, tabs_id) {
+    // If folder is open but not selected, we don't want to collapse it. Instead
+    // we override the removal of the "open" attribute so that the folder is
+    // only selected but remains open. Since this is a toggle event, removing
+    // the "open" attribute instead forces the event to add it back which keeps it open.
+    if (event.target.parentElement.open && !event.target.classList.contains("selected")) {
+        // before event handler removes "open"
+        event.target.parentElement.removeAttribute("open");
+    }
+
     var els = document.querySelectorAll(".folder-item-summary.selected");
     var els = document.querySelectorAll(".folder-item-summary.selected");
     [...els].forEach(el => {
     [...els].forEach(el => {
         el.classList.remove("selected");
         el.classList.remove("selected");
@@ -261,18 +268,9 @@ function extraNetworksFolderClick(event, tabs_id) {
     event.target.classList.add("selected");
     event.target.classList.add("selected");
 
 
     var searchTextArea = gradioApp().querySelector("#" + tabs_id + ' > label > textarea');
     var searchTextArea = gradioApp().querySelector("#" + tabs_id + ' > label > textarea');
-    var text = event.target.classList.contains("search-all") ? "" : event.target.firstChild.textContent.trim();
+    var text = event.target.classList.contains("search-all") ? "" : event.target.getAttribute("data-path");
     searchTextArea.value = text;
     searchTextArea.value = text;
     updateInput(searchTextArea);
     updateInput(searchTextArea);
-
-    if (event.target.parentElement.open) {
-        // before close
-        console.log("closed");
-    } else {
-        // before open
-        console.log("opened");
-        //console.log("Opened:", event.target.parentElement);
-    }
 }
 }
 
 
 function extraNetworksSearchButton(tabs_id, event) {
 function extraNetworksSearchButton(tabs_id, event) {

+ 39 - 74
modules/ui_extra_networks.py

@@ -48,23 +48,24 @@ def get_tree(paths: Union[str, list[str]], items: dict[str, ExtraNetworksItem])
     if isinstance(paths, (str,)):
     if isinstance(paths, (str,)):
         paths = [paths]
         paths = [paths]
 
 
-    def _get_tree(_paths: list[str]):
+    def _get_tree(_paths: list[str], _root: str):
         _res = {}
         _res = {}
         for path in _paths:
         for path in _paths:
+            relpath = os.path.relpath(path, _root)
             if os.path.isdir(path):
             if os.path.isdir(path):
                 dir_items = os.listdir(path)
                 dir_items = os.listdir(path)
                 # Ignore empty directories.
                 # Ignore empty directories.
                 if not dir_items:
                 if not dir_items:
                     continue
                     continue
-                dir_tree = _get_tree([os.path.join(path, x) for x in dir_items])
+                dir_tree = _get_tree([os.path.join(path, x) for x in dir_items], _root)
                 # We only want to store non-empty folders in the tree.
                 # We only want to store non-empty folders in the tree.
                 if dir_tree:
                 if dir_tree:
-                    _res[os.path.basename(path)] = dir_tree
+                    _res[relpath] = dir_tree
             else:
             else:
                 if path not in items:
                 if path not in items:
                     continue
                     continue
                 # Add the ExtraNetworksItem to the result.
                 # Add the ExtraNetworksItem to the result.
-                _res[os.path.basename(path)] = items[path]
+                _res[relpath] = items[path]
         return _res
         return _res
 
 
     res = {}
     res = {}
@@ -73,11 +74,13 @@ def get_tree(paths: Union[str, list[str]], items: dict[str, ExtraNetworksItem])
     # the value can be an empty dict if the directory is empty. We want these
     # the value can be an empty dict if the directory is empty. We want these
     # placeholders for empty dirs so we can inform the user later.
     # placeholders for empty dirs so we can inform the user later.
     for path in paths:
     for path in paths:
-        short_path = os.path.basename(path)
+        root = os.path.dirname(path)
+        relpath = os.path.relpath(path, root)
         # Wrap the path in a list since that is what the `_get_tree` expects.
         # Wrap the path in a list since that is what the `_get_tree` expects.
-        res[short_path] = _get_tree([path])
-        if res[short_path]:
-            res[short_path] = res[short_path][os.path.basename(path)]
+        res[relpath] = _get_tree([path], root)
+        if res[relpath]:
+            # We need to pull the inner path out one for these root dirs.
+            res[relpath] = res[relpath][relpath]
 
 
     return res
     return res
 
 
@@ -245,6 +248,17 @@ class ExtraNetworksPage:
 
 
         sort_keys = " ".join([f'data-sort-{k}="{html.escape(str(v))}"' for k, v in item.get("sort_keys", {}).items()]).strip()
         sort_keys = " ".join([f'data-sort-{k}="{html.escape(str(v))}"' for k, v in item.get("sort_keys", {}).items()]).strip()
 
 
+        search_terms_html = ""
+        search_term_template = "<span style='{style}' class='{class}'>{search_term}</span>"
+        for search_term in item.get("search_terms", []):
+            search_terms_html += search_term_template.format(
+                **{
+                    "style": "display: none;",
+                    "class": "search_terms" + (" search_only" if search_only else ""),
+                    "search_term": search_term,
+                }
+            )
+
         # Some items here might not be used depending on HTML template used.
         # Some items here might not be used depending on HTML template used.
         args = {
         args = {
             "background_image": background_image,
             "background_image": background_image,
@@ -258,7 +272,7 @@ class ExtraNetworksPage:
             "prompt": item.get("prompt", None),
             "prompt": item.get("prompt", None),
             "save_card_preview": '"' + html.escape(f"""return saveCardPreview(event, {quote_js(tabname)}, {quote_js(item["local_preview"])})""") + '"',
             "save_card_preview": '"' + html.escape(f"""return saveCardPreview(event, {quote_js(tabname)}, {quote_js(item["local_preview"])})""") + '"',
             "search_only": " search_only" if search_only else "",
             "search_only": " search_only" if search_only else "",
-            "search_term": item.get("search_term", ""),
+            "search_terms": search_terms_html,
             "sort_keys": sort_keys,
             "sort_keys": sort_keys,
             "style": f"'display: none; {height}{width}; font-size: {shared.opts.extra_networks_card_text_scale*100}%'",
             "style": f"'display: none; {height}{width}; font-size: {shared.opts.extra_networks_card_text_scale*100}%'",
             "tabname": quote_js(tabname),
             "tabname": quote_js(tabname),
@@ -278,7 +292,7 @@ class ExtraNetworksPage:
         Returns:
         Returns:
             HTML string generated for this tree view.
             HTML string generated for this tree view.
         """
         """
-        res = f""
+        res = ""
 
 
         # Generate HTML for the tree.
         # Generate HTML for the tree.
         roots = self.allowed_directories_for_previews()
         roots = self.allowed_directories_for_previews()
@@ -291,7 +305,8 @@ class ExtraNetworksPage:
         file_template = "<li class='file-item'>{card}</li>"
         file_template = "<li class='file-item'>{card}</li>"
         dir_template = (
         dir_template = (
             "<details {attributes} class='folder-item'>"
             "<details {attributes} class='folder-item'>"
-            "<summary class='folder-item-summary' onclick='extraNetworksFolderClick(event, \"{tabname}_extra_search\");'>"
+            "<summary class='folder-item-summary' data-path='{data_path}' "
+            "onclick='extraNetworksFolderClick(event, \"{tabname}_extra_search\");'>"
             "{folder_name}"
             "{folder_name}"
             "</summary>"
             "</summary>"
             "<ul class='folder-container'>{content}</ul>"
             "<ul class='folder-container'>{content}</ul>"
@@ -309,16 +324,15 @@ class ExtraNetworksPage:
                     item_html = self.create_item_html(tabname, v.item, self.card_page_minimal_template)
                     item_html = self.create_item_html(tabname, v.item, self.card_page_minimal_template)
                     _res += file_template.format(**{"card": item_html})
                     _res += file_template.format(**{"card": item_html})
                 else:
                 else:
-                    tmp = dir_template.format(
+                    _res += dir_template.format(
                         **{
                         **{
                             "attributes": "",
                             "attributes": "",
                             "tabname": tabname,
                             "tabname": tabname,
-                            "folder_name": k,
+                            "folder_name": os.path.basename(k),
+                            "data_path": k,
                             "content": _build_tree(v),
                             "content": _build_tree(v),
                         }
                         }
                     )
                     )
-                    _res += tmp
-                    
             return _res
             return _res
 
 
         # Add each root directory to the tree.
         # Add each root directory to the tree.
@@ -329,65 +343,15 @@ class ExtraNetworksPage:
                 **{
                 **{
                     "attributes": "open" if v else "open",
                     "attributes": "open" if v else "open",
                     "tabname": tabname,
                     "tabname": tabname,
-                    "folder_name": k,
+                    "folder_name": os.path.basename(k),
+                    "data_path": k,
                     "content": _build_tree(v),
                     "content": _build_tree(v),
                 }
                 }
             )
             )
             res += "</ul>"
             res += "</ul>"
         res += "</ul>"
         res += "</ul>"
-
         return res
         return res
 
 
-    def create_subdirs_html(self, tabname):
-        subdirs = {}
-
-        for parentdir in [os.path.abspath(x) for x in self.allowed_directories_for_previews()]:
-            for root, dirs, _ in sorted(os.walk(parentdir, followlinks=True), key=lambda x: shared.natural_sort_key(x[0])):
-                for dirname in sorted(dirs, key=shared.natural_sort_key):
-                    x = os.path.join(root, dirname)
-
-                    if not os.path.isdir(x):
-                        continue
-
-                    subdir = os.path.abspath(x)[len(parentdir):].replace("\\", "/")
-
-                    if shared.opts.extra_networks_dir_button_function:
-                        if not subdir.startswith("/"):
-                            subdir = "/" + subdir
-                    else:
-                        while subdir.startswith("/"):
-                            subdir = subdir[1:]
-
-                    is_empty = len(os.listdir(x)) == 0
-                    if not is_empty and not subdir.endswith("/"):
-                        subdir = subdir + "/"
-
-                    if ("/." in subdir or subdir.startswith(".")) and not shared.opts.extra_networks_show_hidden_directories:
-                        continue
-
-                    subdirs[subdir] = 1
-
-        if subdirs:
-            subdirs = {"": 1, **subdirs}
-
-        subdirs_html_template = (
-            "<button class='lg secondary gradio-button custom-button {classes}' "
-            "onclick='extraNetworksSearchButton(\"{tabname}_extra_search\", event)'>"
-            "{content}"
-            "</button>"
-        )
-        return "".join(
-            [
-                subdirs_html_template.format(
-                    **{
-                        "classes": "search-all" if not subdir else "",
-                        "tabname": tabname,
-                        "content": html.escape(subdir if subdir else "all"),
-                    }
-                ) for subdir in subdirs
-            ]
-        )
-
     def create_card_view_html(self, tabname):
     def create_card_view_html(self, tabname):
         res = ""
         res = ""
         self.items = {x["name"]: x for x in self.list_items()}
         self.items = {x["name"]: x for x in self.list_items()}
@@ -405,7 +369,6 @@ class ExtraNetworksPage:
         self.items = {x["name"]: x for x in self.list_items()}
         self.items = {x["name"]: x for x in self.list_items()}
 
 
         tree_view_html = self.create_tree_view_html(tabname)
         tree_view_html = self.create_tree_view_html(tabname)
-        subdirs_html = self.create_subdirs_html(tabname)
         card_view_html = self.create_card_view_html(tabname)
         card_view_html = self.create_card_view_html(tabname)
         network_type_id = self.name.replace(" ", "_")
         network_type_id = self.name.replace(" ", "_")
 
 
@@ -414,7 +377,6 @@ class ExtraNetworksPage:
                 "tabname": tabname,
                 "tabname": tabname,
                 "network_type_id": network_type_id,
                 "network_type_id": network_type_id,
                 "tree_html": tree_view_html,
                 "tree_html": tree_view_html,
-                "subdirs_html": subdirs_html,
                 "items_html": card_view_html,
                 "items_html": card_view_html,
             }
             }
         )
         )
@@ -534,7 +496,12 @@ def create_ui(interface: gr.Blocks, unrelated_tabs, tabname):
             elem_id = f"{tabname}_{page.id_page}_cards_html"
             elem_id = f"{tabname}_{page.id_page}_cards_html"
             page_elem = gr.HTML('Loading...', elem_id=elem_id)
             page_elem = gr.HTML('Loading...', elem_id=elem_id)
             ui.pages.append(page_elem)
             ui.pages.append(page_elem)
-            page_elem.change(fn=lambda: None, _js='function(){applyExtraNetworkFilter(' + quote_js(tabname) + '); return []}', inputs=[], outputs=[])
+            page_elem.change(
+                fn=lambda: None,
+                _js=f"function(){{applyExtraNetworkFilter({tabname}_extra_search); return []}}",
+                inputs=[],
+                outputs=[],
+            )
 
 
             editor = page.create_user_metadata_editor(ui, tabname)
             editor = page.create_user_metadata_editor(ui, tabname)
             editor.create_ui()
             editor.create_ui()
@@ -542,18 +509,16 @@ def create_ui(interface: gr.Blocks, unrelated_tabs, tabname):
 
 
             related_tabs.append(tab)
             related_tabs.append(tab)
 
 
-    edit_search = gr.Textbox('', show_label=False, elem_id=tabname+"_extra_search", elem_classes="search", placeholder="Search...", visible=False, interactive=True)
+    edit_search = gr.Textbox('', show_label=False, elem_id=f"{tabname}_extra_search", elem_classes="search", placeholder="Search...", visible=False, interactive=True)
     dropdown_sort = gr.Dropdown(choices=['Path', 'Name', 'Date Created', 'Date Modified', ], value=shared.opts.extra_networks_card_order_field, elem_id=tabname+"_extra_sort", elem_classes="sort", multiselect=False, visible=False, show_label=False, interactive=True, label=tabname+"_extra_sort_order")
     dropdown_sort = gr.Dropdown(choices=['Path', 'Name', 'Date Created', 'Date Modified', ], value=shared.opts.extra_networks_card_order_field, elem_id=tabname+"_extra_sort", elem_classes="sort", multiselect=False, visible=False, show_label=False, interactive=True, label=tabname+"_extra_sort_order")
     button_sortorder = ToolButton(switch_values_symbol, elem_id=tabname+"_extra_sortorder", elem_classes=["sortorder"] + ([] if shared.opts.extra_networks_card_order == "Ascending" else ["sortReverse"]), visible=False, tooltip="Invert sort order")
     button_sortorder = ToolButton(switch_values_symbol, elem_id=tabname+"_extra_sortorder", elem_classes=["sortorder"] + ([] if shared.opts.extra_networks_card_order == "Ascending" else ["sortReverse"]), visible=False, tooltip="Invert sort order")
     button_refresh = gr.Button('Refresh', elem_id=tabname+"_extra_refresh", visible=False)
     button_refresh = gr.Button('Refresh', elem_id=tabname+"_extra_refresh", visible=False)
-    checkbox_show_dirs = gr.Checkbox(True, label='Show dirs', elem_id=tabname+"_extra_show_dirs", elem_classes="show-dirs", visible=False)
 
 
     tab_controls = [
     tab_controls = [
         edit_search,
         edit_search,
         dropdown_sort,
         dropdown_sort,
         button_sortorder,
         button_sortorder,
         button_refresh,
         button_refresh,
-        checkbox_show_dirs,
     ]
     ]
 
 
     ui.button_save_preview = gr.Button('Save preview', elem_id=tabname+"_save_preview", visible=False)
     ui.button_save_preview = gr.Button('Save preview', elem_id=tabname+"_save_preview", visible=False)
@@ -562,7 +527,7 @@ def create_ui(interface: gr.Blocks, unrelated_tabs, tabname):
     for tab in unrelated_tabs:
     for tab in unrelated_tabs:
         tab.select(
         tab.select(
             fn=lambda: [gr.update(visible=False) for _ in tab_controls],
             fn=lambda: [gr.update(visible=False) for _ in tab_controls],
-            _js="function(){ extraNetworksUrelatedTabSelected('" + tabname + "'); }",
+            _js=f"function(){{ extraNetworksUnrelatedTabSelected('{tabname}'); }}",
             inputs=[],
             inputs=[],
             outputs=tab_controls,
             outputs=tab_controls,
             show_progress=False,
             show_progress=False,

+ 4 - 1
modules/ui_extra_networks_checkpoints.py

@@ -21,13 +21,16 @@ class ExtraNetworksPageCheckpoints(ui_extra_networks.ExtraNetworksPage):
             return
             return
 
 
         path, ext = os.path.splitext(checkpoint.filename)
         path, ext = os.path.splitext(checkpoint.filename)
+        search_terms = [self.search_terms_from_path(checkpoint.filename)]
+        if checkpoint.sha256:
+            search_terms.append(checkpoint.sha256)
         return {
         return {
             "name": checkpoint.name_for_extra,
             "name": checkpoint.name_for_extra,
             "filename": checkpoint.filename,
             "filename": checkpoint.filename,
             "shorthash": checkpoint.shorthash,
             "shorthash": checkpoint.shorthash,
             "preview": self.find_preview(path),
             "preview": self.find_preview(path),
             "description": self.find_description(path),
             "description": self.find_description(path),
-            "search_term": self.search_terms_from_path(checkpoint.filename) + " " + (checkpoint.sha256 or ""),
+            "search_terms": search_terms,
             "onclick": '"' + html.escape(f"""return selectCheckpoint({quote_js(name)})""") + '"',
             "onclick": '"' + html.escape(f"""return selectCheckpoint({quote_js(name)})""") + '"',
             "local_preview": f"{path}.{shared.opts.samples_format}",
             "local_preview": f"{path}.{shared.opts.samples_format}",
             "metadata": checkpoint.metadata,
             "metadata": checkpoint.metadata,

+ 4 - 2
modules/ui_extra_networks_hypernets.py

@@ -20,14 +20,16 @@ class ExtraNetworksPageHypernetworks(ui_extra_networks.ExtraNetworksPage):
         path, ext = os.path.splitext(full_path)
         path, ext = os.path.splitext(full_path)
         sha256 = sha256_from_cache(full_path, f'hypernet/{name}')
         sha256 = sha256_from_cache(full_path, f'hypernet/{name}')
         shorthash = sha256[0:10] if sha256 else None
         shorthash = sha256[0:10] if sha256 else None
-
+        search_terms = [self.search_terms_from_path(path)]
+        if sha256:
+            search_terms.append(sha256)
         return {
         return {
             "name": name,
             "name": name,
             "filename": full_path,
             "filename": full_path,
             "shorthash": shorthash,
             "shorthash": shorthash,
             "preview": self.find_preview(path),
             "preview": self.find_preview(path),
             "description": self.find_description(path),
             "description": self.find_description(path),
-            "search_term": self.search_terms_from_path(path) + " " + (sha256 or ""),
+            "search_terms": search_terms,
             "prompt": quote_js(f"<hypernet:{name}:") + " + opts.extra_networks_default_multiplier + " + quote_js(">"),
             "prompt": quote_js(f"<hypernet:{name}:") + " + opts.extra_networks_default_multiplier + " + quote_js(">"),
             "local_preview": f"{path}.preview.{shared.opts.samples_format}",
             "local_preview": f"{path}.preview.{shared.opts.samples_format}",
             "sort_keys": {'default': index, **self.get_sort_keys(path + ext)},
             "sort_keys": {'default': index, **self.get_sort_keys(path + ext)},

+ 4 - 1
modules/ui_extra_networks_textual_inversion.py

@@ -18,13 +18,16 @@ class ExtraNetworksPageTextualInversion(ui_extra_networks.ExtraNetworksPage):
             return
             return
 
 
         path, ext = os.path.splitext(embedding.filename)
         path, ext = os.path.splitext(embedding.filename)
+        search_terms = [self.search_terms_from_path(embedding.filename)]
+        if embedding.hash:
+            search_terms.append(embedding.hash)
         return {
         return {
             "name": name,
             "name": name,
             "filename": embedding.filename,
             "filename": embedding.filename,
             "shorthash": embedding.shorthash,
             "shorthash": embedding.shorthash,
             "preview": self.find_preview(path),
             "preview": self.find_preview(path),
             "description": self.find_description(path),
             "description": self.find_description(path),
-            "search_term": self.search_terms_from_path(embedding.filename) + " " + (embedding.hash or ""),
+            "search_terms": search_terms,
             "prompt": quote_js(embedding.name),
             "prompt": quote_js(embedding.name),
             "local_preview": f"{path}.preview.{shared.opts.samples_format}",
             "local_preview": f"{path}.preview.{shared.opts.samples_format}",
             "sort_keys": {'default': index, **self.get_sort_keys(embedding.filename)},
             "sort_keys": {'default': index, **self.get_sort_keys(embedding.filename)},

+ 10 - 14
style.css

@@ -878,16 +878,8 @@ footer {
     margin: 0.3em;
     margin: 0.3em;
 }
 }
 
 
-.extra-network-subdirs{
-    padding: 0.2em 0.35em;
-}
-
-.extra-network-subdirs button{
-    margin: 0 0.15em;
-}
 .extra-networks .tab-nav .search,
 .extra-networks .tab-nav .search,
-.extra-networks .tab-nav .sort,
-.extra-networks .tab-nav .show-dirs
+.extra-networks .tab-nav .sort
 {
 {
     margin: 0.3em;
     margin: 0.3em;
     align-self: center;
     align-self: center;
@@ -1196,6 +1188,10 @@ body.resizing .resize-handle {
     flex-grow: 1;
     flex-grow: 1;
 }
 }
 
 
+.folder-container {
+    margin-left: 1.5em !important;
+}
+
 .file-item,
 .file-item,
 .folder-item,
 .folder-item,
 .folder-item-summary {
 .folder-item-summary {
@@ -1235,7 +1231,7 @@ body.resizing .resize-handle {
     text-overflow: ellipsis;
     text-overflow: ellipsis;
 }
 }
 
 
-.extra-network-pane .extra-network tree ul.folder-container {
+.extra-network-pane .extra-network-tree ul.folder-container {
     list-style: none;
     list-style: none;
     font-size: 1rem;
     font-size: 1rem;
     text-overflow: ellipsis;
     text-overflow: ellipsis;
@@ -1257,15 +1253,15 @@ body.resizing .resize-handle {
     display: flex;
     display: flex;
 }
 }
 
 
-.extra-network-pane .extra-network-subdirs {
-    display: block;
-}
 .extra-network-pane .extra-network-tree {
 .extra-network-pane .extra-network-tree {
     font-size: 1rem;
     font-size: 1rem;
-    width: 25%;
+    min-width: 25%;
+    max-width: 25%;
+    border: 1px solid var(--block-border-color);
 }
 }
 .extra-network-pane .extra-network-cards {
 .extra-network-pane .extra-network-cards {
     flex-grow: 1;
     flex-grow: 1;
+    border: 1px solid var(--block-border-color);
 }
 }
 
 
 .dark .extra-network-tree .folder-item-summary.selected{
 .dark .extra-network-tree .folder-item-summary.selected{