made the queue system use a new html-based renderer

This commit is contained in:
Chris Malone 2025-09-25 22:51:41 +10:00
parent 2783d5401c
commit 4e9726538c

489
wgp.py
View File

@ -1454,50 +1454,87 @@ def finalize_generation_with_state(current_state):
accordion_update = gr.Accordion(open=False) if len(get_gen_info(current_state).get("queue", [])) <= 1 else gr.update() accordion_update = gr.Accordion(open=False) if len(get_gen_info(current_state).get("queue", [])) <= 1 else gr.update()
return gallery_update, abort_btn_update, gen_btn_update, add_queue_btn_update, current_gen_col_update, gen_info_update, accordion_update, current_state return gallery_update, abort_btn_update, gen_btn_update, add_queue_btn_update, current_gen_col_update, gen_info_update, accordion_update, current_state
def get_queue_table(queue): def generate_queue_html(queue):
data = [] if len(queue) <= 1:
if len(queue) == 1: return "<div style='text-align: center; color: grey; padding: 20px;'>Queue is empty.</div>"
return data
table_header = """
<table>
<thead>
<tr>
<th style="width:5%;" class="center-align">Qty</th>
<th style="width:auto;" class="text-left">Prompt</th>
<th style="width:7%;" class="center-align">Length</th>
<th style="width:7%;" class="center-align">Steps</th>
<th style="width:10%;" class="center-align">Start/Ref</th>
<th style="width:10%;" class="center-align">End</th>
<th style="width:4%;" class="center-align" title="Move Up"></th>
<th style="width:4%;" class="center-align" title="Move Down"></th>
<th style="width:4%;" class="center-align" title="Edit"></th>
<th style="width:4%;" class="center-align" title="Remove"></th>
</tr>
</thead>
<tbody>
"""
table_rows = []
for i, item in enumerate(queue): for i, item in enumerate(queue):
if i==0: if i == 0:
continue continue
row_index = i - 1
truncated_prompt = (item['prompt'][:97] + '...') if len(item['prompt']) > 100 else item['prompt'] truncated_prompt = (item['prompt'][:97] + '...') if len(item['prompt']) > 100 else item['prompt']
full_prompt = item['prompt'].replace('"', '&quot;') full_prompt = item['prompt'].replace('"', '&quot;')
prompt_cell = f'<span title="{full_prompt}">{truncated_prompt}</span>' prompt_cell = f'<div class="prompt-cell" title="{full_prompt}">{truncated_prompt}</div>'
start_img_uri =item.get('start_image_data_base64')
start_img_uri = start_img_uri[0] if start_img_uri !=None else None start_img_data = item.get('start_image_data_base64') or [None]
start_img_labels =item.get('start_image_labels') start_img_uri = start_img_data[0]
end_img_uri = item.get('end_image_data_base64') start_img_labels = item.get('start_image_labels', [''])
end_img_uri = end_img_uri[0] if end_img_uri !=None else None
end_img_labels =item.get('end_image_labels') end_img_data = item.get('end_image_data_base64') or [None]
thumbnail_size = "50px" end_img_uri = end_img_data[0]
end_img_labels = item.get('end_image_labels', [''])
num_steps = item.get('steps') num_steps = item.get('steps')
length = item.get('length') length = item.get('length')
start_img_md = "" start_img_md = ""
end_img_md = ""
if start_img_uri: if start_img_uri:
start_img_md = f'<div class="hover-image"><img src="{start_img_uri}" alt="{start_img_labels[0]}" style="max-width:{thumbnail_size}; max-height:{thumbnail_size}; display: block; margin: auto; object-fit: contain;" /><span class="tooltip2">{start_img_labels[0]}</span></div>' start_img_md = f'<div class="hover-image" onclick="showImageModal(\'start_{row_index}\')"><img src="{start_img_uri}" alt="{start_img_labels[0]}" /></div>'
end_img_md = ""
if end_img_uri: if end_img_uri:
end_img_md = f'<div class="hover-image"><img src="{end_img_uri}" alt="{end_img_labels[0]}" style="max-width:{thumbnail_size}; max-height:{thumbnail_size}; display: block; margin: auto; object-fit: contain;" /><span class="tooltip2">{end_img_labels[0]}</span></div>' end_img_md = f'<div class="hover-image" onclick="showImageModal(\'end_{row_index}\')"><img src="{end_img_uri}" alt="{end_img_labels[0]}" /></div>'
up_btn = f"""<button onclick="updateAndTrigger('up_{row_index}')" class="action-button" title="Move Up">↑</button>"""
down_btn = f"""<button onclick="updateAndTrigger('down_{row_index}')" class="action-button" title="Move Down">↓</button>"""
edit_btn = f"""<button onclick="updateAndTrigger('edit_{row_index}')" class="action-button" title="Edit">✏️</button>"""
remove_btn = f"""<button onclick="updateAndTrigger('remove_{row_index}')" class="action-button" title="Remove">✖️</button>"""
row_html = f"""
<tr>
<td class="center-align">{item.get('repeats', "1")}</td>
<td>{prompt_cell}</td>
<td class="center-align">{length}</td>
<td class="center-align">{num_steps}</td>
<td class="center-align">{start_img_md}</td>
<td class="center-align">{end_img_md}</td>
<td class="center-align">{up_btn}</td>
<td class="center-align">{down_btn}</td>
<td class="center-align">{edit_btn}</td>
<td class="center-align">{remove_btn}</td>
</tr>
"""
table_rows.append(row_html)
table_footer = "</tbody></table>"
return table_header + "".join(table_rows) + table_footer
data.append([item.get('repeats', "1"),
prompt_cell,
length,
num_steps,
start_img_md,
end_img_md,
"",
"",
""
])
return data
def update_queue_data(queue, first_time_in_queue =False): def update_queue_data(queue, first_time_in_queue =False):
update_global_queue_ref(queue) update_global_queue_ref(queue)
data = get_queue_table(queue) html_content = generate_queue_html(queue)
return gr.HTML(value=html_content)
return gr.DataFrame(value=data)
def create_html_progress_bar(percentage=0.0, text="Idle", is_idle=True): def create_html_progress_bar(percentage=0.0, text="Idle", is_idle=True):
@ -5153,7 +5190,9 @@ def generate_video(
src_faces = torch.cat([src_faces, torch.full( (3, current_video_length - src_faces.shape[1], 512, 512 ), -1, dtype = src_faces.dtype, device= src_faces.device) ], dim=1) src_faces = torch.cat([src_faces, torch.full( (3, current_video_length - src_faces.shape[1], 512, 512 ), -1, dtype = src_faces.dtype, device= src_faces.device) ], dim=1)
# Sparse Video to Video # Sparse Video to Video
sparse_video_image = get_video_frame(video_guide, aligned_guide_start_frame, return_last_if_missing = True, target_fps = fps, return_PIL = True) if "R" in video_prompt_type else None sparse_video_image = None
if "R" in video_prompt_type:
sparse_video_image = get_video_frame(video_guide, aligned_guide_start_frame, return_last_if_missing = True, target_fps = fps, return_PIL = True)
# Generic Video Preprocessing # Generic Video Preprocessing
process_outside_mask = process_map_outside_mask.get(filter_letters(video_prompt_type, "YWX"), None) process_outside_mask = process_map_outside_mask.get(filter_letters(video_prompt_type, "YWX"), None)
@ -6904,63 +6943,42 @@ def download_loras():
return return
def handle_celll_selection(state, evt: gr.SelectData): def handle_queue_action(state, action_string):
if not action_string:
return gr.HTML(), gr.Tabs()
gen = get_gen_info(state) gen = get_gen_info(state)
queue = gen.get("queue", []) queue = gen.get("queue", [])
if evt.index is None: try:
return gr.update(), gr.update(), gr.update(visible=False), gr.update() action, row_index_str = action_string.split('_')
row_index, col_index = evt.index row_index = int(row_index_str)
except (IndexError, ValueError):
return gr.HTML(), gr.Tabs()
if col_index == 1: if action == "edit":
state["editing_task_index"] = row_index state["editing_task_index"] = row_index
task_to_edit_index = row_index + 1 task_to_edit_index = row_index + 1
if task_to_edit_index < len(queue): if task_to_edit_index < len(queue):
task_data = queue[task_to_edit_index] task_data = queue[task_to_edit_index]
gr.Info(f"Loading task '{task_data['prompt'][:50]}...' for editing.") gr.Info(f"Loading task '{task_data['prompt'][:50]}...' for editing.")
return gr.update(), gr.update(), gr.update(visible=False), gr.Tabs(selected="edit") return update_queue_data(queue), gr.Tabs(selected="edit")
else: else:
gr.Warning("Task index out of bounds.") gr.Warning("Task index out of bounds.")
return gr.update(), gr.update(), gr.update(visible=False), gr.update() return update_queue_data(queue), gr.Tabs()
if col_index in [6, 7, 8]: elif action == "up":
if col_index == 6: cell_value = "" return move_up(queue, [row_index]), gr.Tabs()
elif col_index == 7: cell_value = "" elif action == "down":
elif col_index == 8: cell_value = "" return move_down(queue, [row_index]), gr.Tabs()
if col_index == 6: elif action == "remove":
new_df_data = move_up(queue, [row_index]) new_queue_data = remove_task(queue, [row_index])
return new_df_data, gr.update(), gr.update(visible=False), gr.update() gen["prompts_max"] = gen.get("prompts_max", 0) - 1
elif col_index == 7: update_status(state)
new_df_data = move_down(queue, [row_index]) return new_queue_data, gr.Tabs()
return new_df_data, gr.update(), gr.update(visible=False), gr.update()
elif col_index == 8:
new_df_data = remove_task(queue, [row_index])
gen["prompts_max"] = gen.get("prompts_max",0) - 1
update_status(state)
return new_df_data, gr.update(), gr.update(visible=False), gr.update()
start_img_col_idx = 4 return update_queue_data(queue), gr.Tabs()
end_img_col_idx = 5
image_data_to_show = None
names = []
if col_index == start_img_col_idx:
with lock:
row_index += 1
if row_index < len(queue):
image_data_to_show = queue[row_index].get('start_image_data_base64')
names = queue[row_index].get('start_image_labels')
elif col_index == end_img_col_idx:
with lock:
row_index += 1
if row_index < len(queue):
image_data_to_show = queue[row_index].get('end_image_data_base64')
names = queue[row_index].get('end_image_labels')
if image_data_to_show:
value = get_modal_image( image_data_to_show[0], names[0])
return gr.update(), gr.update(value=value), gr.update(visible=True), gr.update()
else:
return gr.update(), gr.update(), gr.update(visible=False), gr.update()
def change_model(state, model_choice): def change_model(state, model_choice):
if model_choice == None: if model_choice == None:
@ -7185,6 +7203,40 @@ def init_process_queue_if_any(state):
def get_modal_image(image_base64, label): def get_modal_image(image_base64, label):
return "<DIV ALIGN=CENTER><IMG SRC=\"" + image_base64 + "\"><div style='position: absolute; top: 0; left: 0; background: rgba(0,0,0,0.7); color: white; padding: 5px; font-size: 12px;'>" + label + "</div></DIV>" return "<DIV ALIGN=CENTER><IMG SRC=\"" + image_base64 + "\"><div style='position: absolute; top: 0; left: 0; background: rgba(0,0,0,0.7); color: white; padding: 5px; font-size: 12px;'>" + label + "</div></DIV>"
def show_modal_image(state, action_string):
if not action_string:
return gr.HTML(), gr.Column(visible=False)
try:
img_type, row_index_str = action_string.split('_')
row_index = int(row_index_str)
except (ValueError, IndexError):
return gr.HTML(), gr.Column(visible=False)
gen = get_gen_info(state)
queue = gen.get("queue", [])
task_index = row_index + 1
if task_index >= len(queue):
return gr.HTML(), gr.Column(visible=False)
task_item = queue[task_index]
image_data = None
label_data = None
if img_type == 'start':
image_data = task_item.get('start_image_data_base64')
label_data = task_item.get('start_image_labels')
elif img_type == 'end':
image_data = task_item.get('end_image_data_base64')
label_data = task_item.get('end_image_labels')
if not image_data or not label_data:
return gr.HTML(), gr.Column(visible=False)
html_content = get_modal_image(image_data[0], label_data[0])
return gr.HTML(value=html_content), gr.Column(visible=True)
def get_prompt_labels(multi_prompts_gen_type, image_outputs = False): def get_prompt_labels(multi_prompts_gen_type, image_outputs = False):
new_line_text = "each new line of prompt will be used for a window" if multi_prompts_gen_type != 0 else "each new line of prompt will generate " + ("a new image" if image_outputs else "a new video") new_line_text = "each new line of prompt will be used for a window" if multi_prompts_gen_type != 0 else "each new line of prompt will generate " + ("a new image" if image_outputs else "a new video")
return "Prompts (" + new_line_text + ", # lines = comments, ! lines = macros)", "Prompts (" + new_line_text + ", # lines = comments)" return "Prompts (" + new_line_text + ", # lines = comments, ! lines = macros)", "Prompts (" + new_line_text + ", # lines = comments)"
@ -7196,28 +7248,6 @@ def refresh_prompt_labels(multi_prompts_gen_type, image_mode):
prompt_label, wizard_prompt_label = get_prompt_labels(multi_prompts_gen_type, image_mode > 0) prompt_label, wizard_prompt_label = get_prompt_labels(multi_prompts_gen_type, image_mode > 0)
return gr.update(label=prompt_label), gr.update(label = wizard_prompt_label), gr.update(label=get_image_end_label(multi_prompts_gen_type)) return gr.update(label=prompt_label), gr.update(label = wizard_prompt_label), gr.update(label=get_image_end_label(multi_prompts_gen_type))
def show_preview_column_modal(state, column_no):
column_no = int(column_no)
if column_no == -1:
return gr.update(), gr.update(), gr.update()
gen = get_gen_info(state)
queue = gen.get("queue", [])
task = queue[0]
list_uri = []
names = []
start_img_uri = task.get('start_image_data_base64')
if start_img_uri != None:
list_uri += start_img_uri
names += task.get('start_image_labels')
end_img_uri = task.get('end_image_data_base64')
if end_img_uri != None:
list_uri += end_img_uri
names += task.get('end_image_labels')
value = get_modal_image( list_uri[column_no],names[column_no] )
return -1, gr.update(value=value), gr.update(visible=True)
def update_video_guide_outpainting(video_guide_outpainting_value, value, pos): def update_video_guide_outpainting(video_guide_outpainting_value, value, pos):
if len(video_guide_outpainting_value) <= 1: if len(video_guide_outpainting_value) <= 1:
video_guide_outpainting_list = ["0"] * 4 video_guide_outpainting_list = ["0"] * 4
@ -7491,11 +7521,11 @@ def generate_video_tab(update_form = False, state_dict = None, ui_defaults = Non
with gr.Row(): with gr.Row():
with gr.Column(): with gr.Column():
with gr.Column(visible=False, elem_id="image-modal-container") as modal_container: with gr.Column(visible=False, elem_id="image-modal-container") as modal_container:
with gr.Row(elem_id="image-modal-close-button-row"): # with gr.Row(elem_id="image-modal-close-button-row"):
close_modal_button = gr.Button("", size="sm", scale=1) close_modal_button = gr.Button("", size="sm", scale=1)
# modal_image_display = gr.Image(label="Full Resolution Image", interactive=False, show_label=False) modal_html_display = gr.HTML()
modal_image_display = gr.HTML(label="Full Resolution Image") modal_action_input = gr.Text(elem_id="modal_action_input", visible=False)
preview_column_no = gr.Text(visible=False, value=-1, elem_id="preview_column_no") modal_action_trigger = gr.Button(elem_id="modal_action_trigger", visible=False)
with gr.Row(visible= True): #len(loras)>0) as presets_column: with gr.Row(visible= True): #len(loras)>0) as presets_column:
lset_choices = compute_lset_choices(loras_presets) + [(get_new_preset_msg(advanced_ui), "")] lset_choices = compute_lset_choices(loras_presets) + [(get_new_preset_msg(advanced_ui), "")]
with gr.Column(scale=6): with gr.Column(scale=6):
@ -8399,21 +8429,13 @@ def generate_video_tab(update_form = False, state_dict = None, ui_defaults = Non
onemorewindow_btn = gr.Button("Extend this Sample Please !", visible = False) onemorewindow_btn = gr.Button("Extend this Sample Please !", visible = False)
abort_btn = gr.Button("Abort", visible = True) abort_btn = gr.Button("Abort", visible = True)
with gr.Accordion("Queue Management", open=False) as queue_accordion: with gr.Accordion("Queue Management", open=False) as queue_accordion:
with gr.Row( ): with gr.Row():
queue_df = gr.DataFrame( queue_html = gr.HTML(
headers=["Qty","Prompt", "Length","Steps","", "", "", "", ""], value=generate_queue_html(state_dict["gen"]["queue"]),
datatype=[ "str","markdown","str", "markdown", "markdown", "markdown", "str", "str", "str"], elem_id="queue_html_container"
column_widths= ["5%", None, "7%", "7%", "10%", "10%", "3%", "3%", "34"],
interactive=False,
col_count=(9, "fixed"),
wrap=True,
value=[],
line_breaks= True,
visible= True,
elem_id="queue_df",
max_height= 1000
) )
queue_action_input = gr.Text(elem_id="queue_action_input", visible=False)
queue_action_trigger = gr.Button(elem_id="queue_action_trigger", visible=False)
with gr.Row(visible= True): with gr.Row(visible= True):
queue_zip_base64_output = gr.Text(visible=False) queue_zip_base64_output = gr.Text(visible=False)
save_queue_btn = gr.DownloadButton("Save Queue", size="sm") save_queue_btn = gr.DownloadButton("Save Queue", size="sm")
@ -8471,7 +8493,7 @@ def generate_video_tab(update_form = False, state_dict = None, ui_defaults = Non
video_guide_outpainting_checkbox.input(fn=refresh_video_guide_outpainting_row, inputs=[video_guide_outpainting_checkbox, video_guide_outpainting], outputs= [video_guide_outpainting_row,video_guide_outpainting]) video_guide_outpainting_checkbox.input(fn=refresh_video_guide_outpainting_row, inputs=[video_guide_outpainting_checkbox, video_guide_outpainting], outputs= [video_guide_outpainting_row,video_guide_outpainting])
show_advanced.change(fn=switch_advanced, inputs=[state, show_advanced, lset_name], outputs=[advanced_row, preset_buttons_rows, refresh_lora_btn, refresh2_row ,lset_name]).then( show_advanced.change(fn=switch_advanced, inputs=[state, show_advanced, lset_name], outputs=[advanced_row, preset_buttons_rows, refresh_lora_btn, refresh2_row ,lset_name]).then(
fn=switch_prompt_type, inputs = [state, wizard_prompt_activated_var, wizard_variables_var, prompt, wizard_prompt, *prompt_vars], outputs = [wizard_prompt_activated_var, wizard_variables_var, prompt, wizard_prompt, prompt_column_advanced, prompt_column_wizard, prompt_column_wizard_vars, *prompt_vars]) fn=switch_prompt_type, inputs = [state, wizard_prompt_activated_var, wizard_variables_var, prompt, wizard_prompt, *prompt_vars], outputs = [wizard_prompt_activated_var, wizard_variables_var, prompt, wizard_prompt, prompt_column_advanced, prompt_column_wizard, prompt_column_wizard_vars, *prompt_vars])
queue_df.select( fn=handle_celll_selection, inputs=state, outputs=[queue_df, modal_image_display, modal_container, main_tabs]) queue_action_trigger.click(fn=handle_queue_action, inputs=[state, queue_action_input], outputs=[queue_html, main_tabs], show_progress="hidden")
gr.on( triggers=[output.change, output.select], fn=select_video, inputs=[state, output], outputs=[last_choice, video_info, video_buttons_row, image_buttons_row, video_postprocessing_tab, audio_remuxing_tab], show_progress="hidden") gr.on( triggers=[output.change, output.select], fn=select_video, inputs=[state, output], outputs=[last_choice, video_info, video_buttons_row, image_buttons_row, video_postprocessing_tab, audio_remuxing_tab], show_progress="hidden")
preview_trigger.change(refresh_preview, inputs= [state], outputs= [preview], show_progress="hidden") preview_trigger.change(refresh_preview, inputs= [state], outputs= [preview], show_progress="hidden")
PP_MMAudio_setting.change(fn = lambda value : [gr.update(visible = value == 1), gr.update(visible = value == 0)] , inputs = [PP_MMAudio_setting], outputs = [PP_MMAudio_row, PP_custom_audio_row] ) PP_MMAudio_setting.change(fn = lambda value : [gr.update(visible = value == 1), gr.update(visible = value == 0)] , inputs = [PP_MMAudio_setting], outputs = [PP_MMAudio_row, PP_custom_audio_row] )
@ -8506,13 +8528,24 @@ def generate_video_tab(update_form = False, state_dict = None, ui_defaults = Non
if tab_id == 'generate': if tab_id == 'generate':
output_trigger.change(refresh_gallery, output_trigger.change(refresh_gallery,
inputs = [state], inputs = [state],
outputs = [output, gen_info, generate_btn, add_to_queue_btn, current_gen_column, current_gen_buttons_row, queue_df, abort_btn, onemorewindow_btn], outputs = [output, gen_info, generate_btn, add_to_queue_btn, current_gen_column, current_gen_buttons_row, queue_html, abort_btn, onemorewindow_btn],
show_progress="hidden" show_progress="hidden"
) )
preview_column_no.input(show_preview_column_modal, inputs=[state, preview_column_no], outputs=[preview_column_no, modal_image_display, modal_container]) modal_action_trigger.click(
abort_btn.click(abort_generation, [state], [ abort_btn] ) #.then(refresh_gallery, inputs = [state, gen_info], outputs = [output, gen_info, queue_df] ) fn=show_modal_image,
inputs=[state, modal_action_input],
outputs=[modal_html_display, modal_container],
show_progress="hidden"
)
close_modal_button.click(
fn=lambda: gr.Column(visible=False),
inputs=[],
outputs=[modal_container],
show_progress="hidden"
)
abort_btn.click(abort_generation, [state], [ abort_btn] ) #.then(refresh_gallery, inputs = [state, gen_info], outputs = [output, gen_info, queue_html] )
onemoresample_btn.click(fn=one_more_sample,inputs=[state], outputs= [state]) onemoresample_btn.click(fn=one_more_sample,inputs=[state], outputs= [state])
onemorewindow_btn.click(fn=one_more_window,inputs=[state], outputs= [state]) onemorewindow_btn.click(fn=one_more_window,inputs=[state], outputs= [state])
@ -8630,7 +8663,7 @@ def generate_video_tab(update_form = False, state_dict = None, ui_defaults = Non
).then( ).then(
fn=edit_task_in_queue, fn=edit_task_in_queue,
inputs=edit_inputs_components + [state], inputs=edit_inputs_components + [state],
outputs=[queue_df, main_tabs] outputs=[queue_html, main_tabs]
) )
cancel_btn.click( cancel_btn.click(
fn=cancel_edit, fn=cancel_edit,
@ -8681,7 +8714,7 @@ def generate_video_tab(update_form = False, state_dict = None, ui_defaults = Non
outputs= None outputs= None
).then(fn=process_prompt_and_add_tasks, ).then(fn=process_prompt_and_add_tasks,
inputs = [state, model_choice], inputs = [state, model_choice],
outputs=[queue_df, queue_accordion], outputs=[queue_html, queue_accordion],
show_progress="hidden", show_progress="hidden",
).then( ).then(
fn=update_status, fn=update_status,
@ -8697,7 +8730,7 @@ def generate_video_tab(update_form = False, state_dict = None, ui_defaults = Non
outputs= None outputs= None
).then(fn=process_prompt_and_add_tasks, ).then(fn=process_prompt_and_add_tasks,
inputs = [state, model_choice], inputs = [state, model_choice],
outputs= [queue_df, queue_accordion], outputs= [queue_html, queue_accordion],
show_progress="hidden", show_progress="hidden",
).then(fn=prepare_generate_video, ).then(fn=prepare_generate_video,
inputs= [state], inputs= [state],
@ -8724,7 +8757,7 @@ def generate_video_tab(update_form = False, state_dict = None, ui_defaults = Non
gr.on(triggers=[load_queue_btn.upload, main.load], gr.on(triggers=[load_queue_btn.upload, main.load],
fn=load_queue_action, fn=load_queue_action,
inputs=[load_queue_btn, state], inputs=[load_queue_btn, state],
outputs=[queue_df] outputs=[queue_html]
).then( ).then(
fn=lambda s: (gr.update(visible=bool(get_gen_info(s).get("queue",[]))), gr.Accordion(open=True)) if bool(get_gen_info(s).get("queue",[])) else (gr.update(visible=False), gr.update()), fn=lambda s: (gr.update(visible=bool(get_gen_info(s).get("queue",[]))), gr.Accordion(open=True)) if bool(get_gen_info(s).get("queue",[])) else (gr.update(visible=False), gr.update()),
inputs=[state], inputs=[state],
@ -8803,19 +8836,13 @@ def generate_video_tab(update_form = False, state_dict = None, ui_defaults = Non
clear_queue_btn.click( clear_queue_btn.click(
fn=clear_queue_action, fn=clear_queue_action,
inputs=[state], inputs=[state],
outputs=[queue_df] outputs=[queue_html]
).then( ).then(
fn=lambda: (gr.update(visible=False), gr.Accordion(open=False)), fn=lambda: (gr.update(visible=False), gr.Accordion(open=False)),
inputs=None, inputs=None,
outputs=[current_gen_column, queue_accordion] outputs=[current_gen_column, queue_accordion]
) )
close_modal_button.click(
lambda: gr.update(visible=False),
inputs=[],
outputs=[modal_container]
)
if tab_id == 'edit': if tab_id == 'edit':
locals_dict = locals() locals_dict = locals()
gen_inputs = [locals_dict[k] for k in inputs_names] + [state] + extra_inputs gen_inputs = [locals_dict[k] for k in inputs_names] + [state] + extra_inputs
@ -9488,134 +9515,73 @@ def create_ui():
margin: 0 20px; margin: 0 20px;
white-space: nowrap; white-space: nowrap;
} }
.queue-item { #queue_html_container table {
border: 1px solid #ccc; width: 100%;
padding: 10px; border-collapse: collapse;
margin: 5px 0; font-size: 14px;
border-radius: 5px; table-layout: fixed;
} }
.current { #queue_html_container th {
background: #f8f9fa; text-align: left;
border-left: 4px solid #007bff; padding: 10px 8px;
border-bottom: 2px solid #4a5568;
font-weight: bold;
font-size: 11px;
text-transform: uppercase;
color: #a0aec0;
white-space: nowrap;
} }
.task-header { #queue_html_container td {
display: flex; padding: 8px;
justify-content: space-between; border-bottom: 1px solid #2d3748;
margin-bottom: 5px; vertical-align: middle;
} }
.progress-container { #queue_html_container tr:hover td {
height: 10px; background-color: rgba(255, 255, 255, 0.04);
background: #e9ecef;
border-radius: 5px;
overflow: hidden;
} }
.progress-bar { #queue_html_container .prompt-cell {
height: 100%;
background: #007bff;
transition: width 0.3s ease;
}
.task-details {
display: flex;
justify-content: space-between;
font-size: 0.9em;
color: #6c757d;
margin-top: 5px;
}
.task-prompt {
font-size: 0.8em;
color: #868e96;
margin-top: 5px;
white-space: nowrap; white-space: nowrap;
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
} }
#queue_df th { #queue_html_container .action-button {
pointer-events: none; background: none;
border: none;
cursor: pointer;
font-size: 1.3em;
padding: 0;
color: #718096;
transition: color 0.2s;
line-height: 1;
}
#queue_html_container .action-button:hover {
color: #e2e8f0;
}
#queue_html_container .center-align {
text-align: center; text-align: center;
vertical-align: middle;
font-size:11px;
} }
#xqueue_df table { #queue_html_container .text-left {
width: 100%; text-align: left;
overflow: hidden !important;
} }
#xqueue_df::-webkit-scrollbar { #queue_html_container .hover-image img {
display: none !important;
}
#xqueue_df {
scrollbar-width: none !important;
-ms-overflow-style: none !important;
}
.selection-button {
display: none;
}
.cell-selected {
--ring-color: none;
}
#queue_df th:nth-child(1),
#queue_df td:nth-child(1) {
width: 60px;
text-align: center;
vertical-align: middle;
cursor: default !important;
pointer-events: none;
}
#xqueue_df th:nth-child(2),
#queue_df td:nth-child(2) {
text-align: center;
vertical-align: middle;
white-space: normal;
}
#queue_df td:nth-child(2) {
cursor: default !important;
}
#queue_df th:nth-child(3),
#queue_df td:nth-child(3) {
width: 60px;
text-align: center;
vertical-align: middle;
cursor: default !important;
pointer-events: none;
}
#queue_df th:nth-child(4),
#queue_df td:nth-child(4) {
width: 60px;
text-align: center;
white-space: nowrap;
cursor: default !important;
pointer-events: none;
}
#queue_df th:nth-child(5), #queue_df td:nth-child(7),
#queue_df th:nth-child(6), #queue_df td:nth-child(8) {
width: 60px;
text-align: center;
vertical-align: middle;
}
#queue_df td:nth-child(5) img,
#queue_df td:nth-child(6) img {
max-width: 50px; max-width: 50px;
max-height: 50px; max-height: 50px;
object-fit: contain; object-fit: contain;
display: block; display: block;
margin: auto; margin: auto;
cursor: pointer;
} }
#queue_df th:nth-child(7), #queue_df td:nth-child(9), #image-modal-container {
#queue_df th:nth-child(8), #queue_df td:nth-child(10), position: fixed;
#queue_df th:nth-child(9), #queue_df td:nth-child(11) { top: 0;
width: 20px; left: 0;
padding: 2px !important; width: 100%;
cursor: pointer; height: 100%;
text-align: center; background-color: rgba(0, 0, 0, 0.7);
font-weight: bold; justify-content: center;
vertical-align: middle; align-items: center;
} z-index: 1000;
#queue_df td:nth-child(5):hover, padding: 20px;
#queue_df td:nth-child(6):hover, box-sizing: border-box;
#queue_df td:nth-child(7):hover,
#queue_df td:nth-child(8):hover,
#queue_df td:nth-child(9):hover {
background-color: #e0e0e0;
} }
#image-modal-container { #image-modal-container {
position: fixed; position: fixed;
@ -9759,18 +9725,39 @@ def create_ui():
js = """ js = """
function() { function() {
// Attach function to window object to make it globally accessible window.updateAndTrigger = function(action) {
window.sendColIndex = function(index) { const hiddenTextbox = document.querySelector('#queue_action_input textarea');
const input= document.querySelector('#preview_column_no textarea'); const hiddenButton = document.querySelector('#queue_action_trigger');
if (input) {
input.value = index; if (hiddenTextbox && hiddenButton) {
input.dispatchEvent(new Event("input", { bubbles: true })); hiddenTextbox.value = action;
input.focus(); const inputEvent = new Event('input', { bubbles: true });
input.blur(); hiddenTextbox.dispatchEvent(inputEvent);
console.log('Events dispatched for column:', index); hiddenButton.click();
} } else {
console.error("Could not find hidden queue action elements.");
}
};
console.log('updateAndTrigger function for queue is ready.');
window.showImageModal = function(action) {
const hiddenTextbox = document.querySelector('#modal_action_input textarea');
const hiddenButton = document.querySelector('#modal_action_trigger');
if (hiddenTextbox && hiddenButton) {
hiddenTextbox.value = action;
hiddenTextbox.dispatchEvent(new Event('input', { bubbles: true }));
hiddenButton.click();
} else {
console.error("Could not find hidden modal action elements.");
}
};
window.closeImageModal = function() {
const modal = document.querySelector('#image-modal-container');
if (modal) {
modal.style.display = 'none';
}
}; };
console.log('sendColIndex function attached to window');
// cancel wheel usage inside image editor // cancel wheel usage inside image editor
const hit = n => n?.id === "img_editor" || n?.classList?.contains("wheel-pass"); const hit = n => n?.id === "img_editor" || n?.classList?.contains("wheel-pass");