diff --git a/images_history.js b/images_history.js new file mode 100644 index 0000000..c9aa76f --- /dev/null +++ b/images_history.js @@ -0,0 +1,200 @@ +var images_history_click_image = function(){ + if (!this.classList.contains("transform")){ + var gallery = images_history_get_parent_by_class(this, "images_history_cantainor"); + var buttons = gallery.querySelectorAll(".gallery-item"); + var i = 0; + var hidden_list = []; + buttons.forEach(function(e){ + if (e.style.display == "none"){ + hidden_list.push(i); + } + i += 1; + }) + if (hidden_list.length > 0){ + setTimeout(images_history_hide_buttons, 10, hidden_list, gallery); + } + } + images_history_set_image_info(this); +} + +function images_history_disabled_del(){ + gradioApp().querySelectorAll(".images_history_del_button").forEach(function(btn){ + btn.setAttribute('disabled','disabled'); + }); +} + +function images_history_get_parent_by_class(item, class_name){ + var parent = item.parentElement; + while(!parent.classList.contains(class_name)){ + parent = parent.parentElement; + } + return parent; +} + +function images_history_get_parent_by_tagname(item, tagname){ + var parent = item.parentElement; + tagname = tagname.toUpperCase() + while(parent.tagName != tagname){ + parent = parent.parentElement; + } + return parent; +} + +function images_history_hide_buttons(hidden_list, gallery){ + var buttons = gallery.querySelectorAll(".gallery-item"); + var num = 0; + buttons.forEach(function(e){ + if (e.style.display == "none"){ + num += 1; + } + }); + if (num == hidden_list.length){ + setTimeout(images_history_hide_buttons, 10, hidden_list, gallery); + } + for( i in hidden_list){ + buttons[hidden_list[i]].style.display = "none"; + } +} + +function images_history_set_image_info(button){ + var buttons = images_history_get_parent_by_tagname(button, "DIV").querySelectorAll(".gallery-item"); + var index = -1; + var i = 0; + buttons.forEach(function(e){ + if(e == button){ + index = i; + } + if(e.style.display != "none"){ + i += 1; + } + }); + var gallery = images_history_get_parent_by_class(button, "images_history_cantainor"); + var set_btn = gallery.querySelector(".images_history_set_index"); + var curr_idx = set_btn.getAttribute("img_index", index); + if (curr_idx != index) { + set_btn.setAttribute("img_index", index); + images_history_disabled_del(); + } + set_btn.click(); + +} + +function images_history_get_current_img(tabname, img_index, files){ + return [ + tabname, + gradioApp().getElementById(tabname + '_images_history_set_index').getAttribute("img_index"), + files + ]; +} + +function images_history_delete(del_num, tabname, image_index){ + image_index = parseInt(image_index); + var tab = gradioApp().getElementById(tabname + '_images_history'); + var set_btn = tab.querySelector(".images_history_set_index"); + var buttons = []; + tab.querySelectorAll(".gallery-item").forEach(function(e){ + if (e.style.display != 'none'){ + buttons.push(e); + } + }); + var img_num = buttons.length / 2; + del_num = Math.min(img_num - image_index, del_num) + if (img_num <= del_num){ + setTimeout(function(tabname){ + gradioApp().getElementById(tabname + '_images_history_renew_page').click(); + }, 30, tabname); + } else { + var next_img + for (var i = 0; i < del_num; i++){ + buttons[image_index + i].style.display = 'none'; + buttons[image_index + i + img_num].style.display = 'none'; + next_img = image_index + i + 1 + } + var bnt; + if (next_img >= img_num){ + btn = buttons[image_index - 1]; + } else { + btn = buttons[next_img]; + } + setTimeout(function(btn){btn.click()}, 30, btn); + } + images_history_disabled_del(); + +} + +function images_history_turnpage(tabname){ + gradioApp().getElementById(tabname + '_images_history_del_button').setAttribute('disabled','disabled'); + var buttons = gradioApp().getElementById(tabname + '_images_history').querySelectorAll(".gallery-item"); + buttons.forEach(function(elem) { + elem.style.display = 'block'; + }) +} + +function images_history_enable_del_buttons(){ + gradioApp().querySelectorAll(".images_history_del_button").forEach(function(btn){ + btn.removeAttribute('disabled'); + }) +} + +function images_history_init(){ + var tabnames = gradioApp().getElementById("images_history_tabnames_list") + if (tabnames){ + images_history_tab_list = tabnames.querySelector("textarea").value.split(",") + for (var i in images_history_tab_list ){ + var tab = images_history_tab_list[i]; + gradioApp().getElementById(tab + '_images_history').classList.add("images_history_cantainor"); + gradioApp().getElementById(tab + '_images_history_set_index').classList.add("images_history_set_index"); + gradioApp().getElementById(tab + '_images_history_del_button').classList.add("images_history_del_button"); + gradioApp().getElementById(tab + '_images_history_gallery').classList.add("images_history_gallery"); + gradioApp().getElementById(tab + "_images_history_start").setAttribute("style","padding:20px;font-size:25px"); + } + + //preload + if (gradioApp().getElementById("images_history_preload").querySelector("input").checked ){ + var tabs_box = gradioApp().getElementById("tab_images_history").querySelector("div").querySelector("div").querySelector("div"); + tabs_box.setAttribute("id", "images_history_tab"); + var tab_btns = tabs_box.querySelectorAll("button"); + for (var i in images_history_tab_list){ + var tabname = images_history_tab_list[i] + tab_btns[i].setAttribute("tabname", tabname); + tab_btns[i].addEventListener('click', function(){ + var tabs_box = gradioApp().getElementById("images_history_tab"); + if (!tabs_box.classList.contains(this.getAttribute("tabname"))) { + gradioApp().getElementById(this.getAttribute("tabname") + "_images_history_start").click(); + tabs_box.classList.add(this.getAttribute("tabname")) + } + }); + } + tab_btns[0].click() + } + } else { + setTimeout(images_history_init, 500); + } +} + +var images_history_tab_list = ""; +setTimeout(images_history_init, 500); +document.addEventListener("DOMContentLoaded", function() { + var mutationObserver = new MutationObserver(function(m){ + if (images_history_tab_list != ""){ + for (var i in images_history_tab_list ){ + let tabname = images_history_tab_list[i] + var buttons = gradioApp().querySelectorAll('#' + tabname + '_images_history .gallery-item'); + buttons.forEach(function(bnt){ + bnt.addEventListener('click', images_history_click_image, true); + }); + + var cls_btn = gradioApp().getElementById(tabname + '_images_history_gallery').querySelector("svg"); + if (cls_btn){ + cls_btn.addEventListener('click', function(){ + gradioApp().getElementById(tabname + '_images_history_renew_page').click(); + }, false); + } + + } + } + }); + mutationObserver.observe(gradioApp(), { childList:true, subtree:true }); +}); + + diff --git a/scripts/images_history.py b/scripts/images_history.py new file mode 100644 index 0000000..bc5cf11 --- /dev/null +++ b/scripts/images_history.py @@ -0,0 +1,424 @@ +import os +import shutil +import time +import hashlib +import gradio +system_bak_path = "webui_log_and_bak" +custom_tab_name = "custom fold" +faverate_tab_name = "favorites" +tabs_list = ["txt2img", "img2img", "extras", faverate_tab_name] +def is_valid_date(date): + try: + time.strptime(date, "%Y%m%d") + return True + except: + return False + +def reduplicative_file_move(src, dst): + def same_name_file(basename, path): + name, ext = os.path.splitext(basename) + f_list = os.listdir(path) + max_num = 0 + for f in f_list: + if len(f) <= len(basename): + continue + f_ext = f[-len(ext):] if len(ext) > 0 else "" + if f[:len(name)] == name and f_ext == ext: + if f[len(name)] == "(" and f[-len(ext)-1] == ")": + number = f[len(name)+1:-len(ext)-1] + if number.isdigit(): + if int(number) > max_num: + max_num = int(number) + return f"{name}({max_num + 1}){ext}" + name = os.path.basename(src) + save_name = os.path.join(dst, name) + if not os.path.exists(save_name): + shutil.move(src, dst) + else: + name = same_name_file(name, dst) + shutil.move(src, os.path.join(dst, name)) + +def traverse_all_files(curr_path, image_list, all_type=False): + try: + f_list = os.listdir(curr_path) + except: + if all_type or (curr_path[-10:].rfind(".") > 0 and curr_path[-4:] != ".txt" and curr_path[-4:] != ".csv"): + image_list.append(curr_path) + return image_list + for file in f_list: + file = os.path.join(curr_path, file) + if (not all_type) and (file[-4:] == ".txt" or file[-4:] == ".csv"): + pass + elif os.path.isfile(file) and file[-10:].rfind(".") > 0: + image_list.append(file) + else: + image_list = traverse_all_files(file, image_list) + return image_list + +def auto_sorting(dir_name): + bak_path = os.path.join(dir_name, system_bak_path) + if not os.path.exists(bak_path): + os.mkdir(bak_path) + log_file = None + files_list = [] + f_list = os.listdir(dir_name) + for file in f_list: + if file == system_bak_path: + continue + file_path = os.path.join(dir_name, file) + if not is_valid_date(file): + if file[-10:].rfind(".") > 0: + files_list.append(file_path) + else: + files_list = traverse_all_files(file_path, files_list, all_type=True) + + for file in files_list: + date_str = time.strftime("%Y%m%d",time.localtime(os.path.getmtime(file))) + file_path = os.path.dirname(file) + hash_path = hashlib.md5(file_path.encode()).hexdigest() + path = os.path.join(dir_name, date_str, hash_path) + if not os.path.exists(path): + os.makedirs(path) + if log_file is None: + log_file = open(os.path.join(bak_path,"path_mapping.csv"),"a") + log_file.write(f"{hash_path},{file_path}\n") + reduplicative_file_move(file, path) + + date_list = [] + f_list = os.listdir(dir_name) + for f in f_list: + if is_valid_date(f): + date_list.append(f) + elif f == system_bak_path: + continue + else: + try: + reduplicative_file_move(os.path.join(dir_name, f), bak_path) + except: + pass + + today = time.strftime("%Y%m%d",time.localtime(time.time())) + if today not in date_list: + date_list.append(today) + return sorted(date_list, reverse=True) + +def archive_images(dir_name, date_to): + filenames = [] + batch_size =int(opts.images_history_num_per_page * opts.images_history_pages_num) + if batch_size <= 0: + batch_size = opts.images_history_num_per_page * 6 + today = time.strftime("%Y%m%d",time.localtime(time.time())) + date_to = today if date_to is None or date_to == "" else date_to + date_to_bak = date_to + if False: #opts.images_history_reconstruct_directory: + date_list = auto_sorting(dir_name) + for date in date_list: + if date <= date_to: + path = os.path.join(dir_name, date) + if date == today and not os.path.exists(path): + continue + filenames = traverse_all_files(path, filenames) + if len(filenames) > batch_size: + break + filenames = sorted(filenames, key=lambda file: -os.path.getmtime(file)) + else: + filenames = traverse_all_files(dir_name, filenames) + total_num = len(filenames) + tmparray = [(os.path.getmtime(file), file) for file in filenames ] + date_stamp = time.mktime(time.strptime(date_to, "%Y%m%d")) + 86400 + filenames = [] + date_list = {date_to:None} + date = time.strftime("%Y%m%d",time.localtime(time.time())) + for t, f in tmparray: + date = time.strftime("%Y%m%d",time.localtime(t)) + date_list[date] = None + if t <= date_stamp: + filenames.append((t, f ,date)) + date_list = sorted(list(date_list.keys()), reverse=True) + sort_array = sorted(filenames, key=lambda x:-x[0]) + if len(sort_array) > batch_size: + date = sort_array[batch_size][2] + filenames = [x[1] for x in sort_array] + else: + date = date_to if len(sort_array) == 0 else sort_array[-1][2] + filenames = [x[1] for x in sort_array] + filenames = [x[1] for x in sort_array if x[2]>= date] + num = len(filenames) + last_date_from = date_to_bak if num == 0 else time.strftime("%Y%m%d", time.localtime(time.mktime(time.strptime(date, "%Y%m%d")) - 1000)) + date = date[:4] + "/" + date[4:6] + "/" + date[6:8] + date_to_bak = date_to_bak[:4] + "/" + date_to_bak[4:6] + "/" + date_to_bak[6:8] + load_info = "