@ -13,6 +13,9 @@ import html
from modules import extensions , shared , paths
available_extensions = { " extensions " : [ ] }
def check_access ( ) :
assert not shared . cmd_opts . disable_extension_access , " extension access disabed because of commandline flags "
@ -96,6 +99,14 @@ def extension_table():
return code
def normalize_git_url ( url ) :
if url is None :
return " "
url = url . replace ( " .git " , " " )
return url
def install_extension_from_url ( dirname , url ) :
check_access ( )
@ -103,14 +114,15 @@ def install_extension_from_url(dirname, url):
if dirname is None or dirname == " " :
* parts , last_part = url . split ( ' / ' )
last_part = last_part. replace ( " .git " , " " )
last_part = normalize_git_url( last_part )
dirname = last_part
target_dir = os . path . join ( extensions . extensions_dir , dirname )
assert not os . path . exists ( target_dir ) , f ' Extension directory already exists: { target_dir } '
assert len ( [ x for x in extensions . extensions if x . remote == url ] ) == 0 , ' Extension with this URL is already installed '
normalized_url = normalize_git_url ( url )
assert len ( [ x for x in extensions . extensions if normalize_git_url ( x . remote ) == normalized_url ] ) == 0 , ' Extension with this URL is already installed '
tmpdir = os . path . join ( paths . script_path , " tmp " , dirname )
@ -128,18 +140,80 @@ def install_extension_from_url(dirname, url):
shutil . rmtree ( tmpdir , True )
def install_extension_from_index ( url ) :
ext_table , message = install_extension_from_url ( None , url )
return refresh_available_extensions_from_data ( ) , ext_table , message
def refresh_available_extensions ( url ) :
global available_extensions
import urllib . request
with urllib . request . urlopen ( url ) as response :
text = response . read ( )
available_extensions = json . loads ( text )
return url , refresh_available_extensions_from_data ( ) , ' '
def refresh_available_extensions_from_data ( ) :
extlist = available_extensions [ " extensions " ]
installed_extension_urls = { normalize_git_url ( extension . remote ) : extension . name for extension in extensions . extensions }
code = f """ <!-- { time . time ( ) } -->
< table id = " available_extensions " >
< thead >
< tr >
< th > Extension < / th >
< th > Description < / th >
< th > Action < / th >
< / tr >
< / thead >
< tbody >
"""
for ext in extlist :
name = ext . get ( " name " , " noname " )
url = ext . get ( " url " , None )
description = ext . get ( " description " , " " )
if url is None :
continue
existing = installed_extension_urls . get ( normalize_git_url ( url ) , None )
install_code = f """ <input onclick= " install_extension_from_index(this, ' { html . escape ( url ) } ' ) " type= " button " value= " { " Install " if not existing else " Installed " } " { " disabled=disabled " if existing else " " } class= " gr-button gr-button-lg gr-button-secondary " > """
code + = f """
< tr >
< td > < a href = " { html.escape(url)} " > { html . escape ( name ) } < / a > < / td >
< td > { html . escape ( description ) } < / td >
< td > { install_code } < / td >
< / tr >
"""
code + = """
< / tbody >
< / table >
"""
return code
def create_ui ( ) :
import modules . ui
with gr . Blocks ( analytics_enabled = False ) as ui :
with gr . Tabs ( elem_id = " tabs_extensions " ) as tabs :
with gr . TabItem ( " Installed " ) :
extensions_disabled_list = gr . Text ( elem_id = " extensions_disabled_list " , visible = False )
extensions_update_list = gr . Text ( elem_id = " extensions_update_list " , visible = False )
with gr . Row ( ) :
apply = gr . Button ( value = " Apply and restart UI " , variant = " primary " )
check = gr . Button ( value = " Check for updates " )
extensions_disabled_list = gr . Text ( elem_id = " extensions_disabled_list " , visible = False ) . style ( container = False )
extensions_update_list = gr . Text ( elem_id = " extensions_update_list " , visible = False ) . style ( container = False )
extensions_table = gr . HTML ( lambda : extension_table ( ) )
@ -157,16 +231,38 @@ def create_ui():
outputs = [ extensions_table ] ,
)
with gr . TabItem ( " Available " ) :
with gr . Row ( ) :
refresh_available_extensions_button = gr . Button ( value = " Load from: " , variant = " primary " )
available_extensions_index = gr . Text ( value = " https://raw.githubusercontent.com/wiki/AUTOMATIC1111/stable-diffusion-webui/Extensions-index.md " , label = " Extension index URL " ) . style ( container = False )
extension_to_install = gr . Text ( elem_id = " extension_to_install " , visible = False )
install_extension_button = gr . Button ( elem_id = " install_extension_button " , visible = False )
install_result = gr . HTML ( )
available_extensions_table = gr . HTML ( )
refresh_available_extensions_button . click (
fn = modules . ui . wrap_gradio_call ( refresh_available_extensions , extra_outputs = [ gr . update ( ) , gr . update ( ) ] ) ,
inputs = [ available_extensions_index ] ,
outputs = [ available_extensions_index , available_extensions_table , install_result ] ,
)
install_extension_button . click (
fn = modules . ui . wrap_gradio_call ( install_extension_from_index , extra_outputs = [ gr . update ( ) , gr . update ( ) ] ) ,
inputs = [ extension_to_install ] ,
outputs = [ available_extensions_table , extensions_table , install_result ] ,
)
with gr . TabItem ( " Install from URL " ) :
install_url = gr . Text ( label = " URL for extension ' s git repository " )
install_dirname = gr . Text ( label = " Local directory name " , placeholder = " Leave empty for auto " )
intall_button = gr . Button ( value = " Install " , variant = " primary " )
intall_result = gr . HTML ( elem_id = " extension_install_result " )
in s tall_button = gr . Button ( value = " Install " , variant = " primary " )
in s tall_result = gr . HTML ( elem_id = " extension_install_result " )
intall_button . click (
in s tall_button. click (
fn = modules . ui . wrap_gradio_call ( install_extension_from_url , extra_outputs = [ gr . update ( ) ] ) ,
inputs = [ install_dirname , install_url ] ,
outputs = [ extensions_table , intall_result ] ,
outputs = [ extensions_table , in s tall_result] ,
)
return ui