import gradio as gr from core.settings import VAE_DIR, LORA_DIR, EMBEDDING_DIR, ARCHITECTURES_CONFIG from utils.app_utils import save_uploaded_file_with_hash from ui.shared.ui_components import ( MAX_CONTROLNETS, MAX_IPADAPTERS, MAX_EMBEDDINGS, MAX_CONDITIONINGS, MAX_LORAS ) from .config_loaders import ( load_controlnet_config, load_anima_controlnet_lllite_config, load_diffsynth_controlnet_config, load_ipadapter_config ) def on_vae_upload(file_obj): if not file_obj: return gr.update(), gr.update(), None hashed_filename = save_uploaded_file_with_hash(file_obj, VAE_DIR) return hashed_filename, "File", file_obj def on_lora_upload(file_obj): if not file_obj: return gr.update(), gr.update() hashed_filename = save_uploaded_file_with_hash(file_obj, LORA_DIR) return hashed_filename, "File" def on_embedding_upload(file_obj): if not file_obj: return gr.update(), gr.update(), None hashed_filename = save_uploaded_file_with_hash(file_obj, EMBEDDING_DIR) return hashed_filename, "File", file_obj def create_lora_event_handlers(prefix, ui_components): lora_rows = ui_components.get(f'lora_rows_{prefix}') if not lora_rows: return lora_ids = ui_components[f'lora_ids_{prefix}'] lora_scales = ui_components[f'lora_scales_{prefix}'] lora_uploads = ui_components[f'lora_uploads_{prefix}'] count_state = ui_components[f'lora_count_state_{prefix}'] add_button = ui_components[f'add_lora_button_{prefix}'] del_button = ui_components[f'delete_lora_button_{prefix}'] def add_lora_row(c): updates = {} if c < MAX_LORAS: c += 1 updates[lora_rows[c - 1]] = gr.update(visible=True) updates[count_state] = c updates[add_button] = gr.update(visible=c < MAX_LORAS) updates[del_button] = gr.update(visible=c > 1) return updates def del_lora_row(c): updates = {} if c > 1: updates[lora_rows[c - 1]] = gr.update(visible=False) updates[lora_ids[c - 1]] = "" updates[lora_scales[c - 1]] = 0.0 updates[lora_uploads[c - 1]] = None c -= 1 updates[count_state] = c updates[add_button] = gr.update(visible=True) updates[del_button] = gr.update(visible=c > 1) return updates add_outputs = [count_state, add_button, del_button] + lora_rows del_outputs = [count_state, add_button, del_button] + lora_rows + lora_ids + lora_scales + lora_uploads add_button.click(add_lora_row, [count_state], add_outputs, show_progress=False) del_button.click(del_lora_row, [count_state], del_outputs, show_progress=False) def create_controlnet_event_handlers(prefix, ui_components): cn_rows = ui_components.get(f'controlnet_rows_{prefix}') if not cn_rows: return cn_types = ui_components[f'controlnet_types_{prefix}'] cn_series = ui_components[f'controlnet_series_{prefix}'] cn_filepaths = ui_components[f'controlnet_filepaths_{prefix}'] cn_images = ui_components[f'controlnet_images_{prefix}'] cn_strengths = ui_components[f'controlnet_strengths_{prefix}'] count_state = ui_components[f'controlnet_count_state_{prefix}'] add_button = ui_components[f'add_controlnet_button_{prefix}'] del_button = ui_components[f'delete_controlnet_button_{prefix}'] accordion = ui_components[f'controlnet_accordion_{prefix}'] base_model_comp = ui_components.get(f'base_model_{prefix}') actual_arch_comp = base_model_comp if base_model_comp else gr.State("SDXL") def add_cn_row(c): c += 1 updates = { count_state: c, cn_rows[c-1]: gr.update(visible=True), add_button: gr.update(visible=c < MAX_CONTROLNETS), del_button: gr.update(visible=True) } return updates def del_cn_row(c): c -= 1 updates = { count_state: c, cn_rows[c]: gr.update(visible=False), cn_images[c]: None, cn_strengths[c]: 1.0, add_button: gr.update(visible=True), del_button: gr.update(visible=c > 0) } return updates add_outputs = [count_state, add_button, del_button] + cn_rows del_outputs = [count_state, add_button, del_button] + cn_rows + cn_images + cn_strengths add_button.click(fn=add_cn_row, inputs=[count_state], outputs=add_outputs, show_progress=False) del_button.click(fn=del_cn_row, inputs=[count_state], outputs=del_outputs, show_progress=False) def on_cn_type_change(selected_type, model_name): from core.settings import MODEL_TYPE_MAP m_type = MODEL_TYPE_MAP.get(model_name, "SDXL") if model_name else "SDXL" cn_full_config = load_controlnet_config() architectures_dict = ARCHITECTURES_CONFIG.get('architectures', {}) controlnet_key = architectures_dict.get(m_type, {}).get("controlnet_key", m_type) cn_config = cn_full_config.get(controlnet_key, []) series_choices = [] if selected_type: series_choices = sorted(list(set( model.get("Series", "Default") for model in cn_config if selected_type in model.get("Type", []) ))) default_series = series_choices[0] if series_choices else None filepath = "None" if default_series: for model in cn_config: if model.get("Series") == default_series and selected_type in model.get("Type", []): filepath = model.get("Filepath") break return gr.update(choices=series_choices, value=default_series), filepath def on_cn_series_change(selected_series, selected_type, model_name): from core.settings import MODEL_TYPE_MAP m_type = MODEL_TYPE_MAP.get(model_name, "SDXL") if model_name else "SDXL" cn_full_config = load_controlnet_config() architectures_dict = ARCHITECTURES_CONFIG.get('architectures', {}) controlnet_key = architectures_dict.get(m_type, {}).get("controlnet_key", m_type) cn_config = cn_full_config.get(controlnet_key, []) filepath = "None" if selected_series and selected_type: for model in cn_config: if model.get("Series") == selected_series and selected_type in model.get("Type", []): filepath = model.get("Filepath") break return filepath for i in range(MAX_CONTROLNETS): cn_types[i].change( fn=on_cn_type_change, inputs=[cn_types[i], actual_arch_comp], outputs=[cn_series[i], cn_filepaths[i]], show_progress=False ) cn_series[i].change( fn=on_cn_series_change, inputs=[cn_series[i], cn_types[i], actual_arch_comp], outputs=[cn_filepaths[i]], show_progress=False ) def on_accordion_expand(*images): return [gr.update() for _ in images] accordion.expand( fn=on_accordion_expand, inputs=cn_images, outputs=cn_images, show_progress=False ) def create_anima_controlnet_lllite_event_handlers(prefix, ui_components): cn_rows = ui_components.get(f'anima_controlnet_lllite_rows_{prefix}') if not cn_rows: return cn_types = ui_components[f'anima_controlnet_lllite_types_{prefix}'] cn_series = ui_components[f'anima_controlnet_lllite_series_{prefix}'] cn_filepaths = ui_components[f'anima_controlnet_lllite_filepaths_{prefix}'] cn_images = ui_components[f'anima_controlnet_lllite_images_{prefix}'] cn_strengths = ui_components[f'anima_controlnet_lllite_strengths_{prefix}'] count_state = ui_components[f'anima_controlnet_lllite_count_state_{prefix}'] add_button = ui_components[f'add_anima_controlnet_lllite_button_{prefix}'] del_button = ui_components[f'delete_anima_controlnet_lllite_button_{prefix}'] accordion = ui_components[f'anima_controlnet_lllite_accordion_{prefix}'] def add_cn_row(c): c += 1 updates = { count_state: c, cn_rows[c-1]: gr.update(visible=True), add_button: gr.update(visible=c < MAX_CONTROLNETS), del_button: gr.update(visible=True) } return updates def del_cn_row(c): c -= 1 updates = { count_state: c, cn_rows[c]: gr.update(visible=False), cn_images[c]: None, cn_strengths[c]: 1.0, add_button: gr.update(visible=True), del_button: gr.update(visible=c > 0) } return updates add_outputs = [count_state, add_button, del_button] + cn_rows del_outputs = [count_state, add_button, del_button] + cn_rows + cn_images + cn_strengths add_button.click(fn=add_cn_row, inputs=[count_state], outputs=add_outputs, show_progress=False) del_button.click(fn=del_cn_row, inputs=[count_state], outputs=del_outputs, show_progress=False) def on_cn_type_change(selected_type): cn_config = load_anima_controlnet_lllite_config() series_choices = [] if selected_type: series_choices = sorted(list(set( model.get("Series", "Default") for model in cn_config if selected_type in model.get("Type", []) ))) default_series = series_choices[0] if series_choices else None filepath = "None" if default_series: for model in cn_config: if model.get("Series") == default_series and selected_type in model.get("Type", []): filepath = model.get("Filepath") break return gr.update(choices=series_choices, value=default_series), filepath def on_cn_series_change(selected_series, selected_type): cn_config = load_anima_controlnet_lllite_config() filepath = "None" if selected_series and selected_type: for model in cn_config: if model.get("Series") == selected_series and selected_type in model.get("Type", []): filepath = model.get("Filepath") break return filepath for i in range(MAX_CONTROLNETS): cn_types[i].change( fn=on_cn_type_change, inputs=[cn_types[i]], outputs=[cn_series[i], cn_filepaths[i]], show_progress=False ) cn_series[i].change( fn=on_cn_series_change, inputs=[cn_series[i], cn_types[i]], outputs=[cn_filepaths[i]], show_progress=False ) def on_accordion_expand(*images): return [gr.update() for _ in images] accordion.expand( fn=on_accordion_expand, inputs=cn_images, outputs=cn_images, show_progress=False ) def create_diffsynth_controlnet_event_handlers(prefix, ui_components): cn_rows = ui_components.get(f'diffsynth_controlnet_rows_{prefix}') if not cn_rows: return cn_types = ui_components[f'diffsynth_controlnet_types_{prefix}'] cn_series = ui_components[f'diffsynth_controlnet_series_{prefix}'] cn_filepaths = ui_components[f'diffsynth_controlnet_filepaths_{prefix}'] cn_images = ui_components[f'diffsynth_controlnet_images_{prefix}'] cn_strengths = ui_components[f'diffsynth_controlnet_strengths_{prefix}'] count_state = ui_components[f'diffsynth_controlnet_count_state_{prefix}'] add_button = ui_components[f'add_diffsynth_controlnet_button_{prefix}'] del_button = ui_components[f'delete_diffsynth_controlnet_button_{prefix}'] accordion = ui_components[f'diffsynth_controlnet_accordion_{prefix}'] base_model_comp = ui_components.get(f'base_model_{prefix}') actual_arch_comp = base_model_comp if base_model_comp else gr.State("SDXL") def add_cn_row(c): c += 1 updates = { count_state: c, cn_rows[c-1]: gr.update(visible=True), add_button: gr.update(visible=c < MAX_CONTROLNETS), del_button: gr.update(visible=True) } return updates def del_cn_row(c): c -= 1 updates = { count_state: c, cn_rows[c]: gr.update(visible=False), cn_images[c]: None, cn_strengths[c]: 1.0, add_button: gr.update(visible=True), del_button: gr.update(visible=c > 0) } return updates add_outputs = [count_state, add_button, del_button] + cn_rows del_outputs = [count_state, add_button, del_button] + cn_rows + cn_images + cn_strengths add_button.click(fn=add_cn_row, inputs=[count_state], outputs=add_outputs, show_progress=False) del_button.click(fn=del_cn_row, inputs=[count_state], outputs=del_outputs, show_progress=False) def on_cn_type_change(selected_type, model_name): from core.settings import MODEL_TYPE_MAP m_type = MODEL_TYPE_MAP.get(model_name, "SDXL") if model_name else "SDXL" cn_full_config = load_diffsynth_controlnet_config() architectures_dict = ARCHITECTURES_CONFIG.get('architectures', {}) controlnet_key = architectures_dict.get(m_type, {}).get("controlnet_key", m_type) cn_config = cn_full_config.get(controlnet_key, []) series_choices = [] if selected_type: series_choices = sorted(list(set( model.get("Series", "Default") for model in cn_config if selected_type in model.get("Type", []) ))) default_series = series_choices[0] if series_choices else None filepath = "None" if default_series: for model in cn_config: if model.get("Series") == default_series and selected_type in model.get("Type", []): filepath = model.get("Filepath") break return gr.update(choices=series_choices, value=default_series), filepath def on_cn_series_change(selected_series, selected_type, model_name): from core.settings import MODEL_TYPE_MAP m_type = MODEL_TYPE_MAP.get(model_name, "SDXL") if model_name else "SDXL" cn_full_config = load_diffsynth_controlnet_config() architectures_dict = ARCHITECTURES_CONFIG.get('architectures', {}) controlnet_key = architectures_dict.get(m_type, {}).get("controlnet_key", m_type) cn_config = cn_full_config.get(controlnet_key, []) filepath = "None" if selected_series and selected_type: for model in cn_config: if model.get("Series") == selected_series and selected_type in model.get("Type", []): filepath = model.get("Filepath") break return filepath for i in range(MAX_CONTROLNETS): cn_types[i].change( fn=on_cn_type_change, inputs=[cn_types[i], actual_arch_comp], outputs=[cn_series[i], cn_filepaths[i]], show_progress=False ) cn_series[i].change( fn=on_cn_series_change, inputs=[cn_series[i], cn_types[i], actual_arch_comp], outputs=[cn_filepaths[i]], show_progress=False ) def on_accordion_expand(*images): return [gr.update() for _ in images] accordion.expand( fn=on_accordion_expand, inputs=cn_images, outputs=cn_images, show_progress=False ) def create_flux1_ipadapter_event_handlers(prefix, ui_components): fipa_rows = ui_components.get(f'flux1_ipadapter_rows_{prefix}') if not fipa_rows: return count_state = ui_components[f'flux1_ipadapter_count_state_{prefix}'] add_button = ui_components[f'add_flux1_ipadapter_button_{prefix}'] del_button = ui_components[f'delete_flux1_ipadapter_button_{prefix}'] def add_fipa_row(c): c += 1 return { count_state: c, fipa_rows[c - 1]: gr.update(visible=True), add_button: gr.update(visible=c < MAX_IPADAPTERS), del_button: gr.update(visible=True), } def del_fipa_row(c): c -= 1 return { count_state: c, fipa_rows[c]: gr.update(visible=False), add_button: gr.update(visible=True), del_button: gr.update(visible=c > 0), } add_outputs = [count_state, add_button, del_button] + fipa_rows del_outputs = [count_state, add_button, del_button] + fipa_rows add_button.click(fn=add_fipa_row, inputs=[count_state], outputs=add_outputs, show_progress=False) del_button.click(fn=del_fipa_row, inputs=[count_state], outputs=del_outputs, show_progress=False) def create_sd3_ipadapter_event_handlers(prefix, ui_components): ipa_rows = ui_components.get(f'sd3_ipadapter_rows_{prefix}') if not ipa_rows: return count_state = ui_components[f'sd3_ipadapter_count_state_{prefix}'] add_button = ui_components[f'add_sd3_ipadapter_button_{prefix}'] del_button = ui_components[f'delete_sd3_ipadapter_button_{prefix}'] images = ui_components[f'sd3_ipadapter_images_{prefix}'] weights = ui_components[f'sd3_ipadapter_weights_{prefix}'] start_percents = ui_components[f'sd3_ipadapter_start_percents_{prefix}'] end_percents = ui_components[f'sd3_ipadapter_end_percents_{prefix}'] def add_ipa_row(c): c += 1 return { count_state: c, ipa_rows[c - 1]: gr.update(visible=True), add_button: gr.update(visible=c < MAX_IPADAPTERS), del_button: gr.update(visible=True), } def del_ipa_row(c): c -= 1 return { count_state: c, ipa_rows[c]: gr.update(visible=False), images[c]: None, weights[c]: 0.5, start_percents[c]: 0.0, end_percents[c]: 1.0, add_button: gr.update(visible=True), del_button: gr.update(visible=c > 0), } add_outputs = [count_state, add_button, del_button] + ipa_rows del_outputs = [count_state, add_button, del_button] + ipa_rows + images + weights + start_percents + end_percents add_button.click(fn=add_ipa_row, inputs=[count_state], outputs=add_outputs, show_progress=False) del_button.click(fn=del_ipa_row, inputs=[count_state], outputs=del_outputs, show_progress=False) def create_style_event_handlers(prefix, ui_components): style_rows = ui_components.get(f'style_rows_{prefix}') if not style_rows: return count_state = ui_components[f'style_count_state_{prefix}'] add_button = ui_components[f'add_style_button_{prefix}'] del_button = ui_components[f'delete_style_button_{prefix}'] def add_style_row(c): c += 1 return { count_state: c, style_rows[c - 1]: gr.update(visible=True), add_button: gr.update(visible=c < 5), del_button: gr.update(visible=True), } def del_style_row(c): c -= 1 return { count_state: c, style_rows[c]: gr.update(visible=False), add_button: gr.update(visible=True), del_button: gr.update(visible=c > 0), } add_outputs = [count_state, add_button, del_button] + style_rows del_outputs = [count_state, add_button, del_button] + style_rows add_button.click(fn=add_style_row, inputs=[count_state], outputs=add_outputs, show_progress=False) del_button.click(fn=del_style_row, inputs=[count_state], outputs=del_outputs, show_progress=False) def create_ipadapter_event_handlers(prefix, ui_components): ipa_rows = ui_components.get(f'ipadapter_rows_{prefix}') if not ipa_rows: return ipa_lora_strengths = ui_components[f'ipadapter_lora_strengths_{prefix}'] ipa_final_preset = ui_components[f'ipadapter_final_preset_{prefix}'] ipa_final_lora_strength = ui_components[f'ipadapter_final_lora_strength_{prefix}'] count_state = ui_components[f'ipadapter_count_state_{prefix}'] add_button = ui_components[f'add_ipadapter_button_{prefix}'] del_button = ui_components[f'delete_ipadapter_button_{prefix}'] accordion = ui_components[f'ipadapter_accordion_{prefix}'] def add_ipa_row(c): c += 1 return { count_state: c, ipa_rows[c - 1]: gr.update(visible=True), add_button: gr.update(visible=c < MAX_IPADAPTERS), del_button: gr.update(visible=True), } def del_ipa_row(c): c -= 1 return { count_state: c, ipa_rows[c]: gr.update(visible=False), add_button: gr.update(visible=True), del_button: gr.update(visible=c > 0), } add_outputs = [count_state, add_button, del_button] + ipa_rows del_outputs = [count_state, add_button, del_button] + ipa_rows add_button.click(fn=add_ipa_row, inputs=[count_state], outputs=add_outputs, show_progress=False) del_button.click(fn=del_ipa_row, inputs=[count_state], outputs=del_outputs, show_progress=False) def on_preset_change(preset_value): config = load_ipadapter_config() faceid_presets = [] if config: faceid_presets.extend(config.get("IPAdapter_FaceID_presets", {}).get("SDXL", [])) faceid_presets.extend(config.get("IPAdapter_FaceID_presets", {}).get("SD1.5", [])) is_visible = preset_value in faceid_presets updates = [gr.update(visible=is_visible)] * (MAX_IPADAPTERS + 1) return updates all_lora_strength_sliders = [ipa_final_lora_strength] + ipa_lora_strengths ipa_final_preset.change(fn=on_preset_change, inputs=[ipa_final_preset], outputs=all_lora_strength_sliders, show_progress=False) accordion.expand(fn=lambda *imgs: [gr.update() for _ in imgs], inputs=ui_components[f'ipadapter_images_{prefix}'], outputs=ui_components[f'ipadapter_images_{prefix}'], show_progress=False) def create_reference_latent_event_handlers(prefix, ui_components): ref_rows = ui_components.get(f'reference_latent_rows_{prefix}') if not ref_rows: return count_state = ui_components[f'reference_latent_count_state_{prefix}'] add_button = ui_components[f'add_reference_latent_button_{prefix}'] del_button = ui_components[f'delete_reference_latent_button_{prefix}'] images = ui_components[f'reference_latent_images_{prefix}'] def add_ref_row(c): c += 1 return { count_state: c, ref_rows[c - 1]: gr.update(visible=True), add_button: gr.update(visible=c < 10), del_button: gr.update(visible=True), } def del_ref_row(c): c -= 1 return { count_state: c, ref_rows[c]: gr.update(visible=False), images[c]: None, add_button: gr.update(visible=True), del_button: gr.update(visible=c > 0), } add_outputs = [count_state, add_button, del_button] + ref_rows del_outputs = [count_state, add_button, del_button] + ref_rows + images add_button.click(fn=add_ref_row, inputs=[count_state], outputs=add_outputs, show_progress=False) del_button.click(fn=del_ref_row, inputs=[count_state], outputs=del_outputs, show_progress=False) def create_hidream_o1_reference_event_handlers(prefix, ui_components): ref_rows = ui_components.get(f'hidream_o1_reference_rows_{prefix}') if not ref_rows: return count_state = ui_components[f'hidream_o1_reference_count_state_{prefix}'] add_button = ui_components[f'add_hidream_o1_reference_button_{prefix}'] del_button = ui_components[f'delete_hidream_o1_reference_button_{prefix}'] images = ui_components[f'hidream_o1_reference_images_{prefix}'] def add_ref_row(c): c += 1 return { count_state: c, ref_rows[c - 1]: gr.update(visible=True), add_button: gr.update(visible=c < 10), del_button: gr.update(visible=True), } def del_ref_row(c): c -= 1 return { count_state: c, ref_rows[c]: gr.update(visible=False), images[c]: None, add_button: gr.update(visible=True), del_button: gr.update(visible=c > 0), } add_outputs = [count_state, add_button, del_button] + ref_rows del_outputs = [count_state, add_button, del_button] + ref_rows + images add_button.click(fn=add_ref_row, inputs=[count_state], outputs=add_outputs, show_progress=False) del_button.click(fn=del_ref_row, inputs=[count_state], outputs=del_outputs, show_progress=False) def create_embedding_event_handlers(prefix, ui_components): rows = ui_components.get(f'embedding_rows_{prefix}') if not rows: return ids = ui_components[f'embeddings_ids_{prefix}'] files = ui_components[f'embeddings_files_{prefix}'] count_state = ui_components[f'embedding_count_state_{prefix}'] add_button = ui_components[f'add_embedding_button_{prefix}'] del_button = ui_components[f'delete_embedding_button_{prefix}'] def add_row(c): c += 1 return { count_state: c, rows[c - 1]: gr.update(visible=True), add_button: gr.update(visible=c < MAX_EMBEDDINGS), del_button: gr.update(visible=True) } def del_row(c): c -= 1 return { count_state: c, rows[c]: gr.update(visible=False), ids[c]: "", files[c]: None, add_button: gr.update(visible=True), del_button: gr.update(visible=c > 0) } add_outputs = [count_state, add_button, del_button] + rows del_outputs = [count_state, add_button, del_button] + rows + ids + files add_button.click(fn=add_row, inputs=[count_state], outputs=add_outputs, show_progress=False) del_button.click(fn=del_row, inputs=[count_state], outputs=del_outputs, show_progress=False) def create_conditioning_event_handlers(prefix, ui_components): rows = ui_components.get(f'conditioning_rows_{prefix}') if not rows: return prompts = ui_components[f'conditioning_prompts_{prefix}'] count_state = ui_components[f'conditioning_count_state_{prefix}'] add_button = ui_components[f'add_conditioning_button_{prefix}'] del_button = ui_components[f'delete_conditioning_button_{prefix}'] def add_row(c): c += 1 return { count_state: c, rows[c - 1]: gr.update(visible=True), add_button: gr.update(visible=c < MAX_CONDITIONINGS), del_button: gr.update(visible=True), } def del_row(c): c -= 1 return { count_state: c, rows[c]: gr.update(visible=False), prompts[c]: "", add_button: gr.update(visible=True), del_button: gr.update(visible=c > 0), } add_outputs = [count_state, add_button, del_button] + rows del_outputs = [count_state, add_button, del_button] + rows + prompts add_button.click(fn=add_row, inputs=[count_state], outputs=add_outputs, show_progress=False) del_button.click(fn=del_row, inputs=[count_state], outputs=del_outputs, show_progress=False)