Unverified Commit b1fd2aaa authored by AUTOMATIC1111's avatar AUTOMATIC1111 Committed by GitHub
Browse files

Merge pull request #10943 from catboxanon/sort

Allow dynamically sorting extra networks in UI
parents 08109b9b 9009e25c
Loading
Loading
Loading
Loading
+3 −1
Original line number Original line Diff line number Diff line
@@ -13,7 +13,7 @@ class ExtraNetworksPageLora(ui_extra_networks.ExtraNetworksPage):
        lora.list_available_loras()
        lora.list_available_loras()


    def list_items(self):
    def list_items(self):
        for name, lora_on_disk in lora.available_loras.items():
        for index, (name, lora_on_disk) in enumerate(lora.available_loras.items()):
            path, ext = os.path.splitext(lora_on_disk.filename)
            path, ext = os.path.splitext(lora_on_disk.filename)


            alias = lora_on_disk.get_alias()
            alias = lora_on_disk.get_alias()
@@ -27,6 +27,8 @@ class ExtraNetworksPageLora(ui_extra_networks.ExtraNetworksPage):
                "prompt": json.dumps(f"<lora:{alias}:") + " + opts.extra_networks_default_multiplier + " + json.dumps(">"),
                "prompt": json.dumps(f"<lora:{alias}:") + " + opts.extra_networks_default_multiplier + " + json.dumps(">"),
                "local_preview": f"{path}.{shared.opts.samples_format}",
                "local_preview": f"{path}.{shared.opts.samples_format}",
                "metadata": json.dumps(lora_on_disk.metadata, indent=4) if lora_on_disk.metadata else None,
                "metadata": json.dumps(lora_on_disk.metadata, indent=4) if lora_on_disk.metadata else None,
                "sort_keys": {'default': index, **self.get_sort_keys(lora_on_disk.filename)},

            }
            }


    def allowed_directories_for_previews(self):
    def allowed_directories_for_previews(self):
+1 −1
Original line number Original line Diff line number Diff line
<div class='card' style={style} onclick={card_clicked}>
<div class='card' style={style} onclick={card_clicked} {sort_keys}>
	{background_image}
	{background_image}
	{metadata_button}
	{metadata_button}
	<div class='actions'>
	<div class='actions'>
+50 −0
Original line number Original line Diff line number Diff line
@@ -3,10 +3,17 @@ function setupExtraNetworksForTab(tabname) {


    var tabs = gradioApp().querySelector('#' + tabname + '_extra_tabs > div');
    var tabs = gradioApp().querySelector('#' + tabname + '_extra_tabs > div');
    var search = gradioApp().querySelector('#' + tabname + '_extra_search textarea');
    var search = gradioApp().querySelector('#' + tabname + '_extra_search textarea');
    var sort = gradioApp().getElementById(tabname + '_extra_sort');
    var sortOrder = gradioApp().getElementById(tabname + '_extra_sortorder');
    var refresh = gradioApp().getElementById(tabname + '_extra_refresh');
    var refresh = gradioApp().getElementById(tabname + '_extra_refresh');


    search.classList.add('search');
    search.classList.add('search');
    sort.classList.add('sort');
    sortOrder.classList.add('sortorder');
    sort.dataset.sortkey = 'sortDefault';
    tabs.appendChild(search);
    tabs.appendChild(search);
    tabs.appendChild(sort);
    tabs.appendChild(sortOrder);
    tabs.appendChild(refresh);
    tabs.appendChild(refresh);


    var applyFilter = function() {
    var applyFilter = function() {
@@ -26,8 +33,51 @@ function setupExtraNetworksForTab(tabname) {
        });
        });
    };
    };


    var applySort = function() {
        var reverse = sortOrder.classList.contains("sortReverse");
        var sortKey = sort.querySelector("input").value.toLowerCase().replace("sort", "").replaceAll(" ", "_").replace(/_+$/, "").trim();
        sortKey = sortKey ? "sort" + sortKey.charAt(0).toUpperCase() + sortKey.slice(1) : "";
        var sortKeyStore = sortKey ? sortKey + (reverse ? "Reverse" : "") : "";
        if (!sortKey || sortKeyStore == sort.dataset.sortkey) {
            return;
        }

        sort.dataset.sortkey = sortKeyStore;

        var cards = gradioApp().querySelectorAll('#' + tabname + '_extra_tabs div.card');
        cards.forEach(function(card) {
            card.originalParentElement = card.parentElement;
        });
        var sortedCards = Array.from(cards);
        sortedCards.sort(function(cardA, cardB) {
            var a = cardA.dataset[sortKey];
            var b = cardB.dataset[sortKey];
            if (!isNaN(a) && !isNaN(b)) {
                return parseInt(a) - parseInt(b);
            }

            return (a < b ? -1 : (a > b ? 1 : 0));
        });
        if (reverse) {
            sortedCards.reverse();
        }
        cards.forEach(function(card) {
            card.remove();
        });
        sortedCards.forEach(function(card) {
            card.originalParentElement.appendChild(card);
        });
    };

    search.addEventListener("input", applyFilter);
    search.addEventListener("input", applyFilter);
    applyFilter();
    applyFilter();
    ["change", "blur", "click"].forEach(function(evt) {
        sort.querySelector("input").addEventListener(evt, applySort);
    });
    sortOrder.addEventListener("click", function() {
        sortOrder.classList.toggle("sortReverse");
        applySort();
    });


    extraNetworksApplyFilter[tabname] = applyFilter;
    extraNetworksApplyFilter[tabname] = applyFilter;
}
}
+1 −0
Original line number Original line Diff line number Diff line
@@ -79,6 +79,7 @@ extra_networks_symbol = '\U0001F3B4' # 🎴
switch_values_symbol = '\U000021C5' # ⇅
switch_values_symbol = '\U000021C5' # ⇅
restore_progress_symbol = '\U0001F300' # 🌀
restore_progress_symbol = '\U0001F300' # 🌀
detect_image_size_symbol = '\U0001F4D0'  # 📐
detect_image_size_symbol = '\U0001F4D0'  # 📐
up_down_symbol = '\u2195\ufe0f' # ↕️




def plaintext_to_html(text):
def plaintext_to_html(text):
+18 −0
Original line number Original line Diff line number Diff line
@@ -4,6 +4,7 @@ from pathlib import Path


from modules import shared
from modules import shared
from modules.images import read_info_from_image, save_image_with_geninfo
from modules.images import read_info_from_image, save_image_with_geninfo
from modules.ui import up_down_symbol
import gradio as gr
import gradio as gr
import json
import json
import html
import html
@@ -185,6 +186,8 @@ class ExtraNetworksPage:
        if search_only and shared.opts.extra_networks_hidden_models == "Never":
        if search_only and shared.opts.extra_networks_hidden_models == "Never":
            return ""
            return ""


        sort_keys = " ".join([html.escape(f'data-sort-{k}={v}') for k, v in item.get("sort_keys", {}).items()]).strip()

        args = {
        args = {
            "background_image": background_image,
            "background_image": background_image,
            "style": f"'display: none; {height}{width}'",
            "style": f"'display: none; {height}{width}'",
@@ -198,10 +201,23 @@ class ExtraNetworksPage:
            "search_term": item.get("search_term", ""),
            "search_term": item.get("search_term", ""),
            "metadata_button": metadata_button,
            "metadata_button": metadata_button,
            "search_only": " search_only" if search_only else "",
            "search_only": " search_only" if search_only else "",
            "sort_keys": sort_keys,
        }
        }


        return self.card_page.format(**args)
        return self.card_page.format(**args)


    def get_sort_keys(self, path):
        """
        List of default keys used for sorting in the UI.
        """
        pth = Path(path)
        stat = pth.stat()
        return {
            "date_created": int(stat.st_ctime or 0),
            "date_modified": int(stat.st_mtime or 0),
            "name": pth.name.lower(),
        }

    def find_preview(self, path):
    def find_preview(self, path):
        """
        """
        Find a preview PNG for a given path (without extension) and call link_preview on it.
        Find a preview PNG for a given path (without extension) and call link_preview on it.
@@ -296,6 +312,8 @@ def create_ui(container, button, tabname):
                page_elem.change(fn=lambda: None, _js='function(){applyExtraNetworkFilter(' + json.dumps(tabname) + '); return []}', inputs=[], outputs=[])
                page_elem.change(fn=lambda: None, _js='function(){applyExtraNetworkFilter(' + json.dumps(tabname) + '); return []}', inputs=[], outputs=[])


    gr.Textbox('', show_label=False, elem_id=tabname+"_extra_search", placeholder="Search...", visible=False)
    gr.Textbox('', show_label=False, elem_id=tabname+"_extra_search", placeholder="Search...", visible=False)
    gr.Dropdown(choices=['Default Sort', 'Date Created', 'Date Modified', 'Name'], value='Default Sort', elem_id=tabname+"_extra_sort", multiselect=False, visible=False, show_label=False, interactive=True)
    gr.Button(up_down_symbol, elem_id=tabname+"_extra_sortorder")
    button_refresh = gr.Button('Refresh', elem_id=tabname+"_extra_refresh")
    button_refresh = gr.Button('Refresh', elem_id=tabname+"_extra_refresh")


    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)
Loading