diff --git a/.eslintrc.js b/.eslintrc.js index f33aca09fa0..4777c276e9b 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -87,5 +87,11 @@ module.exports = { modalNextImage: "readonly", // token-counters.js setupTokenCounters: "readonly", + // localStorage.js + localSet: "readonly", + localGet: "readonly", + localRemove: "readonly", + // resizeHandle.js + setupResizeHandle: "writable" } }; diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index d80b24e2bde..cf6a2be86fa 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -26,7 +26,7 @@ body: id: steps attributes: label: Steps to reproduce the problem - description: Please provide us with precise step by step information on how to reproduce the bug + description: Please provide us with precise step by step instructions on how to reproduce the bug value: | 1. Go to .... 2. Press .... @@ -37,64 +37,14 @@ body: id: what-should attributes: label: What should have happened? - description: Tell what you think the normal behavior should be + description: Tell us what you think the normal behavior should be validations: required: true - - type: input - id: commit - attributes: - label: Version or Commit where the problem happens - description: "Which webui version or commit are you running ? (Do not write *Latest Version/repo/commit*, as this means nothing and will have changed by the time we read your issue. Rather, copy the **Version: v1.2.3** link at the bottom of the UI, or from the cmd/terminal if you can't launch it.)" - validations: - required: true - - type: dropdown - id: py-version - attributes: - label: What Python version are you running on ? - multiple: false - options: - - Python 3.10.x - - Python 3.11.x (above, no supported yet) - - Python 3.9.x (below, no recommended) - - type: dropdown - id: platforms - attributes: - label: What platforms do you use to access the UI ? - multiple: true - options: - - Windows - - Linux - - MacOS - - iOS - - Android - - Other/Cloud - - type: dropdown - id: device - attributes: - label: What device are you running WebUI on? - multiple: true - options: - - Nvidia GPUs (RTX 20 above) - - Nvidia GPUs (GTX 16 below) - - AMD GPUs (RX 6000 above) - - AMD GPUs (RX 5000 below) - - CPU - - Other GPUs - - type: dropdown - id: cross_attention_opt + - type: textarea + id: sysinfo attributes: - label: Cross attention optimization - description: What cross attention optimization are you using, Settings -> Optimizations -> Cross attention optimization - multiple: false - options: - - Automatic - - xformers - - sdp-no-mem - - sdp - - Doggettx - - V1 - - InvokeAI - - "None " + label: Sysinfo + description: System info file, generated by WebUI. You can generate it in settings, on the Sysinfo page. Drag the file into the field to upload it. If you submit your report without including the sysinfo file, the report will be closed. If needed, review the report to make sure it includes no personal information you don't want to share. If you can't start WebUI, you can use --dump-sysinfo commandline argument to generate the file. validations: required: true - type: dropdown @@ -108,21 +58,7 @@ body: - Brave - Apple Safari - Microsoft Edge - - type: textarea - id: cmdargs - attributes: - label: Command Line Arguments - description: Are you using any launching parameters/command line arguments (modified webui-user .bat/.sh) ? If yes, please write them below. Write "No" otherwise. - render: Shell - validations: - required: true - - type: textarea - id: extensions - attributes: - label: List of extensions - description: Are you using any extensions other than built-ins? If yes, provide a list, you can copy it at "Extensions" tab. Write "No" otherwise. - validations: - required: true + - Other - type: textarea id: logs attributes: diff --git a/CHANGELOG.md b/CHANGELOG.md index 63a2c7d3972..1cd3572c8e0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,183 @@ +## 1.6.0 + +### Features: + * refiner support [#12371](https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/12371) + * add NV option for Random number generator source setting, which allows to generate same pictures on CPU/AMD/Mac as on NVidia videocards + * add style editor dialog + * hires fix: add an option to use a different checkpoint for second pass ([#12181](https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/12181)) + * option to keep multiple loaded models in memory ([#12227](https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/12227)) + * new samplers: Restart, DPM++ 2M SDE Exponential, DPM++ 2M SDE Heun, DPM++ 2M SDE Heun Karras, DPM++ 2M SDE Heun Exponential, DPM++ 3M SDE, DPM++ 3M SDE Karras, DPM++ 3M SDE Exponential ([#12300](https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/12300), [#12519](https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/12519), [#12542](https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/12542)) + * rework DDIM, PLMS, UniPC to use CFG denoiser same as in k-diffusion samplers: + * makes all of them work with img2img + * makes prompt composition posssible (AND) + * makes them available for SDXL + * always show extra networks tabs in the UI ([#11808](https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/11808)) + * use less RAM when creating models ([#11958](https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/11958), [#12599](https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/12599)) + * textual inversion inference support for SDXL + * extra networks UI: show metadata for SD checkpoints + * checkpoint merger: add metadata support + * prompt editing and attention: add support for whitespace after the number ([ red : green : 0.5 ]) (seed breaking change) ([#12177](https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/12177)) + * VAE: allow selecting own VAE for each checkpoint (in user metadata editor) + * VAE: add selected VAE to infotext + * options in main UI: add own separate setting for txt2img and img2img, correctly read values from pasted infotext, add setting for column count ([#12551](https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/12551)) + * add resize handle to txt2img and img2img tabs, allowing to change the amount of horizontable space given to generation parameters and resulting image gallery ([#12687](https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/12687), [#12723](https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/12723)) + * change default behavior for batching cond/uncond -- now it's on by default, and is disabled by an UI setting (Optimizatios -> Batch cond/uncond) - if you are on lowvram/medvram and are getting OOM exceptions, you will need to enable it + * show current position in queue and make it so that requests are processed in the order of arrival ([#12707](https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/12707)) + * add `--medvram-sdxl` flag that only enables `--medvram` for SDXL models + * prompt editing timeline has separate range for first pass and hires-fix pass (seed breaking change) ([#12457](https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/12457)) + +### Minor: + * img2img batch: RAM savings, VRAM savings, .tif, .tiff in img2img batch ([#12120](https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/12120), [#12514](https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/12514), [#12515](https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/12515)) + * postprocessing/extras: RAM savings ([#12479](https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/12479)) + * XYZ: in the axis labels, remove pathnames from model filenames + * XYZ: support hires sampler ([#12298](https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/12298)) + * XYZ: new option: use text inputs instead of dropdowns ([#12491](https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/12491)) + * add gradio version warning + * sort list of VAE checkpoints ([#12297](https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/12297)) + * use transparent white for mask in inpainting, along with an option to select the color ([#12326](https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/12326)) + * move some settings to their own section: img2img, VAE + * add checkbox to show/hide dirs for extra networks + * Add TAESD(or more) options for all the VAE encode/decode operation ([#12311](https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/12311)) + * gradio theme cache, new gradio themes, along with explanation that the user can input his own values ([#12346](https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/12346), [#12355](https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/12355)) + * sampler fixes/tweaks: s_tmax, s_churn, s_noise, s_tmax ([#12354](https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/12354), [#12356](https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/12356), [#12357](https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/12357), [#12358](https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/12358), [#12375](https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/12375), [#12521](https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/12521)) + * update README.md with correct instructions for Linux installation ([#12352](https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/12352)) + * option to not save incomplete images, on by default ([#12338](https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/12338)) + * enable cond cache by default + * git autofix for repos that are corrupted ([#12230](https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/12230)) + * allow to open images in new browser tab by middle mouse button ([#12379](https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/12379)) + * automatically open webui in browser when running "locally" ([#12254](https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/12254)) + * put commonly used samplers on top, make DPM++ 2M Karras the default choice + * zoom and pan: option to auto-expand a wide image, improved integration ([#12413](https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/12413), [#12727](https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/12727)) + * option to cache Lora networks in memory + * rework hires fix UI to use accordion + * face restoration and tiling moved to settings - use "Options in main UI" setting if you want them back + * change quicksettings items to have variable width + * Lora: add Norm module, add support for bias ([#12503](https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/12503)) + * Lora: output warnings in UI rather than fail for unfitting loras; switch to logging for error output in console + * support search and display of hashes for all extra network items ([#12510](https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/12510)) + * add extra noise param for img2img operations ([#12564](https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/12564)) + * support for Lora with bias ([#12584](https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/12584)) + * make interrupt quicker ([#12634](https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/12634)) + * configurable gallery height ([#12648](https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/12648)) + * make results column sticky ([#12645](https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/12645)) + * more hash filename patterns ([#12639](https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/12639)) + * make image viewer actually fit the whole page ([#12635](https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/12635)) + * make progress bar work independently from live preview display which results in it being updated a lot more often + * forbid Full live preview method for medvram and add a setting to undo the forbidding + * make it possible to localize tooltips and placeholders + * add option to align with sgm repo's sampling implementation ([#12818](https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/12818)) + * Restore faces and Tiling generation parameters have been moved to settings out of main UI + * if you want to put them back into main UI, use `Options in main UI` setting on the UI page. + +### Extensions and API: + * gradio 3.41.2 + * also bump versions for packages: transformers, GitPython, accelerate, scikit-image, timm, tomesd + * support tooltip kwarg for gradio elements: gr.Textbox(label='hello', tooltip='world') + * properly clear the total console progressbar when using txt2img and img2img from API + * add cmd_arg --disable-extra-extensions and --disable-all-extensions ([#12294](https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/12294)) + * shared.py and webui.py split into many files + * add --loglevel commandline argument for logging + * add a custom UI element that combines accordion and checkbox + * avoid importing gradio in tests because it spams warnings + * put infotext label for setting into OptionInfo definition rather than in a separate list + * make `StableDiffusionProcessingImg2Img.mask_blur` a property, make more inline with PIL `GaussianBlur` ([#12470](https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/12470)) + * option to make scripts UI without gr.Group + * add a way for scripts to register a callback for before/after just a single component's creation + * use dataclass for StableDiffusionProcessing + * store patches for Lora in a specialized module instead of inside torch + * support http/https URLs in API ([#12663](https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/12663), [#12698](https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/12698)) + * add extra noise callback ([#12616](https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/12616)) + * dump current stack traces when exiting with SIGINT + * add type annotations for extra fields of shared.sd_model + +### Bug Fixes: + * Don't crash if out of local storage quota for javascriot localStorage + * XYZ plot do not fail if an exception occurs + * fix missing TI hash in infotext if generation uses both negative and positive TI ([#12269](https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/12269)) + * localization fixes ([#12307](https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/12307)) + * fix sdxl model invalid configuration after the hijack + * correctly toggle extras checkbox for infotext paste ([#12304](https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/12304)) + * open raw sysinfo link in new page ([#12318](https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/12318)) + * prompt parser: Account for empty field in alternating words syntax ([#12319](https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/12319)) + * add tab and carriage return to invalid filename chars ([#12327](https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/12327)) + * fix api only Lora not working ([#12387](https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/12387)) + * fix options in main UI misbehaving when there's just one element + * make it possible to use a sampler from infotext even if it's hidden in the dropdown + * fix styles missing from the prompt in infotext when making a grid of batch of multiplie images + * prevent bogus progress output in console when calculating hires fix dimensions + * fix --use-textbox-seed + * fix broken `Lora/Networks: use old method` option ([#12466](https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/12466)) + * properly return `None` for VAE hash when using `--no-hashing` ([#12463](https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/12463)) + * MPS/macOS fixes and optimizations ([#12526](https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/12526)) + * add second_order to samplers that mistakenly didn't have it + * when refreshing cards in extra networks UI, do not discard user's custom resolution + * fix processing error that happens if batch_size is not a multiple of how many prompts/negative prompts there are ([#12509](https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/12509)) + * fix inpaint upload for alpha masks ([#12588](https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/12588)) + * fix exception when image sizes are not integers ([#12586](https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/12586)) + * fix incorrect TAESD Latent scale ([#12596](https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/12596)) + * auto add data-dir to gradio-allowed-path ([#12603](https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/12603)) + * fix exception if extensuions dir is missing ([#12607](https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/12607)) + * fix issues with api model-refresh and vae-refresh ([#12638](https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/12638)) + * fix img2img background color for transparent images option not being used ([#12633](https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/12633)) + * attempt to resolve NaN issue with unstable VAEs in fp32 mk2 ([#12630](https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/12630)) + * implement missing undo hijack for SDXL + * fix xyz swap axes ([#12684](https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/12684)) + * fix errors in backup/restore tab if any of config files are broken ([#12689](https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/12689)) + * fix SD VAE switch error after model reuse ([#12685](https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/12685)) + * fix trying to create images too large for the chosen format ([#12667](https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/12667)) + * create Gradio temp directory if necessary ([#12717](https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/12717)) + * prevent possible cache loss if exiting as it's being written by using an atomic operation to replace the cache with the new version + * set devices.dtype_unet correctly + * run RealESRGAN on GPU for non-CUDA devices ([#12737](https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/12737)) + * prevent extra network buttons being obscured by description for very small card sizes ([#12745](https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/12745)) + * fix error that causes some extra networks to be disabled if both and are present in the prompt + * fix defaults settings page breaking when any of main UI tabs are hidden + * fix incorrect save/display of new values in Defaults page in settings + * fix for Reload UI function: if you reload UI on one tab, other opened tabs will no longer stop working + * fix an error that prevents VAE being reloaded after an option change if a VAE near the checkpoint exists ([#12797](https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/12737)) + * hide broken image crop tool ([#12792](https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/12737)) + * don't show hidden samplers in dropdown for XYZ script ([#12780](https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/12737)) + * fix style editing dialog breaking if it's opened in both img2img and txt2img tabs + * fix a bug allowing users to bypass gradio and API authentication (reported by vysecurity) + * fix notification not playing when built-in webui tab is inactive ([#12834](https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/12834)) + * honor `--skip-install` for extension installers ([#12832](https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/12832)) + * don't print blank stdout in extension installers ([#12833](https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/12832), [#12855](https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/12855)) + * do not change quicksettings dropdown option when value returned is `None` ([#12854](https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/12854)) + * get progressbar to display correctly in extensions tab + + +## 1.5.2 + +### Bug Fixes: + * fix memory leak when generation fails + * update doggettx cross attention optimization to not use an unreasonable amount of memory in some edge cases -- suggestion by MorkTheOrk + + +## 1.5.1 + +### Minor: + * support parsing text encoder blocks in some new LoRAs + * delete scale checker script due to user demand + +### Extensions and API: + * add postprocess_batch_list script callback + +### Bug Fixes: + * fix TI training for SD1 + * fix reload altclip model error + * prepend the pythonpath instead of overriding it + * fix typo in SD_WEBUI_RESTARTING + * if txt2img/img2img raises an exception, finally call state.end() + * fix composable diffusion weight parsing + * restyle Startup profile for black users + * fix webui not launching with --nowebui + * catch exception for non git extensions + * fix some options missing from /sdapi/v1/options + * fix for extension update status always saying "unknown" + * fix display of extra network cards that have `<>` in the name + * update lora extension to work with python 3.8 + + ## 1.5.0 ### Features: diff --git a/CITATION.cff b/CITATION.cff new file mode 100644 index 00000000000..819363f3bb9 --- /dev/null +++ b/CITATION.cff @@ -0,0 +1,7 @@ +cff-version: 1.2.0 +message: "If you use this software, please cite it as below." +authors: + - given-names: Anapnoe +title: "Stable Diffusion Web UI-UX" +date-released: 2023-11-01 +url: "https://github.com/anapnoe/stable-diffusion-webui-ux" diff --git a/CODEOWNERS b/CODEOWNERS index bfa1095d8d3..7438c9bc69d 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -1,4 +1,4 @@ -* @anapnoe +* @AUTOMATIC1111 # if you were managing a localization and were removed from this file, this is because # the intended way to do localizations now is via extensions. See: diff --git a/README.md b/README.md index e74074735d0..2af2a43da65 100644 --- a/README.md +++ b/README.md @@ -1,68 +1,12 @@ -# Stable Diffusion web UI-UX -Not just a browser interface based on Gradio library for Stable Diffusion. -A pixel perfect design, mobile friendly, customizable interface that adds accessibility, ease of use and extended functionallity to the stable diffusion web ui. -Enjoy! +# Stable Diffusion web UI-UX +A bespoke, highly adaptable user interface for the Stable Diffusion, utilizing the powerful Gradio library. This cutting-edge browser interface offer an unparalleled level of customization and optimization for users, setting it apart from other web interfaces. +![](screenshot.png) -Default theme - -![anapnoe_uiux](https://user-images.githubusercontent.com/124302297/227973574-6003142d-0c7c-41c6-9966-0792a94549e9.png) - -## Features of ui-ux -- resizable viewport -- switchable viewports (DoubleClick on the split handler to swap views) option in settings for default position -- mobile navigation -- top header tabs (option setting) -- hidden tabs (option setting) no need to restart this is a different implementation -- drag and drop reordable quick settings offcanvas aside view -- drag and drop images to txt2img and img2img and import generation info parameters along with a preview image -- ignore - remove overrides when import [multiselect] (option setting) -- resizable cards for extra networks and number of rows (option setting) -- lazy loading alternative offcanvas aside view for extra networks (option setting) -- live preview image fit method (option setting) -- generated image fit method (option setting) -- max resolution output for txt2img and img2img (option setting) -- performant dispatch for gradio's range slider and input number field issue: https://github.com/gradio-app/gradio/issues/3204 (option setting) latest update uses only one instance clone to mediate for the release event -- ticks input range sliders (option setting) -- pacman preloader unified colors on reload ui -- frame border animation when generating images -- progress bar on top of the page always visible (when scroll for mobile) -- remix icons -- style theme configurator extension to customize every aspect of theme in real time with cool global functions to change the hue / saturation / brightness or invert the theme colors -- pan and zoom in out functionality for sketch, inpaint, inpaint sketch -- fullscreen support for sketch, inpaint, inpaint sketch -- better lightbox with zoom in-out mobile gestures support etc.. - -## TODO -- small arrows next to icons sent to inpaint, extras, img2img etc -- component gallery navigate to previous generations inside the txt2img, img2img interface -- and auto load the current generation settings -- credits/about page display all 300+ contributors so far inside the UI - -Quick Settings aside off-canvas view - drag and drop to custom sort your settings - -![anapnoe_uiux_quicksettings](https://user-images.githubusercontent.com/124302297/227967695-f8bb01b5-5cc9-4238-80dd-06e261378d6e.png) - - -Extra Networks aside off-canvas view - -![anapnoe_uiux_extra_networks](https://user-images.githubusercontent.com/124302297/227968001-20eab8f5-da91-4a11-9fe0-230fec4ba720.png) - - -Detail img2img sketch view - -![anapnoe_uiux_sketch](https://user-images.githubusercontent.com/124302297/227973727-084da8e0-931a-4c62-ab73-39e988fd4523.png) - - -Theme Configurator - aside off-canvas view - -![anapnoe_uiux_theme_config](https://user-images.githubusercontent.com/124302297/227967844-45063edb-eb40-4224-9666-f506d21d7780.png) - - -Mobile 395px width - -![anapnoe_uiux_mobile](https://user-images.githubusercontent.com/124302297/227987709-36231d30-e6da-424a-8930-cc0c55a0b979.png) - +## Todo +- Mobile Support +- Fullscreen Gallery Support +- UI-UX Options in Settings ## Features @@ -90,7 +34,7 @@ Mobile 395px width - CodeFormer, face restoration tool as an alternative to GFPGAN - RealESRGAN, neural network upscaler - ESRGAN, neural network upscaler with a lot of third party models - - SwinIR and Swin2SR([see here](https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/2092)), neural network upscalers + - SwinIR and Swin2SR ([see here](https://github.com/AUTOMATIC1111/stable-diffusion-webui/pull/2092)), neural network upscalers - LDSR, Latent diffusion super resolution upscaling - Resizing aspect ratio options - Sampling method selection @@ -108,7 +52,7 @@ Mobile 395px width - drag and drop an image/text-parameters to promptbox - Read Generation Parameters Button, loads parameters in promptbox to UI - Settings page -- Running arbitrary python code from UI (must run with --allow-code to enable) +- Running arbitrary python code from UI (must run with `--allow-code` to enable) - Mouseover hints for most UI elements - Possible to change defaults/mix/max/step values for UI elements via text config - Tiling support, a checkbox to create images that can be tiled like textures @@ -131,7 +75,7 @@ Mobile 395px width - also supports weights for prompts: `a cat :1.2 AND a dog AND a penguin :2.2` - No token limit for prompts (original stable diffusion lets you use up to 75 tokens) - DeepDanbooru integration, creates danbooru style tags for anime prompts -- [xformers](https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/Xformers), major speed increase for select cards: (add --xformers to commandline args) +- [xformers](https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/Xformers), major speed increase for select cards: (add `--xformers` to commandline args) - via extension: [History tab](https://github.com/yfszzx/stable-diffusion-webui-images-browser): view, direct and delete images conveniently within the UI - Generate forever option - Training tab @@ -140,39 +84,41 @@ Mobile 395px width - Clip skip - Hypernetworks - Loras (same as Hypernetworks but more pretty) -- A sparate UI where you can choose, with preview, which embeddings, hypernetworks or Loras to add to your prompt. +- A separate UI where you can choose, with preview, which embeddings, hypernetworks or Loras to add to your prompt - Can select to load a different VAE from settings screen - Estimated completion time in progress bar - API -- Support for dedicated [inpainting model](https://github.com/runwayml/stable-diffusion#inpainting-with-stable-diffusion) by RunwayML. +- Support for dedicated [inpainting model](https://github.com/runwayml/stable-diffusion#inpainting-with-stable-diffusion) by RunwayML - via extension: [Aesthetic Gradients](https://github.com/AUTOMATIC1111/stable-diffusion-webui-aesthetic-gradients), a way to generate images with a specific aesthetic by using clip images embeds (implementation of [https://github.com/vicgalle/stable-diffusion-aesthetic-gradients](https://github.com/vicgalle/stable-diffusion-aesthetic-gradients)) - [Stable Diffusion 2.0](https://github.com/Stability-AI/stablediffusion) support - see [wiki](https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/Features#stable-diffusion-20) for instructions - [Alt-Diffusion](https://arxiv.org/abs/2211.06679) support - see [wiki](https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/Features#alt-diffusion) for instructions - Now without any bad letters! - Load checkpoints in safetensors format -- Eased resolution restriction: generated image's domension must be a multiple of 8 rather than 64 +- Eased resolution restriction: generated image's dimension must be a multiple of 8 rather than 64 - Now with a license! - Reorder elements in the UI from settings screen -- ## Installation and Running -Make sure the required [dependencies](https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/Dependencies) are met and follow the instructions available for both [NVidia](https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/Install-and-Run-on-NVidia-GPUs) (recommended) and [AMD](https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/Install-and-Run-on-AMD-GPUs) GPUs. +Make sure the required [dependencies](https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/Dependencies) are met and follow the instructions available for: +- [NVidia](https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/Install-and-Run-on-NVidia-GPUs) (recommended) +- [AMD](https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/Install-and-Run-on-AMD-GPUs) GPUs. +- [Intel CPUs, Intel GPUs (both integrated and discrete)](https://github.com/openvinotoolkit/stable-diffusion-webui/wiki/Installation-on-Intel-Silicon) (external wiki page) Alternatively, use online services (like Google Colab): - [List of Online Services](https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/Online-Services) -### Installation on Windows +### Automatic Installation on Windows 1. Install [Python 3.10.6](https://www.python.org/downloads/release/python-3106/) (Newer version of Python does not support torch), checking "Add Python to PATH". 2. Install [git](https://git-scm.com/download/win). -3. Download the stable-diffusion-webui-ux repository, for example by running `git clone https://github.com/anapnoe/stable-diffusion-webui-ux.git`. +3. Download the stable-diffusion-webui repository, for example by running `git clone https://github.com/anapnoe/stable-diffusion-webui-ux.git`. 4. Run `webui-user.bat` from Windows Explorer as normal, non-administrator, user. -### Installation on Linux +### Automatic Installation on Linux 1. Install the dependencies: ```bash # Debian-based: -sudo apt install wget git python3 python3-venv +sudo apt install wget git python3 python3-venv libgl1 libglib2.0-0 # Red Hat-based: sudo dnf install wget git python3 # Arch-based: @@ -180,17 +126,16 @@ sudo pacman -S wget git python3 ``` 2. Navigate to the directory you would like the webui to be installed and execute the following command: ```bash -bash <(wget -qO- https://raw.githubusercontent.com/anapnoe/stable-diffusion-webui-ux/master/webui.sh) +wget -q https://raw.githubusercontent.com/anapnoe/stable-diffusion-webui-ux/master/webui.sh ``` 3. Run `webui.sh`. 4. Check `webui-user.sh` for options. ### Installation on Apple Silicon Find the instructions [here](https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/Installation-on-Apple-Silicon). -and replace the path in step 3 with `git clone https://github.com/anapnoe/stable-diffusion-webui-ux` ## Contributing -Here's how to add code to the original repo: [Contributing](https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/Contributing) +Here's how to add code to this repo: [Contributing](https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/Contributing) ## Documentation @@ -227,5 +172,6 @@ Licenses for borrowed code can be found in `Settings -> Licenses` screen, and al - UniPC sampler - Wenliang Zhao - https://github.com/wl-zhao/UniPC - TAESD - Ollin Boer Bohan - https://github.com/madebyollin/taesd - LyCORIS - KohakuBlueleaf +- Restart sampling - lambertae - https://github.com/Newbeeer/diffusion_restart_sampling - Initial Gradio script - posted on 4chan by an Anonymous user. Thank you Anonymous user. - (You) diff --git a/extensions-builtin/Lora/extra_networks_lora.py b/extensions-builtin/Lora/extra_networks_lora.py index ba2945c6fe1..005ff32cbe3 100644 --- a/extensions-builtin/Lora/extra_networks_lora.py +++ b/extensions-builtin/Lora/extra_networks_lora.py @@ -6,9 +6,14 @@ class ExtraNetworkLora(extra_networks.ExtraNetwork): def __init__(self): super().__init__('lora') + self.errors = {} + """mapping of network names to the number of errors the network had during operation""" + def activate(self, p, params_list): additional = shared.opts.sd_lora + self.errors.clear() + if additional != "None" and additional in networks.available_networks and not any(x for x in params_list if x.items[0] == additional): p.all_prompts = [x + f"" for x in p.all_prompts] params_list.append(extra_networks.ExtraNetworkParams(items=[additional, shared.opts.extra_networks_default_multiplier])) @@ -56,4 +61,7 @@ def activate(self, p, params_list): p.extra_generation_params["Lora hashes"] = ", ".join(network_hashes) def deactivate(self, p): - pass + if self.errors: + p.comment("Networks with errors: " + ", ".join(f"{k} ({v})" for k, v in self.errors.items())) + + self.errors.clear() diff --git a/extensions-builtin/Lora/lora_patches.py b/extensions-builtin/Lora/lora_patches.py new file mode 100644 index 00000000000..59859e6f94f --- /dev/null +++ b/extensions-builtin/Lora/lora_patches.py @@ -0,0 +1,31 @@ +import torch + +import networks +from modules import patches + + +class LoraPatches: + def __init__(self): + self.Linear_forward = patches.patch(__name__, torch.nn.Linear, 'forward', networks.network_Linear_forward) + self.Linear_load_state_dict = patches.patch(__name__, torch.nn.Linear, '_load_from_state_dict', networks.network_Linear_load_state_dict) + self.Conv2d_forward = patches.patch(__name__, torch.nn.Conv2d, 'forward', networks.network_Conv2d_forward) + self.Conv2d_load_state_dict = patches.patch(__name__, torch.nn.Conv2d, '_load_from_state_dict', networks.network_Conv2d_load_state_dict) + self.GroupNorm_forward = patches.patch(__name__, torch.nn.GroupNorm, 'forward', networks.network_GroupNorm_forward) + self.GroupNorm_load_state_dict = patches.patch(__name__, torch.nn.GroupNorm, '_load_from_state_dict', networks.network_GroupNorm_load_state_dict) + self.LayerNorm_forward = patches.patch(__name__, torch.nn.LayerNorm, 'forward', networks.network_LayerNorm_forward) + self.LayerNorm_load_state_dict = patches.patch(__name__, torch.nn.LayerNorm, '_load_from_state_dict', networks.network_LayerNorm_load_state_dict) + self.MultiheadAttention_forward = patches.patch(__name__, torch.nn.MultiheadAttention, 'forward', networks.network_MultiheadAttention_forward) + self.MultiheadAttention_load_state_dict = patches.patch(__name__, torch.nn.MultiheadAttention, '_load_from_state_dict', networks.network_MultiheadAttention_load_state_dict) + + def undo(self): + self.Linear_forward = patches.undo(__name__, torch.nn.Linear, 'forward') + self.Linear_load_state_dict = patches.undo(__name__, torch.nn.Linear, '_load_from_state_dict') + self.Conv2d_forward = patches.undo(__name__, torch.nn.Conv2d, 'forward') + self.Conv2d_load_state_dict = patches.undo(__name__, torch.nn.Conv2d, '_load_from_state_dict') + self.GroupNorm_forward = patches.undo(__name__, torch.nn.GroupNorm, 'forward') + self.GroupNorm_load_state_dict = patches.undo(__name__, torch.nn.GroupNorm, '_load_from_state_dict') + self.LayerNorm_forward = patches.undo(__name__, torch.nn.LayerNorm, 'forward') + self.LayerNorm_load_state_dict = patches.undo(__name__, torch.nn.LayerNorm, '_load_from_state_dict') + self.MultiheadAttention_forward = patches.undo(__name__, torch.nn.MultiheadAttention, 'forward') + self.MultiheadAttention_load_state_dict = patches.undo(__name__, torch.nn.MultiheadAttention, '_load_from_state_dict') + diff --git a/extensions-builtin/Lora/network.py b/extensions-builtin/Lora/network.py index 8ecfa29a87a..d8e8dfb7ff0 100644 --- a/extensions-builtin/Lora/network.py +++ b/extensions-builtin/Lora/network.py @@ -1,3 +1,4 @@ +from __future__ import annotations import os from collections import namedtuple import enum @@ -132,7 +133,7 @@ def calc_scale(self): return 1.0 - def finalize_updown(self, updown, orig_weight, output_shape): + def finalize_updown(self, updown, orig_weight, output_shape, ex_bias=None): if self.bias is not None: updown = updown.reshape(self.bias.shape) updown += self.bias.to(orig_weight.device, dtype=orig_weight.dtype) @@ -144,7 +145,10 @@ def finalize_updown(self, updown, orig_weight, output_shape): if orig_weight.size().numel() == updown.size().numel(): updown = updown.reshape(orig_weight.shape) - return updown * self.calc_scale() * self.multiplier() + if ex_bias is not None: + ex_bias = ex_bias * self.multiplier() + + return updown * self.calc_scale() * self.multiplier(), ex_bias def calc_updown(self, target): raise NotImplementedError() diff --git a/extensions-builtin/Lora/network_full.py b/extensions-builtin/Lora/network_full.py index 109b4c2c594..bf6930e96c0 100644 --- a/extensions-builtin/Lora/network_full.py +++ b/extensions-builtin/Lora/network_full.py @@ -14,9 +14,14 @@ def __init__(self, net: network.Network, weights: network.NetworkWeights): super().__init__(net, weights) self.weight = weights.w.get("diff") + self.ex_bias = weights.w.get("diff_b") def calc_updown(self, orig_weight): output_shape = self.weight.shape updown = self.weight.to(orig_weight.device, dtype=orig_weight.dtype) + if self.ex_bias is not None: + ex_bias = self.ex_bias.to(orig_weight.device, dtype=orig_weight.dtype) + else: + ex_bias = None - return self.finalize_updown(updown, orig_weight, output_shape) + return self.finalize_updown(updown, orig_weight, output_shape, ex_bias) diff --git a/extensions-builtin/Lora/network_norm.py b/extensions-builtin/Lora/network_norm.py new file mode 100644 index 00000000000..ce450158068 --- /dev/null +++ b/extensions-builtin/Lora/network_norm.py @@ -0,0 +1,28 @@ +import network + + +class ModuleTypeNorm(network.ModuleType): + def create_module(self, net: network.Network, weights: network.NetworkWeights): + if all(x in weights.w for x in ["w_norm", "b_norm"]): + return NetworkModuleNorm(net, weights) + + return None + + +class NetworkModuleNorm(network.NetworkModule): + def __init__(self, net: network.Network, weights: network.NetworkWeights): + super().__init__(net, weights) + + self.w_norm = weights.w.get("w_norm") + self.b_norm = weights.w.get("b_norm") + + def calc_updown(self, orig_weight): + output_shape = self.w_norm.shape + updown = self.w_norm.to(orig_weight.device, dtype=orig_weight.dtype) + + if self.b_norm is not None: + ex_bias = self.b_norm.to(orig_weight.device, dtype=orig_weight.dtype) + else: + ex_bias = None + + return self.finalize_updown(updown, orig_weight, output_shape, ex_bias) diff --git a/extensions-builtin/Lora/networks.py b/extensions-builtin/Lora/networks.py index 17cbe1bb7fe..96f935b236f 100644 --- a/extensions-builtin/Lora/networks.py +++ b/extensions-builtin/Lora/networks.py @@ -1,12 +1,15 @@ +import logging import os import re +import lora_patches import network import network_lora import network_hada import network_ia3 import network_lokr import network_full +import network_norm import torch from typing import Union @@ -19,6 +22,7 @@ network_ia3.ModuleTypeIa3(), network_lokr.ModuleTypeLokr(), network_full.ModuleTypeFull(), + network_norm.ModuleTypeNorm(), ] @@ -31,6 +35,8 @@ "resnets": { "conv1": "in_layers_2", "conv2": "out_layers_3", + "norm1": "in_layers_0", + "norm2": "out_layers_0", "time_emb_proj": "emb_layers_1", "conv_shortcut": "skip_connection", } @@ -190,11 +196,19 @@ def load_network(name, network_on_disk): net.modules[key] = net_module if keys_failed_to_match: - print(f"Failed to match keys when loading network {network_on_disk.filename}: {keys_failed_to_match}") + logging.debug(f"Network {network_on_disk.filename} didn't match keys: {keys_failed_to_match}") return net +def purge_networks_from_memory(): + while len(networks_in_memory) > shared.opts.lora_in_memory_limit and len(networks_in_memory) > 0: + name = next(iter(networks_in_memory)) + networks_in_memory.pop(name, None) + + devices.torch_gc() + + def load_networks(names, te_multipliers=None, unet_multipliers=None, dyn_dims=None): already_loaded = {} @@ -212,15 +226,19 @@ def load_networks(names, te_multipliers=None, unet_multipliers=None, dyn_dims=No failed_to_load_networks = [] - for i, name in enumerate(names): + for i, (network_on_disk, name) in enumerate(zip(networks_on_disk, names)): net = already_loaded.get(name, None) - network_on_disk = networks_on_disk[i] - if network_on_disk is not None: + if net is None: + net = networks_in_memory.get(name) + if net is None or os.path.getmtime(network_on_disk.filename) > net.mtime: try: net = load_network(name, network_on_disk) + + networks_in_memory.pop(name, None) + networks_in_memory[name] = net except Exception as e: errors.display(e, f"loading network {network_on_disk.filename}") continue @@ -231,7 +249,7 @@ def load_networks(names, te_multipliers=None, unet_multipliers=None, dyn_dims=No if net is None: failed_to_load_networks.append(name) - print(f"Couldn't find network with name {name}") + logging.info(f"Couldn't find network with name {name}") continue net.te_multiplier = te_multipliers[i] if te_multipliers else 1.0 @@ -240,23 +258,38 @@ def load_networks(names, te_multipliers=None, unet_multipliers=None, dyn_dims=No loaded_networks.append(net) if failed_to_load_networks: - sd_hijack.model_hijack.comments.append("Failed to find networks: " + ", ".join(failed_to_load_networks)) + sd_hijack.model_hijack.comments.append("Networks not found: " + ", ".join(failed_to_load_networks)) + purge_networks_from_memory() -def network_restore_weights_from_backup(self: Union[torch.nn.Conv2d, torch.nn.Linear, torch.nn.MultiheadAttention]): + +def network_restore_weights_from_backup(self: Union[torch.nn.Conv2d, torch.nn.Linear, torch.nn.GroupNorm, torch.nn.LayerNorm, torch.nn.MultiheadAttention]): weights_backup = getattr(self, "network_weights_backup", None) + bias_backup = getattr(self, "network_bias_backup", None) - if weights_backup is None: + if weights_backup is None and bias_backup is None: return - if isinstance(self, torch.nn.MultiheadAttention): - self.in_proj_weight.copy_(weights_backup[0]) - self.out_proj.weight.copy_(weights_backup[1]) + if weights_backup is not None: + if isinstance(self, torch.nn.MultiheadAttention): + self.in_proj_weight.copy_(weights_backup[0]) + self.out_proj.weight.copy_(weights_backup[1]) + else: + self.weight.copy_(weights_backup) + + if bias_backup is not None: + if isinstance(self, torch.nn.MultiheadAttention): + self.out_proj.bias.copy_(bias_backup) + else: + self.bias.copy_(bias_backup) else: - self.weight.copy_(weights_backup) + if isinstance(self, torch.nn.MultiheadAttention): + self.out_proj.bias = None + else: + self.bias = None -def network_apply_weights(self: Union[torch.nn.Conv2d, torch.nn.Linear, torch.nn.MultiheadAttention]): +def network_apply_weights(self: Union[torch.nn.Conv2d, torch.nn.Linear, torch.nn.GroupNorm, torch.nn.LayerNorm, torch.nn.MultiheadAttention]): """ Applies the currently selected set of networks to the weights of torch layer self. If weights already have this particular set of networks applied, does nothing. @@ -271,7 +304,10 @@ def network_apply_weights(self: Union[torch.nn.Conv2d, torch.nn.Linear, torch.nn wanted_names = tuple((x.name, x.te_multiplier, x.unet_multiplier, x.dyn_dim) for x in loaded_networks) weights_backup = getattr(self, "network_weights_backup", None) - if weights_backup is None: + if weights_backup is None and wanted_names != (): + if current_names != (): + raise RuntimeError("no backup weights found and current weights are not unchanged") + if isinstance(self, torch.nn.MultiheadAttention): weights_backup = (self.in_proj_weight.to(devices.cpu, copy=True), self.out_proj.weight.to(devices.cpu, copy=True)) else: @@ -279,21 +315,41 @@ def network_apply_weights(self: Union[torch.nn.Conv2d, torch.nn.Linear, torch.nn self.network_weights_backup = weights_backup + bias_backup = getattr(self, "network_bias_backup", None) + if bias_backup is None: + if isinstance(self, torch.nn.MultiheadAttention) and self.out_proj.bias is not None: + bias_backup = self.out_proj.bias.to(devices.cpu, copy=True) + elif getattr(self, 'bias', None) is not None: + bias_backup = self.bias.to(devices.cpu, copy=True) + else: + bias_backup = None + self.network_bias_backup = bias_backup + if current_names != wanted_names: network_restore_weights_from_backup(self) for net in loaded_networks: module = net.modules.get(network_layer_name, None) if module is not None and hasattr(self, 'weight'): - with torch.no_grad(): - updown = module.calc_updown(self.weight) - - if len(self.weight.shape) == 4 and self.weight.shape[1] == 9: - # inpainting model. zero pad updown to make channel[1] 4 to 9 - updown = torch.nn.functional.pad(updown, (0, 0, 0, 0, 0, 5)) + try: + with torch.no_grad(): + updown, ex_bias = module.calc_updown(self.weight) + + if len(self.weight.shape) == 4 and self.weight.shape[1] == 9: + # inpainting model. zero pad updown to make channel[1] 4 to 9 + updown = torch.nn.functional.pad(updown, (0, 0, 0, 0, 0, 5)) + + self.weight += updown + if ex_bias is not None and hasattr(self, 'bias'): + if self.bias is None: + self.bias = torch.nn.Parameter(ex_bias) + else: + self.bias += ex_bias + except RuntimeError as e: + logging.debug(f"Network {net.name} layer {network_layer_name}: {e}") + extra_network_lora.errors[net.name] = extra_network_lora.errors.get(net.name, 0) + 1 - self.weight += updown - continue + continue module_q = net.modules.get(network_layer_name + "_q_proj", None) module_k = net.modules.get(network_layer_name + "_k_proj", None) @@ -301,21 +357,33 @@ def network_apply_weights(self: Union[torch.nn.Conv2d, torch.nn.Linear, torch.nn module_out = net.modules.get(network_layer_name + "_out_proj", None) if isinstance(self, torch.nn.MultiheadAttention) and module_q and module_k and module_v and module_out: - with torch.no_grad(): - updown_q = module_q.calc_updown(self.in_proj_weight) - updown_k = module_k.calc_updown(self.in_proj_weight) - updown_v = module_v.calc_updown(self.in_proj_weight) - updown_qkv = torch.vstack([updown_q, updown_k, updown_v]) - updown_out = module_out.calc_updown(self.out_proj.weight) - - self.in_proj_weight += updown_qkv - self.out_proj.weight += updown_out - continue + try: + with torch.no_grad(): + updown_q, _ = module_q.calc_updown(self.in_proj_weight) + updown_k, _ = module_k.calc_updown(self.in_proj_weight) + updown_v, _ = module_v.calc_updown(self.in_proj_weight) + updown_qkv = torch.vstack([updown_q, updown_k, updown_v]) + updown_out, ex_bias = module_out.calc_updown(self.out_proj.weight) + + self.in_proj_weight += updown_qkv + self.out_proj.weight += updown_out + if ex_bias is not None: + if self.out_proj.bias is None: + self.out_proj.bias = torch.nn.Parameter(ex_bias) + else: + self.out_proj.bias += ex_bias + + except RuntimeError as e: + logging.debug(f"Network {net.name} layer {network_layer_name}: {e}") + extra_network_lora.errors[net.name] = extra_network_lora.errors.get(net.name, 0) + 1 + + continue if module is None: continue - print(f'failed to calculate network weights for layer {network_layer_name}') + logging.debug(f"Network {net.name} layer {network_layer_name}: couldn't find supported operation") + extra_network_lora.errors[net.name] = extra_network_lora.errors.get(net.name, 0) + 1 self.network_current_names = wanted_names @@ -342,7 +410,7 @@ def network_forward(module, input, original_forward): if module is None: continue - y = module.forward(y, input) + y = module.forward(input, y) return y @@ -354,44 +422,74 @@ def network_reset_cached_weight(self: Union[torch.nn.Conv2d, torch.nn.Linear]): def network_Linear_forward(self, input): if shared.opts.lora_functional: - return network_forward(self, input, torch.nn.Linear_forward_before_network) + return network_forward(self, input, originals.Linear_forward) network_apply_weights(self) - return torch.nn.Linear_forward_before_network(self, input) + return originals.Linear_forward(self, input) def network_Linear_load_state_dict(self, *args, **kwargs): network_reset_cached_weight(self) - return torch.nn.Linear_load_state_dict_before_network(self, *args, **kwargs) + return originals.Linear_load_state_dict(self, *args, **kwargs) def network_Conv2d_forward(self, input): if shared.opts.lora_functional: - return network_forward(self, input, torch.nn.Conv2d_forward_before_network) + return network_forward(self, input, originals.Conv2d_forward) network_apply_weights(self) - return torch.nn.Conv2d_forward_before_network(self, input) + return originals.Conv2d_forward(self, input) def network_Conv2d_load_state_dict(self, *args, **kwargs): network_reset_cached_weight(self) - return torch.nn.Conv2d_load_state_dict_before_network(self, *args, **kwargs) + return originals.Conv2d_load_state_dict(self, *args, **kwargs) + + +def network_GroupNorm_forward(self, input): + if shared.opts.lora_functional: + return network_forward(self, input, originals.GroupNorm_forward) + + network_apply_weights(self) + + return originals.GroupNorm_forward(self, input) + + +def network_GroupNorm_load_state_dict(self, *args, **kwargs): + network_reset_cached_weight(self) + + return originals.GroupNorm_load_state_dict(self, *args, **kwargs) + + +def network_LayerNorm_forward(self, input): + if shared.opts.lora_functional: + return network_forward(self, input, originals.LayerNorm_forward) + + network_apply_weights(self) + + return originals.LayerNorm_forward(self, input) + + +def network_LayerNorm_load_state_dict(self, *args, **kwargs): + network_reset_cached_weight(self) + + return originals.LayerNorm_load_state_dict(self, *args, **kwargs) def network_MultiheadAttention_forward(self, *args, **kwargs): network_apply_weights(self) - return torch.nn.MultiheadAttention_forward_before_network(self, *args, **kwargs) + return originals.MultiheadAttention_forward(self, *args, **kwargs) def network_MultiheadAttention_load_state_dict(self, *args, **kwargs): network_reset_cached_weight(self) - return torch.nn.MultiheadAttention_load_state_dict_before_network(self, *args, **kwargs) + return originals.MultiheadAttention_load_state_dict(self, *args, **kwargs) def list_available_networks(): @@ -459,9 +557,14 @@ def infotext_pasted(infotext, params): params["Prompt"] += "\n" + "".join(added) +originals: lora_patches.LoraPatches = None + +extra_network_lora = None + available_networks = {} available_network_aliases = {} loaded_networks = [] +networks_in_memory = {} available_network_hash_lookup = {} forbidden_network_aliases = {} diff --git a/extensions-builtin/Lora/scripts/lora_script.py b/extensions-builtin/Lora/scripts/lora_script.py index cd28afc92e7..ef23968c563 100644 --- a/extensions-builtin/Lora/scripts/lora_script.py +++ b/extensions-builtin/Lora/scripts/lora_script.py @@ -1,57 +1,30 @@ import re -import torch import gradio as gr from fastapi import FastAPI import network import networks import lora # noqa:F401 +import lora_patches import extra_networks_lora import ui_extra_networks_lora from modules import script_callbacks, ui_extra_networks, extra_networks, shared + def unload(): - torch.nn.Linear.forward = torch.nn.Linear_forward_before_network - torch.nn.Linear._load_from_state_dict = torch.nn.Linear_load_state_dict_before_network - torch.nn.Conv2d.forward = torch.nn.Conv2d_forward_before_network - torch.nn.Conv2d._load_from_state_dict = torch.nn.Conv2d_load_state_dict_before_network - torch.nn.MultiheadAttention.forward = torch.nn.MultiheadAttention_forward_before_network - torch.nn.MultiheadAttention._load_from_state_dict = torch.nn.MultiheadAttention_load_state_dict_before_network + networks.originals.undo() def before_ui(): ui_extra_networks.register_page(ui_extra_networks_lora.ExtraNetworksPageLora()) - extra_network = extra_networks_lora.ExtraNetworkLora() - extra_networks.register_extra_network(extra_network) - extra_networks.register_extra_network_alias(extra_network, "lyco") - - -if not hasattr(torch.nn, 'Linear_forward_before_network'): - torch.nn.Linear_forward_before_network = torch.nn.Linear.forward - -if not hasattr(torch.nn, 'Linear_load_state_dict_before_network'): - torch.nn.Linear_load_state_dict_before_network = torch.nn.Linear._load_from_state_dict + networks.extra_network_lora = extra_networks_lora.ExtraNetworkLora() + extra_networks.register_extra_network(networks.extra_network_lora) + extra_networks.register_extra_network_alias(networks.extra_network_lora, "lyco") -if not hasattr(torch.nn, 'Conv2d_forward_before_network'): - torch.nn.Conv2d_forward_before_network = torch.nn.Conv2d.forward -if not hasattr(torch.nn, 'Conv2d_load_state_dict_before_network'): - torch.nn.Conv2d_load_state_dict_before_network = torch.nn.Conv2d._load_from_state_dict - -if not hasattr(torch.nn, 'MultiheadAttention_forward_before_network'): - torch.nn.MultiheadAttention_forward_before_network = torch.nn.MultiheadAttention.forward - -if not hasattr(torch.nn, 'MultiheadAttention_load_state_dict_before_network'): - torch.nn.MultiheadAttention_load_state_dict_before_network = torch.nn.MultiheadAttention._load_from_state_dict - -torch.nn.Linear.forward = networks.network_Linear_forward -torch.nn.Linear._load_from_state_dict = networks.network_Linear_load_state_dict -torch.nn.Conv2d.forward = networks.network_Conv2d_forward -torch.nn.Conv2d._load_from_state_dict = networks.network_Conv2d_load_state_dict -torch.nn.MultiheadAttention.forward = networks.network_MultiheadAttention_forward -torch.nn.MultiheadAttention._load_from_state_dict = networks.network_MultiheadAttention_load_state_dict +networks.originals = lora_patches.LoraPatches() script_callbacks.on_model_loaded(networks.assign_network_names_to_compvis_modules) script_callbacks.on_script_unloaded(unload) @@ -65,6 +38,7 @@ def before_ui(): "lora_add_hashes_to_infotext": shared.OptionInfo(True, "Add Lora hashes to infotext"), "lora_show_all": shared.OptionInfo(False, "Always show all networks on the Lora page").info("otherwise, those detected as for incompatible version of Stable Diffusion will be hidden"), "lora_hide_unknown_for_versions": shared.OptionInfo([], "Hide networks of unknown versions for model versions", gr.CheckboxGroup, {"choices": ["SD1", "SD2", "SDXL"]}), + "lora_in_memory_limit": shared.OptionInfo(0, "Number of Lora networks to keep cached in memory", gr.Number, {"precision": 0}), })) @@ -121,3 +95,5 @@ def network_replacement(m): script_callbacks.on_infotext_pasted(infotext_pasted) + +shared.opts.onchange("lora_in_memory_limit", networks.purge_networks_from_memory) diff --git a/extensions-builtin/Lora/ui_edit_user_metadata.py b/extensions-builtin/Lora/ui_edit_user_metadata.py index 2ca997f7ce9..c7011909055 100644 --- a/extensions-builtin/Lora/ui_edit_user_metadata.py +++ b/extensions-builtin/Lora/ui_edit_user_metadata.py @@ -70,6 +70,7 @@ def get_metadata_table(self, name): metadata = item.get("metadata") or {} keys = { + 'ss_output_name': "Output name:", 'ss_sd_model_name': "Model:", 'ss_clip_skip': "Clip skip:", 'ss_network_module': "Kohya module:", @@ -167,7 +168,7 @@ def create_editor(self): random_prompt = gr.Textbox(label='Random prompt', lines=4, max_lines=4, interactive=False) with gr.Column(scale=1, min_width=120): - generate_random_prompt = gr.Button('Generate').style(full_width=True, size="lg") + generate_random_prompt = gr.Button('Generate', size="lg", scale=1) self.edit_notes = gr.TextArea(label='Notes', lines=4) diff --git a/extensions-builtin/Lora/ui_extra_networks_lora.py b/extensions-builtin/Lora/ui_extra_networks_lora.py index 1311b2f41a0..55409a7829d 100644 --- a/extensions-builtin/Lora/ui_extra_networks_lora.py +++ b/extensions-builtin/Lora/ui_extra_networks_lora.py @@ -25,9 +25,10 @@ def create_item(self, name, index=None, enable_filter=True): item = { "name": name, "filename": lora_on_disk.filename, - "preview": self.find_preview(path) if self.find_preview(path) else './file=html/card-no-preview.png', + "shorthash": lora_on_disk.shorthash, + "preview": self.find_preview(path), "description": self.find_description(path), - "search_term": self.search_terms_from_path(lora_on_disk.filename), + "search_term": self.search_terms_from_path(lora_on_disk.filename) + " " + (lora_on_disk.hash or ""), "local_preview": f"{path}.{shared.opts.samples_format}", "metadata": lora_on_disk.metadata, "sort_keys": {'default': index, **self.get_sort_keys(lora_on_disk.filename)}, @@ -67,7 +68,7 @@ def create_item(self, name, index=None, enable_filter=True): def list_items(self): for index, name in enumerate(networks.available_networks): item = self.create_item(name, index) - + if item is not None: yield item diff --git a/extensions-builtin/anapnoe-sd-theme-editor/javascript/ui_theme.js b/extensions-builtin/anapnoe-sd-theme-editor/javascript/ui_theme.js new file mode 100644 index 00000000000..eebc2d193a8 --- /dev/null +++ b/extensions-builtin/anapnoe-sd-theme-editor/javascript/ui_theme.js @@ -0,0 +1,419 @@ +function hexToRgb(color) { + var hex = color[0] === "#" ? color.slice(1) : color; + var c; // expand the short hex by doubling each character, fc0 -> ffcc00 + + if (hex.length !== 6) { + hex = (function() { + var result = []; + + for ( + var _i = 0, _Array$from = Array.from(hex); + _i < _Array$from.length; + _i++ + ) { + c = _Array$from[_i]; + result.push("".concat(c).concat(c)); + } + + return result; + })().join(""); + } + + var colorStr = hex.match(/#?(.{2})(.{2})(.{2})/).slice(1); + var rgb = colorStr.map(function(col) { + return parseInt(col, 16); + }); + rgb.push(1); + return rgb; +} + +function rgbToHsl(rgb) { + var r = rgb[0] / 255; + var g = rgb[1] / 255; + var b = rgb[2] / 255; + var max = Math.max(r, g, b); + var min = Math.min(r, g, b); + var diff = max - min; + var add = max + min; + var hue = + min === max + ? 0 + : r === max + ? (60 * (g - b) / diff + 360) % 360 + : g === max ? 60 * (b - r) / diff + 120 : 60 * (r - g) / diff + 240; + var lum = 0.5 * add; + var sat = + lum === 0 ? 0 : lum === 1 ? 1 : lum <= 0.5 ? diff / add : diff / (2 - add); + var h = Math.round(hue); + var s = Math.round(sat * 100); + var l = Math.round(lum * 100); + var a = rgb[3] || 1; + return [h, s, l, a]; +} + +function hexToHsl(color) { + var rgb = hexToRgb(color); + var hsl = rgbToHsl(rgb); + return "hsl(" + hsl[0] + "deg " + hsl[1] + "% " + hsl[2] + "%)"; +} + +function hslToHex(h, s, l) { + l /= 100; + var a = s * Math.min(l, 1 - l) / 100; + + var f = function f(n) { + var k = (n + h / 30) % 12; + var color = l - a * Math.max(Math.min(k - 3, 9 - k, 1), -1); + return Math.round(255 * Math.max(0, Math.min(color, 1))) + .toString(16) + .padStart(2, "0"); // convert to Hex and prefix "0" if needed + }; + + return "#".concat(f(0)).concat(f(8)).concat(f(4)); +} + +function hsl2rgb(h, s, l) { + var a = s * Math.min(l, 1 - l); + + var f = function f(n) { + var k = + arguments.length > 1 && arguments[1] !== undefined + ? arguments[1] + : (n + h / 30) % 12; + return l - a * Math.max(Math.min(k - 3, 9 - k, 1), -1); + }; + + return [f(0), f(8), f(4)]; +} + +function invertColor(hex) { + if (hex.indexOf("#") === 0) { + hex = hex.slice(1); + } // convert 3-digit hex to 6-digits. + + if (hex.length === 3) { + hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2]; + } + + if (hex.length !== 6) { + throw new Error("Invalid HEX color."); + } // invert color components + + var r = (255 - parseInt(hex.slice(0, 2), 16)).toString(16), + g = (255 - parseInt(hex.slice(2, 4), 16)).toString(16), + b = (255 - parseInt(hex.slice(4, 6), 16)).toString(16); // pad each with zeros and return + + return "#" + padZero(r) + padZero(g) + padZero(b); +} + +function padZero(str, len) { + len = len || 2; + var zeros = new Array(len).join("0"); + return (zeros + str).slice(-len); +} + +function getValsWrappedIn(str, c1, c2) { + var rg = new RegExp("(?<=\\" + c1 + ")(.*?)(?=\\" + c2 + ")", "g"); + return str.match(rg); +} + +var styleobj = {}; +var hslobj = {}; +var isColorsInv; + +var toHSLArray = function toHSLArray(hslStr) { + return hslStr.match(/\d+/g).map(Number); +}; + +function offsetColorsHSV(ohsl) { + var inner_styles = ""; + + for (var key in styleobj) { + var keyVal = styleobj[key]; + + if (keyVal.indexOf("#") != -1 || keyVal.indexOf("hsl") != -1) { + var colcomp = document.body.querySelector("#" + key + " input"); + + if (colcomp) { + var hsl = void 0; + + if (keyVal.indexOf("#") != -1) { + keyVal = keyVal.replace(/\s+/g, ""); //inv ? keyVal = invertColor(keyVal) : 0; + + if (isColorsInv) { + keyVal = invertColor(keyVal); + styleobj[key] = keyVal; + } + + hsl = rgbToHsl(hexToRgb(keyVal)); + } else { + if (isColorsInv) { + var c = toHSLArray(keyVal); + + var _hex = hslToHex(c[0], c[1], c[2]); + + keyVal = invertColor(_hex); + styleobj[key] = keyVal; + hsl = rgbToHsl(hexToRgb(keyVal)); + } else { + hsl = toHSLArray(keyVal); + } + } + + var h = (parseInt(hsl[0]) + parseInt(ohsl[0])) % 360; + var s = parseInt(hsl[1]) + parseInt(ohsl[1]); + var l = parseInt(hsl[2]) + parseInt(ohsl[2]); + var hex = hslToHex( + h, + Math.min(Math.max(s, 0), 100), + Math.min(Math.max(l, 0), 100) + ); + colcomp.value = hex; + hslobj[key] = "hsl(" + h + "deg " + s + "% " + l + "%)"; + inner_styles += key + ":" + hslobj[key] + ";"; + } + } else { + inner_styles += key + ":" + styleobj[key] + ";"; + } + } + + isColorsInv = false; + var preview_styles = document.body.querySelector("#preview-styles"); + preview_styles.innerHTML = ":root {" + inner_styles + "}"; + preview_styles.innerHTML += + "@media only screen and (max-width: 860px) {:root{--ae-outside-gap-size: var(--ae-mobile-outside-gap-size);--ae-inside-padding-size: var(--ae-mobile-inside-padding-size);}}"; + var vars_textarea = document.body.querySelector("#theme_vars textarea"); + vars_textarea.value = inner_styles; + window.updateInput(vars_textarea); +} + +function updateTheme(vars) { + var inner_styles = ""; + + var _loop = function _loop(i) { + var key = vars[i].split(":"); + var id = key[0].replace(/\s+/g, ""); + var val = key[1].trim(); + styleobj[id] = val; + inner_styles += id + ":" + val + ";"; + document.body.querySelectorAll("#" + id + " input").forEach(function(elem) { + if (val.indexOf("hsl") != -1) { + var hsl = toHSLArray(val); + var hex = hslToHex(hsl[0], hsl[1], hsl[2]); + elem.value = hex; + } else { + elem.value = val.split("px")[0]; + } + }); + }; + + for (var i = 0; i < vars.length - 1; i++) { + _loop(i); + } + + var preview_styles = document.body.querySelector("#preview-styles"); + + if (preview_styles) { + preview_styles.innerHTML = ":root {" + inner_styles + "}"; + preview_styles.innerHTML += + "@media only screen and (max-width: 860px) {:root{--ae-outside-gap-size: var(--ae-mobile-outside-gap-size);--ae-inside-padding-size: var(--ae-mobile-inside-padding-size);}}"; + } else { + var r = document.body; + var style = document.createElement("style"); + style.id = "preview-styles"; + style.innerHTML = ":root {" + inner_styles + "}"; + style.innerHTML += + "@media only screen and (max-width: 860px) {:root{--ae-outside-gap-size: var(--ae-mobile-outside-gap-size);--ae-inside-padding-size: var(--ae-mobile-inside-padding-size);}}"; + r.appendChild(style); + } + + var vars_textarea = document.body.querySelector("#theme_vars textarea"); + var css_textarea = document.body.querySelector("#theme_css textarea"); + vars_textarea.value = inner_styles; + css_textarea.value = css_textarea.value; //console.log(Object); + + window.updateInput(vars_textarea); + window.updateInput(css_textarea); +} + +function applyTheme() { + console.log("apply"); +} + +function initTheme(styles) { + var css_styles = styles.split("/*BREAKPOINT_CSS_CONTENT*/"); + var init_css_vars = css_styles[0].split("}")[0].split("{")[1]; + init_css_vars = init_css_vars.replace(/\n|\r/g, ""); + var init_vars = init_css_vars.split(";"); + var vars = init_vars; //console.log(vars); + + var vars_textarea = document.body.querySelector("#theme_vars textarea"); + var css_textarea = document.body.querySelector("#theme_css textarea"); + vars_textarea.value = init_css_vars; + var additional_styles = css_styles[1] !== undefined ? css_styles[1] : ""; + css_textarea.value = + "/*BREAKPOINT_CSS_CONTENT*/" + + additional_styles + + "/*BREAKPOINT_CSS_CONTENT*/"; + updateTheme(vars); + var preview_styles = document.body.querySelector("#preview-styles"); + + if (!preview_styles) { + var style = document.createElement("style"); + style.id = "preview-styles"; + style.innerHTML = styles; + document.body.appendChild(style); + } + + var intervalChange; + document.body + .querySelectorAll("#ui_theme_settings input") + .forEach(function(elem) { + elem.addEventListener("input", function(e) { + var celem = e.currentTarget; + var val = e.currentTarget.value; + var curr_val; + + switch (e.currentTarget.type) { + case "range": + celem = celem.parentElement; + val = e.currentTarget.value + "px"; + break; + + case "color": + celem = celem.parentElement.parentElement; + val = e.currentTarget.value; + break; + + case "number": + celem = celem.parentElement.parentElement.parentElement; + val = e.currentTarget.value + "px"; + break; + } + + if (celem.id === "--ae-input-slider-height") { + val = e.currentTarget.value; + } + + styleobj[celem.id] = val; //console.log(styleobj); + + if (intervalChange != null) clearInterval(intervalChange); + intervalChange = setTimeout(function() { + var inner_styles = ""; + + for (var key in styleobj) { + inner_styles += key + ":" + styleobj[key] + ";"; + } + + vars = inner_styles.split(";"); + preview_styles.innerHTML = ":root {" + inner_styles + "}"; + preview_styles.innerHTML += + "@media only screen and (max-width: 860px) {:root{--ae-outside-gap-size: var(--ae-mobile-outside-gap-size);--ae-inside-padding-size: var(--ae-mobile-inside-padding-size);}}"; + vars_textarea.value = inner_styles; + window.updateInput(vars_textarea); + + offsetColorsHSV(hsloffset); + }, 1000); + }); + }); + var reset_btn = document.getElementById("theme_reset_btn"); + reset_btn.addEventListener("click", function(e) { + e.preventDefault(); + e.stopPropagation(); + document.body + .querySelectorAll("#ui_theme_hsv input") + .forEach(function(elem) { + elem.value = 0; + }); + hsloffset = [0, 0, 0]; + updateTheme(init_vars); + }); + var intervalCheck; + + function dropDownOnChange() { + if (init_css_vars !== vars_textarea.value) { + clearInterval(intervalCheck); + init_css_vars = vars_textarea.value.replace(/\n|\r/g, ""); + vars_textarea.value = init_css_vars; + init_vars = init_css_vars.split(";"); + vars = init_vars; + updateTheme(vars); + } + } + + var drop_down = document.body.querySelector("#themes_drop_down input"); + drop_down.addEventListener("click", function(e) { + if (intervalCheck !== null) clearInterval(intervalCheck); + vars_textarea.value = init_css_vars; + intervalCheck = setInterval(dropDownOnChange, 500); + }); + var hsloffset = [0, 0, 0]; + var hue = document.body + .querySelectorAll("#theme_hue input") + .forEach(function(elem) { + elem.addEventListener("change", function(e) { + e.preventDefault(); + e.stopPropagation(); + hsloffset[0] = e.currentTarget.value; + offsetColorsHSV(hsloffset); + }); + }); + var sat = document.body + .querySelectorAll("#theme_sat input") + .forEach(function(elem) { + elem.addEventListener("change", function(e) { + e.preventDefault(); + e.stopPropagation(); + hsloffset[1] = e.currentTarget.value; + offsetColorsHSV(hsloffset); + }); + }); + var brt = document.body + .querySelectorAll("#theme_brt input") + .forEach(function(elem) { + elem.addEventListener("change", function(e) { + e.preventDefault(); + e.stopPropagation(); + hsloffset[2] = e.currentTarget.value; + offsetColorsHSV(hsloffset); + }); + }); + var inv_btn = document.getElementById("theme_invert_btn"); + inv_btn.addEventListener("click", function(e) { + e.preventDefault(); + e.stopPropagation(); + isColorsInv = !isColorsInv; + offsetColorsHSV(hsloffset); + }); +} + +function observeGradioApp() { + var observer = new MutationObserver(function() { + var css = document.querySelector('[rel="stylesheet"][href*="user"]'); + var block = gradioApp().getElementById("tab_ui_theme"); + + if (css && block) { + observer.disconnect(); + setTimeout(function() { + var rootRules = Array.from(css.sheet.cssRules).filter(function( + cssRule + ) { + return ( + cssRule instanceof CSSStyleRule && cssRule.selectorText === ":root" + ); + }); + var rootCssText = rootRules[0].cssText; //console.log("Loading theme vars", rootCssText); + + initTheme(rootCssText); + }, "500"); + } + }); + observer.observe(gradioApp(), { + childList: true, + subtree: true + }); +} + +document.addEventListener("DOMContentLoaded", function() { + observeGradioApp(); +}); diff --git a/extensions-builtin/anapnoe-sd-theme-editor/scripts/ui_theme.py b/extensions-builtin/anapnoe-sd-theme-editor/scripts/ui_theme.py new file mode 100644 index 00000000000..399798e1c83 --- /dev/null +++ b/extensions-builtin/anapnoe-sd-theme-editor/scripts/ui_theme.py @@ -0,0 +1,163 @@ +import os +import shutil +from pathlib import Path +import gradio as gr +import modules.scripts as scripts +from modules import script_callbacks, shared + +basedir = scripts.basedir() +webui_dir = Path(basedir).parents[1] + +themes_folder = os.path.join(basedir, "themes") +javascript_folder = os.path.join(basedir, "javascript") +webui_style_path = os.path.join(webui_dir, "user.css") + +def get_files(folder, file_filter=[], file_list=[], split=False): + file_list = [file_name if not split else os.path.splitext(file_name)[0] for file_name in os.listdir(folder) if os.path.isfile(os.path.join(folder, file_name)) and file_name not in file_filter] + return file_list + + +def on_ui_tabs(): + + with gr.Blocks(analytics_enabled=False) as ui_theme: + with gr.Row(): + with gr.Column(): + with gr.Row(): + themes_dropdown = gr.Dropdown(label="Themes", elem_id="themes_drop_down", interactive=True, choices=get_files(themes_folder,[".css, .txt"]), type="value") + save_as_filename = gr.Text(label="Save / Save as") + with gr.Row(): + reset_button = gr.Button(elem_id="theme_reset_btn", value="Reset", variant="primary") + #apply_button = gr.Button(elem_id="theme_apply_btn", value="Apply", variant="primary") + save_button = gr.Button(value="Save", variant="primary") + #delete_button = gr.Button(value="Delete", variant="primary") + + #with gr.Accordion(label="Debug View", open=True): + with gr.Row(elem_id="theme_hidden"): + vars_text = gr.Textbox(label="Vars", elem_id="theme_vars", show_label=True, lines=7, interactive=False, visible=True) + css_text = gr.Textbox(label="Css", elem_id="theme_css", show_label=True, lines=7, interactive=False, visible=True) + #result_text = gr.Text(elem_id="theme_result", interactive=False, visible=False) + + with gr.Accordion(label="Theme Color adjustments", open=True): + with gr.Row(): + with gr.Column(elem_id="ui_theme_hsv"): + gr.Slider(elem_id="theme_hue", label='Hue', minimum=0, maximum=360, step=1) + gr.Slider(elem_id="theme_sat", label='Saturation', minimum=-100, maximum=100, step=1, value=0, interactive=True) + gr.Slider(elem_id="theme_brt", label='Lightness', minimum=-50, maximum=50, step=1, value=0, interactive=True) + + gr.Button(elem_id="theme_invert_btn", value="Invert", variant="primary") + + with gr.Column(elem_id="ui_theme_settings"): + with gr.Accordion(label="Main", open=False): + gr.ColorPicker(elem_id="--ae-main-bg-color", interactive=True, label="Background color") + gr.ColorPicker(elem_id="--ae-primary-color", label="Primary color") + gr.ColorPicker(elem_id="--ae-secondary-color", label="Secondary color") + + with gr.Accordion(label="Spacing", open=False): + gr.Slider(elem_id="--ae-gap-size-val", label='Gap size', minimum=0, maximum=8, step=1) + + """ with gr.Accordion(elem_classes="hidden", label="Spacing (Mobile)", open=False): + gr.Slider(elem_id="--ae-mobile-gap-size-val", label='Gap size', minimum=0, maximum=8, step=1) """ + + with gr.Accordion(label="Panel", open=False): + gr.ColorPicker(elem_id="--ae-panel-bg-color", label="Panel background color") + gr.ColorPicker(elem_id="--ae-panel-border-color", label="Panel border color") + gr.Slider(elem_id="--ae-panel-padding", label='Panel padding', minimum=0, maximum=10, step=1) + gr.Slider(elem_id="--ae-border-radius", label='Panel border radius', minimum=0, maximum=8, step=1) + gr.Slider(elem_id="--ae-border-size", label='Panel border size', minimum=0, maximum=4, step=1) + + with gr.Accordion(label="Component", open=False): + + gr.Slider(elem_id="--ae-input-height", label='Component size', minimum=28, maximum=45, step=1) + gr.Slider(elem_id="--ae-input-slider-height", label='Slider height', minimum=0.1, maximum=1, step=0.1) + gr.Slider(elem_id="--ae-input-padding", label='Padding', minimum=0, maximum=10, step=1) + gr.Slider(elem_id="--ae-input-font-size", label='Font size', minimum=10, maximum=16, step=1) + gr.Slider(elem_id="--ae-input-line-height", label='Line height', minimum=10, maximum=40, step=1) + gr.Slider(elem_id="--ae-input-border-size", label='Border size', minimum=0, maximum=4, step=1) + gr.Slider(elem_id="--ae-input-border-radius", label='Border radius', minimum=0, maximum=8, step=1) + + gr.ColorPicker(elem_id="--ae-input-bg-color", label="Input background color") + gr.ColorPicker(elem_id="--ae-input-border-color", label="Input border color") + gr.ColorPicker(elem_id="--ae-input-text-color", label="Input text color") + gr.ColorPicker(elem_id="--ae-input-placeholder-color", label="Input placeholder color") + + gr.ColorPicker(elem_id="--ae-label-color", label="Label color") + gr.ColorPicker(elem_id="--ae-secondary-label-color", label="Secondary label color") + + gr.ColorPicker(elem_id="--ae-input-hover-text-color", label="Input hover text color") + + + + with gr.Accordion(label="Group", open=False): + gr.ColorPicker(elem_id="--ae-group-bg-color", label="Group background color") + gr.ColorPicker(elem_id="--ae-group-border-color", label="Group border color") + gr.Slider(elem_id="--ae-group-padding", label='Group padding', minimum=0, maximum=10, step=1) + gr.Slider(elem_id="--ae-group-radius", label='Group border radius', minimum=0, maximum=8, step=1) + gr.Slider(elem_id="--ae-group-border-size", label='Group border size', minimum=0, maximum=4, step=1) + gr.Slider(elem_id="--ae-group-gap", label='Group gap size', minimum=0, maximum=8, step=1) + + + + + def save_theme( vars_text, css_text, filename): + style_data= ":root{" + vars_text + "}" + css_text + with open(os.path.join(themes_folder, f"{filename}.css"), 'w', encoding="utf-8") as file: + file.write(vars_text) + file.close() + with open(webui_style_path, 'w', encoding="utf-8") as file: + file.write(style_data) + file.close() + themes_dropdown.choices=get_files(themes_folder,[".css, .txt"]) + return gr.update(choices=themes_dropdown.choices, value=f"{filename}.css") + + def open_theme(filename, css_text): + with open(os.path.join(themes_folder, f"{filename}"), 'r') as file: + vars_text=file.read() + no_ext=filename.rsplit('.', 1)[0] + #save_theme( vars_text, css_text, no_ext) + # shared.state.interrupt() + # shared.state.need_restart = True + return [vars_text, no_ext] + + # def delete_theme(filename): + # try: + # os.remove(os.path.join(themes_folder, filename)) + # except FileNotFoundError: + # pass + + # delete_button.click( + # fn = lambda: delete_theme() + # ) + + save_button.click( + fn=save_theme, + inputs=[vars_text, css_text, save_as_filename], + outputs=themes_dropdown + ) + + themes_dropdown.change( + fn=open_theme, + #_js = "applyTheme", + inputs=[themes_dropdown, css_text], + outputs=[vars_text, save_as_filename] + ) + + # apply_button.click( + # fn=None, + # _js = "applyTheme" + # ) + + # vars_text.change( + # fn=None, + # _js = "applyTheme", + # inputs=[], + # outputs=[vars_text, css_text] + # ) + + + + + return (ui_theme, 'Theme', 'ui_theme'), + + + +script_callbacks.on_ui_tabs(on_ui_tabs) \ No newline at end of file diff --git a/extensions-builtin/anapnoe-sd-theme-editor/style.css b/extensions-builtin/anapnoe-sd-theme-editor/style.css new file mode 100644 index 00000000000..3e19ab0d5d9 --- /dev/null +++ b/extensions-builtin/anapnoe-sd-theme-editor/style.css @@ -0,0 +1,36 @@ +#theme_hidden, +#setting_ui_header_tabs .theme, +#setting_ui_hidden_tabs .theme { + display: none !important; +} + +#tab_ui_theme [id*="color"] label { + display: flex; + align-items: center; + pointer-events: none; +} +#tab_ui_theme [id*="color"] label span { + min-width: 50% !important; +} +#tab_ui_theme [id*="color"] label input { + flex-grow: 1; + pointer-events: all; + cursor: pointer; +} + +#settings_ui_theme > div > div { + flex-direction: row; + flex-wrap: wrap; +} +#settings_ui_theme > div > div > div { + max-width: 30%; +} + +#tab_ui_theme > div { + padding: 16px !important; + padding-top: 0 !important; +} + +#ui_theme_hsv + button { + min-width: unset; +} diff --git a/extensions-builtin/anapnoe-sd-theme-editor/themes/sdxl_alpha.css b/extensions-builtin/anapnoe-sd-theme-editor/themes/sdxl_alpha.css new file mode 100644 index 00000000000..ebaf8380019 --- /dev/null +++ b/extensions-builtin/anapnoe-sd-theme-editor/themes/sdxl_alpha.css @@ -0,0 +1 @@ +--ae-primary-color:hsl(205deg 83% 46%);--ae-secondary-color:hsl(325deg 83% 46%);--ae-main-bg-color:rgb(32 32 32);--ae-input-height:35px;--ae-input-slider-height:0.6;--ae-input-icon-height:calc(var(--ae-input-height) - var(--ae-input-border-size) * 2);--ae-input-padding:5px;--ae-input-font-size:14px;--ae-input-line-height:23px;--ae-label-color:rgba(255, 255, 255, 0.75);--ae-secondary-label-color:rgba(255, 255, 255, 0.5);--ae-input-border-size:2px;--ae-input-border-radius:0px;--ae-input-text-color:rgba(255, 255, 255, 0.75);--ae-input-placeholder-color:rgba(255, 255, 255, 0.35);--ae-input-bg-color:rgba(0, 0, 0, 0.25);--ae-input-border-color:rgba(0, 0, 0, 0.1);--ae-input-hover-text-color:rgba(255, 255, 255, 0.75);--ae-panel-bg-color:rgba(64, 64, 64, 0.5);--ae-panel-border-color:rgba(64, 64, 64, 0.75);--ae-panel-padding:5px;--ae-border-radius:5px;--ae-border-size:2px;--ae-gap-size-val:5px;--ae-gap-size:max(var(--ae-gap-size-val), var(--ae-border-size));--ae-border-size-neg:calc(var(--ae-border-size) * -1);--ae-border-size-x2:calc((var(--ae-border-size) * 2) + 0px);--ae-group-bg-color:hsl(0deg 0% 16%);--ae-group-padding:2px;--ae-group-radius:7px;--ae-group-border-size:2px;--ae-group-border-color:hsl(0deg 0% 16%);--ae-group-gap:6px;--ae-panel-border-radius:0px;--ae-subpanel-border-radius:8px;--ae-outside-gap-size:8px;--ae-inside-padding-size:8px;--ae-tool-button-size:34px;--ae-tool-button-radius:16px;--ae-generate-button-height:70px;--ae-max-padding:max( var(--ae-outside-gap-size), var(--ae-inside-padding-size) );--ae-icon-size:22px;--ae-mobile-outside-gap-size:2px;--ae-mobile-inside-padding-size:2px;--panel-border-radius:4px;--subpanel-border-radius:8px;--outside-gap-size:8px;--inside-padding-size:8px;--tool-button-size:34px;--tool-button-radius:16px;--generate-button-height:70px;--max-padding:max(var(--outside-gap-size),var(--inside-padding-size));--icon-size:22px;--mobile-outside-gap-size:3px;--mobile-inside-padding-size:3px; \ No newline at end of file diff --git a/extensions-builtin/anapnoe-sd-theme-editor/themes/sdxl_default.css b/extensions-builtin/anapnoe-sd-theme-editor/themes/sdxl_default.css new file mode 100644 index 00000000000..5ad1606b458 --- /dev/null +++ b/extensions-builtin/anapnoe-sd-theme-editor/themes/sdxl_default.css @@ -0,0 +1 @@ +--ae-primary-color:hsl(168deg 97% 41%);--ae-secondary-color:hsl(225deg 6% 13%);--ae-main-bg-color:hsl(0deg 0% 10%);--ae-input-height:35px;--ae-input-slider-height:0.5;--ae-input-icon-height:calc(var(--ae-input-height) - var(--ae-input-border-size) * 2);--ae-input-padding:5px;--ae-input-font-size:12px;--ae-input-line-height:24px;--ae-label-color:hsl(216deg 5% 60%);--ae-secondary-label-color:hsl(216deg 5% 60%);--ae-input-border-size:0px;--ae-input-border-radius:0px;--ae-input-text-color:hsl(216deg 5% 60%);--ae-input-placeholder-color:hsl(168deg 97% 41%);--ae-input-bg-color:hsl(225deg 6% 13%);--ae-input-border-color:hsl(228deg 6% 17%);--ae-input-hover-text-color:hsl(225deg 6% 13%);--ae-panel-bg-color:hsl(225deg 5% 17%);--ae-panel-border-color:hsl(214deg 5% 30%);--ae-panel-padding:5px;--ae-border-radius:0px;--ae-border-size:1px;--ae-gap-size-val:5px;--ae-gap-size:max(var(--ae-gap-size-val), var(--ae-border-size));--ae-border-size-neg:calc(var(--ae-border-size) * -1);--ae-border-size-x2:calc((var(--ae-border-size) * 2) + 0px);--ae-group-bg-color:hsl(225deg 6% 13%);--ae-group-padding:2px;--ae-group-radius:0px;--ae-group-border-size:1px;--ae-group-border-color:hsl(225deg 6% 13%);--ae-group-gap:5px;--ae-panel-border-radius:0px;--ae-subpanel-border-radius:8px;--ae-outside-gap-size:8px;--ae-inside-padding-size:8px;--ae-tool-button-size:34px;--ae-tool-button-radius:16px;--ae-generate-button-height:70px;--ae-max-padding:max( var(--ae-outside-gap-size), var(--ae-inside-padding-size) );--ae-icon-size:22px;--ae-mobile-outside-gap-size:2px;--ae-mobile-inside-padding-size:2px;--panel-border-radius:4px;--subpanel-border-radius:8px;--outside-gap-size:8px;--inside-padding-size:8px;--tool-button-size:34px;--tool-button-radius:16px;--generate-button-height:70px;--max-padding:max(var(--outside-gap-size),var(--inside-padding-size));--icon-size:22px;--mobile-outside-gap-size:3px;--mobile-inside-padding-size:3px; \ No newline at end of file diff --git a/extensions-builtin/anapnoe-sd-theme-editor/themes/sdxl_light.css b/extensions-builtin/anapnoe-sd-theme-editor/themes/sdxl_light.css new file mode 100644 index 00000000000..d046467b812 --- /dev/null +++ b/extensions-builtin/anapnoe-sd-theme-editor/themes/sdxl_light.css @@ -0,0 +1 @@ +--ae-primary-color:hsl(0deg 0% 0%);--ae-secondary-color:hsl(225deg 6% 13%);--ae-main-bg-color:hsl(0deg 0% 95%);--ae-input-height:28px;--ae-input-slider-height:0.5;--ae-input-icon-height:calc(var(--ae-input-height) - var(--ae-input-border-size) * 2);--ae-input-padding:5px;--ae-input-font-size:12px;--ae-input-line-height:16px;--ae-label-color:hsl(0deg 0% 15%);--ae-secondary-label-color:hsl(0deg 100% 50%);--ae-input-border-size:1px;--ae-input-border-radius:0px;--ae-input-text-color:hsl(0deg 0% 0%);--ae-input-placeholder-color:hsl(0deg 0% 89%);--ae-input-bg-color:hsl(0deg 100% 100%);--ae-input-border-color:hsl(0deg 0% 95%);--ae-input-hover-text-color:hsl(0deg 100% 100%);--ae-panel-bg-color:hsl(0deg 0% 98%);--ae-panel-border-color:hsl(0deg 0% 87%);--ae-panel-padding:5px;--ae-border-radius:5px;--ae-border-size:0px;--ae-gap-size-val:3px;--ae-gap-size:max(var(--ae-gap-size-val), var(--ae-border-size));--ae-border-size-neg:calc(var(--ae-border-size) * -1);--ae-border-size-x2:calc((var(--ae-border-size) * 2) + 0px);--ae-group-bg-color:hsl(0deg 0% 94%);--ae-group-padding:2px;--ae-group-radius:6px;--ae-group-border-size:0px;--ae-group-border-color:hsl(0deg 0% 94%);--ae-group-gap:2px;--ae-panel-border-radius:0px;--ae-subpanel-border-radius:8px;--ae-outside-gap-size:8px;--ae-inside-padding-size:8px;--ae-tool-button-size:34px;--ae-tool-button-radius:16px;--ae-generate-button-height:70px;--ae-max-padding:max( var(--ae-outside-gap-size), var(--ae-inside-padding-size) );--ae-icon-size:22px;--ae-mobile-outside-gap-size:2px;--ae-mobile-inside-padding-size:2px; \ No newline at end of file diff --git a/extensions-builtin/anapnoe-sd-theme-editor/themes/sdxl_minimal.css b/extensions-builtin/anapnoe-sd-theme-editor/themes/sdxl_minimal.css new file mode 100644 index 00000000000..04696bb0c01 --- /dev/null +++ b/extensions-builtin/anapnoe-sd-theme-editor/themes/sdxl_minimal.css @@ -0,0 +1 @@ +--ae-primary-color:hsl(168deg 96% 42%);--ae-secondary-color:hsl(225deg 6% 13%);--ae-main-bg-color:hsl(0deg 0% 8%);--ae-input-height:35px;--ae-input-slider-height:0.5;--ae-input-icon-height:calc(var(--ae-input-height) - var(--ae-input-border-size) * 2);--ae-input-padding:5px;--ae-input-font-size:14px;--ae-input-line-height:20px;--ae-label-color:hsl(0deg 0% 65%);--ae-secondary-label-color:hsl(0deg 100% 50%);--ae-input-border-size:2px;--ae-input-border-radius:5px;--ae-input-text-color:hsl(168deg 96% 42%);--ae-input-placeholder-color:hsl(168deg 96% 42%);--ae-input-bg-color:hsl(0deg 0% 10%);--ae-input-border-color:hsl(0deg 0% 10%);--ae-input-hover-text-color:hsl(240deg 18% 12%);--ae-panel-bg-color:hsl(0deg 0% 17%);--ae-panel-border-color:hsl(0deg 0% 17%);--ae-panel-padding:5px;--ae-border-radius:0px;--ae-border-size:2px;--ae-gap-size-val:6px;--ae-gap-size:max(var(--ae-gap-size-val), var(--ae-border-size));--ae-border-size-neg:calc(var(--ae-border-size) * -1);--ae-border-size-x2:calc((var(--ae-border-size) * 2) + 0px);--ae-group-bg-color:hsl(225deg 7% 11%);--ae-group-padding:0px;--ae-group-radius:0px;--ae-group-border-size:0px;--ae-group-border-color:hsl(240deg 16% 16%);--ae-group-gap:2px;--ae-panel-border-radius:4px;--ae-subpanel-border-radius:4px;--ae-outside-gap-size:1px;--ae-inside-padding-size:5px;--ae-tool-button-size:34px;--ae-tool-button-radius:16px;--ae-generate-button-height:70px;--ae-max-padding:max(var(--ae-outside-gap-size),var(--ae-inside-padding-size));--ae-icon-size:22px;--ae-mobile-outside-gap-size:3px;--ae-mobile-inside-padding-size:3px;--panel-border-radius:4px;--subpanel-border-radius:8px;--outside-gap-size:8px;--inside-padding-size:8px;--tool-button-size:34px;--tool-button-radius:16px;--generate-button-height:70px;--max-padding:max(var(--outside-gap-size),var(--inside-padding-size));--icon-size:22px;--mobile-outside-gap-size:3px;--mobile-inside-padding-size:3px; \ No newline at end of file diff --git a/extensions-builtin/anapnoe-sd-theme-editor/themes/sdxl_minimal_orange.css b/extensions-builtin/anapnoe-sd-theme-editor/themes/sdxl_minimal_orange.css new file mode 100644 index 00000000000..7d84204c4d4 --- /dev/null +++ b/extensions-builtin/anapnoe-sd-theme-editor/themes/sdxl_minimal_orange.css @@ -0,0 +1 @@ +--ae-primary-color:hsl(18deg 124% 42%);--ae-secondary-color:hsl(225deg 6% 13%);--ae-main-bg-color:hsl(210deg 28% 8%);--ae-input-height:35px;--ae-input-slider-height:0.5;--ae-input-icon-height:calc(var(--ae-input-height) - var(--ae-input-border-size) * 2);--ae-input-padding:5px;--ae-input-font-size:14px;--ae-input-line-height:20px;--ae-label-color:hsl(210deg 28% 65%);--ae-secondary-label-color:hsl(0deg 100% 50%);--ae-input-border-size:2px;--ae-input-border-radius:5px;--ae-input-text-color:hsl(18deg 100% 42%);--ae-input-placeholder-color:hsl(18deg 100% 42%);--ae-input-bg-color:hsl(210deg 28% 10%);--ae-input-border-color:hsl(210deg 28% 10%);--ae-input-hover-text-color:hsl(240deg 18% 12%);--ae-panel-bg-color:hsl(210deg 28% 17%);--ae-panel-border-color:hsl(210deg 28% 17%);--ae-panel-padding:5px;--ae-border-radius:0px;--ae-border-size:2px;--ae-gap-size-val:6px;--ae-gap-size:max(var(--ae-gap-size-val), var(--ae-border-size));--ae-border-size-neg:calc(var(--ae-border-size) * -1);--ae-border-size-x2:calc((var(--ae-border-size) * 2) + 0px);--ae-group-bg-color:hsl(225deg 7% 11%);--ae-group-padding:0px;--ae-group-radius:0px;--ae-group-border-size:0px;--ae-group-border-color:hsl(240deg 16% 16%);--ae-group-gap:2px;--ae-panel-border-radius:4px;--ae-subpanel-border-radius:4px;--ae-outside-gap-size:4px;--ae-inside-padding-size:4px;--ae-tool-button-size:34px;--ae-tool-button-radius:16px;--ae-generate-button-height:70px;--ae-max-padding:max(var(--ae-outside-gap-size),var(--ae-inside-padding-size));--ae-icon-size:22px;--ae-mobile-outside-gap-size:3px;--ae-mobile-inside-padding-size:3px;--panel-border-radius:4px;--subpanel-border-radius:8px;--outside-gap-size:8px;--inside-padding-size:8px;--tool-button-size:34px;--tool-button-radius:16px;--generate-button-height:70px;--max-padding:max(var(--outside-gap-size),var(--inside-padding-size));--icon-size:22px;--mobile-outside-gap-size:3px;--mobile-inside-padding-size:3px; \ No newline at end of file diff --git a/extensions-builtin/anapnoe-sd-theme-editor/themes/sdxl_moonlight.css b/extensions-builtin/anapnoe-sd-theme-editor/themes/sdxl_moonlight.css new file mode 100644 index 00000000000..5bde3e5e665 --- /dev/null +++ b/extensions-builtin/anapnoe-sd-theme-editor/themes/sdxl_moonlight.css @@ -0,0 +1 @@ +--ae-primary-color:hsl(222deg 75% 62%);--ae-secondary-color:hsl(225deg 6% 13%);--ae-main-bg-color:hsl(240deg 16% 6%);--ae-input-height:35px;--ae-input-slider-height:0.5;--ae-input-icon-height:calc(var(--ae-input-height) - var(--ae-input-border-size) * 2);--ae-input-padding:5px;--ae-input-font-size:14px;--ae-input-line-height:20px;--ae-label-color:hsl(185deg 66% 85%);--ae-secondary-label-color:hsl(0deg 100% 50%);--ae-input-border-size:2px;--ae-input-border-radius:5px;--ae-input-text-color:hsl(222deg 75% 62%);--ae-input-placeholder-color:hsl(222deg 75% 62%);--ae-input-bg-color:hsl(240deg 17% 8%);--ae-input-border-color:hsl(240deg 20% 16%);--ae-input-hover-text-color:hsl(240deg 18% 12%);--ae-panel-bg-color:hsl(240deg 18% 12%);--ae-panel-border-color:hsl(240deg 16% 16%);--ae-panel-padding:5px;--ae-border-radius:0px;--ae-border-size:2px;--ae-gap-size-val:6px;--ae-gap-size:max(var(--ae-gap-size-val), var(--ae-border-size));--ae-border-size-neg:calc(var(--ae-border-size) * -1);--ae-border-size-x2:calc((var(--ae-border-size) * 2) + 0px);--ae-group-bg-color:hsl(225deg 7% 11%);--ae-group-padding:0px;--ae-group-radius:0px;--ae-group-border-size:0px;--ae-group-border-color:hsl(240deg 16% 16%);--ae-group-gap:2px;--ae-panel-border-radius:0px;--ae-subpanel-border-radius:8px;--ae-outside-gap-size:8px;--ae-inside-padding-size:8px;--ae-tool-button-size:34px;--ae-tool-button-radius:16px;--ae-generate-button-height:70px;--ae-max-padding:max(var(--ae-outside-gap-size),var(--ae-inside-padding-size));--ae-icon-size:22px;--ae-mobile-outside-gap-size:2px;--ae-mobile-inside-padding-size:2px; \ No newline at end of file diff --git a/extensions-builtin/anapnoe-sd-theme-editor/themes/sdxl_orange.css b/extensions-builtin/anapnoe-sd-theme-editor/themes/sdxl_orange.css new file mode 100644 index 00000000000..715c5624f25 --- /dev/null +++ b/extensions-builtin/anapnoe-sd-theme-editor/themes/sdxl_orange.css @@ -0,0 +1 @@ +--ae-primary-color:hsl(15deg 77% 58%);--ae-secondary-color:hsl(225deg 6% 13%);--ae-main-bg-color:hsl(0deg 0% 10%);--ae-input-height:28px;--ae-input-slider-height:0.5;--ae-input-icon-height:calc(var(--ae-input-height) - var(--ae-input-border-size) * 2);--ae-input-padding:5px;--ae-input-font-size:12px;--ae-input-line-height:16px;--ae-label-color:hsl(216deg 5% 60%);--ae-secondary-label-color:hsl(0deg 100% 50%);--ae-input-border-size:1px;--ae-input-border-radius:0px;--ae-input-text-color:hsl(15deg 77% 58%);--ae-input-placeholder-color:hsl(216deg 5% 60%);--ae-input-bg-color:hsl(225deg 6% 13%);--ae-input-border-color:hsl(228deg 6% 17%);--ae-input-hover-text-color:hsl(16deg 94% 93%);--ae-panel-bg-color:hsl(225deg 5% 17%);--ae-panel-border-color:hsl(214deg 5% 30%);--ae-panel-padding:5px;--ae-border-radius:5px;--ae-border-size:0px;--ae-gap-size-val:3px;--ae-gap-size:max(var(--ae-gap-size-val), var(--ae-border-size));--ae-border-size-neg:calc(var(--ae-border-size) * -1);--ae-border-size-x2:calc((var(--ae-border-size) * 2) + 0px);--ae-group-bg-color:hsl(225deg 6% 13%);--ae-group-padding:2px;--ae-group-radius:6px;--ae-group-border-size:0px;--ae-group-border-color:hsl(225deg 6% 13%);--ae-group-gap:2px;--ae-panel-border-radius:0px;--ae-subpanel-border-radius:8px;--ae-outside-gap-size:8px;--ae-inside-padding-size:8px;--ae-tool-button-size:34px;--ae-tool-button-radius:16px;--ae-generate-button-height:70px;--ae-max-padding:max( var(--ae-outside-gap-size), var(--ae-inside-padding-size) );--ae-icon-size:22px;--ae-mobile-outside-gap-size:2px;--ae-mobile-inside-padding-size:2px; \ No newline at end of file diff --git a/extensions-builtin/anapnoe-sd-theme-editor/themes/sdxl_quad.css b/extensions-builtin/anapnoe-sd-theme-editor/themes/sdxl_quad.css new file mode 100644 index 00000000000..97442448ce7 --- /dev/null +++ b/extensions-builtin/anapnoe-sd-theme-editor/themes/sdxl_quad.css @@ -0,0 +1 @@ +--ae-primary-color:hsl(168deg 97% 41%);--ae-secondary-color:hsl(225deg 6% 13%);--ae-main-bg-color:hsl(0deg 0% 10%);--ae-input-height:35px;--ae-input-slider-height:0.5;--ae-input-icon-height:calc(var(--ae-input-height) - var(--ae-input-border-size) * 2);--ae-input-padding:5px;--ae-input-font-size:14px;--ae-input-line-height:23px;--ae-label-color:hsl(210deg 4% 80%);--ae-secondary-label-color:hsl(0deg 100% 50%);--ae-input-border-size:1px;--ae-input-border-radius:5px;--ae-input-text-color:hsl(168deg 97% 41%);--ae-input-placeholder-color:hsl(168deg 97% 41%);--ae-input-bg-color:hsl(225deg 6% 13%);--ae-input-border-color:hsl(210deg 6% 20%);--ae-input-hover-text-color:hsl(240deg 18% 12%);--ae-panel-bg-color:hsl(225deg 5% 17%);--ae-panel-border-color:hsl(220deg 5% 25%);--ae-panel-padding:5px;--ae-border-radius:0px;--ae-border-size:1px;--ae-gap-size-val:6px;--ae-gap-size:max(var(--ae-gap-size-val), var(--ae-border-size));--ae-border-size-neg:calc(var(--ae-border-size) * -1);--ae-border-size-x2:calc((var(--ae-border-size) * 2) + 0px);--ae-group-bg-color:hsl(225deg 7% 11%);--ae-group-padding:0px;--ae-group-radius:0px;--ae-group-border-size:0px;--ae-group-border-color:hsl(240deg 16% 16%);--ae-group-gap:1px;--ae-panel-border-radius:0px;--ae-subpanel-border-radius:8px;--ae-outside-gap-size:8px;--ae-inside-padding-size:8px;--ae-tool-button-size:34px;--ae-tool-button-radius:16px;--ae-generate-button-height:70px;--ae-max-padding:max(var(--ae-outside-gap-size),var(--ae-inside-padding-size));--ae-icon-size:22px;--ae-mobile-outside-gap-size:2px;--ae-mobile-inside-padding-size:2px;--panel-border-radius:4px;--subpanel-border-radius:8px;--outside-gap-size:8px;--inside-padding-size:8px;--tool-button-size:34px;--tool-button-radius:16px;--generate-button-height:70px;--max-padding:max(var(--outside-gap-size),var(--inside-padding-size));--icon-size:22px;--mobile-outside-gap-size:3px;--mobile-inside-padding-size:3px; \ No newline at end of file diff --git a/extensions-builtin/anapnoe-sd-theme-editor/themes/sdxl_thick_group_green.css b/extensions-builtin/anapnoe-sd-theme-editor/themes/sdxl_thick_group_green.css new file mode 100644 index 00000000000..3deb6d32e79 --- /dev/null +++ b/extensions-builtin/anapnoe-sd-theme-editor/themes/sdxl_thick_group_green.css @@ -0,0 +1 @@ +--ae-primary-color:hsl(168deg 97% 41%);--ae-secondary-color:hsl(225deg 6% 13%);--ae-main-bg-color:hsl(0deg 0% 10%);--ae-input-height:35px;--ae-input-slider-height:0.5;--ae-input-icon-height:calc(var(--ae-input-height) - var(--ae-input-border-size) * 2);--ae-input-padding:5px;--ae-input-font-size:14px;--ae-input-line-height:20px;--ae-label-color:hsl(216deg 5% 60%);--ae-secondary-label-color:hsl(0deg 100% 50%);--ae-input-border-size:0px;--ae-input-border-radius:5px;--ae-input-text-color:hsl(168deg 97% 41%);--ae-input-placeholder-color:hsl(168deg 97% 41%);--ae-input-bg-color:hsl(225deg 6% 13%);--ae-input-border-color:hsl(228deg 6% 17%);--ae-input-hover-text-color:hsl(168deg 96% 80%);--ae-panel-bg-color:hsl(225deg 5% 17%);--ae-panel-border-color:hsl(210deg 6% 20%);--ae-panel-padding:5px;--ae-border-radius:5px;--ae-border-size:2px;--ae-gap-size-val:5px;--ae-gap-size:max(var(--ae-gap-size-val), var(--ae-border-size));--ae-border-size-neg:calc(var(--ae-border-size) * -1);--ae-border-size-x2:calc((var(--ae-border-size) * 2) + 0px);--ae-group-bg-color:hsl(225deg 6% 13%);--ae-group-padding:3px;--ae-group-radius:8px;--ae-group-border-size:1px;--ae-group-border-color:hsl(225deg 6% 13%);--ae-group-gap:5px;--ae-panel-border-radius:0px;--ae-subpanel-border-radius:8px;--ae-outside-gap-size:8px;--ae-inside-padding-size:8px;--ae-tool-button-size:34px;--ae-tool-button-radius:16px;--ae-generate-button-height:70px;--ae-max-padding:max( var(--ae-outside-gap-size), var(--ae-inside-padding-size) );--ae-icon-size:22px;--ae-mobile-outside-gap-size:2px;--ae-mobile-inside-padding-size:2px;--panel-border-radius:4px;--subpanel-border-radius:8px;--outside-gap-size:8px;--inside-padding-size:8px;--tool-button-size:34px;--tool-button-radius:16px;--generate-button-height:70px;--max-padding:max(var(--outside-gap-size),var(--inside-padding-size));--icon-size:22px;--mobile-outside-gap-size:3px;--mobile-inside-padding-size:3px; \ No newline at end of file diff --git a/extensions-builtin/anapnoe-sd-theme-editor/themes/sdxl_thin_cyan.css b/extensions-builtin/anapnoe-sd-theme-editor/themes/sdxl_thin_cyan.css new file mode 100644 index 00000000000..7de81f79793 --- /dev/null +++ b/extensions-builtin/anapnoe-sd-theme-editor/themes/sdxl_thin_cyan.css @@ -0,0 +1 @@ +--ae-primary-color:hsl(190deg 75% 60%);--ae-secondary-color:hsl(225deg 6% 13%);--ae-main-bg-color:hsl(0deg 0% 10%);--ae-input-height:35px;--ae-input-slider-height:0.5;--ae-input-icon-height:calc(var(--ae-input-height) - var(--ae-input-border-size) * 2);--ae-input-padding:5px;--ae-input-font-size:12px;--ae-input-line-height:23px;--ae-label-color:hsl(216deg 5% 60%);--ae-secondary-label-color:hsl(0deg 100% 50%);--ae-input-border-size:1px;--ae-input-border-radius:0px;--ae-input-text-color:hsl(216deg 5% 60%);--ae-input-placeholder-color:hsl(190deg 75% 60%);--ae-input-bg-color:hsl(225deg 6% 13%);--ae-input-border-color:hsl(228deg 6% 17%);--ae-input-hover-text-color:hsl(225deg 6% 13%);--ae-panel-bg-color:hsl(225deg 5% 17%);--ae-panel-border-color:hsl(214deg 5% 30%);--ae-panel-padding:5px;--ae-border-radius:0px;--ae-border-size:1px;--ae-gap-size-val:5px;--ae-gap-size:max(var(--ae-gap-size-val), var(--ae-border-size));--ae-border-size-neg:calc(var(--ae-border-size) * -1);--ae-border-size-x2:calc((var(--ae-border-size) * 2) + 0px);--ae-group-bg-color:hsl(225deg 6% 13%);--ae-group-padding:2px;--ae-group-radius:0px;--ae-group-border-size:1px;--ae-group-border-color:hsl(225deg 6% 13%);--ae-group-gap:5px;--ae-panel-border-radius:0px;--ae-subpanel-border-radius:8px;--ae-outside-gap-size:8px;--ae-inside-padding-size:8px;--ae-tool-button-size:34px;--ae-tool-button-radius:16px;--ae-generate-button-height:70px;--ae-max-padding:max( var(--ae-outside-gap-size), var(--ae-inside-padding-size) );--ae-icon-size:22px;--ae-mobile-outside-gap-size:2px;--ae-mobile-inside-padding-size:2px;--panel-border-radius:4px;--subpanel-border-radius:8px;--outside-gap-size:8px;--inside-padding-size:8px;--tool-button-size:34px;--tool-button-radius:16px;--generate-button-height:70px;--max-padding:max(var(--outside-gap-size),var(--inside-padding-size));--icon-size:22px;--mobile-outside-gap-size:3px;--mobile-inside-padding-size:3px; \ No newline at end of file diff --git a/extensions-builtin/anapnoe-sd-theme-editor/themes/sdxl_tron2.css b/extensions-builtin/anapnoe-sd-theme-editor/themes/sdxl_tron2.css new file mode 100644 index 00000000000..b48ad837904 --- /dev/null +++ b/extensions-builtin/anapnoe-sd-theme-editor/themes/sdxl_tron2.css @@ -0,0 +1 @@ +--ae-main-bg-color:hsl(185deg 75% 3%);--ae-primary-color:hsl(182deg 95% 51%);--ae-input-bg-color:hsl(184deg 89% 7%);--ae-input-border-color:hsl(185deg 72% 25%);--ae-panel-bg-color:hsl(185deg 73% 3%);--ae-panel-border-color:hsl(185deg 72% 25%);--ae-panel-border-radius:0px;--ae-subpanel-border-radius:0px;--ae-outside-gap-size:2px;--ae-inside-padding-size:8px;--ae-tool-button-size:34px;--ae-tool-button-radius:16px;--ae-generate-button-height:70px;--ae-max-padding:max(var(--ae-outside-gap-size),var(--ae-inside-padding-size));--ae-icon-size:22px;--ae-label-color:hsl(182deg 95% 75%);--ae-mobile-outside-gap-size:2px;--ae-mobile-inside-padding-size:8px;--ae-input-height:35px;--ae-input-slider-height:0.5;--ae-gap-size-val:1px;--ae-input-font-size:11px;--ae-input-line-height:23px;--ae-input-border-size:1px;--ae-input-border-radius:0px;--ae-input-padding:5px;--ae-panel-padding:5px;--ae-border-radius:0px;--ae-border-size:1px;--ae-group-padding:0px;--ae-group-radius:0px;--ae-group-border-size:0px;--ae-group-gap:1px;--ae-group-bg-color:hsl(185deg 73% 3%);--ae-group-border-color:hsl(185deg 73% 3%);--ae-secondary-color:hsl(225deg 6% 13%);--ae-input-text-color:hsl(168deg 75% 70%);--ae-input-placeholder-color:hsl(185deg 72% 25%);--ae-secondary-label-color:hsl(0deg 100% 50%);--ae-input-hover-text-color:hsl(182deg 94% 80%); \ No newline at end of file diff --git a/extensions-builtin/anapnoe-sd-uiux/html/favicon.svg b/extensions-builtin/anapnoe-sd-uiux/html/favicon.svg new file mode 100644 index 00000000000..0cd7e9a2238 --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/favicon.svg @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/extensions-builtin/anapnoe-sd-uiux/html/images/Guru_meditation.gif b/extensions-builtin/anapnoe-sd-uiux/html/images/Guru_meditation.gif new file mode 100644 index 00000000000..66e9dcd426a Binary files /dev/null and b/extensions-builtin/anapnoe-sd-uiux/html/images/Guru_meditation.gif differ diff --git a/extensions-builtin/anapnoe-sd-uiux/html/images/anapnoe-gradio-app-visual-builder.png b/extensions-builtin/anapnoe-sd-uiux/html/images/anapnoe-gradio-app-visual-builder.png new file mode 100644 index 00000000000..9b8ecb386ad Binary files /dev/null and b/extensions-builtin/anapnoe-sd-uiux/html/images/anapnoe-gradio-app-visual-builder.png differ diff --git a/extensions-builtin/anapnoe-sd-uiux/html/images/anapnoe-ui-ux-orange.png b/extensions-builtin/anapnoe-sd-uiux/html/images/anapnoe-ui-ux-orange.png new file mode 100644 index 00000000000..7e447cdc16e Binary files /dev/null and b/extensions-builtin/anapnoe-sd-uiux/html/images/anapnoe-ui-ux-orange.png differ diff --git a/extensions-builtin/anapnoe-sd-uiux/html/images/anapnoe-ui-ux.png b/extensions-builtin/anapnoe-sd-uiux/html/images/anapnoe-ui-ux.png new file mode 100644 index 00000000000..2875b064e40 Binary files /dev/null and b/extensions-builtin/anapnoe-sd-uiux/html/images/anapnoe-ui-ux.png differ diff --git a/extensions-builtin/anapnoe-sd-uiux/html/images/workspaces.png b/extensions-builtin/anapnoe-sd-uiux/html/images/workspaces.png new file mode 100644 index 00000000000..d60477c1cf3 Binary files /dev/null and b/extensions-builtin/anapnoe-sd-uiux/html/images/workspaces.png differ diff --git a/html/svg/add-box-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/add-box-line.svg similarity index 100% rename from html/svg/add-box-line.svg rename to extensions-builtin/anapnoe-sd-uiux/html/svg/add-box-line.svg diff --git a/extensions-builtin/anapnoe-sd-uiux/html/svg/ai-generate.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/ai-generate.svg new file mode 100644 index 00000000000..0d5aa6f8489 --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/svg/ai-generate.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/extensions-builtin/anapnoe-sd-uiux/html/svg/arrow-down-s-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/arrow-down-s-line.svg new file mode 100644 index 00000000000..6c073430bf0 --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/svg/arrow-down-s-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/html/svg/arrow-go-back-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/arrow-go-back-line.svg similarity index 100% rename from html/svg/arrow-go-back-line.svg rename to extensions-builtin/anapnoe-sd-uiux/html/svg/arrow-go-back-line.svg diff --git a/extensions-builtin/anapnoe-sd-uiux/html/svg/arrow-right-s-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/arrow-right-s-line.svg new file mode 100644 index 00000000000..48dcbb05bcd --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/svg/arrow-right-s-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/extensions-builtin/anapnoe-sd-uiux/html/svg/arrow-right-up-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/arrow-right-up-line.svg new file mode 100644 index 00000000000..8dfe241a86c --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/svg/arrow-right-up-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/extensions-builtin/anapnoe-sd-uiux/html/svg/arrow-up-circle-fill.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/arrow-up-circle-fill.svg new file mode 100644 index 00000000000..53a9828e4d8 --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/svg/arrow-up-circle-fill.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/extensions-builtin/anapnoe-sd-uiux/html/svg/arrow-up-circle-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/arrow-up-circle-line.svg new file mode 100644 index 00000000000..6e2876a7745 --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/svg/arrow-up-circle-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/extensions-builtin/anapnoe-sd-uiux/html/svg/arrow-up-down-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/arrow-up-down-line.svg new file mode 100644 index 00000000000..e4fee21bbcf --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/svg/arrow-up-down-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/extensions-builtin/anapnoe-sd-uiux/html/svg/arrow-up-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/arrow-up-line.svg new file mode 100644 index 00000000000..da830a68c0e --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/svg/arrow-up-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/extensions-builtin/anapnoe-sd-uiux/html/svg/arrow-up-s-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/arrow-up-s-line.svg new file mode 100644 index 00000000000..f5111cd3a61 --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/svg/arrow-up-s-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/html/svg/artboard-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/artboard-line.svg similarity index 100% rename from html/svg/artboard-line.svg rename to extensions-builtin/anapnoe-sd-uiux/html/svg/artboard-line.svg diff --git a/html/svg/aspect-ratio-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/aspect-ratio-line.svg similarity index 100% rename from html/svg/aspect-ratio-line.svg rename to extensions-builtin/anapnoe-sd-uiux/html/svg/aspect-ratio-line.svg diff --git a/html/svg/ball-pen-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/ball-pen-line.svg similarity index 100% rename from html/svg/ball-pen-line.svg rename to extensions-builtin/anapnoe-sd-uiux/html/svg/ball-pen-line.svg diff --git a/extensions-builtin/anapnoe-sd-uiux/html/svg/bard-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/bard-line.svg new file mode 100644 index 00000000000..7cd55f73d31 --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/svg/bard-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/extensions-builtin/anapnoe-sd-uiux/html/svg/bill-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/bill-line.svg new file mode 100644 index 00000000000..e9a7ba3a69a --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/svg/bill-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/html/svg/bmc-logo2.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/bmc-logo2.svg similarity index 100% rename from html/svg/bmc-logo2.svg rename to extensions-builtin/anapnoe-sd-uiux/html/svg/bmc-logo2.svg diff --git a/extensions-builtin/anapnoe-sd-uiux/html/svg/box-1-fill.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/box-1-fill.svg new file mode 100644 index 00000000000..c1ce271aa3d --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/svg/box-1-fill.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/extensions-builtin/anapnoe-sd-uiux/html/svg/box-1-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/box-1-line.svg new file mode 100644 index 00000000000..10ca0b6879b --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/svg/box-1-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/extensions-builtin/anapnoe-sd-uiux/html/svg/box-2-fill.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/box-2-fill.svg new file mode 100644 index 00000000000..017444ff22a --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/svg/box-2-fill.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/extensions-builtin/anapnoe-sd-uiux/html/svg/box-2-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/box-2-line.svg new file mode 100644 index 00000000000..3e558a68c8a --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/svg/box-2-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/extensions-builtin/anapnoe-sd-uiux/html/svg/box-3-fill.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/box-3-fill.svg new file mode 100644 index 00000000000..2812f7f7abf --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/svg/box-3-fill.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/extensions-builtin/anapnoe-sd-uiux/html/svg/box-3-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/box-3-line.svg new file mode 100644 index 00000000000..34fef19ddc4 --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/svg/box-3-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/extensions-builtin/anapnoe-sd-uiux/html/svg/boxing-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/boxing-line.svg new file mode 100644 index 00000000000..d60a815b9d4 --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/svg/boxing-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/html/svg/brush-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/brush-line.svg similarity index 100% rename from html/svg/brush-line.svg rename to extensions-builtin/anapnoe-sd-uiux/html/svg/brush-line.svg diff --git a/extensions-builtin/anapnoe-sd-uiux/html/svg/bug-2-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/bug-2-line.svg new file mode 100644 index 00000000000..350993d6271 --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/svg/bug-2-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/extensions-builtin/anapnoe-sd-uiux/html/svg/camera-lens-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/camera-lens-line.svg new file mode 100644 index 00000000000..5adb92980a3 --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/svg/camera-lens-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/html/svg/checkbox-blank-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/checkbox-blank-line.svg similarity index 100% rename from html/svg/checkbox-blank-line.svg rename to extensions-builtin/anapnoe-sd-uiux/html/svg/checkbox-blank-line.svg diff --git a/html/svg/checkbox-indeterminate-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/checkbox-indeterminate-line.svg similarity index 100% rename from html/svg/checkbox-indeterminate-line.svg rename to extensions-builtin/anapnoe-sd-uiux/html/svg/checkbox-indeterminate-line.svg diff --git a/extensions-builtin/anapnoe-sd-uiux/html/svg/checkbox-multiple-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/checkbox-multiple-line.svg new file mode 100644 index 00000000000..2c23848ced8 --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/svg/checkbox-multiple-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/html/svg/clipboard-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/clipboard-line.svg similarity index 100% rename from html/svg/clipboard-line.svg rename to extensions-builtin/anapnoe-sd-uiux/html/svg/clipboard-line.svg diff --git a/html/svg/close-circle-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/close-circle-line.svg similarity index 100% rename from html/svg/close-circle-line.svg rename to extensions-builtin/anapnoe-sd-uiux/html/svg/close-circle-line.svg diff --git a/html/svg/close-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/close-line.svg similarity index 100% rename from html/svg/close-line.svg rename to extensions-builtin/anapnoe-sd-uiux/html/svg/close-line.svg diff --git a/html/svg/compass-4-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/compass-4-line.svg similarity index 100% rename from html/svg/compass-4-line.svg rename to extensions-builtin/anapnoe-sd-uiux/html/svg/compass-4-line.svg diff --git a/html/svg/computer-fill.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/computer-fill.svg similarity index 100% rename from html/svg/computer-fill.svg rename to extensions-builtin/anapnoe-sd-uiux/html/svg/computer-fill.svg diff --git a/extensions-builtin/anapnoe-sd-uiux/html/svg/contract-left-right-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/contract-left-right-line.svg new file mode 100644 index 00000000000..dfeb9607eab --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/svg/contract-left-right-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/extensions-builtin/anapnoe-sd-uiux/html/svg/contract-up-down-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/contract-up-down-line.svg new file mode 100644 index 00000000000..c52aaf32544 --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/svg/contract-up-down-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/html/svg/contrast-drop-2-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/contrast-drop-2-line.svg similarity index 100% rename from html/svg/contrast-drop-2-line.svg rename to extensions-builtin/anapnoe-sd-uiux/html/svg/contrast-drop-2-line.svg diff --git a/extensions-builtin/anapnoe-sd-uiux/html/svg/corner-up-right-fill.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/corner-up-right-fill.svg new file mode 100644 index 00000000000..55510a950a5 --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/svg/corner-up-right-fill.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/extensions-builtin/anapnoe-sd-uiux/html/svg/corner-up-right-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/corner-up-right-line.svg new file mode 100644 index 00000000000..e561b5b7aab --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/svg/corner-up-right-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/html/svg/cpu-fill.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/cpu-fill.svg similarity index 100% rename from html/svg/cpu-fill.svg rename to extensions-builtin/anapnoe-sd-uiux/html/svg/cpu-fill.svg diff --git a/html/svg/cpu-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/cpu-line.svg similarity index 100% rename from html/svg/cpu-line.svg rename to extensions-builtin/anapnoe-sd-uiux/html/svg/cpu-line.svg diff --git a/extensions-builtin/anapnoe-sd-uiux/html/svg/crop-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/crop-line.svg new file mode 100644 index 00000000000..d0fef9b6cb9 --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/svg/crop-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/html/svg/delete-bin-2-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/delete-bin-2-line.svg similarity index 100% rename from html/svg/delete-bin-2-line.svg rename to extensions-builtin/anapnoe-sd-uiux/html/svg/delete-bin-2-line.svg diff --git a/html/svg/delete-bin-5-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/delete-bin-5-line.svg similarity index 100% rename from html/svg/delete-bin-5-line.svg rename to extensions-builtin/anapnoe-sd-uiux/html/svg/delete-bin-5-line.svg diff --git a/html/svg/dice-1.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/dice-1.svg similarity index 100% rename from html/svg/dice-1.svg rename to extensions-builtin/anapnoe-sd-uiux/html/svg/dice-1.svg diff --git a/html/svg/download-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/download-line.svg similarity index 100% rename from html/svg/download-line.svg rename to extensions-builtin/anapnoe-sd-uiux/html/svg/download-line.svg diff --git a/extensions-builtin/anapnoe-sd-uiux/html/svg/draft-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/draft-line.svg new file mode 100644 index 00000000000..f12c2b29c4e --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/svg/draft-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/html/svg/drag-drop-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/drag-drop-line.svg similarity index 100% rename from html/svg/drag-drop-line.svg rename to extensions-builtin/anapnoe-sd-uiux/html/svg/drag-drop-line.svg diff --git a/html/svg/drag-move-2-fill.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/drag-move-2-fill.svg similarity index 100% rename from html/svg/drag-move-2-fill.svg rename to extensions-builtin/anapnoe-sd-uiux/html/svg/drag-move-2-fill.svg diff --git a/extensions-builtin/anapnoe-sd-uiux/html/svg/drop-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/drop-line.svg new file mode 100644 index 00000000000..b39581aebd7 --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/svg/drop-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/extensions-builtin/anapnoe-sd-uiux/html/svg/dvd-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/dvd-line.svg new file mode 100644 index 00000000000..8fbf4cd539e --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/svg/dvd-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/extensions-builtin/anapnoe-sd-uiux/html/svg/edit-box-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/edit-box-line.svg new file mode 100644 index 00000000000..c2cf8237844 --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/svg/edit-box-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/extensions-builtin/anapnoe-sd-uiux/html/svg/edit-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/edit-line.svg new file mode 100644 index 00000000000..a92e54f3a5b --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/svg/edit-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/extensions-builtin/anapnoe-sd-uiux/html/svg/emotion-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/emotion-line.svg new file mode 100644 index 00000000000..9c90cdc63e8 --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/svg/emotion-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/extensions-builtin/anapnoe-sd-uiux/html/svg/equalizer-fill.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/equalizer-fill.svg new file mode 100644 index 00000000000..c7e0da6ad63 --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/svg/equalizer-fill.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/extensions-builtin/anapnoe-sd-uiux/html/svg/equalizer-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/equalizer-line.svg new file mode 100644 index 00000000000..be81d93624f --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/svg/equalizer-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/html/svg/file-download-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/file-download-line.svg similarity index 100% rename from html/svg/file-download-line.svg rename to extensions-builtin/anapnoe-sd-uiux/html/svg/file-download-line.svg diff --git a/extensions-builtin/anapnoe-sd-uiux/html/svg/file-edit-fill.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/file-edit-fill.svg new file mode 100644 index 00000000000..dc3ef11a7df --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/svg/file-edit-fill.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/extensions-builtin/anapnoe-sd-uiux/html/svg/file-info-fill.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/file-info-fill.svg new file mode 100644 index 00000000000..c0ea9a09cea --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/svg/file-info-fill.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/extensions-builtin/anapnoe-sd-uiux/html/svg/file-info-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/file-info-line.svg new file mode 100644 index 00000000000..d64ca2939c4 --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/svg/file-info-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/html/svg/file-zip-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/file-zip-line.svg similarity index 100% rename from html/svg/file-zip-line.svg rename to extensions-builtin/anapnoe-sd-uiux/html/svg/file-zip-line.svg diff --git a/extensions-builtin/anapnoe-sd-uiux/html/svg/flashlight-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/flashlight-line.svg new file mode 100644 index 00000000000..fe131573ff2 --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/svg/flashlight-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/extensions-builtin/anapnoe-sd-uiux/html/svg/focus-2-fill.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/focus-2-fill.svg new file mode 100644 index 00000000000..f873ad325e8 --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/svg/focus-2-fill.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/extensions-builtin/anapnoe-sd-uiux/html/svg/focus-2-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/focus-2-line.svg new file mode 100644 index 00000000000..84c537b42f6 --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/svg/focus-2-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/extensions-builtin/anapnoe-sd-uiux/html/svg/focus-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/focus-line.svg new file mode 100644 index 00000000000..b5819e898c1 --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/svg/focus-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/html/svg/folder-open-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/folder-open-line.svg similarity index 100% rename from html/svg/folder-open-line.svg rename to extensions-builtin/anapnoe-sd-uiux/html/svg/folder-open-line.svg diff --git a/html/svg/fullscreen-exit-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/fullscreen-exit-line.svg similarity index 100% rename from html/svg/fullscreen-exit-line.svg rename to extensions-builtin/anapnoe-sd-uiux/html/svg/fullscreen-exit-line.svg diff --git a/html/svg/fullscreen-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/fullscreen-line.svg similarity index 100% rename from html/svg/fullscreen-line.svg rename to extensions-builtin/anapnoe-sd-uiux/html/svg/fullscreen-line.svg diff --git a/html/svg/github-fill.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/github-fill.svg similarity index 100% rename from html/svg/github-fill.svg rename to extensions-builtin/anapnoe-sd-uiux/html/svg/github-fill.svg diff --git a/extensions-builtin/anapnoe-sd-uiux/html/svg/github-fill.xml b/extensions-builtin/anapnoe-sd-uiux/html/svg/github-fill.xml new file mode 100644 index 00000000000..8fe0e919681 --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/svg/github-fill.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/html/svg/gradio-fill.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/gradio-fill.svg similarity index 100% rename from html/svg/gradio-fill.svg rename to extensions-builtin/anapnoe-sd-uiux/html/svg/gradio-fill.svg diff --git a/extensions-builtin/anapnoe-sd-uiux/html/svg/gradio-fill.xml b/extensions-builtin/anapnoe-sd-uiux/html/svg/gradio-fill.xml new file mode 100644 index 00000000000..6ea1d1d8a6b --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/svg/gradio-fill.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/html/svg/grid-fill.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/grid-fill.svg similarity index 100% rename from html/svg/grid-fill.svg rename to extensions-builtin/anapnoe-sd-uiux/html/svg/grid-fill.svg diff --git a/html/svg/grid-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/grid-line.svg similarity index 100% rename from html/svg/grid-line.svg rename to extensions-builtin/anapnoe-sd-uiux/html/svg/grid-line.svg diff --git a/extensions-builtin/anapnoe-sd-uiux/html/svg/group-2-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/group-2-line.svg new file mode 100644 index 00000000000..de5a2c3e53c --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/svg/group-2-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/html/svg/heart-add-fill.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/heart-add-fill.svg similarity index 100% rename from html/svg/heart-add-fill.svg rename to extensions-builtin/anapnoe-sd-uiux/html/svg/heart-add-fill.svg diff --git a/html/svg/heart-fill.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/heart-fill.svg similarity index 100% rename from html/svg/heart-fill.svg rename to extensions-builtin/anapnoe-sd-uiux/html/svg/heart-fill.svg diff --git a/html/svg/heart-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/heart-line.svg similarity index 100% rename from html/svg/heart-line.svg rename to extensions-builtin/anapnoe-sd-uiux/html/svg/heart-line.svg diff --git a/extensions-builtin/anapnoe-sd-uiux/html/svg/image-2-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/image-2-line.svg new file mode 100644 index 00000000000..2f66534089b --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/svg/image-2-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/extensions-builtin/anapnoe-sd-uiux/html/svg/image-add-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/image-add-line.svg new file mode 100644 index 00000000000..12c227bbbbf --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/svg/image-add-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/extensions-builtin/anapnoe-sd-uiux/html/svg/image-edit-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/image-edit-line.svg new file mode 100644 index 00000000000..b5601596b96 --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/svg/image-edit-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/html/svg/image-icon.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/image-icon.svg similarity index 100% rename from html/svg/image-icon.svg rename to extensions-builtin/anapnoe-sd-uiux/html/svg/image-icon.svg diff --git a/extensions-builtin/anapnoe-sd-uiux/html/svg/image-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/image-line.svg new file mode 100644 index 00000000000..7b1d5e24f5d --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/svg/image-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/html/svg/image-update.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/image-update.svg similarity index 100% rename from html/svg/image-update.svg rename to extensions-builtin/anapnoe-sd-uiux/html/svg/image-update.svg diff --git a/html/svg/infinity-fill.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/infinity-fill.svg similarity index 100% rename from html/svg/infinity-fill.svg rename to extensions-builtin/anapnoe-sd-uiux/html/svg/infinity-fill.svg diff --git a/html/svg/information-fill.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/information-fill.svg similarity index 100% rename from html/svg/information-fill.svg rename to extensions-builtin/anapnoe-sd-uiux/html/svg/information-fill.svg diff --git a/html/svg/information-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/information-line.svg similarity index 100% rename from html/svg/information-line.svg rename to extensions-builtin/anapnoe-sd-uiux/html/svg/information-line.svg diff --git a/extensions-builtin/anapnoe-sd-uiux/html/svg/install-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/install-line.svg new file mode 100644 index 00000000000..ef9c67a7791 --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/svg/install-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/html/svg/landscape-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/landscape-line.svg similarity index 100% rename from html/svg/landscape-line.svg rename to extensions-builtin/anapnoe-sd-uiux/html/svg/landscape-line.svg diff --git a/extensions-builtin/anapnoe-sd-uiux/html/svg/layout-2-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/layout-2-line.svg new file mode 100644 index 00000000000..7afdae1fb92 --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/svg/layout-2-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/extensions-builtin/anapnoe-sd-uiux/html/svg/layout-grid-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/layout-grid-line.svg new file mode 100644 index 00000000000..8cb42b0320d --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/svg/layout-grid-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/extensions-builtin/anapnoe-sd-uiux/html/svg/list-settings-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/list-settings-line.svg new file mode 100644 index 00000000000..b4cad12564f --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/svg/list-settings-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/extensions-builtin/anapnoe-sd-uiux/html/svg/loop-right-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/loop-right-line.svg new file mode 100644 index 00000000000..1267be061e3 --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/svg/loop-right-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/html/svg/magic-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/magic-line.svg similarity index 100% rename from html/svg/magic-line.svg rename to extensions-builtin/anapnoe-sd-uiux/html/svg/magic-line.svg diff --git a/extensions-builtin/anapnoe-sd-uiux/html/svg/markup-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/markup-line.svg new file mode 100644 index 00000000000..49b7ab78397 --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/svg/markup-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/html/svg/menu-4-fill.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/menu-4-fill.svg similarity index 100% rename from html/svg/menu-4-fill.svg rename to extensions-builtin/anapnoe-sd-uiux/html/svg/menu-4-fill.svg diff --git a/html/svg/menu-add-fill.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/menu-add-fill.svg similarity index 100% rename from html/svg/menu-add-fill.svg rename to extensions-builtin/anapnoe-sd-uiux/html/svg/menu-add-fill.svg diff --git a/html/svg/menu-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/menu-line.svg similarity index 100% rename from html/svg/menu-line.svg rename to extensions-builtin/anapnoe-sd-uiux/html/svg/menu-line.svg diff --git a/extensions-builtin/anapnoe-sd-uiux/html/svg/menu-search-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/menu-search-line.svg new file mode 100644 index 00000000000..59d56f45ce7 --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/svg/menu-search-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/extensions-builtin/anapnoe-sd-uiux/html/svg/meteor-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/meteor-line.svg new file mode 100644 index 00000000000..fac2b8c5dec --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/svg/meteor-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/html/svg/more-2-fill.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/more-2-fill.svg similarity index 100% rename from html/svg/more-2-fill.svg rename to extensions-builtin/anapnoe-sd-uiux/html/svg/more-2-fill.svg diff --git a/extensions-builtin/anapnoe-sd-uiux/html/svg/node-tree.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/node-tree.svg new file mode 100644 index 00000000000..7693acca96f --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/svg/node-tree.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/extensions-builtin/anapnoe-sd-uiux/html/svg/organization-chart.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/organization-chart.svg new file mode 100644 index 00000000000..f16aae8d10f --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/svg/organization-chart.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/html/svg/paint-brush-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/paint-brush-line.svg similarity index 100% rename from html/svg/paint-brush-line.svg rename to extensions-builtin/anapnoe-sd-uiux/html/svg/paint-brush-line.svg diff --git a/extensions-builtin/anapnoe-sd-uiux/html/svg/paint-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/paint-line.svg new file mode 100644 index 00000000000..5839c207439 --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/svg/paint-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/html/svg/pantone-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/pantone-line.svg similarity index 100% rename from html/svg/pantone-line.svg rename to extensions-builtin/anapnoe-sd-uiux/html/svg/pantone-line.svg diff --git a/html/svg/picture-in-picture-exit-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/picture-in-picture-exit-line.svg similarity index 100% rename from html/svg/picture-in-picture-exit-line.svg rename to extensions-builtin/anapnoe-sd-uiux/html/svg/picture-in-picture-exit-line.svg diff --git a/extensions-builtin/anapnoe-sd-uiux/html/svg/planet-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/planet-line.svg new file mode 100644 index 00000000000..3bb04682ad3 --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/svg/planet-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/extensions-builtin/anapnoe-sd-uiux/html/svg/play-circle-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/play-circle-line.svg new file mode 100644 index 00000000000..af5e178ee42 --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/svg/play-circle-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/extensions-builtin/anapnoe-sd-uiux/html/svg/play-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/play-line.svg new file mode 100644 index 00000000000..c9c6b6eb32e --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/svg/play-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/extensions-builtin/anapnoe-sd-uiux/html/svg/plug-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/plug-line.svg new file mode 100644 index 00000000000..5e20db981e9 --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/svg/plug-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/html/svg/pulse-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/pulse-line.svg similarity index 100% rename from html/svg/pulse-line.svg rename to extensions-builtin/anapnoe-sd-uiux/html/svg/pulse-line.svg diff --git a/extensions-builtin/anapnoe-sd-uiux/html/svg/pushpin-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/pushpin-line.svg new file mode 100644 index 00000000000..b86e5654de1 --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/svg/pushpin-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/html/svg/question-answer-fill.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/question-answer-fill.svg similarity index 100% rename from html/svg/question-answer-fill.svg rename to extensions-builtin/anapnoe-sd-uiux/html/svg/question-answer-fill.svg diff --git a/html/svg/question-answer-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/question-answer-line.svg similarity index 100% rename from html/svg/question-answer-line.svg rename to extensions-builtin/anapnoe-sd-uiux/html/svg/question-answer-line.svg diff --git a/html/svg/recycle-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/recycle-line.svg similarity index 100% rename from html/svg/recycle-line.svg rename to extensions-builtin/anapnoe-sd-uiux/html/svg/recycle-line.svg diff --git a/html/svg/refresh-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/refresh-line.svg similarity index 100% rename from html/svg/refresh-line.svg rename to extensions-builtin/anapnoe-sd-uiux/html/svg/refresh-line.svg diff --git a/html/svg/reply-fill.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/reply-fill.svg similarity index 100% rename from html/svg/reply-fill.svg rename to extensions-builtin/anapnoe-sd-uiux/html/svg/reply-fill.svg diff --git a/html/svg/reply-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/reply-line.svg similarity index 100% rename from html/svg/reply-line.svg rename to extensions-builtin/anapnoe-sd-uiux/html/svg/reply-line.svg diff --git a/html/svg/restart-fill.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/restart-fill.svg similarity index 100% rename from html/svg/restart-fill.svg rename to extensions-builtin/anapnoe-sd-uiux/html/svg/restart-fill.svg diff --git a/extensions-builtin/anapnoe-sd-uiux/html/svg/robot-2-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/robot-2-line.svg new file mode 100644 index 00000000000..434f3da60f3 --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/svg/robot-2-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/extensions-builtin/anapnoe-sd-uiux/html/svg/rocket-fill.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/rocket-fill.svg new file mode 100644 index 00000000000..ad9a5941b4d --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/svg/rocket-fill.svg @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/extensions-builtin/anapnoe-sd-uiux/html/svg/ruler-2-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/ruler-2-line.svg new file mode 100644 index 00000000000..cd589354eb4 --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/svg/ruler-2-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/extensions-builtin/anapnoe-sd-uiux/html/svg/run-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/run-line.svg new file mode 100644 index 00000000000..7254f4607d8 --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/svg/run-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/html/svg/save-2-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/save-2-line.svg similarity index 100% rename from html/svg/save-2-line.svg rename to extensions-builtin/anapnoe-sd-uiux/html/svg/save-2-line.svg diff --git a/html/svg/save-3-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/save-3-line.svg similarity index 100% rename from html/svg/save-3-line.svg rename to extensions-builtin/anapnoe-sd-uiux/html/svg/save-3-line.svg diff --git a/extensions-builtin/anapnoe-sd-uiux/html/svg/seo-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/seo-line.svg new file mode 100644 index 00000000000..670c46a8e06 --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/svg/seo-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/extensions-builtin/anapnoe-sd-uiux/html/svg/settings-3-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/settings-3-line.svg new file mode 100644 index 00000000000..dbc30971bbc --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/svg/settings-3-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/extensions-builtin/anapnoe-sd-uiux/html/svg/shape-fill.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/shape-fill.svg new file mode 100644 index 00000000000..6200ce7aace --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/svg/shape-fill.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/extensions-builtin/anapnoe-sd-uiux/html/svg/shapes-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/shapes-line.svg new file mode 100644 index 00000000000..b7d77105085 --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/svg/shapes-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/extensions-builtin/anapnoe-sd-uiux/html/svg/shut-down-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/shut-down-line.svg new file mode 100644 index 00000000000..a8ab6b14feb --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/svg/shut-down-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/extensions-builtin/anapnoe-sd-uiux/html/svg/skip-forward-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/skip-forward-line.svg new file mode 100644 index 00000000000..6da48dab54e --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/svg/skip-forward-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/extensions-builtin/anapnoe-sd-uiux/html/svg/skip-forward-mini-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/skip-forward-mini-line.svg new file mode 100644 index 00000000000..03d788adb15 --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/svg/skip-forward-mini-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/extensions-builtin/anapnoe-sd-uiux/html/svg/sort-asc.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/sort-asc.svg new file mode 100644 index 00000000000..411e658ec39 --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/svg/sort-asc.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/extensions-builtin/anapnoe-sd-uiux/html/svg/sort-desc.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/sort-desc.svg new file mode 100644 index 00000000000..85a5a1aad5e --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/svg/sort-desc.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/extensions-builtin/anapnoe-sd-uiux/html/svg/sound-module-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/sound-module-line.svg new file mode 100644 index 00000000000..02b9ddb06fa --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/svg/sound-module-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/extensions-builtin/anapnoe-sd-uiux/html/svg/sparkling-2-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/sparkling-2-line.svg new file mode 100644 index 00000000000..f9802f57682 --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/svg/sparkling-2-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/extensions-builtin/anapnoe-sd-uiux/html/svg/sparkling-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/sparkling-line.svg new file mode 100644 index 00000000000..6a70ce237d5 --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/svg/sparkling-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/html/svg/spotlight/arrow.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/spotlight/arrow.svg similarity index 100% rename from html/svg/spotlight/arrow.svg rename to extensions-builtin/anapnoe-sd-uiux/html/svg/spotlight/arrow.svg diff --git a/html/svg/spotlight/error.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/spotlight/error.svg similarity index 100% rename from html/svg/spotlight/error.svg rename to extensions-builtin/anapnoe-sd-uiux/html/svg/spotlight/error.svg diff --git a/html/svg/spotlight/pause.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/spotlight/pause.svg similarity index 100% rename from html/svg/spotlight/pause.svg rename to extensions-builtin/anapnoe-sd-uiux/html/svg/spotlight/pause.svg diff --git a/html/svg/spotlight/pixel.gif b/extensions-builtin/anapnoe-sd-uiux/html/svg/spotlight/pixel.gif similarity index 100% rename from html/svg/spotlight/pixel.gif rename to extensions-builtin/anapnoe-sd-uiux/html/svg/spotlight/pixel.gif diff --git a/html/svg/spotlight/play.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/spotlight/play.svg similarity index 100% rename from html/svg/spotlight/play.svg rename to extensions-builtin/anapnoe-sd-uiux/html/svg/spotlight/play.svg diff --git a/html/svg/spotlight/preloader.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/spotlight/preloader.svg similarity index 100% rename from html/svg/spotlight/preloader.svg rename to extensions-builtin/anapnoe-sd-uiux/html/svg/spotlight/preloader.svg diff --git a/html/svg/spotlight/theme.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/spotlight/theme.svg similarity index 100% rename from html/svg/spotlight/theme.svg rename to extensions-builtin/anapnoe-sd-uiux/html/svg/spotlight/theme.svg diff --git a/html/svg/stack-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/stack-line.svg similarity index 100% rename from html/svg/stack-line.svg rename to extensions-builtin/anapnoe-sd-uiux/html/svg/stack-line.svg diff --git a/extensions-builtin/anapnoe-sd-uiux/html/svg/star-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/star-line.svg new file mode 100644 index 00000000000..2455a96921d --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/svg/star-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/extensions-builtin/anapnoe-sd-uiux/html/svg/stop-circle-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/stop-circle-line.svg new file mode 100644 index 00000000000..25ac41f3c44 --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/svg/stop-circle-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/extensions-builtin/anapnoe-sd-uiux/html/svg/stop-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/stop-line.svg new file mode 100644 index 00000000000..2b44ad7055e --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/svg/stop-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/html/svg/t-box-fill.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/t-box-fill.svg similarity index 100% rename from html/svg/t-box-fill.svg rename to extensions-builtin/anapnoe-sd-uiux/html/svg/t-box-fill.svg diff --git a/extensions-builtin/anapnoe-sd-uiux/html/svg/t-box-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/t-box-line.svg new file mode 100644 index 00000000000..cd9a38fe24a --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/svg/t-box-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/extensions-builtin/anapnoe-sd-uiux/html/svg/team-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/team-line.svg new file mode 100644 index 00000000000..699419d7033 --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/svg/team-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/html/svg/terminal-box-fill.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/terminal-box-fill.svg similarity index 100% rename from html/svg/terminal-box-fill.svg rename to extensions-builtin/anapnoe-sd-uiux/html/svg/terminal-box-fill.svg diff --git a/extensions-builtin/anapnoe-sd-uiux/html/svg/terminal-box-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/terminal-box-line.svg new file mode 100644 index 00000000000..e03c93f622a --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/svg/terminal-box-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/extensions-builtin/anapnoe-sd-uiux/html/svg/text.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/text.svg new file mode 100644 index 00000000000..00ba6b6dc9e --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/svg/text.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/extensions-builtin/anapnoe-sd-uiux/html/svg/trophy-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/trophy-line.svg new file mode 100644 index 00000000000..9cb05f0b5ff --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/svg/trophy-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/extensions-builtin/anapnoe-sd-uiux/html/svg/unpin-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/unpin-line.svg new file mode 100644 index 00000000000..61f7d33da7a --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/svg/unpin-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/extensions-builtin/anapnoe-sd-uiux/html/svg/user-smile-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/user-smile-line.svg new file mode 100644 index 00000000000..d9608530eb5 --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/svg/user-smile-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/extensions-builtin/anapnoe-sd-uiux/html/svg/variation-settings.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/variation-settings.svg new file mode 100644 index 00000000000..baec2dee1aa --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/svg/variation-settings.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/extensions-builtin/anapnoe-sd-uiux/html/svg/video-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/video-line.svg new file mode 100644 index 00000000000..e2e1c928480 --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/svg/video-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/extensions-builtin/anapnoe-sd-uiux/html/svg/vip-diamond-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/vip-diamond-line.svg new file mode 100644 index 00000000000..408dd262e76 --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/svg/vip-diamond-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/html/svg/zoom-in-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/zoom-in-line.svg similarity index 100% rename from html/svg/zoom-in-line.svg rename to extensions-builtin/anapnoe-sd-uiux/html/svg/zoom-in-line.svg diff --git a/html/svg/zoom-out-line.svg b/extensions-builtin/anapnoe-sd-uiux/html/svg/zoom-out-line.svg similarity index 100% rename from html/svg/zoom-out-line.svg rename to extensions-builtin/anapnoe-sd-uiux/html/svg/zoom-out-line.svg diff --git a/extensions-builtin/anapnoe-sd-uiux/html/templates/template-about.html b/extensions-builtin/anapnoe-sd-uiux/html/templates/template-about.html new file mode 100644 index 00000000000..f2b305786ef --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/templates/template-about.html @@ -0,0 +1,127 @@ +
+
+
+

Anapnoe UI-UX Core

+
+

Anapnoe UI-UX Core extension leverages a custom-made visual editor and a cutting-edge component library + to facilitate the rapid development of sophisticated Gradio applications. + In addition to its visually appealing design and well-planned layout, this extension + offers several performance enhancements to both the Stable Diffusion web UI and the + Gradio + framework. These optimizations include: +

+
    +
  • Replacing all default Gradio stylesheets in the DOM with an optimized version that promote + better visual coherence across components.
  • +
  • Eliminating inline styles and Svelte classes from the DOM to minimize clutter and improve + efficiency.
  • +
  • Removing unnecessary "img2img Extra Networks" from the DOM to reduce duplicated images and event + listeners.
  • +
  • Eradicating inline event listeners from "txt2img Extra Networks" cards and action buttons.
  • +
  • Applying an event delegation pattern to further streamline the code by consolidating event + handling for "txt2img Extra Networks" cards and action buttons.
  • +
+

+ Although the current optimizations provide significant benefits, they are still applied after the + DOM has been loaded. A more effective approach would be to eliminate these unnecessary elements + entirely from the backend. This is an area for improvement and will be address in the future + releases of + Stable Diffusion web + UI-UX. +

+ +

+ Any extensions that replicate "Extra Network Cards" will not be officially supported. + However, if certain extensions hold significant value for your workflow, you can initiate a discussion. + If the community expresses interest and support for these optimizations, + I will be willing to submit pull requests to the extension's author to implement them. +

+
+
+
+

+ Open Source +

+
+

+ Open source projects play a crucial role in protecting user privacy and security, + advocating for unhindered access to source code, and nurturing a more transparent technology + ecosystem. + By supporting this project through your donation, you'll contribute to its ongoing development + without any compromise + from advertisements or corporate agendas, and ensure that it stays freely accessible, current, and + open to all. +

There is only so much time in a day that a person can otherwise give (Dave Glick). +
+

+
+
+
+

+ Sponsors & Supporters +

+
+

+ Our sponsors and supporters will be prominently featured on a dedicated tab and on the GitHub page, + highlighting their commitment to advancing innovation in development. + As a heartfelt thank you, they'll get early access to all new features and premium add-ons. + +

+ Donate now, and join forces to + create a sustainable realm of open source software that benefits everyone. + +
+

+
+ +
+
+
+

Upcoming add-ons for UI-UX

+
+
+

+ Workspaces UI-UX +

+
+

+ With workspaces extension, you can craft personalized views and arrange them in any way that suits your preferences, + allowing you to tailor-make workflows that cater to your specific needs. +

+ Anapnoe UI-UX default theme +

+ Become a supporter and get early access to Workspaces for UI-UX. +

+
+ + +
+
+

+ Advanced Theme Style configurator [planned] +

+
+

+ A sophisticated theme editor allowing you to personalize icons, fonts, and range sliders. + Tailor the visual experience of the user interface with the Advanced Theme Style configurator. +

+
+
+
+

+ Visual Builder for Gradio Apps [work in progress] +

+
+

+ Introducing a low-code visual editor builder for Gradio Apps. + Create templates and customize Gradio apps without extensive programming knowledge. Drag, drop, design, and deploy - all within a user-friendly interface. + Build anything from simple AI applications to complex enterprise solutions. +

+ Anapnoe Gradio Visual editor +
+
+
+
+
\ No newline at end of file diff --git a/extensions-builtin/anapnoe-sd-uiux/html/templates/template-app-root.html b/extensions-builtin/anapnoe-sd-uiux/html/templates/template-app-root.html new file mode 100644 index 00000000000..d3e2643a9fa --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/templates/template-app-root.html @@ -0,0 +1,323 @@ +
+
+ + + + +
+ + + + + +
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+ + + +
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+ + + + +
+
+
+
+
+
+
+ + + +
+
+ +
\ No newline at end of file diff --git a/extensions-builtin/anapnoe-sd-uiux/html/templates/template-aside-extra-networks.html b/extensions-builtin/anapnoe-sd-uiux/html/templates/template-aside-extra-networks.html new file mode 100644 index 00000000000..2a70aef9efa --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/templates/template-aside-extra-networks.html @@ -0,0 +1,123 @@ +
+
+ + + +
+
+ + + + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + +
+
\ No newline at end of file diff --git a/extensions-builtin/anapnoe-sd-uiux/html/templates/template-extensions.html b/extensions-builtin/anapnoe-sd-uiux/html/templates/template-extensions.html new file mode 100644 index 00000000000..450e894b24f --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/templates/template-extensions.html @@ -0,0 +1,15 @@ +
+
+
+
+
+
+
+
+ +
+
+
+
+
+
\ No newline at end of file diff --git a/extensions-builtin/anapnoe-sd-uiux/html/templates/template-extra-networks.html b/extensions-builtin/anapnoe-sd-uiux/html/templates/template-extra-networks.html new file mode 100644 index 00000000000..7c40249c7b2 --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/templates/template-extra-networks.html @@ -0,0 +1,55 @@ +
+
+ + + + + + + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
\ No newline at end of file diff --git a/extensions-builtin/anapnoe-sd-uiux/html/templates/template-extras-params.html b/extensions-builtin/anapnoe-sd-uiux/html/templates/template-extras-params.html new file mode 100644 index 00000000000..f264df9b855 --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/templates/template-extras-params.html @@ -0,0 +1,97 @@ +
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+ + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
\ No newline at end of file diff --git a/extensions-builtin/anapnoe-sd-uiux/html/templates/template-extras-results.html b/extensions-builtin/anapnoe-sd-uiux/html/templates/template-extras-results.html new file mode 100644 index 00000000000..36a855abbb2 --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/templates/template-extras-results.html @@ -0,0 +1,51 @@ + +
+
+
+
+
+
+
+
+
+ + + + + +
+
+
+
+
+
+
+
+
+
+
+
+ \ No newline at end of file diff --git a/extensions-builtin/anapnoe-sd-uiux/html/templates/template-img2img-params.html b/extensions-builtin/anapnoe-sd-uiux/html/templates/template-img2img-params.html new file mode 100644 index 00000000000..7b56bc4b7f4 --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/templates/template-img2img-params.html @@ -0,0 +1,384 @@ +
+
+
+
+ + + + + + +
+
+ + + + + + +
+
+
+
+
+
+
+
+
+ + +
+
+
+
+
+
+
+
+
+ + +
+
+
+
+ + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+
+
+ +
+
+
+
+ +
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+ Inpaint options + +
+
+
+
+
+
+
+
+ Resize mode + +
+
+
+
+
+
+
+
+
+
+ + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + + +
+
+
+
+
+
+
+
+ + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+
+
+
+
+
+ +
+
+
+ +
\ No newline at end of file diff --git a/extensions-builtin/anapnoe-sd-uiux/html/templates/template-img2img-results.html b/extensions-builtin/anapnoe-sd-uiux/html/templates/template-img2img-results.html new file mode 100644 index 00000000000..ff6041c3e2f --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/templates/template-img2img-results.html @@ -0,0 +1,65 @@ + +
+
+
+
+
+
+
+
+
+ + + + + + + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+ \ No newline at end of file diff --git a/extensions-builtin/anapnoe-sd-uiux/html/templates/template-model-merger.html b/extensions-builtin/anapnoe-sd-uiux/html/templates/template-model-merger.html new file mode 100644 index 00000000000..d70d6058057 --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/templates/template-model-merger.html @@ -0,0 +1,129 @@ + +
+
+ + + +
+
+
+
+ + +
+
+
+ + + +
+
+ + +
+ + + +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+ + + +
+
+ +
+
+ +
+
+
+
+
+ +
+
+
+ +
+
+
+ + +
+
+
+ +
+
+ +
+
+ +
+
+ + + + + + +
+
+
+ + + +
+
+
+ +
diff --git a/extensions-builtin/anapnoe-sd-uiux/html/templates/template-pnginfo.html b/extensions-builtin/anapnoe-sd-uiux/html/templates/template-pnginfo.html new file mode 100644 index 00000000000..f77ab7cb5bc --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/templates/template-pnginfo.html @@ -0,0 +1,47 @@ +
+
+
+
+ + + + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ \ No newline at end of file diff --git a/extensions-builtin/anapnoe-sd-uiux/html/templates/template-quicksettings.html b/extensions-builtin/anapnoe-sd-uiux/html/templates/template-quicksettings.html new file mode 100644 index 00000000000..00b1d172295 --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/templates/template-quicksettings.html @@ -0,0 +1,21 @@ + + + + + + +
+
+
+
+
+
+
+
+
+
+ +
+
+ \ No newline at end of file diff --git a/extensions-builtin/anapnoe-sd-uiux/html/templates/template-settings.html b/extensions-builtin/anapnoe-sd-uiux/html/templates/template-settings.html new file mode 100644 index 00000000000..96e4b351be5 --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/templates/template-settings.html @@ -0,0 +1,35 @@ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+ +
+
\ No newline at end of file diff --git a/extensions-builtin/anapnoe-sd-uiux/html/templates/template-sponsors.html b/extensions-builtin/anapnoe-sd-uiux/html/templates/template-sponsors.html new file mode 100644 index 00000000000..fe35403cf53 --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/templates/template-sponsors.html @@ -0,0 +1,13 @@ +
+
+
+

+ 💎 Sponsors +

+ +

+ 🥇 Supporters +

+
+
+
\ No newline at end of file diff --git a/extensions-builtin/anapnoe-sd-uiux/html/templates/template-theme.html b/extensions-builtin/anapnoe-sd-uiux/html/templates/template-theme.html new file mode 100644 index 00000000000..73acf38a96d --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/templates/template-theme.html @@ -0,0 +1,22 @@ + + + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + + \ No newline at end of file diff --git a/extensions-builtin/anapnoe-sd-uiux/html/templates/template-train-results.html b/extensions-builtin/anapnoe-sd-uiux/html/templates/template-train-results.html new file mode 100644 index 00000000000..aeeb6005f75 --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/templates/template-train-results.html @@ -0,0 +1,17 @@ + +
+
+
+ +
+
+
+
+
+
+
+
+ + +
+ \ No newline at end of file diff --git a/extensions-builtin/anapnoe-sd-uiux/html/templates/template-txt2img-params.html b/extensions-builtin/anapnoe-sd-uiux/html/templates/template-txt2img-params.html new file mode 100644 index 00000000000..68d40ffa3ad --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/templates/template-txt2img-params.html @@ -0,0 +1,302 @@ +
+
+
+
+ + + + + + +
+
+ + + + +
+
+
+
+
+
+
+
+
+
+
+
+ + +
+
+
+
+ + +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+
+
+ +
+
+
+
+ +
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + +
+
+
+ +
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + + +
+
+
+
+
+
+
+
+ + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+
+
+
+
+
+
+ + + +
+
+
+ +
+
\ No newline at end of file diff --git a/extensions-builtin/anapnoe-sd-uiux/html/templates/template-txt2img-results.html b/extensions-builtin/anapnoe-sd-uiux/html/templates/template-txt2img-results.html new file mode 100644 index 00000000000..0a7ae429e42 --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/html/templates/template-txt2img-results.html @@ -0,0 +1,66 @@ + +
+ +
+
+
+
+
+
+
+
+ + + + + + + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+ \ No newline at end of file diff --git a/extensions-builtin/anapnoe-sd-uiux/javascript/anapnoe_sd_uiux_core.js b/extensions-builtin/anapnoe-sd-uiux/javascript/anapnoe_sd_uiux_core.js new file mode 100644 index 00000000000..b6356bcc88b --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/javascript/anapnoe_sd_uiux_core.js @@ -0,0 +1,1302 @@ +//var orig_all_gallery_buttons = window.all_gallery_buttons; +window.all_gallery_buttons = function(){ + //orig_all_gallery_buttons(); + var tabitem = gradioApp().querySelector('#main-nav-bar button.active')?.getAttribute('tabitemid'); + var visibleGalleryButtons = []; + if(tabitem){ + //console.log(tabitem, allGalleryButtons); + var allGalleryButtons = gradioApp().querySelectorAll(tabitem+' .gradio-gallery .thumbnails > .thumbnail-small'); + allGalleryButtons?.forEach(function(elem) { + if (elem.parentElement.offsetParent && elem.parentElement.offsetParent !== document.body) { + visibleGalleryButtons.push(elem); + } + }); + } + return visibleGalleryButtons; +} + +window.extraNetworksSearchButton = function(tabs_id, e) { + var button = e.target; + const attr = e.target.parentElement.parentElement.getAttribute("search-field"); + var searchTextarea = gradioApp().querySelector(attr); + //console.log(button, searchTextarea) + var text = button.classList.contains("search-all") ? "" : button.textContent.trim(); + searchTextarea.value = text; + window.updateInput(searchTextarea); +} + +window.imageMaskResize = function(){ + // override function empty we dont need any fix here +} + +window.extraNetworksEditUserMetadata = function(event, tabname, extraPage, cardName) { + //var id = tabname + '_' + extraPage + '_edit_user_metadata'; + var tid = 'txt2img_' + extraPage + '_edit_user_metadata'; + var editor = extraPageUserMetadataEditors[tid]; + if (!editor) { + editor = {}; + editor.page = gradioApp().getElementById(tid); + editor.nameTextarea = gradioApp().querySelector("#" + tid + "_name" + ' textarea'); + editor.button = gradioApp().querySelector("#" + tid + "_button"); + extraPageUserMetadataEditors[tid] = editor; + } + + editor.nameTextarea.value = cardName; + updateInput(editor.nameTextarea); + + editor.button.click(); + + popup(editor.page); + + //event.stopPropagation(); +} + +async function getContributors(repoName, page = 1) { + let request = await fetch(`https://api.github.com/repos/${repoName}/contributors?per_page=100&page=${page}`, { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + } + }); + + // print data from the fetch on screen + let contributorsList = await request.json(); + return contributorsList; +} + +async function getAllContributorsRecursive(repoName, page = 1, allContributors = []) { + const list = await getContributors(repoName, page); + allContributors = allContributors.concat(list); + + if (list.length === 100) { + return getAllContributorsRecursive(repoName, page + 1, allContributors); + } + + // The base case: when the list is empty, return allContributors + return allContributors; +} + +localStorage.setItem('UiUxReady', "false"); +localStorage.setItem('UiUxComplete', "false"); +const default_ext_path = './file=extensions-builtin/anapnoe-sd-uiux/html/templates/'; +const default_libs_path = './file=extensions-builtin/anapnoe-sd-uiux/html/libs/'; +let total = 0; +let active_main_tab;// = document.querySelector("#tab_txt2img");//null +let loggerUiUx; +const split_instances = []; +const anapnoe_app_id = "#anapnoe_app"; + + +function getRootContainer() { + return document.getElementById('tab_anapnoe_sd_uiux_core'); +} + +function mainTabs(element, tab) { + if(active_main_tab){ + active_main_tab.style.display = 'none'; + } + const ntab = document.querySelector(tab); + if(ntab){ + ntab.style.display = 'block'; + //console.log(tab, ntab); + active_main_tab = ntab; + + } + +} + +function setAttrSelector(parent_elem, content_div, count, index, length) { + + //const t = parent_elem.getAttribute("data-timeout"); + //const delay = t ? parseInt(t) : 0; + + //setTimeout(() => { + + const mcount = count % 2; + //const parent_elem = this.el; + + const s = parent_elem.getAttribute("data-selector"); + const sp = parent_elem.getAttribute("data-parent-selector"); + + + let target_elem; + + switch (mcount) { + case 0: + target_elem = document.querySelector(`${sp} ${s}`); + break; + case 1: + target_elem = content_div.querySelector(`${s}`); + break; + } + + if (target_elem && parent_elem) { + parent_elem.append(target_elem); + total += 1; + console.log("register | Ref", index, sp, s); + const d = parent_elem.getAttribute('droppable'); + + if (d) { + const childs = Array.from(parent_elem.children); + //console.log("droppable", target_elem, parent_elem, childs); + childs.forEach((c) => { + if (c !== target_elem) { + if (target_elem.className.indexOf('gradio-accordion') !== -1) { + target_elem.children[2].append(c); + } else { + target_elem.append(c); + } + } + }); + } + + const hb = parent_elem.getAttribute("show-button"); + if(hb){document.querySelector(hb)?.classList.remove("hidden");} + + } else if (count < 4) { + + const t = parent_elem.getAttribute("data-timeout"); + const delay = t ? parseInt(t) : 500; + + setTimeout(() => { + console.log( count + 1, "retry | ", delay, " | Ref", index, sp, s); + setAttrSelector(parent_elem, content_div, count + 1, index, length); + }, delay); + + } else { + console.log("error | Ref", index, sp, s); + total += 1; + + } + + if(total === length){ + console.log("Runtime components initilized"); + localStorage.setItem('UiUxReady', true); + } + + //}, delay ); + +} + +function testpopup(){ + const content_div = document.querySelector('#popup_tabitem'); + //const meta_id = document.querySelector('.global-popup-inner > div')?.id; + content_div.querySelectorAll(`.portal`).forEach((el, index, array) => { + /* + const childs = Array.from(el.children); + childs.forEach((c) => { + const ac = c.getAttribute("meta-Id"); + if(ac){ + if(ac === meta_id){ + c.style.display = ""; + el.style.display = ""; + + }else{ + c.style.display = "none"; + if(childs.length === 1){ + el.style.display = "none"; + } + } + }else{ + c.setAttribute("meta-id", meta_id); + } + }); + */ + setAttrSelector(el, content_div, 0, index, array.length); + }); + + /* + content_div.querySelectorAll(`.ae-popup .edit-user-metadata-buttons button`).forEach((el) => { + } + */ +} + +function createButtons4Extensions() { + + const other_extensions = document.querySelector(`#other_extensions`); + const other_views = document.querySelector(`#split-left`); + //const other_views = document.querySelector(`#no-split-app`); + document.querySelectorAll(`#tabs > .tabitem`).forEach((c) => { + const cid = c.id; + const nid = cid.split('tab_')[1]; + if( cid !== "tab_txt2img" && + cid !== "tab_img2img" && + cid !== "tab_extras" && + cid !== "tab_pnginfo" && + cid !== "tab_train" && + cid !== "tab_modelmerger" && + cid !== "tab_settings" && + cid !== "tab_extensions" && + cid !== "tab_ui_theme" && + cid !== "tab_anapnoe_dock" && + cid !== "tab_anapnoe_sd_uiux_core") + + { + //tab_openpose_editor + const temp = document.createElement('div'); + temp.innerHTML= ` + `; + const btn = temp.firstElementChild; + other_extensions.append(btn); + //console.log(other_extensions, btn); + + temp.innerHTML= ` +
+
+
+
`; + + const view = temp.firstElementChild; + //console.log(other_views, view); + other_views.append(view); + } + + }); + +} + +function setupExtraNetworksSearchSort(){ + + const applyFilter = function(e) { + const search_term = e.target.value.toLowerCase(); + const cards = e.target.getAttribute("data-target"); + //console.log(search_term, cards ) + gradioApp().querySelectorAll(cards).forEach(function(elem) { + //const text = elem.querySelector(".search_term").textContent;//elem.getAttribute("data-path").toLowerCase().split("\\").join("/"); + const text = elem.querySelector('.name').textContent.toLowerCase() + " " + elem.querySelector('.search_term').textContent.toLowerCase(); + let visible = text.indexOf(search_term) != -1; + if (search_term.length < 3) { + visible = true; + } + elem.style.display = visible ? "" : "none"; + }); + }; + + document.querySelectorAll('.search_extra_networks').forEach((el) => { + el.addEventListener("input", applyFilter); + }) + + function applySort(el, sortKey) { + + function comparator(cardA, cardB) { + var a = cardA.getAttribute(sortKey); + var b = cardB.getAttribute(sortKey); + if (!isNaN(a) && !isNaN(b)) { + return parseInt(a) - parseInt(b); + } + return (a < b ? -1 : (a > b ? 1 : 0)); + } + + const cards_selector = el.getAttribute("data-target"); + const cards = gradioApp().querySelectorAll(cards_selector); + const cards_parent = cards[0].parentElement; + const cardsArray = Array.from(cards); + let sorted = cardsArray.sort(comparator); + + const reverse_button = el.nextElementSibling;//closest(".reverse-order"); + const reverse = reverse_button.className.indexOf("active") !== -1; + if (reverse) { + sorted.reverse(); + } + sorted.forEach(e => cards_parent.appendChild(e)); + + } + + document.querySelectorAll('.extra_networks_order_by').forEach((el) => { + el.addEventListener('change', function(e) { + applySort(e.target, this.value); + //console.log('You selected: ', this.value); + }); + el.nextElementSibling.addEventListener('click', function(e) { + applySort(el, el.value); + console.log('You selected: ', el.value); + }); + }) + +} + +function updateExtraNetworksCards(el){ + + console.log("Starting optimizations for", el.id); + el.querySelectorAll(".card, .card-button").forEach((card) => { + const onclick_data = card.getAttribute("onClick"); + card.setAttribute("data-apply", onclick_data); + card.removeAttribute("onClick"); + if(card.getAttribute("data-name")){ + console.log("Remove EventListener", card.getAttribute("data-name")) + }else{ + const card_closest = card.closest(".card"); + console.log("Remove EventListener", `${card_closest.getAttribute("data-name")} - ${card.getAttribute("title")}`) + } + + }) + + console.log("Attach EventListener", el.id); + el.addEventListener("click", function(e) { + const ctarget = e.target; + if(ctarget && ctarget.className.indexOf("card") !== -1) { + let data_apply = ctarget.getAttribute("data-apply"); + if(!data_apply){ + const onclick_data = ctarget.getAttribute("onClick"); + if(onclick_data){ + ctarget.setAttribute("data-apply", onclick_data); + ctarget.removeAttribute("onClick"); + } + } + + const tabkey = active_main_tab.id.split("tab_")[1]; + if(tabkey === "img2img"){ + data_apply = data_apply?.replace("txt2img", "img2img"); + }else{ + data_apply = data_apply?.replace("img2img", "txt2img"); + } + + ctarget.setAttribute("onClick", data_apply ); + ctarget.click(); + ctarget.removeAttribute("onClick"); + + if(ctarget.className.indexOf("card-button") !== -1){ + data_apply = data_apply?.replace("img2img", "txt2img"); + popup_trigger.click(); + testpopup(); + } + + } + }) + + document.querySelectorAll("#txt2img_styles_edit_button, #img2img_styles_edit_button").forEach((elm) => { + elm.addEventListener("click", function(e) { + popup_trigger.click(); + testpopup(); + }) + }) + + + +} + +function setupAnimationEventListeners(){ + document.addEventListener('animationend', function (e) { + if (e.animationName === 'fade-out') { + e.target.classList.add('hidden'); + } + }); + + document.addEventListener('animationstart', function (e) { + if (e.animationName === 'fade-out') { + if (e.target.className.indexOf('notransition') !== -1) { + e.target.classList.add('hidden'); + } + } + if (e.animationName === 'fade-in') { + e.target.classList.remove('hidden'); + } + }); +} + +function showContributors(){ + const contributors_btn = document.querySelector('#contributors'); + const contributors_view = document.querySelector('#contributors_tabitem'); + const temp = document.createElement('div'); + temp.id = 'contributors_grid'; + temp.innerHTML = `Kindly allow us a moment to retrieve the contributors. + We're grateful for the many individuals who have generously put their time and effort to make this possible.`; + contributors_view.append(temp); + + contributors_btn.addEventListener('click', function(e) { + //console.log(getAllContributors("anapnoe/stable-diffusion-webui-ux")); + if(!contributors_btn.getAttribute("data-visited")){ + contributors_btn.setAttribute("data-visited", "true"); + const promise = getAllContributorsRecursive("anapnoe/stable-diffusion-webui-ux"); + promise.then(function (result) { + //console.log(result) + temp.innerHTML = ""; + for (let i = 0; i < result.length; i++) { + const login = result[i].login; + const html_url = result[i].html_url; + const avatar_url = result[i].avatar_url; + temp.innerHTML += ` + +
+
+ ${login} +
+
`; + } + }) + } + }); +} + +function onUiUxReady(content_div){ + + const interval = setInterval(() => { + const isUiUxReady = localStorage.getItem('UiUxReady'); + if( isUiUxReady === "true"){ + clearInterval(interval); + + const logger_screen = document.querySelector("#logger_screen"); + if(logger_screen){ + const asideconsole = document.querySelector("#layout-console-log"); + asideconsole.append(loggerUiUx); + logger_screen.remove(); + } + + + console.log("Starting optimizations for Extra Networks"); + /* content_div.querySelector("#img2img_textual_inversion_cards_html")?.remove(); + content_div.querySelector("#img2img_checkpoints_cards_html")?.remove(); + content_div.querySelector("#img2img_hypernetworks_cards_html")?.remove(); + content_div.querySelector("#img2img_lora_cards_html")?.remove(); + + console.log("Remove element #img2img_textual_inversion_cards_html"); + console.log("Remove element #img2img_checkpoints_cards_html"); + console.log("Remove element #img2img_hypernetworks_cards_html"); + console.log("Remove element #img2img_lora_cards_html"); */ + + content_div.querySelectorAll(".extra-network-cards").forEach((el) => { + updateExtraNetworksCards(el); + }); + + console.log("Finishing optimizations for Extra Networks"); + + + + setupExtraNetworksSearchSort(); + + const ch_input = document.querySelector ("#setting_sd_model_checkpoint .secondary-wrap input"); + //const hash_target = document.querySelector('#sd_checkpoint_hash'); + //const hash_old_value = hash_target.textContent; + const hash_old_value = ch_input.value; + let oldcard = document.querySelector(`#txt2img_checkpoints_cards .card[data-apply*="${hash_old_value}"]`); + if(oldcard){ + oldcard?.classList.add("selected"); + console.log("Checkpoint name:", oldcard.getAttribute("data-name"), "
"); + } + + const ch_footer_preload = document.querySelector("#txt2img_checkpoints_main_footer .model-preloader"); + const ch_footer_selected = document.querySelector("#txt2img_checkpoints_main_footer .model-selected"); + + const ch_preload = document.querySelector ("#setting_sd_model_checkpoint .wrap"); + ch_footer_preload.append(ch_preload); + + const preload_model_observer = new MutationObserver(function (mutations) { + mutations.forEach(function (m) { + if(oldcard){ + const hash_target = document.querySelector('#sd_checkpoint_hash'); + const hash_value = hash_target.textContent; + const card = document.querySelector(`#txt2img_checkpoints_cards .card[data-apply*="${hash_value}"]`); + if(card){ + if(oldcard !== card){ + oldcard.classList.remove("selected"); + card.classList.add("selected"); + oldcard = card; + ch_footer_selected.textContent = ch_input.value; + console.log("Checkpoint:", ch_input.value) + } + } + } + }); + }); + + preload_model_observer.observe(ch_preload, { childList: true, subtree: false }); + + + setupGenerateObservers(); + + localStorage.setItem('UiUxComplete', true); + + //const main_nav_content = document.querySelector('#main_nav_content'); + //const sidebar_tabs = document.querySelector('#sidebar_tabs'); + //main_nav_content.append(sidebar_tabs); + showContributors() + + // sd max resolution output + function sdMaxOutputResolution(value) { + gradioApp().querySelectorAll('[id$="2img_width"] input,[id$="2img_height"] input').forEach((elem) => { + elem.max = value; + }) + } + gradioApp().querySelector("#setting_uiux_max_resolution_output").addEventListener('input', function (e) { + let intvalue = parseInt(e.target.value); + intvalue = Math.min(Math.max(intvalue, 512), 16384); + sdMaxOutputResolution(intvalue); + }) + sdMaxOutputResolution(window.opts.uiux_max_resolution_output); + + + + + + } + }, 500); + + +} + +function setupGenerateObservers(){ + + const keys = ["#txt2img", "#img2img"]; + keys.forEach((key) => { + + const tib = document.querySelector(key+'_interrupt'); + const tgb = document.querySelector(key+'_generate'); + const ti = tib.closest('.portal'); + const tg = tgb.closest('.ae-button'); + const ts = document.querySelector(key+'_skip').closest('.portal'); + const loop = document.querySelector(key+'_loop'); + + tib.addEventListener("click", function () { + loop.classList.add('stop'); + }); + + const gen_observer = new MutationObserver(function (mutations) { + mutations.forEach(function (m) { + + if (tib.style.display === 'none') { + + if (loop.className.indexOf('stop') !== -1 || loop.className.indexOf('active') === -1) { + loop.classList.remove('stop'); + ti.classList.add('disable'); + ts.classList.add('disable'); + tg.classList.remove('active'); + } else if (loop.className.indexOf('active') !== -1) { + tgb.click(); + } + } else { + ti.classList.remove('disable'); + ts.classList.remove('disable'); + tg.classList.add('active'); + } + }); + }); + + gen_observer.observe(tib, { attributes: true, attributeFilter: ['style'] }); + }); + +} + +function initDefaultComponents(content_div) { + const anapnoe_app = document.querySelector(anapnoe_app_id); + content_div.querySelectorAll(`div.split`).forEach((el) => { + + let id = el.id; + let nid = content_div.querySelector(`#${id}`); + + const dir = nid?.getAttribute('direction') === 'vertical' ? 'vertical' : 'horizontal'; + const gutter = nid?.getAttribute('gutterSize') || '8'; + + const containers = content_div.querySelectorAll(`#${id} > div.split-container`); + const len = containers.length; + const r = 100 / len; + const ids = [], isize = [], msize = []; + + for (let j = 0; j < len; j++) { + const c = containers[j]; + ids.push(`#${c.id}`); + const ji = c.getAttribute('data-initSize'); + const jm = c.getAttribute('data-minSize'); + isize.push(ji ? parseInt(ji) : r); + msize.push(jm ? parseInt(jm) : Infinity); + } + + console.log("Split component", ids, isize, msize, dir, gutter); + + split_instances[id] = Split(ids, { + sizes: isize, + minSize: msize, + direction: dir, + gutterSize: parseInt(gutter), + snapOffset: 0, + dragInterval: 1, + //expandToMin: true, + elementStyle: function (dimension, size, gutterSize) { + //console.log(dimension, size, gutterSize); + return { + 'flex-basis': 'calc(' + size + '% - ' + gutterSize + 'px)', + } + }, + gutterStyle: function (dimension, gutterSize) { + return { + 'flex-basis': gutterSize + 'px', + 'min-width': gutterSize + 'px', + 'min-height': gutterSize + 'px', + } + }, + }); + + }); + + //console.log(split_instances) + + content_div.querySelectorAll(`.portal`).forEach((el, index, array) => { + setAttrSelector(el, content_div, 0, index, array.length); + }); + + content_div.querySelectorAll(`.accordion-bar`).forEach((c) => { + const acc = c.parentElement; + const acc_split = acc.closest('.split-container'); + + let ctrg = c; + const atg = acc.getAttribute('iconTrigger'); + if (atg) { + const icn = content_div.querySelector(atg); + if (icn) { + ctrg = icn; + c.classList.add('pointer-events-none'); + } + } + + if (acc.className.indexOf('accordion-vertical') !== -1 && acc_split.className.indexOf('split') !== -1) { + + acc.classList.add('expand'); + //const acc_gutter = acc_split.previousElementSibling; + const acc_split_id = acc_split.parentElement.id; + const split_instance = split_instances[acc_split_id]; + acc_split.setAttribute('data-sizes', JSON.stringify(split_instance.getSizes())); + + ctrg?.addEventListener("click", () => { + acc.classList.toggle('expand'); + //acc_gutter.classList.toggle('pointer-events-none'); + if (acc_split.className.indexOf('v-expand') !== -1) { + acc_split.classList.remove('v-expand'); + split_instance.setSizes(JSON.parse(acc_split.getAttribute('data-sizes'))) + } else { + acc_split.classList.add('v-expand'); + let sizes = split_instance.getSizes(); + acc_split.setAttribute('data-sizes', JSON.stringify(sizes)); + + //console.log(sizes) + sizes[sizes.length-1] = 0; + sizes[sizes.length-2] = 100; + + const padding = parseFloat(window.getComputedStyle(c, null).getPropertyValue('padding-left')) * 2; + acc_split.style.minWidth = c.offsetWidth+padding+"px"; + + split_instance.setSizes(sizes) + } + }); + + } else { + ctrg?.addEventListener("click", () => { acc.classList.toggle('expand') }); + } + }); + + + function callToAction(el, tids, pid) { + + const acc_bar = el.closest(".accordion-bar"); + if (acc_bar) { + const acc = acc_bar.parentElement; + if (acc.className.indexOf('expand') === -1) { + let ctrg = acc_bar; + const atg = acc.getAttribute('iconTrigger'); + if (atg) { + const icn = content_div.querySelector(atg); + if (icn) { + ctrg = icn; + } + } + ctrg.click(); + } + } + + const txt = el.querySelector('span')?.innerHTML.toLowerCase(); + //console.log(txt, pid) + if (txt && pid) { + document.querySelectorAll(`${pid} .tab-nav button, [data-parent-selector="${pid}"] .tab-nav button`).forEach(function (elm) { + /* console.log(elm.innerHTML, txt) */ + if (elm.innerHTML.toLowerCase().indexOf(txt) !== -1) { + elm.click(); + } + }); + } + + + } + + content_div.querySelectorAll(`.xtabs-tab`).forEach((el) => { + + el.addEventListener('click', () => { + const tabParent = el.parentElement; + const tgroup = el.getAttribute("tabGroup"); + const pid = el.getAttribute("data-click"); + + function hideActive(tab) { + tab.classList.remove('active'); + const tids = tab.getAttribute("tabItemId"); + anapnoe_app.querySelectorAll(tids).forEach((tabItem) => { + //tabItem.classList.add('hidden'); + tabItem.classList.remove('fade-in'); + tabItem.classList.add('fade-out'); + }); + } + + if (tgroup) { + anapnoe_app.querySelectorAll(`[tabGroup="${tgroup}"]`) + .forEach((tab) => { + if (tab.className.indexOf('active') !== -1) { + hideActive(tab); + } + }); + + } else if (tabParent) { + const tabs = [].slice.call(tabParent.children); + tabs.forEach((tab) => { + if (tab.className.indexOf('active') !== -1) { + hideActive(tab); + } + }); + } + + const tids = el.getAttribute("tabItemId"); + anapnoe_app.querySelectorAll(tids).forEach((tabItem) => { + //tabItem.classList.remove('hidden'); + tabItem.classList.remove('fade-out'); + tabItem.classList.add('fade-in'); + //console.log('tab', tids, tabItem); + const mobile_attr = tabItem.getAttribute("mobile"); + if(mobile_attr){ + const mobile_target = anapnoe_app.querySelector(mobile_attr); + if(mobile_target){ + tabItem.append(mobile_target); + } + } + + }); + + el.classList.add('active'); + callToAction(el, tids, pid); + + + + + }); + + const active = el.getAttribute("active"); + if (!active) { + const tids = el.getAttribute("tabItemId"); + anapnoe_app.querySelectorAll(tids).forEach((tabItem) => { + //tabItem.classList.add('hidden'); + tabItem.classList.remove('fade-in'); + tabItem.classList.add('fade-out'); + }); + } + + }); + + content_div.querySelectorAll(`.xtabs-tab[active]`).forEach((el) => { + el.classList.add('active'); + const tids = el.getAttribute("tabItemId"); + const pid = el.getAttribute("data-click"); + anapnoe_app.querySelectorAll(tids).forEach((tabItem) => { + //tabItem.classList.remove('hidden'); + tabItem.classList.remove('fade-out'); + tabItem.classList.add('fade-in'); + }); + callToAction(el, tids, pid); + //console.log('tab', tids, el); + }); + + content_div.querySelectorAll(`.ae-button`).forEach((el) => { + const toggle = el.getAttribute("toggle"); + const active = el.getAttribute("active"); + const input = el.querySelector('input'); + + if (input) { + if (input.checked === true && !active) { + input.click(); + } else if (input.checked === false && active) { + input.click(); + } + } + + if (active) { + el.classList.add('active'); + } else { + el.classList.remove('active'); + } + + + if (toggle) { + el.addEventListener('click', (e) => { + const input = el.querySelector('input'); + if (input) { + input.click(); + if (input.checked === true) { + el.classList.add('active'); + } else if (input.checked === false) { + el.classList.remove('active'); + } + } else { + el.classList.toggle('active'); + } + }); + } + + const adc = el.getAttribute("data-click"); + if(adc){ + el.addEventListener('click', (e) => { + + if(el.className.indexOf("refresh-extra-networks") !== -1){ + const ctemp = el.closest(".template"); + const ckey = ctemp?.getAttribute("key") || "txt2img"; + //console.log(ckey); + setTimeout(() => { + const tempnet = document.querySelector(`#txt2img_temp_tabitem #${ckey}_cards`); + if(tempnet){ + ctemp.querySelector(".extra-network-cards")?.remove(); + ctemp.querySelector(".extra-network-subdirs")?.remove(); + ctemp.querySelectorAll(`.portal`).forEach((el, index, array) => { + setAttrSelector(el, ctemp, 0, index, array.length); + }); + updateExtraNetworksCards(ctemp); + } + }, 1000); + + } + + //}else{ + document.querySelectorAll(adc).forEach((el) => { + el.click(); + }) + //} + }) + } + + }); + + // step ticks for performant input range + function uiux_show_input_range_ticks(value, interactive) { + if (value) { + const range_selectors = "input[type='range']"; + //const range_selectors = "[id$='_clone']:is(input[type='range'])"; + gradioApp() + .querySelectorAll(range_selectors) + .forEach(function (elem) { + let spacing = (elem.step / (elem.max - elem.min)) * 100.0; + let tsp = "max(3px, calc(" + spacing + "% - 1px))"; + let fsp = "max(4px, calc(" + spacing + "% + 0px))"; + var style = elem.style; + style.setProperty( + "--ae-slider-bg-overlay", + "repeating-linear-gradient( 90deg, transparent, transparent " + + tsp + + ", var(--ae-input-border-color) " + + tsp + + ", var(--ae-input-border-color) " + + fsp + + " )" + ); + }); + } else if (interactive) { + gradioApp() + .querySelectorAll("input[type='range']") + .forEach(function (elem) { + var style = elem.style; + style.setProperty("--ae-slider-bg-overlay", "transparent"); + }); + } + } + + gradioApp().querySelector("#setting_uiux_show_input_range_ticks input").addEventListener("click", function (e) { + uiux_show_input_range_ticks(e.target.checked, true); + }); + uiux_show_input_range_ticks(window.opts.uiux_show_input_range_ticks); + + + /* function remove_overrides(){ + let checked_overrides = []; + gradioApp().querySelectorAll("#setting_ignore_overrides input").forEach(function (elem, i){ + if(elem.checked){ + checked_overrides[i] = elem.nextElementSibling.innerHTML; + } + }) + //console.log(checked_overrides); + gradioApp().querySelectorAll("[id$='2img_override_settings'] .token").forEach(function (token){ + let token_arr = token.querySelector("span").innerHTML.split(":"); + let token_name = token_arr[0]; + let token_value = token_arr[1]; + token_value = token_value.replaceAll(" ", ""); + + if(token_name.indexOf("Model hash") != -1){ + const info_label = gradioApp().querySelector("[id$='2img_override_settings'] label span"); + info_label.innerHTML = "Override settings MDL: unknown"; + for (let m=0; m"; + break; + } + } + } + if(checked_overrides.indexOf(token_name) != -1){ + token.querySelector(".token-remove").click(); + gradioApp().querySelector("[id$='2img_override_settings']").classList.add("show"); + }else{ + // maybe we add them again, for now we can select and add the removed tokens manually from the drop down + } + }) + } + gradioApp().querySelector("#setting_ignore_overrides").addEventListener('click', function (e) { + setTimeout(function() { remove_overrides(); }, 100); + }) */ + + function uiux_no_slider_layout(value) { + if (value) { + anapnoe_app.classList.add("no-slider-layout"); + } else { + anapnoe_app.classList.remove("no-slider-layout"); + } + } + + gradioApp().querySelector("#setting_uiux_no_slider_layout input").addEventListener("click", function (e) { + uiux_no_slider_layout(e.target.checked, true); + }); + + uiux_no_slider_layout(window.opts.uiux_no_slider_layout); + + + + // try to attach Logger Screen to main before full UIUXReady + const asideconsole = document.querySelector("#layout-console-log"); + asideconsole.append(loggerUiUx); + document.querySelector("#logger_screen")?.remove(); + + +} + +function setupOnLoadResources() { + + const content_div = document.querySelector("#anapnoe_app"); + gradioApp().insertAdjacentElement('afterbegin', content_div); + + active_main_tab = document.querySelector("#tab_txt2img"); + createButtons4Extensions(); + setupAnimationEventListeners(); + + //const tempDiv = document.createElement('div'); + const initSplitLib = function () { + initDefaultComponents(content_div); + onUiUxReady(content_div); + } + + const script = document.createElement('script'); + script.id = 'splitjs-main'; + script.setAttribute("data-scope", "#anapnoe_app"); + script.onload = initSplitLib; + script.src = 'https://unpkg.com/split.js/dist/split.js'; + + content_div.appendChild(script); + +} + +function removeStyleAssets(){ + + //console.log("Starting optimizations for Extra Networks"); + console.log("Starting optimizations"); + document.querySelector("#img2img_textual_inversion_cards_html")?.remove(); + document.querySelector("#img2img_checkpoints_cards_html")?.remove(); + document.querySelector("#img2img_hypernetworks_cards_html")?.remove(); + document.querySelector("#img2img_lora_cards_html")?.remove(); + + console.log("Remove element #img2img_textual_inversion_cards_html"); + console.log("Remove element #img2img_checkpoints_cards_html"); + console.log("Remove element #img2img_hypernetworks_cards_html"); + console.log("Remove element #img2img_lora_cards_html"); + + document.querySelectorAll(` + [rel="stylesheet"][href*="/assets/"], + [rel="stylesheet"][href*="theme.css"], + [rel="stylesheet"][href*="file=style.css"]` + ).forEach((c) => { + c.remove(); + //loggerUiUx.innerHTML = `Remove stylesheets ${c.getAttribute("href")}`; + console.log("Remove stylesheet", c.getAttribute("href")); + + }); + + const styler = document.querySelectorAll('.styler, [class*="svelte"]:not(input)'); + const count = styler.length; + let s = 0; + styler.forEach((c) => { + if(c.style.display !== "none" && c.style.display !== "block"){ + //if(c.className.indexOf('hidden') === -1 && c.className.indexOf('hide') === -1){ + c.removeAttribute("style"); + s++; + //} + } + + [...c.classList].filter(c => { + return c.match(/^svelte.*/) + }).forEach(e => { + c.classList.remove(e) + }); + + }); + //loggerUiUx.innerHTML = `Remove inline styles from DOM selectors:${count} removed:${s}`; + console.log("Remove inline styles from DOM", "Total Selectors:", count, "Removed Selectors:", s); + console.log("Finishing optimizations"); + //console.log("Loading template files"); + templateData(); +} + +function getNestedTemplates(container) { + const nestedData = []; + container.querySelectorAll(`.template:not([status])`).forEach((el, j) => { + //console.log(el, j) + const obj = {}; + const url = el.getAttribute('url'); + if(url){ + obj.url = url; + }else{ + obj.url = default_ext_path; + } + const key = el.getAttribute('key'); + if(key){ + obj.key = key; + } + const template = el.getAttribute('template'); + if(template){ + obj.template = `${template}.html`; + }else{ + obj.template = `${el.id}.html`; + } + obj.id = el.id; + nestedData.push(obj); + }); + + return nestedData; +} + +function loadCurrentTemplate(data, i, callback) { + const curr_data = data[i]; + const xmlHttp = new XMLHttpRequest(); + const next = i < data.length; + let target; + + if(next){ + + if(curr_data?.parent){ + target = curr_data.parent; + }else if(curr_data?.id){ + target = document.querySelector(`#${curr_data.id}`); + } + + if(target){ + + xmlHttp.onreadystatechange = function () { + + if (xmlHttp.readyState == 4 && xmlHttp.status == 200) { + let tempDiv = document.createElement('div'); + if(curr_data.key){ + const filtered = xmlHttp.responseText.replace(/\s*\{\{.*?\}\}\s*/g, curr_data.key); + tempDiv.innerHTML = filtered; + }else{ + tempDiv.innerHTML = xmlHttp.responseText; + } + + const nestedData = getNestedTemplates(tempDiv); + if(nestedData.length > 0){ + data = data.concat(nestedData); + } + + //console.log(data) + target.setAttribute("status", "true"); + target.append(tempDiv.firstElementChild); + + loadCurrentTemplate(data, i+1, callback); + + }else if (xmlHttp.readyState == 4 && xmlHttp.status == 404) { + target.setAttribute("status", "error"); + loadCurrentTemplate(data, i+1, callback) + } + }; + + const url = `${curr_data.url}${curr_data.template}`; + console.log("Loading template", url); + xmlHttp.open("GET", url, true); // true for asynchronous + xmlHttp.send(null); + + } + + }else{ + //console.log("InitScripts") + //loggerUiUx.innerHTML = `Finished`; + console.log("Template files merged successfully"); + console.log("Init runtime components"); + callback(); + //setupOnLoadResources(); + + } + + + +} + +function templateData() { + + const path = default_ext_path; + const data = [ + { + url: path, + template:'template-app-root.html', + parent: getRootContainer() + } + ]; + + loadCurrentTemplate(data, 0, setupOnLoadResources); + +} + + +function setupLogger() { + + const tempDiv = document.createElement('div'); + tempDiv.id = "logger_screen"; + tempDiv.style = ` + position: fixed; + inset: 0; + background-color: black; + z-index: 99999; + display: flex; + flex-direction: column; + overflow:auto; + `; + + loggerUiUx = document.createElement('div'); + loggerUiUx.id = "logger"; + tempDiv.append(loggerUiUx); + document.body.append(tempDiv); + + (function (logger) { + console.old = console.log; + console.log = function () { + var output = "", arg, i; + + output += ` +
${new Date().toLocaleString().replace(',','')}`; + for (i = 0; i < arguments.length; i++) { + arg = arguments[i]; + const argstr = arg.toString().toLowerCase(); + let acolor = ""; + if(argstr.indexOf("remove") !== -1 || argstr.indexOf("error") !== -1){ + acolor += " log-remove" + }else if(argstr.indexOf("loading") !== -1 + || argstr.indexOf("| ref") !== -1 + || argstr.indexOf("initial") !== -1 + || argstr.indexOf("optimiz") !== -1 + || argstr.indexOf("python") !== -1 + || argstr.indexOf("success") !== -1){ + acolor += " log-load"; + }else if(argstr.indexOf("[") !== -1){ + acolor += " log-object"; + } + + if(arg.toString().indexOf(".css") !== -1 || arg.toString().indexOf(".html") !== -1 ){ + acolor += " log-url"; + }else if(arg.toString().indexOf("\n") !== -1 ){ + output += "
" + } + + output += ` + `; + if ( + typeof arg === "object" && + typeof JSON === "object" && + typeof JSON.stringify === "function" + ) { + output += JSON.stringify(arg); + } else { + output += arg; + } + + output += " "; + } + + logger.innerHTML += output + "
"; + console.old.apply(undefined, arguments); + }; + })(document.getElementById("logger")); + + + console.log( + '\n',"╔═╗╔═╦╦═╗╔═╦═╦╦═╦═╗", + '\n',"║╬╚╣║║║╬╚╣╬║║║║╬║╩╣", + '\n',"╚══╩╩═╩══╣╔╩╩═╩═╩═╝", + '\n',"─────────╚╝" + ); + + console.log("Initialize Anapnoe UI/UX runtime engine version 0.0.1"); + console.log(navigator.userAgent); + const versions = gradioApp().querySelector(".versions"); + console.log(versions.innerHTML); + + console.log("Console log enabled: ", window.opts.uiux_enable_console_log); + console.log("Maximum resolution output: ", window.opts.uiux_max_resolution_output); + console.log("Ignore overrides: ", window.opts.uiux_ignore_overrides); + console.log("Show ticks for input range slider: ", window.opts.uiux_show_input_range_ticks); + + + + const isFirefox = navigator.userAgent.toLowerCase().includes('firefox'); + if(isFirefox){ + console.log("Go to the Firefox about:config page, then search and toggle layout. css.has-selector. enabled") + } + + if(!window.opts.uiux_enable_console_log){ + console.log = function() {} + } + + + let link = document.querySelector("link[rel~='icon']"); + if (!link) { + link = document.createElement('link'); + link.rel = 'icon'; + document.head.appendChild(link); + } + link.href = './file=extensions-builtin/anapnoe-sd-uiux/html/favicon.svg'; + + removeStyleAssets(); + +} + + +function observeGradioInit() { + const observer = new MutationObserver(() => { + const block = gradioApp().querySelector("#tab_anapnoe_sd_uiux_core"); + //const t = gradioApp().querySelector("#txt2img_textual_inversion_cards_html .card:last-child"); + //const c = gradioApp().querySelector("#txt2img_checkpoints_cards_html .card:last-child"); + //const h = gradioApp().querySelector("#txt2img_hypernetworks_cards_html > div:first-child"); + //const l = gradioApp().querySelector("#txt2img_lora_cards_html .card:last-child"); + if (block) { + //if (block && t && c && h && l) { + if (window.opts && Object.keys(window.opts).length) { + observer.disconnect(); + setTimeout(() => { + setupLogger(); + }, 1000); + } + + + } + }); + observer.observe(gradioApp(), { childList: true, subtree: true }); +} + + +/* onUiLoaded(function() { + setupLogger(); +}); */ + +document.addEventListener("DOMContentLoaded", () => { + observeGradioInit(); +}); \ No newline at end of file diff --git a/extensions-builtin/anapnoe-sd-uiux/scripts/anapnoe_sd_uiux.py b/extensions-builtin/anapnoe-sd-uiux/scripts/anapnoe_sd_uiux.py new file mode 100644 index 00000000000..f509e1d0e52 --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/scripts/anapnoe_sd_uiux.py @@ -0,0 +1,121 @@ +import os +from pathlib import Path +import gradio as gr +import modules.scripts as scripts +from modules import script_callbacks, shared +from modules.generation_parameters_copypaste import infotext_to_setting_name_mapping + + +shared.options_templates.update(shared.options_section(('uiux_core', "Anapnoe UI-UX"), { + "uiux_enable_console_log": shared.OptionInfo(False, "Enable console log"), + "uiux_max_resolution_output": shared.OptionInfo(2048, "Max resolution output for txt2img and img2img"), + "uiux_show_input_range_ticks": shared.OptionInfo(True, "Show ticks for input range slider"), + "uiux_no_slider_layout": shared.OptionInfo(False, "No input range sliders"), + "uiux_ignore_overrides": shared.OptionInfo([], "Ignore Overrides", gr.CheckboxGroup, lambda: {"choices": [x[0] for x in infotext_to_setting_name_mapping]}), + + })) + + +basedir = scripts.basedir() +html_folder = os.path.join(basedir, "html") + +layouts_folder = os.path.join(basedir, "layouts") +javascript_folder = os.path.join(basedir, "javascript") + +def get_files(folder, file_filter=[], file_list=[], split=False): + file_list = [file_name if not split else os.path.splitext(file_name)[0] for file_name in os.listdir(folder) if os.path.isfile(os.path.join(folder, file_name)) and file_name not in file_filter] + return file_list + +html = """ + + +

My First JavaScript

+ +
+ + +""" + +scripts = """ +async () => { + // set testFn() function on globalThis, so you html onlclick can access it + globalThis.testFn = () => { + document.getElementById('demo').innerHTML = "Hello" + } +} +""" + +# with gr.Blocks() as demo: + # input_mic = gr.HTML(html) + # out_text = gr.Textbox() + # # run script function on load, + # demo.load(None,None,None,_js=scripts) +# static_dir = Path('./static') +# static_dir.mkdir(parents=True, exist_ok=True) + +# def predict(text_input): + # file_name = f"{datetime.utcnow().strftime('%s')}.html" + # file_path = html_folder / file_name + # print(file_path) + # with open(file_path, "w") as f: + # f.write(f""" + # + # + #
+ #

Hello {text_input} From Gradio Iframe

+ #

Filename: {file_name}

+ # + # """) + # iframe = f"""""" + # link = f'{file_name}' + # return link, iframe + + + +def on_ui_tabs(): + + with gr.Blocks(analytics_enabled=False) as anapnoe_sd_uiux_core: + """ with gr.Row(): + with gr.Column(): + with gr.Row(): + layouts_dropdown = gr.Dropdown(label="Layout", elem_id="layout_drop_down", interactive=True, choices=get_files(layouts_folder,[".json"]), type="value") + layout_save_as_filename = gr.Text(label="Save / Save as", elem_id="layout_save_as_name",) + with gr.Row(): + layout_reset_button = gr.Button(elem_id="layout_reset_btn", value="Reset", variant="primary") + layout_save_button = gr.Button(value="Save", elem_id="layout_save_btn", variant="primary") + with gr.Row(elem_id="layout_hidden"): + layout_json = gr.Textbox(label="Json", elem_id="layout_json", show_label=True, lines=7, interactive=False, visible=True) + + def save_layout( layout_json, filename): + with open(os.path.join(layouts_folder, f"{filename}.json"), 'w', encoding="utf-8") as file: + file.write(layout_json) + file.close() + layouts_dropdown.choices=get_files(layouts_folder,[".json"]) + return gr.update(choices=layouts_dropdown.choices, value=f"{filename}.json") + + def open_layout(filename): + with open(os.path.join(layouts_folder, f"{filename}"), 'r') as file: + layout_json=file.read() + no_ext=filename.rsplit('.', 1)[0] + return [layout_json, no_ext] + + + layout_save_button.click( + fn=save_layout, + inputs=[layout_json, layout_save_as_filename], + outputs=layouts_dropdown + ) + + layouts_dropdown.change( + fn=open_layout, + inputs=[layouts_dropdown], + outputs=[layout_json, layout_save_as_filename] + ) """ + + + + return (anapnoe_sd_uiux_core, 'UI-UX Core', 'anapnoe_sd_uiux_core'), + + + +script_callbacks.on_ui_tabs(on_ui_tabs) \ No newline at end of file diff --git a/extensions-builtin/anapnoe-sd-uiux/style.css b/extensions-builtin/anapnoe-sd-uiux/style.css new file mode 100644 index 00000000000..dbb80db0316 --- /dev/null +++ b/extensions-builtin/anapnoe-sd-uiux/style.css @@ -0,0 +1,3268 @@ +* { + box-sizing: border-box; + transition-property: color, opacity, background-color, border-color; + transition-duration: 0.2s; + transition-timing-function: ease-out; +} + +:root { + --ae-primary-color: #1485d8; + --ae-secondary-color: #d81485; + --ae-main-bg-color: rgb(32 32 32); + + --ae-input-height: 35px; + --ae-input-slider-height: 0.6; + --ae-input-icon-height: calc(var(--ae-input-height) - var(--ae-input-border-size) * 2); + --ae-input-padding: 5px; + --ae-input-font-size: 14px; + --ae-input-line-height: 14px; + --ae-label-color: rgba(255, 255, 255, 0.75); + --ae-secondary-label-color: rgba(255, 255, 255, 0.5); + --ae-input-border-size: 2px; + --ae-input-border-radius: 0px; + + --ae-input-text-color: rgba(255, 255, 255, 0.75); + --ae-input-placeholder-color: rgba(255, 255, 255, 0.35); + --ae-input-bg-color: rgba(0, 0, 0, 0.25); + --ae-input-border-color: rgba(0, 0, 0, 0.1); + + --ae-input-hover-text-color: rgba(255, 255, 255, 0.75); + + --ae-panel-bg-color: rgba(64, 64, 64, 0.5); + --ae-panel-border-color: rgba(64, 64, 64, 0.75); + --ae-panel-padding: 5px; + --ae-border-radius: 5px; + --ae-border-size: 2px; + --ae-gap-size-val: 5px; + + --ae-gap-size: max(var(--ae-gap-size-val), var(--ae-border-size)); + --ae-border-size-neg: calc(var(--ae-border-size) * -1); + --ae-border-size-x2: calc((var(--ae-border-size) * 2) + 0px); + + --ae-group-bg-color: rgba(0, 0, 0, 0.25); + --ae-group-padding: 2px; + --ae-group-radius: 7px; + --ae-group-border-size: 2px; + --ae-group-border-color: rgba(0, 0, 0, 0.25); + --ae-group-gap: 6px; + +} + +body { + margin: 0; + color: var(--ae-label-color); + font-size: var(--ae-input-font-size); + /* line-height: 16px; */ + background-color: var(--ae-main-bg-color); + font-family: "IBM Plex Mono", monospace; +} + +.portal, +* .panel { + background-color: var(--ae-panel-bg-color); + padding: var(--ae-panel-padding); + border-radius: var(--ae-border-radius); + outline: var(--ae-border-size) solid var(--ae-panel-border-color); + flex-direction: column; + display: flex; + flex: 1 1 0%; + justify-content: space-between; + height: auto; +} + +* .panel { + flex-direction: inherit; + justify-content: flex-start !important; +} + +* .no-panel .portal { + background-color: transparent;; +} + +.flexbox { + display: flex; + justify-content: flex-start; + align-items: stretch; + flex-wrap: wrap; + padding: 0; + margin: 0; + flex: 1 1 0%; + gap: 5px; + min-width: min(160px, 100%); + flex-grow: 1; +} + +.flexbox.row { + flex-direction: row; +} + +.flexbox.col { + flex-direction: column; + flex-wrap: nowrap; + justify-content: center; +} + +.flexbox.group{ + background-color: var(--ae-group-bg-color); + padding: var(--ae-group-padding);; + border-radius: var(--ae-group-radius) ; + outline: var(--ae-group-border-size) solid var(--ae-group-border-color); + gap: var(--ae-group-gap); +} +.sub-group{ + background-color: transparent !important; + outline: none !important; + padding: 0 !important; +} +.inset{ + padding: 2px !important; + margin: -2px; +} + +.flexbox.group .flexbox:not(.no-border) { + gap: var(--ae-group-gap); +} + +.grow-all div:not(.shrink){ + flex-grow: 1 !important; +} + +.unset-min-width { + flex-grow: 0; + min-width: unset; +} + +.row { + gap: var(--ae-gap-size); + flex-direction: row; +} + +.col { + gap: var(--ae-gap-size); + flex-direction: column; +} + +.no-border { + outline: var(--ae-border-size) solid var(--ae-panel-border-color); + border-radius: var(--ae-border-radius); + background-color: var(--ae-panel-bg-color); + /* gap: 0; */ + min-width: unset; + padding: var(--ae-panel-padding); +} + +.shrink { + min-width: unset; + flex-wrap: nowrap; + white-space: nowrap; + flex-grow: 0; +} + +.no-wrap { + flex-wrap: nowrap; +} + +.fb-60 { + flex-basis: 66%; + min-width: min(220px, 100%); +} + +.fb-40 { + flex-basis: 32.5%; +} + +.min-width { + min-width: min(220px, 100%); +} + +*.gradio-button.tool { + padding: 0; + align-self: flex-end; +} + +.fb-50 { + flex-basis: 49%; +} + +.flexbox.no-border.shrink { + color: black; +} + +.no-border>* { + align-self: flex-end; + background-color: transparent; + outline: none; + flex-basis: 0%; + flex-grow: 1; + padding: 0; +} + +.invisible *.gradio-button.tool { + font-size: 0; + line-height: 0; + background-color: var(--ae-input-bg-color); +} + +.invisible *.gradio-button.tool:hover { + background-color: var(--ae-primary-color); +} + +.invisible *.gradio-button.tool:hover .mask-icon { + background-color: var(--ae-input-hover-text-color); +} + +*.tab-nav button:hover, +*.tab-nav button.selected, +*.gradio-button:hover { + color: var(--ae-input-hover-text-color); +} + +.portal.no-border { + flex-basis: 0%; +} + +.portal.gap { + gap: var(--ae-gap-size); +} + +.portal.gap>* { + gap: var(--ae-gap-size); + display: flex; + flex-direction: column; +} + +.portal.gap>div>* { + gap: var(--ae-gap-size); + display: flex; + flex-direction: row; +} + +.portal.no-min-width { + min-width: unset; + width: 0%; + height: 100%; +} + +* select, +* input, +* textarea, +* button { + background: var(--ae-input-bg-color); + border: var(--ae-input-border-size) solid var(--ae-input-border-color); + border-radius: var(--ae-border-radius); + vertical-align: middle; + line-height: var(--ae-input-line-height); + font-size: var(--ae-input-font-size); + padding: var(--ae-input-padding); + color: var(--ae-input-text-color); + margin: 0; + min-height: var(--ae-input-height); +} + +*.gradio-textbox label { + flex-direction: column; + display: flex; +} + +*.gradio-slider label { + flex-direction: column; + display: flex; +} + +* label>span { + border: var(--ae-input-border-size) solid transparent; + margin-bottom: 5px; + vertical-align: middle; + margin-top: 0; + color: var(--ae-label-color); + font-family: inherit; + line-height: 20px; + font-size: var(--ae-input-font-size); +} + +*.gradio-slider .head { + margin-bottom: 0; + display: grid; + grid-template-columns: auto 70px; +} + +*.gradio-slider input[type="range"] { + height: calc(var(--ae-input-height) * var(--ae-input-slider-height)); + width: 100%; + min-height: calc(var(--ae-input-height) * var(--ae-input-slider-height)); + margin-bottom: calc(var(--ae-input-height) * (1 - var(--ae-input-slider-height)) * 0.5); + margin-top: calc(var(--ae-input-height) * (1 - var(--ae-input-slider-height)) * 0.5); + padding: 0; +} +* .no-slider-layout .gradio-slider input[type="range"] { + display:none; +} +* .no-slider-layout .gradio-slider .head { + flex-direction: column; + display: flex; +} +* .no-slider-layout .gradio-slider input[type="number"] { + line-height: var(--ae-input-line-height); + font-size: var(--ae-input-font-size); + padding: var(--ae-input-padding); + margin: 0; + min-height: var(--ae-input-height); +} +/* * .no-slider-layout .min-width, +* .no-slider-layout .flexbox, +* .no-slider-layout .gradio-slider{ + min-width: unset !important; +} */ + + +*.gradio-dropdown label { + flex-direction: column; + display: flex; + justify-content: space-between; + height: 100%; +} + +* button { + min-width: var(--ae-input-height); + min-height: var(--ae-input-height); +} + +*.gradio-slider input[type="number"] { + line-height: 16px; + /* font-size: 14px; */ + min-height: 22px; + max-height: 22px; + margin-top: 0px; + width: auto; + font-family: inherit; + padding: 0 5px; +} + +*.no-border>*:not(:first-child) { + padding-left: 0; +} + +*.wrap-inner { + display: flex; + position: relative; + flex-wrap: wrap; + align-items: center; + gap: var(--ae-gap-size); +} + +*.gradio-dropdown div.wrap, +* input, +* textarea, +* button { + background: var(--ae-input-bg-color); + border: var(--ae-input-border-size) solid var(--ae-input-border-color); + border-radius: var(--ae-border-radius); + vertical-align: middle; + line-height: var(--ae-input-line-height); + font-size: var(--ae-input-font-size); + padding: var(--ae-input-padding); + color: var(--ae-input-text-color); + margin: 0; + min-height: var(--ae-input-height); +} + +*.shrink { + min-width: unset; + flex-wrap: nowrap; + white-space: nowrap; + flex-grow: 0; +} + +*.hidden { + display: none; +} + +*.gradio-accordion .label-wrap { + min-height: var(--ae-input-height); + align-items: center; + display: flex; + justify-content: space-between; + cursor: pointer; + width: 100%; + margin: 0; + padding: var(--ae-panel-padding) calc(var(--ae-panel-padding) + 4px); + border-radius: var(--ae-border-radius); + outline: var(--ae-border-size) solid var(--ae-panel-border-color); + background-color: var(--ae-input-bg-color); + color: var(--ae-primary-color); + white-space: nowrap; +} + +*.gradio-accordion .label-wrap.open { + margin-bottom: calc(var(--ae-panel-padding) - var(--ae-border-size)); + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; + + /* background-color: var(--ae-panel-bg-color); + outline-color: var(--ae-primary-color); */ +} + +.gradio-accordion:has(> .open) { + /* outline: var(--ae-border-size) solid var(--ae-primary-color) !important; */ + background-color: var(--ae-input-bg-color); + outline: var(--ae-border-size) solid var(--ae-panel-border-color); + border-radius: var(--ae-border-radius); + position:relative; + outline-offset: 0px; +} +.gradio-accordion > div > .gap { + padding: var(--ae-panel-padding); +} + +*.flexbox.align-flex-end { + justify-content: flex-end; +} + +* input[type="checkbox"] { + min-height: var(--ae-input-line-height); +} + +* input[type="radio"] { + min-height: var(--ae-input-line-height); +} + +*.no-bg { + background-color: transparent; + outline: none; +} + +*.gradio-radio label { + display: flex; + align-items: center; + transition: none; + cursor: pointer; + box-shadow: none; + gap: 5px; + flex: 0 1 0%; + background: var(--ae-input-bg-color); + border: var(--ae-input-border-size) solid var(--ae-input-border-color); + border-radius: var(--ae-border-radius); + vertical-align: middle; + line-height: var(--ae-input-line-height); + font-size: var(--ae-input-font-size); + padding: var(--ae-input-padding); + color: var(--ae-input-text-color); + margin: 0; + min-height: var(--ae-input-height); +} + +*.gradio-radio label span { + margin: 0; + white-space: nowrap; + border: 0; +} + +*.gradio-radio .wrap { + gap: 5px; + display: flex; + flex-wrap: wrap; +} + +*.gradio-radio>span { + border: var(--ae-input-border-size) solid transparent; + margin-bottom: 5px; + vertical-align: middle; + margin-top: 0; + color: var(--ae-label-color); + font-family: inherit; + line-height: var(--ae-input-font-size); + font-size: var(--ae-input-font-size); +} + +* textarea::placeholder { + color: var(--ae-input-placeholder-color); + opacity: 1; +} + +*.gradio-gallery .icon { + opacity: 0.5; + height: var(--ae-input-icon-height); + color: var(--ae-input-text-color); +} + +*.gradio-html p { + margin: 0; + font-size: 13px; + line-height: 16px; + color: var(--ae-label-color); +} + +*.gradio-image .image-container { + width: 100%; + height: 100%; +} + +/* *[class*="gradio"] .center { + display: flex; + justify-content: center; + align-items: center; + text-align: center; + cursor: pointer; + width: 100%; + height: 100%; + background: var(--ae-input-bg-color); + border: var(--ae-input-border-size) solid var(--ae-input-border-color); + border-radius: var(--ae-border-radius); + min-height: 25vh; + position: relative; +} */ + +* [data-testid="image"] img { + max-height: 40vh; +} + +*.block { + border: 0 !important; + padding: 0; + margin: 0; + display: flex; + flex-direction: column; + justify-content: space-between; + height: auto; + flex: 1 1 0%; + min-width: min(160px, 100%); +} + +[data-testid="block-label"], +div.float { + position: absolute; + display: inline-flex; + align-items: center; + z-index: 20; + background: var(--ae-input-bg-color); + padding: 3px; + pointer-events: none; + font-weight: normal; + font-size: 10px; + line-height: 10px; + width: fit-content; + border-radius: var(--ae-border-radius); + border-bottom-left-radius: 0; + border-top-right-radius: 0; + border: var(--ae-input-border-size) solid var(--ae-input-border-color); +} + +[data-testid="block-label"] span, +div.float span { + opacity: 0.8; + margin-right: 3px; + width: 11px; + height: 11px; +} +[data-testid="block-label"]{ + position: relative; +} +.gradio-highlightedtext span { + padding: 0; +} + +.gradio-highlightedtext .textfield span { + padding: 2px; + border-radius: 5px; +} + +.gradio-highlightedtext span.textspan span { + color: #000; + border-radius: 5px; + min-width: 16px; + display: inline-block; + text-align: center; +} +.gradio-highlightedtext .textfield{ + display: flex; + gap: 5px; + padding: 5px; + background-color: var(--ae-input-bg-color); + border-radius: var(--ae-border-radius); + margin-top: 5px; + flex-wrap: wrap; +} +[id$="edit_user_metadata"] { + gap: var(--ae-gap-size); + text-align: left; +} +[id$="edit_user_metadata"] .gradio-column.gap{ + flex-grow:1; + justify-content: flex-end; + width: auto; +} +[id$="edit_user_metadata"] .gradio-column.gap:first-child { + flex-grow: 100; +} +[id$="edit_user_metadata"] .extra-network-name{ + font-size: 16px; + flex-grow:0; +} +[id$="edit_user_metadata"] .extra-network-name + .form label, +[id$="edit_user_metadata"] .extra-network-name + .form textarea, +[id$="edit_user_metadata"] .extra-network-name + .form{ + flex-grow:10; +} +[id$="edit_user_metadata"] .extra-network-name ~ .form .gradio-dropdown, +[id$="edit_user_metadata"] .extra-network-name + .form .gradio-textbox { + padding:0; + background-color: transparent; + outline: 0; +} +[id$="edit_user_metadata"] .gradio-column.gap:has(img) { + line-height: 0; +} +[id$="edit_user_metadata"] .scroll-hide{ + overflow-y:auto !important; +} + +* input.svelte-116rqfv { + display: none; +} + +*.wrap.svelte-xwlu1w { + display: flex; + flex-direction: column; + justify-content: center; +} + +* button:hover { + cursor: pointer; + background-color: var(--ae-primary-color); +} +* select:focus, +* input:focus, +* button:focus, +* textarea:focus { + outline: none; + border-color: var(--ae-primary-color); +} + +*.gradio-dropdown input:focus { + outline: var(--ae-input-border-size) solid var(--ae-primary-color); +} + +*.tab-nav button { + border-radius: 0; +} + +*.tab-nav button:first-child { + border-top-left-radius: var(--ae-border-radius); +} + +*.tab-nav button:last-child { + border-top-right-radius: var(--ae-border-radius); +} + +*.tab-item { + background-color: var(--ae-panel-bg-color); + padding: var(--ae-panel-padding); +} + +*.gradio-tabitem { + background-color: var(--ae-input-bg-color); + padding: var(--ae-panel-padding); + border-radius: var(--ae-border-radius); + border-top-left-radius: 0; +} + +button:hover, +button.active, +*.tab-nav button:hover, +*.tab-nav button.selected { + background-color: var(--ae-primary-color); +} + +button.active span, +button:hover span{ + color: var(--ae-input-hover-text-color); +} + +button.active .mask-icon, +button:hover .mask-icon{ + background-color: var(--ae-input-hover-text-color); +} + + + +*.gap { + display: flex; + flex-direction: column; + gap: var(--ae-gap-size); +} + +*.form { + display: inherit; + flex-direction: inherit; + gap: var(--ae-gap-size); + flex: 1 1 0%; + flex-wrap: inherit; +} + +* textarea { + height: auto !important; + overflow-x: hidden; + overflow-y: auto !important; +} + +*.hidden, +*.hide { + display: none !important; +} + +.gradio-column:empty, +.hide-empty:has(.form.hidden), +.hide-empty:has(.gradio-html:first-child:empty) { + display: none; +} + +:not(.portal)>.gradio-row { + display: flex; + flex-direction: row; + flex-wrap: wrap; + gap: var(--ae-gap-size); +} + +:not(.portal)>.gradio-column { + display: flex; + flex-direction: column; + gap: var(--ae-gap-size); + flex-grow: 1; + width: 100%; +} + +:not(.portal)>.gradio-highlightedtext, +:not(.portal)>.gradio-row, +:not(.portal)>.block.gradio-slider, +:not(.portal)>.block.gradio-dropdown, +:not(.portal)>.block.gradio-radio, +:not(.portal)>.block.gradio-checkbox, +:not(.portal)>.block.gradio-textbox { + background-color: var(--ae-panel-bg-color); + padding: var(--ae-panel-padding); + outline: var(--ae-border-size) solid var(--ae-panel-border-color); + border-radius: var(--ae-border-radius); + margin: 0; +} + +:not(.portal)>.gradio-row>.gradio-row>.gradio-column>.block, +:not(.portal)>.gradio-row>.form>.block, +:not(.portal)>.gradio-row .form { + padding: 0; + background-color: transparent; + outline: none; + justify-content: flex-end; +} + +:not(.portal)>.gradio-row .form>.gradio-row { + flex-grow: 1; +} +:not(.portal)>.gradio-audio .wrap, +:not(.portal)>.gradio-video .wrap, +:not(.portal)>.gradio-file .wrap, +:not(.portal)>.gradio-image .wrap { + flex-direction: column; + display: flex; + justify-content: center; + align-items: center; + min-height: 25vh; + width: 100%; + height: 100%; +} + +[data-testid="block-info"] { + display: flex; + flex-direction: column; + text-wrap: wrap; +} + +*.gradio-dropdown { + overflow: visible !important; + pointer-events: none; +} + +*.gradio-dropdown .secondary-wrap input { + border: none !important; + background: none; + min-height: unset; + line-height: calc(var(--ae-input-icon-height) - 10px); + flex-grow: 1; + min-height: calc(var(--ae-input-height) - ( var(--ae-input-border-size) * 2 )); +} + +*.gradio-dropdown .secondary-wrap { + display: flex; + align-items: center; + flex-grow: 1; + gap: var(--ae-gap-size-val); + padding-right: var(--ae-input-height); +} + +*.gradio-dropdown div.wrap { + background: var(--ae-input-bg-color); + padding: 0; + position: relative; + pointer-events: all; +} + +*.gradio-dropdown label>span { + margin-bottom: 5px; +} + +*.gradio-dropdown label>* { + margin-bottom: 0; +} + +* svg.dropdown-arrow { + height: 90%; + position: absolute; + right: 5px; + fill: var(--ae-input-text-color); +} + +* .gradio-dropdown input { + display: flex; + flex: 1 1 100%; + width: 0px; +} + +ul.options { + position: absolute; + z-index: 99999; + margin: 0px !important; + box-shadow: none; + border-radius: var(--ae-border-radius); + background: var(--ae-main-bg-color); + min-width: fit-content; + max-width: 50vh; + max-height: 25vh !important; + overflow: auto; + color: var(--ae-label-color); + list-style: none; + top: var(--ae-input-height) !important; + margin-top: calc(var(--ae-border-size) * -1) !important; + bottom: unset !important; + padding: 0; + width: 100% !important; + outline: var(--ae-border-size) solid var(--ae-input-border-color); + overflow-x: hidden; +} + +li.item { + display: flex; + cursor: pointer; + padding: var(--ae-panel-padding); + justify-content: space-between; + margin: 0; +} + +li.item.active { + background: var(--ae-primary-color); + color: var(--ae-input-hover-text-color); +} + +li.item span { + order: 2; +} + +*.token { + flex-direction: row; + display: flex; + gap: 5px; + line-height: calc(var(--ae-input-height) - (var(--ae-input-border-size) * 2)); + background: var(--ae-panel-bg-color); + outline: var(--ae-input-border-size) solid var(--ae-input-border-color); + border-radius: var(--ae-border-radius); + font-size: var(--ae-input-font-size); + padding: 0 5px; + color: var(--ae-input-text-color); + margin: 0px; + overflow: hidden; +} + +*.token>span { + white-space: nowrap; + text-overflow: ellipsis; + overflow: hidden; +} + +*.token-remove { + display: flex; + flex-direction: column; + align-self: center; + background: var(--ae-input-bg-color); + border-radius: 50%; + padding: 1px; + border: var(--ae-input-border-size) solid var(--ae-input-bg-color); +} + +*.token-remove svg { + fill: var(--ae-input-text-color); +} + +*.gradio-gallery { + justify-content: center; + position: relative; + width: 100%; +} + +*.grid-container { + grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); + display: grid; + gap: var(--ae-gap-size); +} + +*.thumbnails.scroll-hide { + /* display: flex; */ + scroll-behavior: smooth; + overflow: hidden; + align-self: center; + gap: 5px; + height: 100%; + padding: 5px; + flex-grow: 0; + max-height: 60px; +} + +*.thumbnail-small img { + width: 100%; + height: 100%; + object-fit: contain; +} + +*.gradio-gallery .preview { + position: absolute; + z-index: 1; + top: 0; + background-color: var(--ae-main-bg-color); + height: 100%; + display: flex; + flex-direction: column; + width: 100%; + border: var(--ae-border-size) solid var(--ae-input-border-color); +} + +*.gradio-gallery .preview img { + width: 100%; + max-height: 100vh; + object-fit: contain; + background-color: var(--ae-input-bg-color); + border: var(--ae-border-size) solid var(--ae-input-border-color); +} + +*.gradio-gallery .preview>img { + border: 0; +} + +*.grid-wrap { + overflow-y: auto; + position: absolute !important; + z-index: 0; + top: 0; + background-color: var(--ae-main-bg-color); + height: 100%; + display: flex; + flex-direction: column; + width: 100%; +} + +*.thumbnail-lg img { + width: 100%; + height: 100%; + object-fit: contain; + margin-bottom: calc(var(--ae-border-size) * -1); +} + +*.thumbnail-item { + height: auto; + width: 100%; + object-fit: contain; +} + +* button.thumbnail-item.thumbnail-small { + min-width: fit-content; + padding: 0; +} + +* button.thumbnail-item:hover { + background: var(--ae-panel-bg-color); +} + +* button.thumbnail-item.selected { + border: var(--ae-border-size) solid var(--ae-primary-color); +} + +*.gradio-gallery .preview button[aria-label] { + width: var(--ae-input-height); + height: var(--ae-input-height); +} + +*.gradio-gallery .preview .svelte-19sk1im { + right: 0; +} + +*.gradio-gallery .empty { + min-height: 100%; + align-items: center; + display: flex; + justify-content: center; +} + +* .styler { + display: flex; + flex-direction: column; + gap: var(--ae-gap-size); +} + +* .icon-buttons { + position: absolute; + display: flex; + right: 0; + padding: var(--ae-panel-padding); + gap: var(--ae-gap-size); +} + +* .livePreview { + position: absolute; + z-index: 2; + width: 100% !important; + height: 100% !important; + object-fit: contain; + background-color: var(--ae-main-bg-color); +} + +* .livePreview img { + object-fit: contain; + width: 100%; + height: 100%; + position: absolute; +} + +::-webkit-scrollbar { + width: 10px; + height: 10px; +} + +::-webkit-scrollbar-button { + display: none; +} + +::-webkit-scrollbar-thumb, +::-webkit-scrollbar-track { + border-radius: var(--ae-border-radius); + border: var(--ae-input-border-size) solid transparent; + background-clip: content-box; + background-color: var(--ae-input-bg-color); +} + +::-webkit-scrollbar-thumb { + background-color: var(--ae-panel-border-color) +} + +.split { + color: #ddd; + min-height: 50px; + display: flex; + flex-direction: row; + height: 100%; + flex-grow: 1; +} + +.split[direction="vertical"] { + flex-direction: column; + height: 100%; +} + +.split-container { + position: relative; + overflow: auto; +} + +* .gutter.gutter-horizontal { + background: linear-gradient(90deg, + rgba(0, 0, 0, 0) 40%, + var(--ae-panel-bg-color) 45%, + var(--ae-panel-bg-color) 55%, + rgba(0, 0, 0, 0) 60%); +} + +* .gutter.gutter-horizontal:hover { + background: linear-gradient(90deg, + rgba(0, 0, 0, 0) 40%, + var(--ae-primary-color) 45%, + var(--ae-primary-color) 55%, + rgba(0, 0, 0, 0) 60%); + cursor: col-resize; +} + +* .gutter.gutter-vertical { + background: linear-gradient(0deg, + rgba(0, 0, 0, 0) 40%, + var(--ae-panel-bg-color) 45%, + var(--ae-panel-bg-color) 55%, + rgba(0, 0, 0, 0) 60%); +} + +* .gutter.gutter-vertical:hover { + background: linear-gradient(0deg, + rgba(0, 0, 0, 0) 40%, + var(--ae-primary-color) 45%, + var(--ae-primary-color) 55%, + rgba(0, 0, 0, 0) 60%); + cursor: row-resize; +} + +.gutter:has(+ .split-container .accordion-vertical:not(.expand)) { + display: none; +} + +.accordion-title { + font-family: "IBM Plex Mono", monospace; + /* text-shadow: 0px 2px 2px #000000; */ +} + +.accordion { + display: flex; + flex-direction: column; + border-radius: var(--ae-border-radius); + outline: var(--ae-border-size) solid var(--ae-panel-border-color); + background-color: var(--ae-panel-bg-color); +} + +.accordion-container { + display: none; + flex-direction: column; + min-height: 16px; + margin-top: var(--ae-border-size); + gap: var(--ae-gap-size); + padding: var(--ae-panel-padding); +} + +.accordion.expand .accordion-container { + display: flex; +} + +.accordion-bar { + display: flex; + align-items: center; + background-color: var(--ae-panel-bg-color); + justify-content: space-between; + cursor: pointer; + border-radius: var(--ae-border-radius); + outline: var(--ae-border-size) solid var(--ae-panel-border-color); + line-height: var(--ae-input-line-height); + font-size: var(--ae-input-font-size); + padding: var(--ae-panel-padding) calc(var(--ae-panel-padding) + 4px); + color: var(--ae-input-text-color); + margin: 0px; + min-height: var(--ae-input-height); + gap: var(--ae-gap-size); +} + +.accordion-bar .portal { + padding: 0; +} + +.accordion-bar .flexbox { + gap: var(--ae-gap-size); + align-items: center; +} + +.accordion.expand .accordion-bar { + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; +} + +.accordion-icon { + transform: rotate(90deg); +} + +.accordion.expand .accordion-icon { + transform: rotate(0deg); +} + +.accordion-vertical.expand .accordion-icon { + transform: rotate(-90deg); +} + +.accordion-vertical { + margin: calc(var(--ae-panel-padding) * 1); + height: calc(100% - var(--ae-panel-padding) * 2); + position: relative; + flex-direction: row; +} + +.accordion-vertical .accordion-bar { + border-radius: var(--ae-border-radius) !important; + flex-direction: column-reverse; + min-height: 100%; + border-top-right-radius: 0 !important; + border-bottom-right-radius: 0 !important; + flex-grow: 0; + padding: var(--ae-panel-padding); + padding-left: var(--ae-panel-padding); +} + +.accordion-vertical .accordion-container { + margin: 0; + overflow-x: hidden; + position: relative; + height: 100%; + flex-direction: row; + min-height: 100%; + overflow-y: auto; + flex-grow: 1; + margin-left: var(--ae-border-size); +} + +.accordion-vertical .accordion-title { + transform: rotate(-90deg) translateX(50%); + white-space: nowrap; + width: 0; +} + +/* .accordion-bar .xtabs-tab { + justify-content: flex-start; +} */ + +.split-container.v-expand { + flex-basis: 0% !important; + min-width: fit-content; +} + +.split-container.v-expand .accordion-vertical .accordion-bar { + border-radius: var(--ae-border-radius) !important; +} + +.portal.auto-scroll { + flex: 2 2 auto; + overflow-x: hidden; + overflow-y: auto; + min-height: 0px; +} + +.layout { + display: flex; + flex-direction: column; + position: absolute; + inset:0; + padding: var(--ae-panel-padding); + gap: var(--ae-gap-size); +} + +.layout-header { + flex-direction: column; + gap: var(--ae-gap-size); + display: flex; + padding: 0; +} + +.layout-footer { + flex-direction: column; + gap: var(--ae-gap-size); + display: flex; + padding: 0; +} + +.layout-content { + flex-direction: column; + gap: var(--ae-gap-size); + flex-grow: 1; + display: flex; + min-height: 16px; + overflow: auto; + padding: var(--ae-border-size); + margin: calc(var(--ae-border-size) * -1); +} + +.mask-icon { + display: inline-block; + background: var(--ae-input-text-color); + border: var(--ae-input-border-size) solid var(--ae-input-border-color); + border-radius: var(--ae-border-radius); + line-height: var(--ae-input-line-height); + font-size: var(--ae-input-font-size); + padding: var(--ae-input-padding); + color: var(--ae-input-text-color); + margin: 0; + height: calc(var(--ae-input-height) - var(--ae-input-border-size) * 2); + width: calc(var(--ae-input-height) - var(--ae-input-border-size) * 2); + cursor: pointer; + -webkit-mask-size: contain; + -webkit-mask-repeat: no-repeat; + -webkit-mask-position: center center; + max-width: 24px; + max-height: 24px; + border: 0; +} + +/* .mask-icon:hover { + background-color: var(--ae-primary-color); +} */ + +*.invisible { + position: relative; + display: flex; + flex-direction: row; + align-items: center; + justify-content: center; + background-color: transparent; + outline: none; +} + +*.invisible .tool { + background: transparent; +} + +*.invisible label { + display: none; +} + +*.invisible:has(.gradio-checkbox) { + pointer-events: none; +} + +.invisible *.gradio-button { + min-width: var(--ae-input-height); + min-height: var(--ae-input-height); + font-size: 0; + line-height: 0; +} + +/* button .mask-icon:hover { + background-color: var(--ae-input-hover-text-color); +} */ + +.icons-bar { + padding-top: 0; + padding-bottom: 0; + justify-content: center; +} + +.accordion-vertical .icons-bar { + padding-left: 0; + padding-right: 0; + padding-top: var(--ae-panel-padding); + padding-bottom: var(--ae-panel-padding); +} + +.icons-bar .flexbox>.mask-icon { + min-width: calc(var(--ae-input-height) + var(--ae-input-border-size) * 2); +} + +/* .icons-bar .mask-icon:hover { + background-color: var(--ae-input-hover-text-color); +} */ + +.xtabs { + position: relative; + display: flex; + flex-direction: column; + border-radius: var(--ae-border-radius); + outline: var(--ae-border-size) solid var(--ae-panel-border-color); + background-color: var(--ae-panel-bg-color); +} + +.xtabs-item { + flex-direction: column; + min-height: 16px; + gap: var(--ae-gap-size); + padding: var(--ae-panel-padding); +} + +.xtabs-item.active { + display: flex; +} + +.xtabs-tab.active { + background-color: var(--ae-primary-color); +} + +.xtabs-tabs { + display: flex; + flex-wrap: wrap; +} + +.xtabs-tab { + display: flex; + gap: 5px; + align-items: center; + background: var(--ae-input-bg-color); + border: var(--ae-input-border-size) solid var(--ae-input-border-color); + border-radius: var(--ae-border-radius); + line-height: var(--ae-input-line-height); + font-size: var(--ae-input-font-size); + padding: var(--ae-input-padding); + color: var(--ae-input-text-color); + margin: 0; + min-height: var(--ae-input-height); + min-width: var(--ae-input-height); + cursor: pointer; + justify-content: center; +} + +.xtabs-tab:hover { + background-color: var(--ae-primary-color); + color: var(--ae-input-text-color); +} + +/* .xtabs-tab:hover .mask-icon { + background-color: var(--ae-input-hover-text-color); +} */ + +/* .active .mask-icon { + background-color: var(--ae-input-hover-text-color); +} */ + +.accordion-bar .xtabs-tab { + width: 100%; +} + +* [data-testid="image"] img { + object-fit: contain; + width: 100%; + height: 100%; +} + +* [data-testid="image"] .wrap { + display: flex; + flex-direction: column; +} + +.gr-group { + width: 100%; + position: relative; +} + +.border-padding { + padding: var(--ae-panel-padding); +} + +.full-height>textarea, +.full-height { + height: 100% !important; + resize: none; +} + +h1 { + line-height: 1em; + margin: 0; +} + +.no-padding-one, +.no-padding { + padding: 0; +} + +.no-padding>* { + padding: 0; +} + +*.extra-network-cards { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); + gap: var(--ae-gap-size); + /* content-visibility: auto; */ +} + +*.extra-network-cards .card { + display: block; +} + +*.extra-network-cards .card img { + object-fit: cover; + width: 100%; + height: auto; + aspect-ratio: 3/4; + border-radius: var(--ae-border-radius); + transform: scale(1.1); + pointer-events: none; +} + +*.extra-network-cards .card:hover .button-row { + display: flex; +} + +*.extra-network-cards .card:hover { + cursor: pointer; +} + +*.extra-network-cards .card .button-row { + position: absolute; + display: none; + z-index: 1; + top: 0px; + right: 0; + background-color: var(--ae-input-bg-color); + padding: 2px; +} + +*.extra-network-cards .card .card-button:hover { + background-color: var(--ae-primary-color); +} + +*.extra-network-cards .card .card-button { + background-color: var(--ae-label-color); + width: 24px; + height: 24px; +} + +*.extra-network-cards .card { + position: relative; + overflow: hidden; + background-color: var(--ae-input-bg-color); + border-radius: var(--ae-border-radius); + border: var(--ae-border-size) solid var(--ae-input-bg-color); + aspect-ratio: 3/4; +} + +*.actions { + position: absolute; + bottom: 0; + padding: 10px; + background-color: var(--ae-main-bg-color); + font-size: 16px; + font-weight: 600; + left: 0; + right: 0; + display: flex; + flex-direction: column; + gap: 5px; + max-height: 100%; +} + +span.name { + overflow-wrap: anywhere; + /* text-shadow: 0 0px 3px #000; */ + text-transform: uppercase; + display: block; + color: var(--ae-label-color); + text-align: center; +} + +span.description { + font-size: 11px; + line-height: 14px; + display: block; + max-height: 80px; + overflow: hidden; + opacity: 0.6; +} + + + +*.metadata-button { + -webkit-mask-image: url(./html/svg/file-info-fill.svg); +} + +*.edit-button.card-button { + -webkit-mask-image: url(./html/svg/file-edit-fill.svg); +} + +div#flexbox-10 { + justify-content: center; +} + +div#flexbox-10>* { + flex-grow: 0; +} + +div#iobp { + position: relative; + height: 90vh; +} + +[id$="2img_neg_prompt"] textarea, +[id$="2img_prompt"] textarea { + position: absolute; + inset: 0; + resize: none; + font-size: 16px; + line-height: 24px; + width: 100%; + min-height: 100%; +} + +div#layout-3 { + position: relative; + height: 90vh; +} + + +.icon-folder { + -webkit-mask-image: url(./html/svg/folder-open-line.svg); +} + +.icon-save { + -webkit-mask-image: url(./html/svg/save-2-line.svg); +} + +.icon-zip { + -webkit-mask-image: url(./html/svg/file-zip-line.svg); +} + +.icon-2txt2img { + -webkit-mask-image: url(./html/svg/t-box-line.svg); +} + +.icon-2inpaint { + -webkit-mask-image: url(./html/svg/paint-brush-line.svg); +} +.gradio-button:has( [class*="icon-2"])::before, +.gradio-button:has( [class*="icon-2"])::after{ + content: ""; + width: 11px; + height: 11px; + position: absolute; +} + +.gradio-button:has( [class*="icon-2"])::after { + right: 0px; + top: 0px; + background-color: var(--ae-input-hover-text-color); + -webkit-mask-image: url(./html/svg/arrow-up-line.svg); + z-index: 2; +} +.gradio-button:has( [class*="icon-2"])::before { + right: -1px; + top: -1px; + background-color: var(--ae-primary-color); + padding: 1px; + border-radius: 50%; + z-index: 1; +} + +.icon-2extras { + transform: scaleX(-1); + -webkit-mask-image: url(./html/svg/picture-in-picture-exit-line.svg); +} + +.icon-2img2img { + -webkit-mask-image: url(./html/svg/image-line.svg); +} + +.refresh { + -webkit-mask-image: url(./html/svg/loop-right-line.svg); +} + +.icon-info { + -webkit-mask-image: url(./html/svg/information-line.svg); +} + +.icon-crop { + -webkit-mask-image: url(./html/svg/crop-line.svg); +} + +.icon-res-switch { + -webkit-mask-image: url(./html/svg/arrow-up-down-line.svg); +} + +.icon-scripts { + -webkit-mask-image: url(./html/svg/plug-line.svg); +} + +.icon-generate { + -webkit-mask-image: url(./html/svg/ai-generate.svg); +} + +.icon-skip { + -webkit-mask-image: url(./html/svg/skip-forward-line.svg); +} + +.icon-stop { + -webkit-mask-image: url(./html/svg/stop-circle-line.svg); +} + +.icon-loop { + -webkit-mask-image: url(./html/svg/infinity-fill.svg); +} + +.icon-node-tree { + -webkit-mask-image: url(./html/svg/node-tree.svg); +} + +.icon-magic { + -webkit-mask-image: url(./html/svg/magic-line.svg); +} + +.icon-delete { + -webkit-mask-image: url(./html/svg/delete-bin-2-line.svg); +} + +.icon-styles-edit { + -webkit-mask-image: url(./html/svg/draft-line.svg); +} + +.icon-styles-apply { + -webkit-mask-image: url(./html/svg/bill-line.svg); +} + +.icon-dice { + -webkit-mask-image: url(./html/svg/dice-1.svg); +} + +.icon-recycle { + -webkit-mask-image: url(./html/svg/recycle-line.svg); +} + +.icon-equalize { + -webkit-mask-image: url(./html/svg/equalizer-line.svg); +} + +.icon-bug { + -webkit-mask-image: url(./html/svg/bug-2-line.svg); +} + +.icon-prompt { + -webkit-mask-image: url(./html/svg/edit-box-line.svg); +} + +.icon-arrow-down { + -webkit-mask-image: url(./html/svg/arrow-down-s-line.svg); +} +.icon-arrow-up { + -webkit-mask-image: url(./html/svg/arrow-up-s-line.svg); +} + + +.icon-checkpoints { + -webkit-mask-image: url(./html/svg/sparkling-line.svg); +} + +.icon-textual-inversion { + -webkit-mask-image: url(./html/svg/focus-line.svg); +} + +.icon-hypernetworks { + -webkit-mask-image: url(./html/svg/focus-2-line.svg); +} + +.icon-lora { + -webkit-mask-image: url(./html/svg/focus-2-fill.svg); +} + +.icon-quicksettings { + -webkit-mask-image: url(./html/svg/list-settings-line.svg); +} + +.icon-pnginfo { + -webkit-mask-image: url(./html/svg/image-add-line.svg); +} + +.icon-extensions { + -webkit-mask-image: url(./html/svg/box-3-line.svg); +} + +.icon-theme { + -webkit-mask-image: url(./html/svg/contrast-drop-2-line.svg); +} + +.icon-settings { + -webkit-mask-image: url(./html/svg/settings-3-line.svg); +} + +.icon-app-logo { + -webkit-mask-image: url(./html/SDNext_Logo.svg); +} + +.icon-txt2img { + -webkit-mask-image: url(./html/svg/t-box-line.svg); +} + +.icon-img2img { + -webkit-mask-image: url(./html/svg/image-line.svg); +} + +.icon-extras { + transform: scaleX(-1); + -webkit-mask-image: url(./html/svg/picture-in-picture-exit-line.svg); +} + +.icon-model-merger { + transform: rotate(90deg); + -webkit-mask-image: url(./html/svg/organization-chart.svg); +} + +.icon-train { + -webkit-mask-image: url(./html/svg/robot-2-line.svg); +} + +.icon-image-edit { + -webkit-mask-image: url(./html/svg/image-edit-line.svg); +} +.icon-ruler { + -webkit-mask-image: url(./html/svg/ruler-2-line.svg); +} + +.question-answer { + -webkit-mask-image: url(./html/svg/question-answer-line.svg); +} + +.icon-install { + -webkit-mask-image: url(./html/svg/install-line.svg); +} + +.star_count:before +{ + content:""; + -webkit-mask-image: url(./html/svg/star-line.svg); + width: 16px; + height: 16px; + background-color: var(--ae-primary-color); + display: flex; + +} + +.icon-rocket { + -webkit-mask-image: url(./html/svg/rocket-fill.svg); +} +.icon-github { + -webkit-mask-image: url(./html/svg/github-fill.svg); +} +.icon-reload { + -webkit-mask-image: url(./html/svg/restart-fill.svg); +} +.icon-gradio { + -webkit-mask-image: url(./html/svg/gradio-fill.svg); +} + +.icon-sort { + -webkit-mask-image: url(./html/svg/sort-asc.svg); +} +button.active .icon-sort { + -webkit-mask-image: url(./html/svg/sort-desc.svg); +} + +.icon-cancel { + -webkit-mask-image: url(./html/svg/close-line.svg); +} +.icon-terminal { + -webkit-mask-image: url(./html/svg/terminal-box-line.svg); +} + +.icon-dock { + -webkit-mask-image: url(./html/svg/layout-2-line.svg); +} + +.icon-trophy { + -webkit-mask-image: url(./html/svg/trophy-line.svg); +} + +.icon-vip { + -webkit-mask-image: url(./html/svg/vip-diamond-line.svg); +} + +.icon-contributors{ + -webkit-mask-image: url(./html/svg/team-line.svg); +} + +#contributors_grid { + gap: 5px; + align-items: flex-start; + display: grid; + grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); + white-space: nowrap; + overflow: auto; + margin: var(--ae-panel-padding); + padding-right: var(--ae-panel-padding); +} +#contributors_grid a { + align-items: center; + padding: 10px; +} +#contributors_grid figure { + margin: 0; +} +#contributors_grid img { + width: 60px; + border-radius: 50%; +} + +#flexbox-9 { + justify-content: flex-end; +} + +#flexbox-8 { + min-width: 0px; + justify-content: flex-end; +} + +#split-2 { + height: 100%; +} + +#portal-49 { + min-height: 100%; +} + +#portal-50 { + min-height: 100%; +} + + + + + + + + +.icons-bar>* { + flex-grow: 0; +} + +.accordion-bar .xtabs-tab span { + display: none; +} + + + +.xtabs-tab svg { + fill: var(--ae-input-text-color); + position: relative; + top: -2px; +} + +/* #main-nav .xtabs-tab { + background-color: transparent; +} + +#main-nav .xtabs-tab.hover, +#main-nav .xtabs-tab.active { + background-color: var(--ae-input-bg-color); +} +*/ + +div#main-nav { + padding: 0px; + margin: calc(var(--ae-panel-padding) * 2); + margin-right: calc(var(--ae-panel-padding) * -1); + margin-left: calc(var(--ae-panel-padding) * 2); + padding: var(--ae-panel-padding); +} +.no-br{ + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; +} +.no-tr{ + border-top-right-radius: 0; + border-top-left-radius: 0; +} + +.no-rr{ + border-top-right-radius: 0 !important; + border-bottom-right-radius: 0 !important; +} +.no-lr{ + border-top-left-radius: 0 !important; + border-bottom-left-radius: 0 !important; +} + + + +.extra-network-subdirs>button, +.settings-tabs button { + text-align: left; + font-size: 98%; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; +} + +.extra-network-subdirs, +.settings-tabs .tab-nav { + gap: 1px; + display: flex; + flex-direction: column; +} + +.split-container[data-initsize="25"] { + min-width: 135px !important; +} + +.gradio-row:empty, +.hide-empty:has(.form.hidden), +.hide-empty:has(.gradio-html:first-child:empty) { + display: none; +} + +* .settings-comment { + margin: 5px 0; + font-size: 10px; + color: rgba(255, 255, 255, 0.4); +} + +* .settings-comment:has(a) { + font-size: 0; +} + +* .settings-comment a { + font-size: 10px; +} + +* a:not(:has(button)) { + color: var(--ae-input-text-color); + background-color: var(--ae-input-bg-color); + border-radius: 3px; + padding: 2px 10px; + text-decoration: none; +} + +* a:not(:has(button)):hover { + color: var(--ae-input-hover-text-color); + background-color: var(--ae-primary-color); +} + +.spacer-v { + max-height: var(--ae-input-border-size); + min-height: var(--ae-input-border-size); + background-color: var(--ae-input-border-color); +} + +* button[aria-label] { + width: var(--ae-input-height); + height: var(--ae-input-height); +} +* button[aria-label="Edit"] { +display:none; +} + + +* .center.boundedheight { + background-color: var(--ae-input-bg-color); +} + +.ae-button { + display: flex; + align-items: center; + justify-content: center; + gap: var(--ae-gap-size); + border-radius: var(--ae-border-radius); + border: var(--ae-input-border-size) solid var(--ae-input-border-color); + background-color: var(--ae-input-bg-color); + /* padding: var(--ae-panel-padding); */ + cursor: pointer; +} + + +/* .ae-button .mask-icon:hover, +.ae-button.active .mask-icon:hover { + background-color: var(--ae-input-hover-text-color); +} */ + +.ae-button.active { + color: var(--ae-input-hover-text-color); + background-color: var(--ae-primary-color); +} + +.ae-button:hover, +.ae-button.active:hover { + color: var(--ae-input-hover-text-color); + background-color: var(--ae-primary-color); +} + +button:hover .icon-letters, +button.active .icon-letters { + color: var(--ae-input-hover-text-color); +} + +button.active svg, +button:hover svg { + fill: var(--ae-input-hover-text-color); +} + +/* .ae-button:hover .mask-icon { + background-color: var(--ae-input-hover-text-color); +} + +.ae-button:hover span{ + color: var(--ae-input-hover-text-color); +} */ + +.portal:has(.gradio-accordion) { + padding: 0; +} + +.icons-bar .portal { + border: 0; + outline: 0; + background: transparent; +} + +.icons-bar .portal button { + padding: 0; + border: 0; + outline: 0; + background: transparent; +} + +.ae-button .gradio-button { + border: 0; + padding: 0; + min-width: unset; + min-height: unset; + align-items: center; + display: flex; +} + +.ae-button .gradio-button span { + padding: 5px; + font-size: var(--ae-input-font-size); +} + +.padding { + padding: var(--ae-panel-padding); +} + +.ae-button .portal { + padding: 0; + outline: 0; + background: transparent; +} + +.ae-button .portal button { + background-color: transparent !important; +} + +.center { + justify-content: center !important; +} + +#portal-16>div>div:first-child { + display: none; +} + +.toggle-seed { + padding: var(--ae-panel-padding) !important; + min-width: var(--ae-input-height); + height: var(--ae-input-height); +} +.gradio-group:has(> .styler:empty), +.portal:has(> .hide), +.gradio-column:has(> .form:empty), +.gradio-row:has(> .form:empty) { + display: none; +} + +.ae-button .gradio-button span { + padding: 5px; + font-size: var(--ae-input-font-size); +} + + + + +*.disable { + opacity: 0.5; + pointer-events: none; +} +*.disable > button { + display: flex !important; +} + +.generate { + overflow: hidden; +} + +.generate.active>.portal::before { + content: ""; + position: absolute; + height: 200px; + width: 200px; + background-image: linear-gradient(90deg, + rgba(0, 0, 0, 0.1) 0%, + rgba(0, 0, 0, 0.1) 50%, + rgba(255, 255, 255, 0) 51%, + rgba(255, 255, 255, 0) 100%); + background-repeat: repeat; + background-size: 20px; + transform: rotate(30deg); + z-index: 1; + -webkit-animation-name: bg-slide; + -webkit-animation-duration: 3s; + -webkit-animation-iteration-count: infinite; + -webkit-animation-timing-function: linear; +} + +.generate.active>.portal>button { + position: relative; + -webkit-filter: drop-shadow(0px 0px 1px var(--ae-primary-color)) drop-shadow(0px 0px 1px var(--ae-primary-color)) drop-shadow(0px 0px 1px var(--ae-primary-color)) drop-shadow(0px 0px 1px var(--ae-primary-color)); + z-index: 1; +} +/* .generate.active > span{ + display:none !important; +} */ + +* #extensions_installed_top { + display: flex !important; +} + +*.notransition { + transition: none !important; + animation: none !important; + /* animation-duration: 0.0s !important; */ + /* animation-fill-mode: none !important; */ +} + + + +*.fade-in, +*.fade-out { + position: absolute; + inset: 0; + justify-content: flex-start !important; + overflow: auto; + z-index: 999; +} + +*.fade-in { + display: flex !important; + animation: fade-in 0.25s; + animation-fill-mode: forwards; +} + +*.notransition.fade-in { + display: flex !important; + position: initial !important; +} +*.notransition.fade-out { + display: none !important; + position: initial !important; +} + +*.fade-in > div:not(.layout-content) { + flex-grow:0; +} + +*.fade-out { + animation: fade-out 0.25s; + animation-fill-mode: forwards; +} + +*.template { + position: absolute; + inset: 0; +} + +.initial { + position: initial; +} + +.app { + min-height: 100vh; + width: 100%; + gap:0; +} +.app_footer { + flex-grow: 0; + margin: 0; + align-items: center; + gap: 0; +} +.app_footer br { + display:none; +} + +.grow { + flex-grow: 1; +} +.flex-start { + justify-content: flex-start; +} + +/* #main-nav .xtabs-tab { + justify-content: flex-start; +} */ + +#main-nav .xtabs-tab span { + display: none; +} + +#split-left>.xtabs-item { + padding: 0; +} + +.auto { + overflow: auto; +} + +.center.flexbox { + justify-content: center; +} +.center > .portal > button { + align-self: center; +} +.ae-button.tool { + width: var(--ae-input-height); + height: var(--ae-input-height); + min-width: var(--ae-input-height); + min-height: var(--ae-input-height); +} + +.xtabs-tab, +.portal>button { + align-items: center; + justify-content: center; +} + +#sp-ac1>.xtabs-item { + padding: 0; +} + +#template-right-sidebar, +#split-right { + min-width: calc(var(--ae-input-height) + var(--ae-border-size) + ((var(--ae-panel-padding) + var(--ae-input-padding)) * 2) + 1px); + +} + +.flex-start { + justify-content: flex-start !important; +} + +.flex-end { + justify-content: flex-end; +} + +#txt2img_header span { + display: none; +} + +.scroll-hide{ + overflow-y: hidden !important; + resize: none; +} + +.no-labels span{ +display:none; +} + + +[id$='2img_script_container'] > div > .form ~ div { + padding: var(--ae-panel-padding); + outline: var(--ae-input-border-size) solid var(--ae-panel-border-color); + background-color: var(--ae-input-bg-color); + border-radius: var(--ae-border-radius); + border: var(--ae-input-border-size) solid var(--ae-input-border-color); +} +.portal .gradio-accordion div:has( [id^='setting_']) { + display: flex; + flex-direction: row; + flex-wrap: wrap; + flex: 1 1 0%; + min-width: min(160px, 100%); +} +.portal .gradio-accordion .gradio-row:has( [id^='setting_']) { + padding:0; + background-color:transparent; + outline:none; +} + +#imageARPreview { + position: absolute; + top: 0; + left: 0; + outline: 2px solid var(--ae-primary-color); + background: radial-gradient(circle, rgba(0, 0, 0, 0.2) 0%, var(--ae-primary-color) 200%); + z-index: 9000; + pointer-events: none; + display: block; + } + + + .tab-nav button { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} +#resize_mode > span, +.accordion:has( #inpaint_controls.hide){ +display:none; +} + +.accordion:has( #resize_mode) .accordion-bar, +.accordion:has( #inpaint_controls) .accordion-bar{ + background-color:var(--ae-input-bg-color); +} +.icon-left button{ + display: flex; + flex-direction: row-reverse; + gap: 5px; +} + +.thumbnails.scroll-hide{ + display: none; +} +.thumbnails.scroll-hide:has(.thumbnail-item:nth-child(2)) { + display: flex ; +} +.gradio-gallery .preview > img { + height:100% !important; +} +.gradio-gallery:has( .thumbnail-item:nth-child(2)) .preview > img { + height: calc(100% - 60px)!important; +} + +.tabulator { + border: 1px solid var(--ae-panel-border-color); + background-color: var(--ae-panel-bg-color); +} +.tabulator .tabulator-header { + border-bottom: 1px solid var(--ae-panel-border-color); + background-color: var(--ae-panel-bg-color); + color: var(--ae-label-color); +} +.tabulator .tabulator-tableholder .tabulator-table { + background-color: var(--ae-panel-bg-color); + color: var(--ae-label-color); +} +.tabulator-row { + background-color: var(--ae-panel-bg-color); +} +.tabulator-row.tabulator-row-even { + background-color: var(--ae-panel-bg-color); +} +.tabulator-row.tabulator-selectable:hover{ + background-color: var(--ae-input-bg-color); +} +.tabulator-row .tabulator-cell { + border-right: 1px solid var(--ae-panel-border-color); +} + +.rgRow { + transition: none!important; +} + +button.gridjs-sort-neutral { + width: 13px !important; + height: 13px !important; + min-width: unset; + min-height: unset; +} +.gridjs-td a{ + display:block; + +} +.gridjs-tbody, td.gridjs-td { + background-color: var(--ae-panel-bg-color); +} +td.gridjs-td { + border: var(--ae-border-size) solid var(--ae-panel-border-color); + padding: var(--ae-panel-padding); + +} +.gridjs-container { + color: var(--ae-label-color); + font-size: 14px; + font-family:inherit; +} +th.gridjs-th { + background-color: var(--ae-input-bg-color);; + border: var(--ae-border-size) solid var(--ae-input-border-color); + color: var(--ae-label-color); + padding: var(--ae-panel-padding); + +} +th.gridjs-th-sort:focus, th.gridjs-th-sort:hover { + background-color: var(--ae-panel-bg-color); +} +td.gridjs-td[data-column-id="description"] { + flex-grow: 1; +} + +.gridjs-tr { + border: none; + display: flex; + flex-direction: column; + gap: 1px; +} +.gridjs-tbody, td.gridjs-td { + background-color: var(--ae-panel-bg-color); + display: grid; + grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); + gap: var(--ae-gap-size); + overflow-wrap: anywhere; +} + + +.additional, +.additional ul{ + display:none !important; +} +.additional, +.additional ul{ + margin: auto; + padding: 0; + gap: 5px; + margin-bottom: 2px; +} +.card:hover .additional, +.card:hover .additional ul{ + display:flex; +} +.additional ul a { + width: 24px; + height: 24px; + font-size: 125% !important; + align-items: center; + display: flex; + justify-content: center; + margin:0 !important; +} +.params{ + min-width:370px; + +} + +#template-settings .split-container:first-child, +.layout-extra-networks .split-container:first-child { + min-width: 135px; +} +#split-right:not(.v-expand){ + min-width:512px; +} +.layout-extra-networks:has( .show-dirs) .gutter, +.layout-extra-networks:has( .show-dirs) .split-container:first-child { + display :none; +} +.layout-extra-networks:has( .show-dirs:not(.active)) .split-container { + flex-basis: 100% !important; +} +.layout-extra-networks:has( .show-dirs.active) .gutter, +.layout-extra-networks:has( .show-dirs.active) .split-container:first-child { + display :flex; +} +.layout-extra-networks{ + gap:2px; + +} +.layout-extra-networks > div:first-child{ + padding-bottom:0 !important; + +} + +/* tab extensions */ +.tabs_extensions table { + width:100%; +} +.tabs_extensions thead{ + display:none; +} + +.tabs_extensions tbody{ + display: grid; + grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); + gap: var(--ae-gap-size); + content-visibility: auto; +} +.tabs_extensions tr{ + flex-direction: column; + display:flex; + padding:var(--ae-panel-padding); + background-color: var(--ae-panel-bg-color); + gap: 5px; + border: var(--ae-border-size) solid var(--ae-panel-border-color); + border-radius: var(--ae-border-radius); + position:relative; +} +.tabs_extensions td { + display: flex; + text-wrap: wrap; + flex-direction: row; + overflow-wrap: anywhere; + flex-wrap: wrap; + gap:5px; +} +.tabs_extensions td:has(p.info) { + flex-direction: column; + flex-grow: 1; + justify-content: space-between; + gap: 10px; +} +.tabs_extensions td p.info:has(span) { + flex-direction: row; + display: flex; + flex-wrap: wrap; + gap: 7px; + flex-grow: 0; + justify-content: space-between; + align-items: flex-end; +} +.tabs_extensions span.date_added { + max-width: 130px; + text-align: justify; + text-align-last: justify; + color: var(--ae-secondary-label-color); + background-color: var(--ae-input-bg-color); + padding: var(--ae-panel-padding); + border-radius: var(--ae-border-radius); + font-size: 11px; +} +span.star_count { + background-color: var(--ae-input-bg-color); + padding: 5px 10px 5px 5px; + display: flex; + flex-direction: row; + justify-content: center; + border-radius: 5px; + font-size: 0; + line-height: 0; + justify-items: end; + gap: 2px; + align-items: center; +} +span.star_count b { + font-size: 12px; +} + +.tabs_extensions td br { + flex-basis: 100%; + content: ""; +} +.tabs_extensions td a { + font-size: 14px; + padding: 5px; + display:block; +} +.tabs_extensions td button { + display: flex; + flex-grow: 1; + justify-content: center; + align-items: center; +} +.tabs_extensions td label:has(input) { + display: flex; + gap: 5px; + font-size: 14px; + border-radius: 5px; + line-height: 23px; + align-items: flex-start; +} + +/* .tabs_extensions .wrap { + display: flex; + flex-direction: column; + position: relative; + z-index: 1; + background-color: black; + padding: 10px; + gap: 5px; +} +*/ +.tabs_extensions tr:has(a[href=""]) { + background-color: var(--ae-input-bg-color); + border-color: var(--ae-input-border-color); +} +.tabs_extensions td:empty, +.tabs_extensions td:has( a:empty){ + display: none !important; +} + +.tabs_extensions td:nth-child(1) a, +.tabs_extensions td:nth-child(2) a { + background-color: transparent; + color: var(--ae-primary-color); + padding: 0; + font-size: 12px; +} +.tabs_extensions td:nth-child(1) a:hover, +.tabs_extensions td:nth-child(2) a:hover { + color: var(--ae-label-color); +} +.tabs_extensions td:nth-child(1) a { + font-size: 14px; +} + +.gradio-image { + height: 100%; + width: 100%; + object-fit: contain; +} +#pnginfo_image [data-testid="image"] img { + max-height: unset; + min-height: 100%; +} +.full-height>textarea { + overflow-y: auto!important; +} + + +.ae-popup{ + /* position: fixed; + width: 100vw; + height: 100vh; + z-index: 9999; + */ + align-items: center; + background-color: var(--ae-input-bg-color); + justify-content: center !important; +} + +.ae-popup-inner{ + /* width:50vw; + height:50vh; */ + width:100%; + height:100%; + background-color: var(--ae-main-bg-color); + position:relative; +} + + .ae-popup .standalone-card-preview img{ + height: 100%; + width: 100%; + object-fit: contain; + max-height: 45vh; + } + .ae-popup .edit-user-metadata-buttons button:first-child{ + display:none; + } + .global-popup-inner{ + flex-grow: 0; + position: relative; + } + .relative-height{ + flex-grow:0; + position:relative + } + + #popup_close{ + position: absolute; + right: calc(var(--ae-panel-padding) * 2); + bottom: calc(var(--ae-panel-padding) * 3); + height: 24px; + padding-right: calc(var(--ae-panel-padding) * 3); + } + + +.wrap .svelte-zyxd38 svg { + display:none !important; +} +.wrap .progress-text{ + background-color:var(--ae-main-bg-color); + color:var(--ae-label-color); + font-size:10px; + display:flex; + flex-grow:0; +} +#popup_trigger{ + display:none; +} + + +@-webkit-keyframes bg-slide { + from { + background-position: 0%; + } + + to { + background-position: -100%; + } +} + +@-webkit-keyframes fade-in { + 0% { + opacity: 0; + /* transform: scale(0.5); */ + } + + 100% { + opacity: 1; + /* transform: scale(1.0); */ + } +} + +.icon-letters{ + justify-content: center; + text-transform: uppercase; + font-size: 14px; + font-weight: 600; + width: 24px; + line-height: 24px; +} + + +.center.boundedheight.flex { + width: 100% !important; + height: auto !important; + /* max-height: 50vh;*/ + } + + + + .image-container img.absolute-img { + /* position: relative !important; */ + position: absolute !important; + } + + .image-container img { + max-height: 50vh !important; + } + + .image-container { + min-height: 25vh !important; + /* height: auto !important; */ + display: flex; + position:relative; + } + .image-container:has(canvas) { + min-height: 50vh !important; + } + + .absolute-img { + position: relative; + opacity: 0; + } + + .block.gradio-image { + /* height: auto !important; */ + } + + div[data-testid="image"] canvas { + width: auto !important; + height: 100% !important; + position: absolute !important; + /* top: 0 !important; + left: 0 !important; */ + border: 0 !important; + } + + + + #tab_img2img div.center.boundedheight.flex { + display: block !important; + } + +* .center.boundedheight > div:has(.brush), +* .center.boundedheight > div:has([aria-label="Clear"]) { + position: absolute; + padding: var(--ae-panel-padding); + top: 0; + right: 0; + z-index: 999; +} + +* .center.boundedheight > div:has(.brush) { + top: 70px; + min-height: unset; + width: auto; + height: auto; + gap: var(--ae-gap-size); +} + + + +[id*="label_copy_to"]{ + /* flex-basis: 100%; */ + font-size: 12px; + flex-grow: 0; + min-width: 65px; + justify-content: center; + line-height: 12px; +} +[id*="_copy_to_"].gradio-row{ + justify-items: center; + background-color: transparent; + padding: 0; + outline: 0; +} +[id*="_copy_to_"].gradio-row button{ +flex-grow:1; +} +.group-row{ + gap: 1px !important; +} +.group-row > * button, +.group-row > *{ + border-radius: 0 !important; +} +.group-row > *:last-child button, +.group-row > *:last-child{ + border-top-right-radius: var(--ae-border-radius) !important; + border-bottom-right-radius: var(--ae-border-radius) !important; +} +.group-row > *:first-child button, +.group-row > *:first-child{ + border-top-left-radius: var(--ae-border-radius) !important; + border-bottom-left-radius: var(--ae-border-radius) !important; +} + +.progress-flex { + position: absolute; + padding: calc(var(--ae-panel-padding) * 1 ); + bottom: 0; + left: 0; + right: 0; + display:none; +} +.progress-flex > div { + position: relative; + z-index: 123; + white-space: nowrap; + padding: 0; + border-radius: 0; +} +.progress-flex:has( .progress) { + display: flex; +} + +.progress{ + background-color:var(--ae-primary-color); + padding:2px; + border-radius: 0; +} + +iframe{ + border:0; +} +.other> div{ + background: transparent; + outline: 0; +} +.other .gradio-column:first-child{ + flex-grow: 1; + padding: 0; + gap: 0; +} +.other iframe:first-child{ + max-height: calc(100vh - var(--ae-panel-padding) * 6); +} + +.ae-button > a:hover, +.ae-button > a{ + padding: 0; + background-color: transparent; + line-height: 0; +} + +div#workspaces_tabitem > div { + padding: 0; +} + +/*infinite-image-browsing*/ +#tab_infinite-image-browsing_tabitem{ + overflow:hidden; + padding: 0; +} + +/*a1111-sd-webui-tagcomplete*/ +ul{ + padding:0; + margin:0; +} +.autocompleteResults { + background-color: var(--ae-main-bg-color)!important; + border: var(--ae-border-size) solid var(--ae-input-border-color)!important; + border-radius: var(--ae-border-radius)!important; +} +.autocompleteResultsList > li:nth-child(odd) { + background-color: var(--ae-panel-bg-color)!important; +} +.autocompleteResultsList > li.selected { + background-color: var(--ae-primary-color)!important; +} + +.log-row { + display: table; + overflow-wrap: anywhere; +} +.log-row a { + padding: 0 5px; +} +.log-date { + color: #cacaca; + display: table-cell; + white-space: nowrap; + padding: 0px 10px; + font-size: 9px; +} +.log-boolean, +.log-undefined {color: magenta;} +.log-object {color: #cfb0ff;} +.log-string {color: #ffca68;} +.log-number {color: cyan;} +.log-info {color: yellow;} + +.log-string.log-remove {color: #ff4f4f;} +.log-string.log-load {color: #74ff80;} +.log-string.log-url {color: #8fc9ff;} +.log-string.log-object {color: #8fc9ff;} + + +.card.selected { + border: var(--ae-border-size) solid var(--ae-primary-color); +} +.card.selected .actions{ + background-color: var(--ae-primary-color); +} +.column-1{ + column-count: 1; + gap:32px; +} +.column-2{ + columns: 320px 2; + gap:32px; +} +.column-3{ + column-count: 3; + gap:32px; +} +.lcol{ + gap:32px; + align-items: flex-start; + display: grid; + /* grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); */ +} + +.lcol > .col{ +min-width: min(480px, 100%); +} +#about_tabitem { + font-size: 14px; + line-height: 20px; + font-family: monospace; + /* text-align: justify; */ +} +#about_tabitem img{ + display:flex; + width: 100%; + height: auto; +} +#about_tabitem a{ + background-color: transparent; + color:var(--ae-primary-color); + padding: 0; +} +#about_tabitem a:hover{ + color: var(--ae-label-color); +} +#about_tabitem p, h1, h2{ + margin:0; + margin-bottom: calc(var(--ae-panel-padding) * 1 ); +} +#about_tabitem p, #about_tabitem ul, #about_tabitem img { + margin-bottom: 24px; +} +#about_tabitem h1, h2{ + /* margin-top: calc(var(--ae-panel-padding) * 3 ); */ + font-size:20px; + color: var(--ae-primary-color); +} +#about_tabitem ul{ + padding-inline-start: calc(var(--ae-panel-padding) * 4 ); +} +#about_tabitem li::marker{ + color: var(--ae-primary-color); +} +.lrp-32{ + gap:32px; + padding-top: 20px; + padding-left: 32px; + padding-right: 32px; + max-width: 960px; +} +.gradio-audio > .wrap, +.gradio-video > .wrap, +.gradio-file > .wrap, +.gradio-image > .wrap, +.wrap.center.full.translucent{ + min-height: unset; + position: absolute; + z-index: 100; + height: auto; + width: auto; +} + +div#quicksettings { + flex-direction: row; + display: inline-flex; + gap: var(--ae-gap-size); + flex-wrap: wrap; +} +div#quicksettings > div { + flex: 1 0 calc(100% - var(--ae-input-height) * 2); +} +div#quicksettings div + button { + flex: 0 1 0%; + margin-bottom: var(--ae-panel-padding); +} + +.relative{ + position:relative; +} +.accordion-vertical.expand { + flex-grow: 1 !important; +} + +.no-grow{ + flex-grow: 0; +} +#sidebar_secondary_tabs{ + justify-content: flex-end; +} + +#pnginfo_image .center.boundedheight.flex{ + display: flex; + align-items: center; + text-align: center; +} + +.gradio-colorpicker label { + flex-direction: row; + align-items: center; + pointer-events: none; +} +.gradio-colorpicker input { + pointer-events: all; +} + +input[type="radio"], +input[type="checkbox"] { + accent-color: var(--ae-primary-color); + cursor: pointer; +} +.selected span.name { + color: var(--ae-input-hover-text-color); +} +#txt2img_edit_style_close, +#lightboxModal, +.gradio-container.app{ + display:none !important; +} + +.icon-physton { + -webkit-mask-image: url(./html/svg/pantone-line.svg); +} +.physton-prompt { + margin: 0 !important; +} +.physton-prompt .prompt-header .prompt-header-extend.prompt-append { + min-width:240px; + min-height: 26px; +} + +.physton-prompt .prompt-header .prompt-header-extend .extend-content .gradio-checkbox{ + display:none; +} + +.physton-prompt .show-group-tags{ + top: -15px; + right: 5px; +} +.physton-prompt .prompt-header .prompt-header-extend.prompt-append .extend-content { + margin-right: 20px; +} +#train_tabitem .tabs{ + width:100%; +} + +@-webkit-keyframes fade-out { + 0% { + opacity: 1; + /* transform: scale(1.0); */ + } + + 100% { + opacity: 0; + /* transform: scale(0.5); */ + } +} + +@media screen and (-webkit-min-device-pixel-ratio: 0) { + input[type="range"] { + overflow: hidden; + width: 100%; + -webkit-appearance: none; + background-color: var(--ae-input-bg-color); + border: var(--ae-input-border-size) solid var(--ae-input-border-color); + position: relative; + border-radius: var(--ae-border-radius); + } + + input[type="range"]::after { + content: ""; + position: absolute; + height: 100%; + background-image: var(--ae-slider-bg-overlay); + width: 100%; + left: 1px; + } + + input[type="range"]::-webkit-slider-runnable-track { + height: 14px; + -webkit-appearance: none; + color: var(--ae-primary-color); + margin-top: -1px; + } + + input[type="range"]::-webkit-slider-thumb { + width: 0px; + -webkit-appearance: none; + height: 14px; + cursor: ew-resize; + background-color: var(--ae-primary-color); + box-shadow: -1024px 0 0 1024px var(--ae-primary-color); + } +} + +@media (max-width: 768px) { + .xtabs-tab span { + display: none; + } +} + +/* Firefox */ +* { + scrollbar-color: var(--ae-panel-border-color) var(--ae-main-bg-color) !important; + scrollbar-width: thin !important; +} + +input[type="range"]::-moz-range-progress { + background-color: var(--ae-primary-color); + height: 100%; + background-image: var(--ae-slider-bg-overlay); +} + +input[type="range"]::-moz-range-track { + width: 100%; + height: 100%; + background-color: var(--ae-input-bg-color); + border: none; + border-radius: 0px; + position: relative; + background-image: var(--ae-slider-bg-overlay); + opacity: 1; +} + +input[type="range"]::-moz-range-thumb { + border: 0px solid var(--ae-primary-color); + width: 0px; + border-radius: 0%; + background-color: var(--ae-primary-color); +} + +/*hide the outline behind the border*/ +input[type="range"]:-moz-focusring { + outline: 1px solid var(--ae-primary-color); + outline-offset: -1px; +} + +input[type="range"]:focus::-moz-range-track { + background-color: var(--ae-input-bg-color); +} + +input[type="number"] { + -moz-appearance: textfield; +} + +input[type="number"]:hover, +input[type="number"]:focus { + -moz-appearance: initial; +} + +/* IE maybe later */ + +input[type="range"]::-ms-fill-lower { + background-color: var(--ae-primary-color); +} + +input[type="range"]::-ms-fill-upper { + background-color: var(--ae-input-bg-color); +} \ No newline at end of file diff --git a/extensions-builtin/canvas-zoom-and-pan/javascript/zoom.js b/extensions-builtin/canvas-zoom-and-pan/javascript/zoom.js index 30199dcd60a..45c7600ac5f 100644 --- a/extensions-builtin/canvas-zoom-and-pan/javascript/zoom.js +++ b/extensions-builtin/canvas-zoom-and-pan/javascript/zoom.js @@ -12,8 +12,22 @@ onUiLoaded(async() => { "Sketch": elementIDs.sketch }; + // Helper functions // Get active tab + + /** + * Waits for an element to be present in the DOM. + */ + const waitForElement = (id) => new Promise(resolve => { + const checkForElement = () => { + const element = document.querySelector(id); + if (element) return resolve(element); + setTimeout(checkForElement, 100); + }; + checkForElement(); + }); + function getActiveTab(elements, all = false) { const tabs = elements.img2imgTabs.querySelectorAll("button"); @@ -34,7 +48,7 @@ onUiLoaded(async() => { // Wait until opts loaded async function waitForOpts() { - for (;;) { + for (; ;) { if (window.opts && Object.keys(window.opts).length) { return window.opts; } @@ -42,6 +56,11 @@ onUiLoaded(async() => { } } + // Detect whether the element has a horizontal scroll bar + function hasHorizontalScrollbar(element) { + return element.scrollWidth > element.clientWidth; + } + // Function for defining the "Ctrl", "Shift" and "Alt" keys function isModifierKey(event, key) { switch (key) { @@ -201,7 +220,8 @@ onUiLoaded(async() => { canvas_hotkey_overlap: "KeyO", canvas_disabled_functions: [], canvas_show_tooltip: true, - canvas_blur_prompt: false + canvas_auto_expand: true, + canvas_blur_prompt: false, }; const functionMap = { @@ -249,7 +269,7 @@ onUiLoaded(async() => { input?.addEventListener("input", () => restoreImgRedMask(elements)); } - function applyZoomAndPan(elemId) { + function applyZoomAndPan(elemId, isExtension = true) { const targetElement = gradioApp().querySelector(elemId); if (!targetElement) { @@ -361,6 +381,12 @@ onUiLoaded(async() => { panY: 0 }; + if (isExtension) { + targetElement.style.overflow = "hidden"; + } + + targetElement.isZoomed = false; + fixCanvas(); targetElement.style.transform = `scale(${elemData[elemId].zoomLevel}) translate(${elemData[elemId].panX}px, ${elemData[elemId].panY}px)`; @@ -371,8 +397,27 @@ onUiLoaded(async() => { toggleOverlap("off"); fullScreenMode = false; + const closeBtn = targetElement.querySelector("button[aria-label='Remove Image']"); + if (closeBtn) { + closeBtn.addEventListener("click", resetZoom); + } + + if (canvas && isExtension) { + const parentElement = targetElement.closest('[id^="component-"]'); + if ( + canvas && + parseFloat(canvas.style.width) > parentElement.offsetWidth && + parseFloat(targetElement.style.width) > parentElement.offsetWidth + ) { + fitToElement(); + return; + } + + } + if ( canvas && + !isExtension && parseFloat(canvas.style.width) > 865 && parseFloat(targetElement.style.width) > 865 ) { @@ -381,9 +426,6 @@ onUiLoaded(async() => { } targetElement.style.width = ""; - if (canvas) { - targetElement.style.height = canvas.style.height; - } } // Toggle the zIndex of the target element between two values, allowing it to overlap or be overlapped by other elements @@ -439,7 +481,7 @@ onUiLoaded(async() => { // Update the zoom level and pan position of the target element based on the values of the zoomLevel, panX and panY variables function updateZoom(newZoomLevel, mouseX, mouseY) { - newZoomLevel = Math.max(0.5, Math.min(newZoomLevel, 15)); + newZoomLevel = Math.max(0.1, Math.min(newZoomLevel, 15)); elemData[elemId].panX += mouseX - (mouseX * newZoomLevel) / elemData[elemId].zoomLevel; @@ -450,6 +492,10 @@ onUiLoaded(async() => { targetElement.style.transform = `translate(${elemData[elemId].panX}px, ${elemData[elemId].panY}px) scale(${newZoomLevel})`; toggleOverlap("on"); + if (isExtension) { + targetElement.style.overflow = "visible"; + } + return newZoomLevel; } @@ -472,10 +518,12 @@ onUiLoaded(async() => { fullScreenMode = false; elemData[elemId].zoomLevel = updateZoom( elemData[elemId].zoomLevel + - (operation === "+" ? delta : -delta), + (operation === "+" ? delta : -delta), zoomPosX - targetElement.getBoundingClientRect().left, zoomPosY - targetElement.getBoundingClientRect().top ); + + targetElement.isZoomed = true; } } @@ -489,10 +537,19 @@ onUiLoaded(async() => { //Reset Zoom targetElement.style.transform = `translate(${0}px, ${0}px) scale(${1})`; + let parentElement; + + if (isExtension) { + parentElement = targetElement.closest('[id^="component-"]'); + } else { + parentElement = targetElement.parentElement; + } + + // Get element and screen dimensions const elementWidth = targetElement.offsetWidth; const elementHeight = targetElement.offsetHeight; - const parentElement = targetElement.parentElement; + const screenWidth = parentElement.clientWidth; const screenHeight = parentElement.clientHeight; @@ -545,8 +602,12 @@ onUiLoaded(async() => { if (!canvas) return; - if (canvas.offsetWidth > 862) { - targetElement.style.width = canvas.offsetWidth + "px"; + if (canvas.offsetWidth > 862 || isExtension) { + targetElement.style.width = (canvas.offsetWidth + 2) + "px"; + } + + if (isExtension) { + targetElement.style.overflow = "visible"; } if (fullScreenMode) { @@ -648,8 +709,48 @@ onUiLoaded(async() => { mouseY = e.offsetY; } + // Simulation of the function to put a long image into the screen. + // We detect if an image has a scroll bar or not, make a fullscreen to reveal the image, then reduce it to fit into the element. + // We hide the image and show it to the user when it is ready. + + targetElement.isExpanded = false; + function autoExpand() { + const canvas = document.querySelector(`${elemId} canvas[key="interface"]`); + if (canvas) { + if (hasHorizontalScrollbar(targetElement) && targetElement.isExpanded === false) { + targetElement.style.visibility = "hidden"; + setTimeout(() => { + fitToScreen(); + resetZoom(); + targetElement.style.visibility = "visible"; + targetElement.isExpanded = true; + }, 10); + } + } + } + targetElement.addEventListener("mousemove", getMousePosition); + //observers + // Creating an observer with a callback function to handle DOM changes + const observer = new MutationObserver((mutationsList, observer) => { + for (let mutation of mutationsList) { + // If the style attribute of the canvas has changed, by observation it happens only when the picture changes + if (mutation.type === 'attributes' && mutation.attributeName === 'style' && + mutation.target.tagName.toLowerCase() === 'canvas') { + targetElement.isExpanded = false; + setTimeout(resetZoom, 10); + } + } + }); + + // Apply auto expand if enabled + if (hotkeysConfig.canvas_auto_expand) { + targetElement.addEventListener("mousemove", autoExpand); + // Set up an observer to track attribute changes + observer.observe(targetElement, {attributes: true, childList: true, subtree: true}); + } + // Handle events only inside the targetElement let isKeyDownHandlerAttached = false; @@ -754,6 +855,11 @@ onUiLoaded(async() => { if (isMoving && elemId === activeElement) { updatePanPosition(e.movementX, e.movementY); targetElement.style.pointerEvents = "none"; + + if (isExtension) { + targetElement.style.overflow = "visible"; + } + } else { targetElement.style.pointerEvents = "auto"; } @@ -764,13 +870,93 @@ onUiLoaded(async() => { isMoving = false; }; + // Checks for extension + function checkForOutBox() { + const parentElement = targetElement.closest('[id^="component-"]'); + if (parentElement.offsetWidth < targetElement.offsetWidth && !targetElement.isExpanded) { + resetZoom(); + targetElement.isExpanded = true; + } + + if (parentElement.offsetWidth < targetElement.offsetWidth && elemData[elemId].zoomLevel == 1) { + resetZoom(); + } + + if (parentElement.offsetWidth < targetElement.offsetWidth && targetElement.offsetWidth * elemData[elemId].zoomLevel > parentElement.offsetWidth && elemData[elemId].zoomLevel < 1 && !targetElement.isZoomed) { + resetZoom(); + } + } + + if (isExtension) { + targetElement.addEventListener("mousemove", checkForOutBox); + } + + + window.addEventListener('resize', (e) => { + resetZoom(); + + if (isExtension) { + targetElement.isExpanded = false; + targetElement.isZoomed = false; + } + }); + gradioApp().addEventListener("mousemove", handleMoveByKey); + + } - applyZoomAndPan(elementIDs.sketch); - applyZoomAndPan(elementIDs.inpaint); - applyZoomAndPan(elementIDs.inpaintSketch); + applyZoomAndPan(elementIDs.sketch, false); + applyZoomAndPan(elementIDs.inpaint, false); + applyZoomAndPan(elementIDs.inpaintSketch, false); // Make the function global so that other extensions can take advantage of this solution - window.applyZoomAndPan = applyZoomAndPan; + const applyZoomAndPanIntegration = async(id, elementIDs) => { + const mainEl = document.querySelector(id); + if (id.toLocaleLowerCase() === "none") { + for (const elementID of elementIDs) { + const el = await waitForElement(elementID); + if (!el) break; + applyZoomAndPan(elementID); + } + return; + } + + if (!mainEl) return; + mainEl.addEventListener("click", async() => { + for (const elementID of elementIDs) { + const el = await waitForElement(elementID); + if (!el) break; + applyZoomAndPan(elementID); + } + }, {once: true}); + }; + + window.applyZoomAndPan = applyZoomAndPan; // Only 1 elements, argument elementID, for example applyZoomAndPan("#txt2img_controlnet_ControlNet_input_image") + + window.applyZoomAndPanIntegration = applyZoomAndPanIntegration; // for any extension + + /* + The function `applyZoomAndPanIntegration` takes two arguments: + + 1. `id`: A string identifier for the element to which zoom and pan functionality will be applied on click. + If the `id` value is "none", the functionality will be applied to all elements specified in the second argument without a click event. + + 2. `elementIDs`: An array of string identifiers for elements. Zoom and pan functionality will be applied to each of these elements on click of the element specified by the first argument. + If "none" is specified in the first argument, the functionality will be applied to each of these elements without a click event. + + Example usage: + applyZoomAndPanIntegration("#txt2img_controlnet", ["#txt2img_controlnet_ControlNet_input_image"]); + In this example, zoom and pan functionality will be applied to the element with the identifier "txt2img_controlnet_ControlNet_input_image" upon clicking the element with the identifier "txt2img_controlnet". + */ + + // More examples + // Add integration with ControlNet txt2img One TAB + // applyZoomAndPanIntegration("#txt2img_controlnet", ["#txt2img_controlnet_ControlNet_input_image"]); + + // Add integration with ControlNet txt2img Tabs + // applyZoomAndPanIntegration("#txt2img_controlnet",Array.from({ length: 10 }, (_, i) => `#txt2img_controlnet_ControlNet-${i}_input_image`)); + + // Add integration with Inpaint Anything + // applyZoomAndPanIntegration("None", ["#ia_sam_image", "#ia_sel_mask"]); }); diff --git a/extensions-builtin/canvas-zoom-and-pan/scripts/hotkey_config.py b/extensions-builtin/canvas-zoom-and-pan/scripts/hotkey_config.py index 380176ce26c..2d8d2d1c014 100644 --- a/extensions-builtin/canvas-zoom-and-pan/scripts/hotkey_config.py +++ b/extensions-builtin/canvas-zoom-and-pan/scripts/hotkey_config.py @@ -9,6 +9,7 @@ "canvas_hotkey_reset": shared.OptionInfo("R", "Reset zoom and canvas positon"), "canvas_hotkey_overlap": shared.OptionInfo("O", "Toggle overlap").info("Technical button, neededs for testing"), "canvas_show_tooltip": shared.OptionInfo(True, "Enable tooltip on the canvas"), + "canvas_auto_expand": shared.OptionInfo(True, "Automatically expands an image that does not fit completely in the canvas area, similar to manually pressing the S and R buttons"), "canvas_blur_prompt": shared.OptionInfo(False, "Take the focus off the prompt when working with a canvas"), "canvas_disabled_functions": shared.OptionInfo(["Overlap"], "Disable function that you don't use", gr.CheckboxGroup, {"choices": ["Zoom","Adjust brush size", "Moving canvas","Fullscreen","Reset Zoom","Overlap"]}), })) diff --git a/extensions-builtin/canvas-zoom-and-pan/style.css b/extensions-builtin/canvas-zoom-and-pan/style.css index 6bcc9570c45..5d8054e6519 100644 --- a/extensions-builtin/canvas-zoom-and-pan/style.css +++ b/extensions-builtin/canvas-zoom-and-pan/style.css @@ -61,3 +61,6 @@ to {opacity: 1;} } +.styler { + overflow:inherit !important; +} \ No newline at end of file diff --git a/extensions-builtin/extra-options-section/scripts/extra_options_section.py b/extensions-builtin/extra-options-section/scripts/extra_options_section.py index a05e10d865a..983f87ff033 100644 --- a/extensions-builtin/extra-options-section/scripts/extra_options_section.py +++ b/extensions-builtin/extra-options-section/scripts/extra_options_section.py @@ -1,5 +1,7 @@ +import math + import gradio as gr -from modules import scripts, shared, ui_components, ui_settings +from modules import scripts, shared, ui_components, ui_settings, generation_parameters_copypaste from modules.ui_components import FormColumn @@ -19,18 +21,38 @@ def show(self, is_img2img): def ui(self, is_img2img): self.comps = [] self.setting_names = [] + self.infotext_fields = [] + extra_options = shared.opts.extra_options_img2img if is_img2img else shared.opts.extra_options_txt2img + + mapping = {k: v for v, k in generation_parameters_copypaste.infotext_to_setting_name_mapping} with gr.Blocks() as interface: - with gr.Accordion("Options", open=False) if shared.opts.extra_options_accordion and shared.opts.extra_options else gr.Group(), gr.Row(): - for setting_name in shared.opts.extra_options: - with FormColumn(): - comp = ui_settings.create_setting_component(setting_name) + with gr.Accordion("Options", open=False) if shared.opts.extra_options_accordion and extra_options else gr.Group(): + + row_count = math.ceil(len(extra_options) / shared.opts.extra_options_cols) + + for row in range(row_count): + with gr.Row(): + for col in range(shared.opts.extra_options_cols): + index = row * shared.opts.extra_options_cols + col + if index >= len(extra_options): + break + + setting_name = extra_options[index] - self.comps.append(comp) - self.setting_names.append(setting_name) + with FormColumn(): + comp = ui_settings.create_setting_component(setting_name) + + self.comps.append(comp) + self.setting_names.append(setting_name) + + setting_infotext_name = mapping.get(setting_name) + if setting_infotext_name is not None: + self.infotext_fields.append((comp, setting_infotext_name)) def get_settings_values(): - return [ui_settings.get_value_for_setting(key) for key in self.setting_names] + res = [ui_settings.get_value_for_setting(key) for key in self.setting_names] + return res[0] if len(res) == 1 else res interface.load(fn=get_settings_values, inputs=[], outputs=self.comps, queue=False, show_progress=False) @@ -43,6 +65,10 @@ def before_process(self, p, *args): shared.options_templates.update(shared.options_section(('ui', "User interface"), { - "extra_options": shared.OptionInfo([], "Options in main UI", ui_components.DropdownMulti, lambda: {"choices": list(shared.opts.data_labels.keys())}).js("info", "settingsHintsShowQuicksettings").info("setting entries that also appear in txt2img/img2img interfaces").needs_restart(), - "extra_options_accordion": shared.OptionInfo(False, "Place options in main UI into an accordion") + "extra_options_txt2img": shared.OptionInfo([], "Options in main UI - txt2img", ui_components.DropdownMulti, lambda: {"choices": list(shared.opts.data_labels.keys())}).js("info", "settingsHintsShowQuicksettings").info("setting entries that also appear in txt2img interfaces").needs_reload_ui(), + "extra_options_img2img": shared.OptionInfo([], "Options in main UI - img2img", ui_components.DropdownMulti, lambda: {"choices": list(shared.opts.data_labels.keys())}).js("info", "settingsHintsShowQuicksettings").info("setting entries that also appear in img2img interfaces").needs_reload_ui(), + "extra_options_cols": shared.OptionInfo(1, "Options in main UI - number of columns", gr.Number, {"precision": 0}).needs_reload_ui(), + "extra_options_accordion": shared.OptionInfo(False, "Options in main UI - place into an accordion").needs_reload_ui() })) + + diff --git a/extensions-builtin/mobile/javascript/mobile.js b/extensions-builtin/mobile/javascript/mobile.js index 12cae4b7576..652f07ac7ec 100644 --- a/extensions-builtin/mobile/javascript/mobile.js +++ b/extensions-builtin/mobile/javascript/mobile.js @@ -20,7 +20,13 @@ function reportWindowSize() { var button = gradioApp().getElementById(tab + '_generate_box'); var target = gradioApp().getElementById(currentlyMobile ? tab + '_results' : tab + '_actions_column'); target.insertBefore(button, target.firstElementChild); + + gradioApp().getElementById(tab + '_results').classList.toggle('mobile', currentlyMobile); } } window.addEventListener("resize", reportWindowSize); + +onUiLoaded(function() { + reportWindowSize(); +}); diff --git a/extensions-builtin/sd_theme_editor/install.py b/extensions-builtin/sd_theme_editor/install.py deleted file mode 100644 index 5416cb0a402..00000000000 --- a/extensions-builtin/sd_theme_editor/install.py +++ /dev/null @@ -1 +0,0 @@ -import launch diff --git a/extensions-builtin/sd_theme_editor/javascript/ui_theme.js b/extensions-builtin/sd_theme_editor/javascript/ui_theme.js deleted file mode 100644 index 1f065568d8c..00000000000 --- a/extensions-builtin/sd_theme_editor/javascript/ui_theme.js +++ /dev/null @@ -1,435 +0,0 @@ -function hexToRgb(color) { - let hex = color[0] === "#" ? color.slice(1) : color; - let c; - - // expand the short hex by doubling each character, fc0 -> ffcc00 - if (hex.length !== 6) { - hex = (() => { - const result = []; - for (c of Array.from(hex)) { - result.push(`${c}${c}`); - } - return result; - })().join(""); - } - const colorStr = hex.match(/#?(.{2})(.{2})(.{2})/).slice(1); - const rgb = colorStr.map((col) => parseInt(col, 16)); - rgb.push(1); - return rgb; -} - -function rgbToHsl(rgb) { - const r = rgb[0] / 255; - const g = rgb[1] / 255; - const b = rgb[2] / 255; - - const max = Math.max(r, g, b); - const min = Math.min(r, g, b); - const diff = max - min; - const add = max + min; - - const hue = - min === max - ? 0 - : r === max - ? ((60 * (g - b)) / diff + 360) % 360 - : g === max - ? (60 * (b - r)) / diff + 120 - : (60 * (r - g)) / diff + 240; - - const lum = 0.5 * add; - - const sat = - lum === 0 ? 0 : lum === 1 ? 1 : lum <= 0.5 ? diff / add : diff / (2 - add); - - const h = Math.round(hue); - const s = Math.round(sat * 100); - const l = Math.round(lum * 100); - const a = rgb[3] || 1; - - return [h, s, l, a]; -} - -function hexToHsl(color) { - const rgb = hexToRgb(color); - const hsl = rgbToHsl(rgb); - return "hsl(" + hsl[0] + "deg " + hsl[1] + "% " + hsl[2] + "%)"; -} - -function hslToHex(h, s, l) { - l /= 100; - const a = (s * Math.min(l, 1 - l)) / 100; - const f = (n) => { - const k = (n + h / 30) % 12; - const color = l - a * Math.max(Math.min(k - 3, 9 - k, 1), -1); - return Math.round(255 * Math.max(0, Math.min(color, 1))) - .toString(16) - .padStart(2, "0"); // convert to Hex and prefix "0" if needed - }; - return `#${f(0)}${f(8)}${f(4)}`; -} - -function hsl2rgb(h, s, l) { - let a = s * Math.min(l, 1 - l); - let f = (n, k = (n + h / 30) % 12) => - l - a * Math.max(Math.min(k - 3, 9 - k, 1), -1); - return [f(0), f(8), f(4)]; -} - -function invertColor(hex) { - if (hex.indexOf("#") === 0) { - hex = hex.slice(1); - } - // convert 3-digit hex to 6-digits. - if (hex.length === 3) { - hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2]; - } - if (hex.length !== 6) { - throw new Error("Invalid HEX color."); - } - // invert color components - var r = (255 - parseInt(hex.slice(0, 2), 16)).toString(16), - g = (255 - parseInt(hex.slice(2, 4), 16)).toString(16), - b = (255 - parseInt(hex.slice(4, 6), 16)).toString(16); - // pad each with zeros and return - return "#" + padZero(r) + padZero(g) + padZero(b); -} - -function padZero(str, len) { - len = len || 2; - var zeros = new Array(len).join("0"); - return (zeros + str).slice(-len); -} - -function getValsWrappedIn(str, c1, c2) { - var rg = new RegExp("(?<=\\" + c1 + ")(.*?)(?=\\" + c2 + ")", "g"); - return str.match(rg); -} - -let styleobj = {}; -let hslobj = {}; -let isColorsInv; - -const toHSLArray = (hslStr) => hslStr.match(/\d+/g).map(Number); - -function offsetColorsHSV(ohsl) { - let inner_styles = ""; - - for (const key in styleobj) { - let keyVal = styleobj[key]; - - if (keyVal.indexOf("#") != -1 || keyVal.indexOf("hsl") != -1) { - let colcomp = gradioApp().querySelector("#" + key + " input"); - if (colcomp) { - let hsl; - - if (keyVal.indexOf("#") != -1) { - keyVal = keyVal.replace(/\s+/g, ""); - //inv ? keyVal = invertColor(keyVal) : 0; - if (isColorsInv) { - keyVal = invertColor(keyVal); - styleobj[key] = keyVal; - } - hsl = rgbToHsl(hexToRgb(keyVal)); - } else { - if (isColorsInv) { - let c = toHSLArray(keyVal); - let hex = hslToHex(c[0], c[1], c[2]); - keyVal = invertColor(hex); - styleobj[key] = keyVal; - hsl = rgbToHsl(hexToRgb(keyVal)); - } else { - hsl = toHSLArray(keyVal); - } - } - - let h = (parseInt(hsl[0]) + parseInt(ohsl[0])) % 360; - let s = parseInt(hsl[1]) + parseInt(ohsl[1]); - let l = parseInt(hsl[2]) + parseInt(ohsl[2]); - - let hex = hslToHex( - h, - Math.min(Math.max(s, 0), 100), - Math.min(Math.max(l, 0), 100) - ); - - colcomp.value = hex; - - hslobj[key] = "hsl(" + h + "deg " + s + "% " + l + "%)"; - inner_styles += key + ":" + hslobj[key] + ";"; - } - } else { - inner_styles += key + ":" + styleobj[key] + ";"; - } - } - - isColorsInv = false; - - const preview_styles = gradioApp().querySelector("#preview-styles"); - preview_styles.innerHTML = ":root {" + inner_styles + "}"; - preview_styles.innerHTML += - "@media only screen and (max-width: 860px) {:root{--ae-outside-gap-size: var(--ae-mobile-outside-gap-size);--ae-inside-padding-size: var(--ae-mobile-inside-padding-size);}}"; - - const vars_textarea = gradioApp().querySelector("#theme_vars textarea"); - vars_textarea.value = inner_styles; - - const inputEvent = new Event("input"); - Object.defineProperty(inputEvent, "target", { value: vars_textarea }); - vars_textarea.dispatchEvent(inputEvent); -} - -function updateTheme(vars) { - let inner_styles = ""; - - for (let i = 0; i < vars.length - 1; i++) { - let key = vars[i].split(":"); - let id = key[0].replace(/\s+/g, ""); - let val = key[1].trim(); - - styleobj[id] = val; - inner_styles += id + ":" + val + ";"; - - gradioApp() - .querySelectorAll("#" + id + " input") - .forEach((elem) => { - if (val.indexOf("hsl") != -1) { - let hsl = toHSLArray(val); - let hex = hslToHex(hsl[0], hsl[1], hsl[2]); - elem.value = hex; - } else { - elem.value = val.split("px")[0]; - } - }); - } - - const preview_styles = gradioApp().querySelector("#preview-styles"); - - if (preview_styles) { - preview_styles.innerHTML = ":root {" + inner_styles + "}"; - preview_styles.innerHTML += - "@media only screen and (max-width: 860px) {:root{--ae-outside-gap-size: var(--ae-mobile-outside-gap-size);--ae-inside-padding-size: var(--ae-mobile-inside-padding-size);}}"; - } else { - const r = gradioApp(); - const style = document.createElement("style"); - style.id = "preview-styles"; - style.innerHTML = ":root {" + inner_styles + "}"; - style.innerHTML += - "@media only screen and (max-width: 860px) {:root{--ae-outside-gap-size: var(--ae-mobile-outside-gap-size);--ae-inside-padding-size: var(--ae-mobile-inside-padding-size);}}"; - r.appendChild(style); - } - - const vars_textarea = gradioApp().querySelector("#theme_vars textarea"); - const css_textarea = gradioApp().querySelector("#theme_css textarea"); - - vars_textarea.value = inner_styles; - css_textarea.value = css_textarea.value; - - //console.log(Object); - - const vEvent = new Event("input"); - const cEvent = new Event("input"); - Object.defineProperty(vEvent, "target", { value: vars_textarea }); - Object.defineProperty(cEvent, "target", { value: css_textarea }); - vars_textarea.dispatchEvent(vEvent); - css_textarea.dispatchEvent(cEvent); -} - -function applyTheme() { - console.log("apply"); -} - -function initTheme() { - const current_style = gradioApp().querySelector(".gradio-container > style"); - //console.log(current_style); - //const head = document.head; - //head.appendChild(current_style); - - const css_styles = current_style.innerHTML.split( - "/*BREAKPOINT_CSS_CONTENT*/" - ); - let init_css_vars = css_styles[0].split("}")[0].split("{")[1]; - init_css_vars = init_css_vars.replace(/\n|\r/g, ""); - - let init_vars = init_css_vars.split(";"); - let vars = init_vars; - - //console.log(vars); - - const vars_textarea = gradioApp().querySelector("#theme_vars textarea"); - const css_textarea = gradioApp().querySelector("#theme_css textarea"); - //const result_textarea = gradioApp().querySelector('#theme_result textarea'); - vars_textarea.value = init_css_vars; - css_textarea.value = - "/*BREAKPOINT_CSS_CONTENT*/" + css_styles[1] + "/*BREAKPOINT_CSS_CONTENT*/"; - - updateTheme(vars); - - //vars_textarea.addEventListener("change", function(e) { - //e.preventDefault(); - //e.stopPropagation(); - //vars = vars_textarea.value.split(";"); - //console.log(e); - //updateTheme(vars); - - //}) - - const preview_styles = gradioApp().querySelector("#preview-styles"); - let intervalChange; - - gradioApp() - .querySelectorAll("#ui_theme_settings input") - .forEach((elem) => { - elem.addEventListener("input", function (e) { - let celem = e.currentTarget; - let val = e.currentTarget.value; - let curr_val; - - switch (e.currentTarget.type) { - case "range": - celem = celem.parentElement; - val = e.currentTarget.value + "px"; - break; - case "color": - celem = celem.parentElement.parentElement; - val = e.currentTarget.value; - break; - case "number": - celem = celem.parentElement.parentElement.parentElement; - val = e.currentTarget.value + "px"; - break; - } - - styleobj[celem.id] = val; - - //console.log(styleobj); - - if (intervalChange != null) clearInterval(intervalChange); - intervalChange = setTimeout(() => { - let inner_styles = ""; - - for (const key in styleobj) { - inner_styles += key + ":" + styleobj[key] + ";"; - } - - vars = inner_styles.split(";"); - preview_styles.innerHTML = ":root {" + inner_styles + "}"; - preview_styles.innerHTML += - "@media only screen and (max-width: 860px) {:root{--ae-outside-gap-size: var(--ae-mobile-outside-gap-size);--ae-inside-padding-size: var(--ae-mobile-inside-padding-size);}}"; - - vars_textarea.value = inner_styles; - const vEvent = new Event("input"); - Object.defineProperty(vEvent, "target", { value: vars_textarea }); - vars_textarea.dispatchEvent(vEvent); - - offsetColorsHSV(hsloffset); - }, 1000); - }); - }); - - const reset_btn = gradioApp().getElementById("theme_reset_btn"); - reset_btn.addEventListener("click", function (e) { - e.preventDefault(); - e.stopPropagation(); - gradioApp() - .querySelectorAll("#ui_theme_hsv input") - .forEach((elem) => { - elem.value = 0; - }); - hsloffset = [0, 0, 0]; - updateTheme(init_vars); - }); - - /* - const apply_btn = gradioApp().getElementById('theme_apply_btn'); - apply_btn.addEventListener("click", function(e) { - e.preventDefault(); - e.stopPropagation(); - init_css_vars = vars_textarea.value.replace(/\n|\r/g, ""); - vars_textarea.value = init_css_vars; - - init_vars = init_css_vars.split(";"); - vars = init_vars; - updateTheme(vars); - }) - */ - - let intervalCheck; - function dropDownOnChange() { - if (init_css_vars != vars_textarea.value) { - clearInterval(intervalCheck); - init_css_vars = vars_textarea.value.replace(/\n|\r/g, ""); - vars_textarea.value = init_css_vars; - init_vars = init_css_vars.split(";"); - vars = init_vars; - updateTheme(vars); - } - } - - const drop_down = gradioApp().querySelector("#themes_drop_down"); - drop_down.addEventListener("click", function (e) { - if (intervalCheck != null) clearInterval(intervalCheck); - intervalCheck = setInterval(dropDownOnChange, 100); - //console.log("ok"); - }); - - let hsloffset = [0, 0, 0]; - - const hue = gradioApp() - .querySelectorAll("#theme_hue input") - .forEach((elem) => { - elem.addEventListener("change", function (e) { - e.preventDefault(); - e.stopPropagation(); - hsloffset[0] = e.currentTarget.value; - offsetColorsHSV(hsloffset); - }); - }); - - const sat = gradioApp() - .querySelectorAll("#theme_sat input") - .forEach((elem) => { - elem.addEventListener("change", function (e) { - e.preventDefault(); - e.stopPropagation(); - hsloffset[1] = e.currentTarget.value; - offsetColorsHSV(hsloffset); - }); - }); - - const brt = gradioApp() - .querySelectorAll("#theme_brt input") - .forEach((elem) => { - elem.addEventListener("change", function (e) { - e.preventDefault(); - e.stopPropagation(); - hsloffset[2] = e.currentTarget.value; - offsetColorsHSV(hsloffset); - }); - }); - - const inv_btn = gradioApp().getElementById("theme_invert_btn"); - inv_btn.addEventListener("click", function (e) { - e.preventDefault(); - e.stopPropagation(); - isColorsInv = !isColorsInv; - offsetColorsHSV(hsloffset); - }); -} - -function observeGradioApp() { - const observer = new MutationObserver(() => { - const block = gradioApp().getElementById("tab_ui_theme"); - if (block) { - observer.disconnect(); - - setTimeout(() => { - initTheme(); - }, "500"); - } - }); - observer.observe(gradioApp(), { childList: true, subtree: true }); -} - -document.addEventListener("DOMContentLoaded", () => { - observeGradioApp(); -}); diff --git a/extensions-builtin/sd_theme_editor/scripts/ui_theme.py b/extensions-builtin/sd_theme_editor/scripts/ui_theme.py deleted file mode 100644 index 3a2c8a2b8ba..00000000000 --- a/extensions-builtin/sd_theme_editor/scripts/ui_theme.py +++ /dev/null @@ -1,177 +0,0 @@ -import os -import shutil -from pathlib import Path -import gradio as gr -import modules.scripts as scripts -from modules import script_callbacks, shared - -basedir = scripts.basedir() -webui_dir = Path(basedir).parents[1] - -themes_folder = os.path.join(basedir, "themes") -javascript_folder = os.path.join(basedir, "javascript") -webui_style_path = os.path.join(webui_dir, "style.css") - -def get_files(folder, file_filter=[], file_list=[], split=False): - file_list = [file_name if not split else os.path.splitext(file_name)[0] for file_name in os.listdir(folder) if os.path.isfile(os.path.join(folder, file_name)) and file_name not in file_filter] - return file_list - - -def on_ui_tabs(): - - with gr.Blocks(analytics_enabled=False) as ui_theme: - with gr.Row(): - with gr.Column(): - with gr.Row(): - themes_dropdown = gr.Dropdown(label="Themes", elem_id="themes_drop_down", interactive=True, choices=get_files(themes_folder,[".css, .txt"]), type="value") - save_as_filename = gr.Text(label="Save / Save as") - with gr.Row(): - reset_button = gr.Button(elem_id="theme_reset_btn", value="Reset", variant="primary") - #apply_button = gr.Button(elem_id="theme_apply_btn", value="Apply", variant="primary") - save_button = gr.Button(value="Save", variant="primary") - #delete_button = gr.Button(value="Delete", variant="primary") - - #with gr.Accordion(label="Debug View", open=True): - with gr.Row(elem_id="theme_hidden"): - vars_text = gr.Textbox(label="Vars", elem_id="theme_vars", show_label=True, lines=7, interactive=False, visible=True) - css_text = gr.Textbox(label="Css", elem_id="theme_css", show_label=True, lines=7, interactive=False, visible=True) - #result_text = gr.Text(elem_id="theme_result", interactive=False, visible=False) - with gr.Column(elem_id="theme_overflow_container"): - with gr.Accordion(label="Theme Color adjustments", open=True): - with gr.Row(): - with gr.Column(scale=6, elem_id="ui_theme_hsv"): - gr.Slider(elem_id="theme_hue", label='Hue', minimum=0, maximum=360, step=1) - gr.Slider(elem_id="theme_sat", label='Saturation', minimum=-100, maximum=100, step=1, value=0, interactive=True) - gr.Slider(elem_id="theme_brt", label='Lightness', minimum=-50, maximum=50, step=1, value=0, interactive=True) - - gr.Button(elem_id="theme_invert_btn", value="Invert", variant="primary") - - - with gr.Row(elem_id="ui_theme_settings"): - with gr.Column(): - with gr.Column(): - with gr.Accordion(label="Main", open=True): - gr.ColorPicker(elem_id="--ae-main-bg-color", interactive=True, label="Background color") - gr.ColorPicker(elem_id="--ae-primary-color", label="Primary color") - - with gr.Accordion(label="Focus", open=True): - gr.ColorPicker(elem_id="--ae-textarea-focus-color", label="Textarea color") - gr.ColorPicker(elem_id="--ae-input-focus-color", label="Input color") - - with gr.Accordion(label="Spacing", open=True): - gr.Slider(elem_id="--ae-outside-gap-size", label='Gap size', minimum=1, maximum=16, step=1, interactive=True) - gr.Slider(elem_id="--ae-inside-padding-size", label='Padding size', minimum=1, maximum=16, step=1, interactive=True) - - with gr.Accordion(label="Spacing (Mobile)", open=True): - gr.Slider(elem_id="--ae-mobile-outside-gap-size", label='Mobile Gap size', minimum=1, maximum=16, step=1, interactive=True) - gr.Slider(elem_id="--ae-mobile-inside-padding-size", label='Mobile Padding size', minimum=1, maximum=16, step=1, interactive=True) - - with gr.Accordion(label="Panel", open=True): - gr.ColorPicker(elem_id="--ae-label-color", label="Label color") - gr.ColorPicker(elem_id="--ae-frame-bg-color", label="Frame Background color") - gr.ColorPicker(elem_id="--ae-panel-bg-color", label="Background color") - gr.ColorPicker(elem_id="--ae-panel-border-color", label="Border color") - gr.Slider(elem_id="--ae-panel-border-radius", label='Border radius', minimum=0, maximum=16, step=1) - - gr.ColorPicker(elem_id="--ae-input-color", label="Input text color") - gr.ColorPicker(elem_id="--ae-input-bg-color", label="Input background color") - gr.ColorPicker(elem_id="--ae-input-border-color", label="Input border color") - with gr.Column(): - with gr.Row(elem_id="theme_sub-panel"): - - with gr.Accordion(label="SubPanel", open=True): - gr.ColorPicker(elem_id="--ae-subgroup-bg-color", label="Subgoup background color") - #gr.ColorPicker(elem_id="--ae-subgroup-label-color", label="Label color", value="#000000") - gr.ColorPicker(elem_id="--ae-subpanel-bg-color", label="Background color") - gr.ColorPicker(elem_id="--ae-subpanel-border-color", label="Border color") - gr.Slider(elem_id="--ae-subpanel-border-radius", label='Border radius', minimum=0, maximum=16, step=1) - - gr.ColorPicker(elem_id="--ae-subgroup-input-color", label="Input text color") - gr.ColorPicker(elem_id="--ae-subgroup-input-bg-color", label="Input background color") - gr.ColorPicker(elem_id="--ae-subgroup-input-border-color", label="Input border color") - - with gr.Row(): - with gr.Column(): - with gr.Accordion(label="Navigation menu", open=True): - gr.ColorPicker(elem_id="--ae-nav-bg-color", label="Background color") - gr.ColorPicker(elem_id="--ae-nav-color", label="Text color") - gr.ColorPicker(elem_id="--ae-nav-hover-color", label="Hover color") - - with gr.Accordion(label="Icon", open=True): - gr.ColorPicker(elem_id="--ae-icon-color", label="Color") - gr.ColorPicker(elem_id="--ae-icon-hover-color", label="Hover color") - - with gr.Accordion(label="Other", open=True): - gr.ColorPicker(elem_id="--ae-text-color", label="Text color") - gr.ColorPicker(elem_id="--ae-placeholder-color", label="Placeholder color") - gr.ColorPicker(elem_id="--ae-cancel-color", label="Cancel/Interrupt color") - - with gr.Accordion(label="Modal", open=True): - gr.ColorPicker(elem_id="--ae-modal-bg-color", label="Background color") - gr.ColorPicker(elem_id="--ae-modal-icon-color", label="Icon color") - - - - def save_theme( vars_text, css_text, filename): - style_data= ":root{" + vars_text + "}" + css_text - with open(os.path.join(themes_folder, f"{filename}.css"), 'w', encoding="utf-8") as file: - file.write(vars_text) - file.close() - with open(webui_style_path, 'w', encoding="utf-8") as file: - file.write(style_data) - file.close() - themes_dropdown.choices=get_files(themes_folder,[".css, .txt"]) - return gr.update(choices=themes_dropdown.choices, value=f"{filename}.css") - - def open_theme(filename, css_text): - with open(os.path.join(themes_folder, f"{filename}"), 'r') as file: - vars_text=file.read() - no_ext=filename.rsplit('.', 1)[0] - #save_theme( vars_text, css_text, no_ext) - # shared.state.interrupt() - # shared.state.need_restart = True - return [vars_text, no_ext] - - # def delete_theme(filename): - # try: - # os.remove(os.path.join(themes_folder, filename)) - # except FileNotFoundError: - # pass - - # delete_button.click( - # fn = lambda: delete_theme() - # ) - - save_button.click( - fn=save_theme, - inputs=[vars_text, css_text, save_as_filename], - outputs=themes_dropdown - ) - - themes_dropdown.change( - fn=open_theme, - #_js = "applyTheme", - inputs=[themes_dropdown, css_text], - outputs=[vars_text, save_as_filename] - ) - - # apply_button.click( - # fn=None, - # _js = "applyTheme" - # ) - - # vars_text.change( - # fn=None, - # _js = "applyTheme", - # inputs=[], - # outputs=[vars_text, css_text] - # ) - - - - - return (ui_theme, 'Theme', 'ui_theme'), - - - -script_callbacks.on_ui_tabs(on_ui_tabs) \ No newline at end of file diff --git a/extensions-builtin/sd_theme_editor/style.css b/extensions-builtin/sd_theme_editor/style.css deleted file mode 100644 index 51f33101ae1..00000000000 --- a/extensions-builtin/sd_theme_editor/style.css +++ /dev/null @@ -1,113 +0,0 @@ -#theme_menu { - z-index: 9999; - background-color: var(--ae-input-bg-color); - position: relative; - width: 38px; - height: 38px; - border-radius: 100%; - cursor: pointer; - min-width: unset; - max-width: 38px; - align-self: center; -} - -#theme_menu::before { - content: " "; - display: inline-block; - -webkit-mask-size: cover; - mask-size: cover; - background-color: var(--ae-icon-color); - width: var(--ae-icon-size); - height: var(--ae-icon-size); - -webkit-mask: url(./file=html/svg/contrast-drop-2-line.svg) no-repeat 50% 50%; - mask: url(./file=html/svg/contrast-drop-2-line.svg) no-repeat 50% 50%; - cursor: pointer; - position: relative; - left: 50%; - top: 50%; - transform: translate(-50%, -50%) scale(1); -} - -#theme_menu.fixed, -#theme_menu:hover { - background-color: var(--ae-icon-color); -} - -#theme_menu.fixed::before, -#theme_menu:hover::before { - background-color: var(--ae-icon-hover-color); -} - -#theme_overflow_container { - overflow-y: auto; - height: calc( - 100vh - var(--ae-top-header-height) - (var(--ae-outside-gap-size) * 2) - - (var(--ae-inside-padding-size) * 4) - 96px - ); - overflow-x: hidden; -} - -#tab_ui_theme.open { - transform: translateX(0); - box-shadow: rgba(0, 0, 0, 0.4) -30px 0 30px -30px; -} - -#tab_ui_theme.aside { - display: block !important; -} - -#tab_ui_theme.aside { - position: fixed; - top: var(--ae-top-header-height); - width: 90%; - right: 0; - height: calc(100% - var(--ae-top-header-height)); - max-width: 480px; - z-index: 9999; - transform: translateX(100%); - transition: all 0.25s ease 0s; - box-shadow: rgba(0, 0, 0, 0) -30px 0 30px -30px; - padding: calc(1rem - var(--ae-outside-gap-size)); - background-color: var(--ae-main-bg-color) !important; -} -#tab_ui_theme.aside.open { - transform: translateX(0); - box-shadow: rgba(0, 0, 0, 0.4) -30px 0 30px -30px; -} - -#theme_hidden, -#setting_ui_header_tabs .theme, -#setting_ui_hidden_tabs .theme { - display: none !important; -} - -#tab_ui_theme [id*="color"] label { - display: flex; - align-items: center; - pointer-events: none; -} -#tab_ui_theme [id*="color"] label span { - min-width: 50% !important; -} -#tab_ui_theme [id*="color"] label input { - flex-grow: 1; - pointer-events: all; - cursor: pointer; -} - -#settings_ui_theme > div > div { - flex-direction: row; - flex-wrap: wrap; -} -#settings_ui_theme > div > div > div { - max-width: 30%; -} - -#tab_ui_theme > div { - padding: 16px !important; - padding-top: 0 !important; -} - -#ui_theme_hsv + button { - min-width: unset; -} diff --git a/extensions-builtin/sd_theme_editor/themes/Golde.css b/extensions-builtin/sd_theme_editor/themes/Golde.css deleted file mode 100644 index 552505965fa..00000000000 --- a/extensions-builtin/sd_theme_editor/themes/Golde.css +++ /dev/null @@ -1 +0,0 @@ ---ae-main-bg-color:hsl(99deg 11% 8%);--ae-primary-color:hsl(44deg 63% 55%);--ae-input-bg-color:hsl(106deg 8% 12%);--ae-input-border-color:hsl(104deg 9% 32%);--ae-panel-bg-color:hsl(104deg 9% 20%);--ae-panel-border-color:hsl(104deg 9% 32%);--ae-panel-border-radius:4px;--ae-subgroup-bg-color:hsl(99deg 11% 8%);--ae-subgroup-input-bg-color:hsl(99deg 11% 8%);--ae-subgroup-input-border-color:hsl(104deg 9% 32%);--ae-subpanel-bg-color:hsl(106deg 8% 12%);--ae-subpanel-border-color:hsl(104deg 9% 32%);--ae-subpanel-border-radius:8px;--ae-textarea-focus-color:hsl(56deg 30% 36%);--ae-input-focus-color:hsl(44deg 63% 55%);--ae-outside-gap-size:8px;--ae-inside-padding-size:8px;--ae-tool-button-size:34px;--ae-tool-button-radius:16px;--ae-generate-button-height:70px;--ae-cancel-color:hsl(104deg 9% 32%);--ae-max-padding:max(var(--ae-outside-gap-size),var(--ae-inside-padding-size));--ae-icon-color:hsl(105deg 9% 77%);--ae-icon-hover-color:hsl(99deg 11% 8%);--ae-icon-size:22px;--ae-nav-bg-color:hsl(98deg 9% 4%);--ae-nav-color:hsl(105deg 9% 77%);--ae-nav-hover-color:hsl(98deg 9% 4%);--ae-input-color:hsl(44deg 63% 55%);--ae-label-color:hsl(105deg 9% 77%);--ae-subgroup-input-color:hsl(44deg 63% 55%);--ae-placeholder-color:hsl(104deg 9% 32%);--ae-text-color:hsl(105deg 9% 77%);--ae-mobile-outside-gap-size:2px;--ae-mobile-inside-padding-size:2px;--ae-frame-bg-color:hsl(108deg 8% 12%);--ae-modal-bg-color:hsl(96deg 12% 8%);--ae-modal-icon-color:hsl(44deg 63% 55%); \ No newline at end of file diff --git a/extensions-builtin/sd_theme_editor/themes/backup.css b/extensions-builtin/sd_theme_editor/themes/backup.css deleted file mode 100644 index f2537ed37a6..00000000000 --- a/extensions-builtin/sd_theme_editor/themes/backup.css +++ /dev/null @@ -1 +0,0 @@ ---ae-main-bg-color:hsl(0deg 0% 10%);--ae-primary-color:hsl(168deg 96% 42%);--ae-input-bg-color:hsl(225deg 6% 13%);--ae-input-border-color:hsl(214deg 5% 30%);--ae-panel-bg-color:hsl(225deg 5% 17%);--ae-panel-border-color:hsl(214deg 5% 30%);--ae-panel-border-radius:0px;--ae-subgroup-bg-color:hsl(0deg 0% 10%);--ae-subgroup-input-bg-color:hsl(225deg 6% 13%);--ae-subgroup-input-border-color:hsl(214deg 5% 30%);--ae-subpanel-bg-color:hsl(220deg 4% 14%);--ae-subpanel-border-color:hsl(214deg 5% 30%);--ae-subpanel-border-radius:8px;--ae-textarea-focus-color:hsl(210deg 3% 36%);--ae-input-focus-color:hsl(168deg 97% 41%);--ae-outside-gap-size:8px;--ae-inside-padding-size:8px;--ae-tool-button-size:34px;--ae-tool-button-radius:16px;--ae-generate-button-height:70px;--ae-cancel-color:hsl(0deg 84% 60%);--ae-max-padding:max(var(--ae-outside-gap-size),var(--ae-inside-padding-size));--ae-icon-color:hsl(168deg 96% 42%);--ae-icon-hover-color:hsl(0deg 0% 10%);--ae-icon-size:22px;--ae-nav-bg-color:hsl(0deg 0% 4%);--ae-nav-color:hsl(210deg 4% 80%);--ae-nav-hover-color:hsl(0deg 0% 4%);--ae-input-color:hsl(210deg 4% 80%);--ae-label-color:hsl(210deg 4% 80%);--ae-subgroup-input-color:hsl(0deg 100% 100%);--ae-placeholder-color:hsl(214deg 5% 30%);--ae-text-color:hsl(210deg 4% 80%);--ae-mobile-outside-gap-size:3px;--ae-mobile-inside-padding-size:3px;--ae-frame-bg-color:hsl(225deg 6% 13%);--ae-modal-bg-color:hsl(0deg 0% 10%);--ae-modal-icon-color:hsl(168deg 97% 41%); \ No newline at end of file diff --git a/extensions-builtin/sd_theme_editor/themes/d-230-52-94.css b/extensions-builtin/sd_theme_editor/themes/d-230-52-94.css deleted file mode 100644 index 818b6d714d8..00000000000 --- a/extensions-builtin/sd_theme_editor/themes/d-230-52-94.css +++ /dev/null @@ -1 +0,0 @@ ---ae-main-bg-color:hsl(230deg 52% 4%);--ae-primary-color:hsl(38deg 148% 36%);--ae-input-bg-color:hsl(95deg 58% 7%);--ae-input-border-color:hsl(84deg 57% 24%);--ae-panel-bg-color:hsl(95deg 57% 11%);--ae-panel-border-color:hsl(84deg 57% 24%);--ae-panel-border-radius:0px;--ae-subgroup-bg-color:hsl(230deg 52% 4%);--ae-subgroup-input-bg-color:hsl(95deg 58% 7%);--ae-subgroup-input-border-color:hsl(84deg 57% 24%);--ae-subpanel-bg-color:hsl(90deg 56% 8%);--ae-subpanel-border-color:hsl(84deg 57% 24%);--ae-subpanel-border-radius:8px;--ae-textarea-focus-color:hsl(80deg 55% 30%);--ae-input-focus-color:hsl(38deg 149% 35%);--ae-outside-gap-size:8px;--ae-inside-padding-size:8px;--ae-tool-button-size:34px;--ae-tool-button-radius:16px;--ae-generate-button-height:70px;--ae-cancel-color:hsl(230deg 136% 54%);--ae-max-padding:max(var(--ae-outside-gap-size),var(--ae-inside-padding-size));--ae-icon-color:hsl(80deg 56% 74%);--ae-icon-hover-color:hsl(230deg 52% 4%);--ae-icon-size:22px;--ae-nav-bg-color:hsl(230deg 52% 98%);--ae-nav-color:hsl(80deg 56% 74%);--ae-nav-hover-color:hsl(230deg 52% 98%);--ae-input-color:hsl(80deg 56% 74%);--ae-label-color:hsl(80deg 56% 74%);--ae-subgroup-input-color:hsl(230deg 152% 94%);--ae-placeholder-color:hsl(84deg 57% 24%);--ae-text-color:hsl(80deg 56% 74%);--ae-mobile-outside-gap-size:3px;--ae-mobile-inside-padding-size:3px;--ae-frame-bg-color:hsl(94deg 60% 7%);--ae-modal-bg-color:hsl(229deg 52% 4%);--ae-modal-icon-color:hsl(38deg 100% 36%); \ No newline at end of file diff --git a/extensions-builtin/sd_theme_editor/themes/default.css b/extensions-builtin/sd_theme_editor/themes/default.css deleted file mode 100644 index b2131f91c97..00000000000 --- a/extensions-builtin/sd_theme_editor/themes/default.css +++ /dev/null @@ -1 +0,0 @@ ---ae-main-bg-color:hsl(0deg 0% 10%);--ae-primary-color:hsl(168deg 97% 41%);--ae-input-bg-color:hsl(225deg 6% 13%);--ae-input-border-color:hsl(214deg 5% 30%);--ae-panel-bg-color:hsl(225deg 5% 17%);--ae-panel-border-color:hsl(214deg 5% 30%);--ae-panel-border-radius:0px;--ae-subgroup-bg-color:hsl(0deg 0% 10%);--ae-subgroup-input-bg-color:hsl(225deg 6% 13%);--ae-subgroup-input-border-color:hsl(214deg 5% 30%);--ae-subpanel-bg-color:hsl(220deg 4% 14%);--ae-subpanel-border-color:hsl(214deg 5% 30%);--ae-subpanel-border-radius:8px;--ae-textarea-focus-color:hsl(210deg 3% 36%);--ae-input-focus-color:hsl(168deg 97% 41%);--ae-outside-gap-size:8px;--ae-inside-padding-size:8px;--ae-tool-button-size:34px;--ae-tool-button-radius:16px;--ae-generate-button-height:70px;--ae-cancel-color:hsl(0deg 84% 60%);--ae-max-padding:max(var(--ae-outside-gap-size),var(--ae-inside-padding-size));--ae-icon-color:hsl(168deg 97% 41%);--ae-icon-hover-color:hsl(0deg 0% 10%);--ae-icon-size:22px;--ae-nav-bg-color:hsl(0deg 0% 4%);--ae-nav-color:hsl(210deg 4% 80%);--ae-nav-hover-color:hsl(0deg 0% 4%);--ae-input-color:hsl(210deg 4% 80%);--ae-label-color:hsl(210deg 4% 80%);--ae-subgroup-input-color:hsl(210deg 4% 80%);--ae-placeholder-color:hsl(214deg 5% 30%);--ae-text-color:hsl(210deg 4% 80%);--ae-mobile-outside-gap-size:2px;--ae-mobile-inside-padding-size:2px;--ae-frame-bg-color:hsl(225deg 6% 13%);--ae-modal-bg-color:hsl(0deg 0% 10%);--ae-modal-icon-color:hsl(168deg 97% 41%); \ No newline at end of file diff --git a/extensions-builtin/sd_theme_editor/themes/default_cyan.css b/extensions-builtin/sd_theme_editor/themes/default_cyan.css deleted file mode 100644 index 3c1b32cd9e7..00000000000 --- a/extensions-builtin/sd_theme_editor/themes/default_cyan.css +++ /dev/null @@ -1 +0,0 @@ ---ae-main-bg-color:hsl(0deg 0% 10%);--ae-primary-color:hsl(199deg 60% 60%);--ae-input-bg-color:hsl(225deg 6% 13%);--ae-input-border-color:hsl(214deg 5% 30%);--ae-panel-bg-color:hsl(225deg 5% 17%);--ae-panel-border-color:hsl(214deg 5% 30%);--ae-panel-border-radius:0px;--ae-subgroup-bg-color:hsl(0deg 0% 10%);--ae-subgroup-input-bg-color:hsl(225deg 6% 13%);--ae-subgroup-input-border-color:hsl(214deg 5% 30%);--ae-subpanel-bg-color:hsl(220deg 4% 14%);--ae-subpanel-border-color:hsl(214deg 5% 30%);--ae-subpanel-border-radius:8px;--ae-textarea-focus-color:hsl(210deg 3% 36%);--ae-input-focus-color:hsl(199deg 60% 60%);--ae-outside-gap-size:8px;--ae-inside-padding-size:8px;--ae-tool-button-size:34px;--ae-tool-button-radius:16px;--ae-generate-button-height:70px;--ae-cancel-color:hsl(357deg 50% 57%);--ae-max-padding:max(var(--ae-outside-gap-size),var(--ae-inside-padding-size));--ae-icon-color:hsl(210deg 4% 80%);--ae-icon-hover-color:hsl(0deg 0% 10%);--ae-icon-size:22px;--ae-nav-bg-color:hsl(0deg 0% 4%);--ae-nav-color:hsl(210deg 4% 80%);--ae-nav-hover-color:hsl(0deg 0% 4%);--ae-input-color:hsl(210deg 4% 80%);--ae-label-color:hsl(210deg 4% 80%);--ae-subgroup-input-color:hsl(210deg 4% 80%);--ae-placeholder-color:hsl(214deg 5% 30%);--ae-text-color:hsl(210deg 4% 80%);--ae-mobile-outside-gap-size:2px;--ae-mobile-inside-padding-size:2px;--ae-frame-bg-color:hsl(225deg 6% 13%);--ae-modal-bg-color:hsl(0deg 0% 10%);--ae-modal-icon-color:hsl(199deg 60% 60%); \ No newline at end of file diff --git a/extensions-builtin/sd_theme_editor/themes/default_orange.css b/extensions-builtin/sd_theme_editor/themes/default_orange.css deleted file mode 100644 index 736775bec92..00000000000 --- a/extensions-builtin/sd_theme_editor/themes/default_orange.css +++ /dev/null @@ -1 +0,0 @@ ---ae-main-bg-color:hsl(0deg 0% 10%);--ae-primary-color:hsl(16deg 77% 60%);--ae-input-bg-color:hsl(225deg 6% 13%);--ae-input-border-color:hsl(214deg 5% 30%);--ae-panel-bg-color:hsl(225deg 5% 17%);--ae-panel-border-color:hsl(214deg 5% 30%);--ae-panel-border-radius:8px;--ae-subgroup-bg-color:hsl(0deg 0% 10%);--ae-subgroup-input-bg-color:hsl(225deg 6% 13%);--ae-subgroup-input-border-color:hsl(214deg 5% 30%);--ae-subpanel-bg-color:hsl(220deg 4% 14%);--ae-subpanel-border-color:hsl(214deg 5% 30%);--ae-subpanel-border-radius:8px;--ae-textarea-focus-color:hsl(210deg 3% 36%);--ae-input-focus-color:hsl(16deg 77% 60%);--ae-outside-gap-size:8px;--ae-inside-padding-size:8px;--ae-tool-button-size:34px;--ae-tool-button-radius:16px;--ae-generate-button-height:70px;--ae-cancel-color:hsl(193deg 54% 55%);--ae-max-padding:max(var(--ae-outside-gap-size),var(--ae-inside-padding-size));--ae-icon-color:hsl(210deg 4% 80%);--ae-icon-hover-color:hsl(0deg 0% 10%);--ae-icon-size:22px;--ae-nav-bg-color:hsl(0deg 0% 4%);--ae-nav-color:hsl(210deg 4% 80%);--ae-nav-hover-color:hsl(0deg 0% 4%);--ae-input-color:hsl(210deg 4% 80%);--ae-label-color:hsl(210deg 4% 80%);--ae-subgroup-input-color:hsl(210deg 4% 80%);--ae-placeholder-color:hsl(214deg 5% 30%);--ae-text-color:hsl(210deg 4% 80%);--ae-mobile-outside-gap-size:2px;--ae-mobile-inside-padding-size:2px;--ae-frame-bg-color:hsl(225deg 6% 13%);--ae-modal-bg-color:hsl(0deg 0% 10%);--ae-modal-icon-color:hsl(16deg 77% 60%); \ No newline at end of file diff --git a/extensions-builtin/sd_theme_editor/themes/fun.css b/extensions-builtin/sd_theme_editor/themes/fun.css deleted file mode 100644 index 23d77ece681..00000000000 --- a/extensions-builtin/sd_theme_editor/themes/fun.css +++ /dev/null @@ -1 +0,0 @@ ---ae-main-bg-color:hsl(253deg 22% 8%);--ae-primary-color:hsl(76deg 96% 55%);--ae-input-bg-color:hsl(260deg 25% 12%);--ae-input-border-color:hsl(258deg 24% 32%);--ae-panel-bg-color:hsl(258deg 24% 20%);--ae-panel-border-color:hsl(258deg 24% 32%);--ae-panel-border-radius:4px;--ae-subgroup-bg-color:hsl(253deg 22% 8%);--ae-subgroup-input-bg-color:hsl(258deg 24% 8%);--ae-subgroup-input-border-color:hsl(258deg 24% 32%);--ae-subpanel-bg-color:hsl(260deg 25% 12%);--ae-subpanel-border-color:hsl(258deg 24% 32%);--ae-subpanel-border-radius:8px;--ae-textarea-focus-color:hsl(210deg 3% 36%);--ae-input-focus-color:hsl(296deg 96% 55%);--ae-outside-gap-size:8px;--ae-inside-padding-size:8px;--ae-tool-button-size:34px;--ae-tool-button-radius:16px;--ae-generate-button-height:70px;--ae-cancel-color:hsl(258deg 24% 32%);--ae-max-padding:max(var(--ae-outside-gap-size),var(--ae-inside-padding-size));--ae-icon-color:hsl(259deg 24% 77%);--ae-icon-hover-color:hsl(253deg 22% 8%);--ae-icon-size:22px;--ae-nav-bg-color:hsl(252deg 24% 4%);--ae-nav-color:hsl(259deg 24% 77%);--ae-nav-hover-color:hsl(252deg 24% 4%);--ae-input-color:hsl(305deg 96% 55%);--ae-label-color:hsl(259deg 24% 77%);--ae-subgroup-input-color:hsl(76deg 96% 55%);--ae-placeholder-color:hsl(258deg 24% 32%);--ae-text-color:hsl(259deg 24% 77%);--ae-mobile-outside-gap-size:2px;--ae-mobile-inside-padding-size:2px;--ae-frame-bg-color:hsl(260deg 25% 12%);--ae-modal-bg-color:hsl(253deg 22% 8%);--ae-modal-icon-color:hsl(76deg 96% 55%); \ No newline at end of file diff --git a/extensions-builtin/sd_theme_editor/themes/minimal.css b/extensions-builtin/sd_theme_editor/themes/minimal.css deleted file mode 100644 index 279de7ae224..00000000000 --- a/extensions-builtin/sd_theme_editor/themes/minimal.css +++ /dev/null @@ -1 +0,0 @@ ---ae-main-bg-color:hsl(0deg 0% 8%);--ae-primary-color:hsl(168deg 96% 42%);--ae-input-bg-color:hsl(0deg 0% 10%);--ae-input-border-color:hsl(0deg 0% 10%);--ae-panel-bg-color:hsl(0deg 0% 17%);--ae-panel-border-color:hsl(0deg 0% 17%);--ae-panel-border-radius:4px;--ae-subgroup-bg-color:hsl(0deg 0% 10%);--ae-subgroup-input-bg-color:hsl(0deg 0% 10%);--ae-subgroup-input-border-color:hsl(0deg 0% 10%);--ae-subpanel-bg-color:hsl(0deg 0% 14%);--ae-subpanel-border-color:hsl(0deg 0% 15%);--ae-subpanel-border-radius:4px;--ae-textarea-focus-color:hsl(0deg 0% 36%);--ae-input-focus-color:hsl(168deg 97% 41%);--ae-outside-gap-size:1px;--ae-inside-padding-size:5px;--ae-tool-button-size:34px;--ae-tool-button-radius:16px;--ae-generate-button-height:70px;--ae-cancel-color:hsl(0deg 84% 60%);--ae-max-padding:max(var(--ae-outside-gap-size),var(--ae-inside-padding-size));--ae-icon-color:hsl(168deg 96% 42%);--ae-icon-hover-color:hsl(0deg 0% 10%);--ae-icon-size:22px;--ae-nav-bg-color:hsl(0deg 0% 4%);--ae-nav-color:hsl(0deg 0% 80%);--ae-nav-hover-color:hsl(0deg 0% 4%);--ae-input-color:hsl(210deg 4% 80%);--ae-label-color:hsl(0deg 0% 65%);--ae-subgroup-input-color:hsl(0deg 100% 100%);--ae-placeholder-color:hsl(0deg 0% 30%);--ae-text-color:hsl(0deg 0% 80%);--ae-mobile-outside-gap-size:3px;--ae-mobile-inside-padding-size:3px;--ae-frame-bg-color:hsl(0deg 0% 14%);--ae-modal-bg-color:hsl(0deg 0% 10%);--ae-modal-icon-color:hsl(168deg 97% 41%); \ No newline at end of file diff --git a/extensions-builtin/sd_theme_editor/themes/minimal_orange.css b/extensions-builtin/sd_theme_editor/themes/minimal_orange.css deleted file mode 100644 index ef2de97b376..00000000000 --- a/extensions-builtin/sd_theme_editor/themes/minimal_orange.css +++ /dev/null @@ -1 +0,0 @@ ---ae-main-bg-color:hsl(210deg 28% 8%);--ae-primary-color:hsl(18deg 124% 42%);--ae-input-bg-color:hsl(210deg 28% 10%);--ae-input-border-color:hsl(210deg 28% 10%);--ae-panel-bg-color:hsl(210deg 28% 17%);--ae-panel-border-color:hsl(210deg 28% 17%);--ae-panel-border-radius:4px;--ae-subgroup-bg-color:hsl(210deg 28% 10%);--ae-subgroup-input-bg-color:hsl(210deg 28% 10%);--ae-subgroup-input-border-color:hsl(210deg 28% 10%);--ae-subpanel-bg-color:hsl(210deg 28% 14%);--ae-subpanel-border-color:hsl(210deg 28% 15%);--ae-subpanel-border-radius:4px;--ae-textarea-focus-color:hsl(210deg 28% 36%);--ae-input-focus-color:hsl(18deg 125% 41%);--ae-outside-gap-size:8px;--ae-inside-padding-size:8px;--ae-tool-button-size:34px;--ae-tool-button-radius:16px;--ae-generate-button-height:70px;--ae-cancel-color:hsl(210deg 112% 60%);--ae-max-padding:max(var(--ae-outside-gap-size),var(--ae-inside-padding-size));--ae-icon-color:hsl(18deg 124% 42%);--ae-icon-hover-color:hsl(210deg 28% 10%);--ae-icon-size:22px;--ae-nav-bg-color:hsl(210deg 28% 4%);--ae-nav-color:hsl(210deg 28% 80%);--ae-nav-hover-color:hsl(210deg 28% 4%);--ae-input-color:hsl(60deg 32% 80%);--ae-label-color:hsl(210deg 28% 65%);--ae-subgroup-input-color:hsl(210deg 128% 100%);--ae-placeholder-color:hsl(210deg 28% 30%);--ae-text-color:hsl(210deg 28% 80%);--ae-mobile-outside-gap-size:3px;--ae-mobile-inside-padding-size:3px;--ae-frame-bg-color:hsl(210deg 28% 14%);--ae-modal-bg-color:hsl(210deg 28% 10%);--ae-modal-icon-color:hsl(18deg 125% 41%); \ No newline at end of file diff --git a/extensions-builtin/sd_theme_editor/themes/moonlight.css b/extensions-builtin/sd_theme_editor/themes/moonlight.css deleted file mode 100644 index 4f70e44c7d3..00000000000 --- a/extensions-builtin/sd_theme_editor/themes/moonlight.css +++ /dev/null @@ -1 +0,0 @@ ---ae-main-bg-color:hsl(240deg 16% 6%);--ae-primary-color:hsl(222deg 75% 62%);--ae-input-bg-color:hsl(240deg 17% 8%);--ae-input-border-color:hsl(240deg 20% 16%);--ae-panel-bg-color:hsl(240deg 18% 12%);--ae-panel-border-color:hsl(240deg 16% 16%);--ae-panel-border-radius:0px;--ae-subgroup-bg-color:hsl(240deg 17% 8%);--ae-subgroup-input-bg-color:hsl(240deg 17% 8%);--ae-subgroup-input-border-color:hsl(240deg 20% 16%);--ae-subpanel-bg-color:hsl(240deg 18% 10%);--ae-subpanel-border-color:hsl(240deg 20% 16%);--ae-subpanel-border-radius:8px;--ae-textarea-focus-color:hsl(210deg 3% 36%);--ae-input-focus-color:hsl(222deg 75% 62%);--ae-outside-gap-size:8px;--ae-inside-padding-size:8px;--ae-tool-button-size:34px;--ae-tool-button-radius:16px;--ae-generate-button-height:70px;--ae-cancel-color:hsl(222deg 75% 62%);--ae-max-padding:max(var(--ae-outside-gap-size),var(--ae-inside-padding-size));--ae-icon-color:hsl(222deg 75% 62%);--ae-icon-hover-color:hsl(240deg 18% 12%);--ae-icon-size:22px;--ae-nav-bg-color:hsl(240deg 16% 6%);--ae-nav-color:hsl(185deg 66% 85%);--ae-nav-hover-color:hsl(0deg 0% 4%);--ae-input-color:hsl(185deg 66% 85%);--ae-label-color:hsl(185deg 66% 85%);--ae-subgroup-input-color:hsl(185deg 66% 85%);--ae-placeholder-color:hsl(240deg 20% 24%);--ae-text-color:hsl(185deg 66% 85%);--ae-mobile-outside-gap-size:2px;--ae-mobile-inside-padding-size:2px;--ae-frame-bg-color:hsl(240deg 18% 10%);--ae-modal-bg-color:hsl(240deg 16% 6%);--ae-modal-icon-color:hsl(222deg 75% 62%); \ No newline at end of file diff --git a/extensions-builtin/sd_theme_editor/themes/ogxBGreen.css b/extensions-builtin/sd_theme_editor/themes/ogxBGreen.css deleted file mode 100644 index 1e497888732..00000000000 --- a/extensions-builtin/sd_theme_editor/themes/ogxBGreen.css +++ /dev/null @@ -1 +0,0 @@ ---ae-main-bg-color:hsl(195deg 22% 8%);--ae-primary-color:hsl(159deg 96% 55%);--ae-input-bg-color:hsl(202deg 25% 12%);--ae-input-border-color:hsl(200deg 24% 32%);--ae-panel-bg-color:hsl(200deg 24% 20%);--ae-panel-border-color:hsl(200deg 24% 32%);--ae-panel-border-radius:4px;--ae-subgroup-bg-color:hsl(195deg 22% 8%);--ae-subgroup-input-bg-color:hsl(200deg 24% 8%);--ae-subgroup-input-border-color:hsl(200deg 24% 32%);--ae-subpanel-bg-color:hsl(202deg 25% 12%);--ae-subpanel-border-color:hsl(200deg 24% 32%);--ae-subpanel-border-radius:8px;--ae-textarea-focus-color:hsl(152deg 3% 36%);--ae-input-focus-color:hsl(159deg 96% 55%);--ae-outside-gap-size:8px;--ae-inside-padding-size:8px;--ae-tool-button-size:34px;--ae-tool-button-radius:16px;--ae-generate-button-height:70px;--ae-cancel-color:hsl(200deg 24% 32%);--ae-max-padding:max(var(--ae-outside-gap-size),var(--ae-inside-padding-size));--ae-icon-color:hsl(159deg 96% 55%);--ae-icon-hover-color:hsl(195deg 22% 8%);--ae-icon-size:22px;--ae-nav-bg-color:hsl(194deg 24% 4%);--ae-nav-color:hsl(201deg 24% 77%);--ae-nav-hover-color:hsl(194deg 24% 4%);--ae-input-color:hsl(159deg 96% 55%);--ae-label-color:hsl(201deg 24% 77%);--ae-subgroup-input-color:hsl(159deg 96% 55%);--ae-placeholder-color:hsl(200deg 24% 32%);--ae-text-color:hsl(201deg 24% 77%);--ae-mobile-outside-gap-size:3px;--ae-mobile-inside-padding-size:3px;--ae-frame-bg-color:hsl(200deg 25% 12%);--ae-modal-bg-color:hsl(193deg 22% 8%);--ae-modal-icon-color:hsl(159deg 96% 55%); \ No newline at end of file diff --git a/extensions-builtin/sd_theme_editor/themes/ogxCyan.css b/extensions-builtin/sd_theme_editor/themes/ogxCyan.css deleted file mode 100644 index 3ca6e23cb63..00000000000 --- a/extensions-builtin/sd_theme_editor/themes/ogxCyan.css +++ /dev/null @@ -1 +0,0 @@ ---ae-main-bg-color:hsl(253deg 22% 8%);--ae-primary-color:hsl(198deg 96% 55%);--ae-input-bg-color:hsl(260deg 25% 12%);--ae-input-border-color:hsl(258deg 24% 32%);--ae-panel-bg-color:hsl(258deg 24% 20%);--ae-panel-border-color:hsl(258deg 24% 32%);--ae-panel-border-radius:4px;--ae-subgroup-bg-color:hsl(253deg 22% 8%);--ae-subgroup-input-bg-color:hsl(258deg 24% 8%);--ae-subgroup-input-border-color:hsl(258deg 24% 32%);--ae-subpanel-bg-color:hsl(260deg 25% 12%);--ae-subpanel-border-color:hsl(258deg 24% 32%);--ae-subpanel-border-radius:8px;--ae-textarea-focus-color:hsl(210deg 3% 36%);--ae-input-focus-color:hsl(198deg 96% 55%);--ae-outside-gap-size:8px;--ae-inside-padding-size:8px;--ae-tool-button-size:34px;--ae-tool-button-radius:16px;--ae-generate-button-height:70px;--ae-cancel-color:hsl(258deg 24% 32%);--ae-max-padding:max(var(--ae-outside-gap-size),var(--ae-inside-padding-size));--ae-icon-color:hsl(259deg 24% 77%);--ae-icon-hover-color:hsl(253deg 22% 8%);--ae-icon-size:22px;--ae-nav-bg-color:hsl(252deg 24% 4%);--ae-nav-color:hsl(259deg 24% 77%);--ae-nav-hover-color:hsl(252deg 24% 4%);--ae-input-color:hsl(198deg 96% 55%);--ae-label-color:hsl(259deg 24% 77%);--ae-subgroup-input-color:hsl(198deg 96% 55%);--ae-placeholder-color:hsl(258deg 24% 32%);--ae-text-color:hsl(259deg 24% 77%);--ae-mobile-outside-gap-size:2px;--ae-mobile-inside-padding-size:2px;--ae-frame-bg-color:hsl(260deg 25% 12%);--ae-modal-bg-color:hsl(253deg 22% 8%);--ae-modal-icon-color:hsl(198deg 96% 55%); \ No newline at end of file diff --git a/extensions-builtin/sd_theme_editor/themes/ogxCyanInvert.css b/extensions-builtin/sd_theme_editor/themes/ogxCyanInvert.css deleted file mode 100644 index 02b04e2d496..00000000000 --- a/extensions-builtin/sd_theme_editor/themes/ogxCyanInvert.css +++ /dev/null @@ -1 +0,0 @@ ---ae-main-bg-color:hsl(73deg 22% 92%);--ae-primary-color:hsl(18deg 96% 45%);--ae-input-bg-color:hsl(80deg 25% 88%);--ae-input-border-color:hsl(78deg 24% 68%);--ae-panel-bg-color:hsl(78deg 24% 80%);--ae-panel-border-color:hsl(78deg 24% 68%);--ae-panel-border-radius:4px;--ae-subgroup-bg-color:hsl(73deg 22% 92%);--ae-subgroup-input-bg-color:hsl(73deg 22% 92%);--ae-subgroup-input-border-color:hsl(78deg 24% 68%);--ae-subpanel-bg-color:hsl(80deg 25% 88%);--ae-subpanel-border-color:hsl(78deg 24% 68%);--ae-subpanel-border-radius:8px;--ae-textarea-focus-color:hsl(30deg 3% 64%);--ae-input-focus-color:hsl(18deg 96% 45%);--ae-outside-gap-size:8px;--ae-inside-padding-size:8px;--ae-tool-button-size:34px;--ae-tool-button-radius:16px;--ae-generate-button-height:70px;--ae-cancel-color:hsl(78deg 24% 68%);--ae-max-padding:max(var(--ae-outside-gap-size),var(--ae-inside-padding-size));--ae-icon-color:hsl(79deg 24% 23%);--ae-icon-hover-color:hsl(73deg 22% 92%);--ae-icon-size:22px;--ae-nav-bg-color:hsl(72deg 24% 96%);--ae-nav-color:hsl(79deg 24% 23%);--ae-nav-hover-color:hsl(72deg 24% 96%);--ae-input-color:hsl(18deg 96% 45%);--ae-label-color:hsl(79deg 24% 23%);--ae-subgroup-input-color:hsl(18deg 96% 45%);--ae-placeholder-color:hsl(78deg 24% 68%);--ae-text-color:hsl(79deg 24% 23%);--ae-mobile-outside-gap-size:2px;--ae-mobile-inside-padding-size:2px;--ae-frame-bg-color:hsl(80deg 25% 88%);--ae-modal-bg-color:hsl(73deg 22% 92%);--ae-modal-icon-color:hsl(18deg 96% 45%); \ No newline at end of file diff --git a/extensions-builtin/sd_theme_editor/themes/ogxGreen.css b/extensions-builtin/sd_theme_editor/themes/ogxGreen.css deleted file mode 100644 index 077e55e7cc2..00000000000 --- a/extensions-builtin/sd_theme_editor/themes/ogxGreen.css +++ /dev/null @@ -1 +0,0 @@ ---ae-main-bg-color:hsl(253deg 22% 8%);--ae-primary-color:hsl(149deg 96% 55%);--ae-input-bg-color:hsl(260deg 25% 12%);--ae-input-border-color:hsl(258deg 24% 32%);--ae-panel-bg-color:hsl(258deg 24% 20%);--ae-panel-border-color:hsl(258deg 24% 32%);--ae-panel-border-radius:4px;--ae-subgroup-bg-color:hsl(253deg 22% 8%);--ae-subgroup-input-bg-color:hsl(258deg 24% 8%);--ae-subgroup-input-border-color:hsl(258deg 24% 32%);--ae-subpanel-bg-color:hsl(260deg 25% 12%);--ae-subpanel-border-color:hsl(258deg 24% 32%);--ae-subpanel-border-radius:8px;--ae-textarea-focus-color:hsl(210deg 3% 36%);--ae-input-focus-color:hsl(149deg 96% 55%);--ae-outside-gap-size:8px;--ae-inside-padding-size:8px;--ae-tool-button-size:34px;--ae-tool-button-radius:16px;--ae-generate-button-height:70px;--ae-cancel-color:hsl(258deg 24% 32%);--ae-max-padding:max(var(--ae-outside-gap-size),var(--ae-inside-padding-size));--ae-icon-color:hsl(259deg 24% 77%);--ae-icon-hover-color:hsl(253deg 22% 8%);--ae-icon-size:22px;--ae-nav-bg-color:hsl(252deg 24% 4%);--ae-nav-color:hsl(259deg 24% 77%);--ae-nav-hover-color:hsl(252deg 24% 4%);--ae-input-color:hsl(149deg 96% 55%);--ae-label-color:hsl(259deg 24% 77%);--ae-subgroup-input-color:hsl(149deg 96% 55%);--ae-placeholder-color:hsl(258deg 24% 32%);--ae-text-color:hsl(259deg 24% 77%);--ae-mobile-outside-gap-size:3px;--ae-mobile-inside-padding-size:3px;--ae-frame-bg-color:hsl(260deg 25% 12%);--ae-modal-bg-color:hsl(253deg 22% 8%);--ae-modal-icon-color:hsl(253deg 22% 8%); \ No newline at end of file diff --git a/extensions-builtin/sd_theme_editor/themes/ogxRed.css b/extensions-builtin/sd_theme_editor/themes/ogxRed.css deleted file mode 100644 index 3d7d86a14d3..00000000000 --- a/extensions-builtin/sd_theme_editor/themes/ogxRed.css +++ /dev/null @@ -1 +0,0 @@ ---ae-main-bg-color:hsl(253deg 22% 8%);--ae-primary-color:hsl(347deg 96% 55%);--ae-input-bg-color:hsl(260deg 25% 12%);--ae-input-border-color:hsl(258deg 24% 32%);--ae-panel-bg-color:hsl(258deg 24% 20%);--ae-panel-border-color:hsl(258deg 24% 32%);--ae-panel-border-radius:4px;--ae-subgroup-bg-color:hsl(253deg 22% 8%);--ae-subgroup-input-bg-color:hsl(258deg 24% 8%);--ae-subgroup-input-border-color:hsl(258deg 24% 32%);--ae-subpanel-bg-color:hsl(260deg 25% 12%);--ae-subpanel-border-color:hsl(258deg 24% 32%);--ae-subpanel-border-radius:8px;--ae-textarea-focus-color:hsl(210deg 3% 36%);--ae-input-focus-color:hsl(347deg 96% 55%);--ae-outside-gap-size:8px;--ae-inside-padding-size:8px;--ae-tool-button-size:34px;--ae-tool-button-radius:16px;--ae-generate-button-height:70px;--ae-cancel-color:hsl(258deg 24% 32%);--ae-max-padding:max(var(--ae-outside-gap-size),var(--ae-inside-padding-size));--ae-icon-color:hsl(259deg 24% 77%);--ae-icon-hover-color:hsl(253deg 22% 8%);--ae-icon-size:22px;--ae-nav-bg-color:hsl(252deg 24% 4%);--ae-nav-color:hsl(259deg 24% 77%);--ae-nav-hover-color:hsl(252deg 24% 4%);--ae-input-color:hsl(347deg 96% 55%);--ae-label-color:hsl(259deg 24% 77%);--ae-subgroup-input-color:hsl(347deg 96% 55%);--ae-placeholder-color:hsl(258deg 24% 32%);--ae-text-color:hsl(259deg 24% 77%);--ae-mobile-outside-gap-size:3px;--ae-mobile-inside-padding-size:3px;--ae-frame-bg-color:hsl(260deg 25% 12%);--ae-modal-bg-color:hsl(253deg 22% 8%);--ae-modal-icon-color:hsl(347deg 96% 55%); \ No newline at end of file diff --git a/extensions-builtin/sd_theme_editor/themes/retrog.css b/extensions-builtin/sd_theme_editor/themes/retrog.css deleted file mode 100644 index 54839175b58..00000000000 --- a/extensions-builtin/sd_theme_editor/themes/retrog.css +++ /dev/null @@ -1 +0,0 @@ ---ae-main-bg-color:hsl(197deg 97% 14%);--ae-primary-color:hsl(27deg 99% 50%);--ae-input-bg-color:hsl(197deg 98% 16%);--ae-input-border-color:hsl(166deg 62% 33%);--ae-panel-bg-color:hsl(196deg 98% 18%);--ae-panel-border-color:hsl(166deg 62% 33%);--ae-panel-border-radius:0px;--ae-subgroup-bg-color:hsl(197deg 97% 14%);--ae-subgroup-input-bg-color:hsl(197deg 97% 14%);--ae-subgroup-input-border-color:hsl(166deg 62% 33%);--ae-subpanel-bg-color:hsl(197deg 98% 16%);--ae-subpanel-border-color:hsl(166deg 62% 33%);--ae-subpanel-border-radius:8px;--ae-textarea-focus-color:hsl(210deg 3% 36%);--ae-input-focus-color:hsl(222deg 75% 62%);--ae-outside-gap-size:6px;--ae-inside-padding-size:6px;--ae-tool-button-size:34px;--ae-tool-button-radius:16px;--ae-generate-button-height:70px;--ae-cancel-color:hsl(70deg 69% 54%);--ae-max-padding:max(var(--ae-outside-gap-size),var(--ae-inside-padding-size));--ae-icon-color:hsl(27deg 99% 50%);--ae-icon-hover-color:hsl(196deg 98% 18%);--ae-icon-size:22px;--ae-nav-bg-color:hsl(197deg 97% 14%);--ae-nav-color:hsl(70deg 69% 54%);--ae-nav-hover-color:hsl(197deg 97% 14%);--ae-input-color:hsl(70deg 69% 54%);--ae-label-color:hsl(70deg 69% 54%);--ae-subgroup-input-color:hsl(27deg 99% 50%);--ae-placeholder-color:hsl(166deg 62% 33%);--ae-text-color:hsl(185deg 66% 85%);--ae-mobile-outside-gap-size:3px;--ae-mobile-inside-padding-size:3px;--ae-frame-bg-color:hsl(197deg 98% 16%);--ae-modal-bg-color:hsl(197deg 97% 14%);--ae-modal-icon-color:hsl(27deg 99% 50%); \ No newline at end of file diff --git a/extensions-builtin/sd_theme_editor/themes/tron.css b/extensions-builtin/sd_theme_editor/themes/tron.css deleted file mode 100644 index 65c3248a427..00000000000 --- a/extensions-builtin/sd_theme_editor/themes/tron.css +++ /dev/null @@ -1 +0,0 @@ ---ae-main-bg-color:hsl(185deg 75% 3%);--ae-primary-color:hsl(182deg 95% 51%);--ae-input-bg-color:hsl(185deg 73% 3%);--ae-input-border-color:hsl(185deg 72% 25%);--ae-panel-bg-color:hsl(180deg 76% 5%);--ae-panel-border-color:hsl(185deg 72% 25%);--ae-panel-border-radius:0px;--ae-subgroup-bg-color:hsl(185deg 73% 3%);--ae-subgroup-input-bg-color:hsl(185deg 73% 3%);--ae-subgroup-input-border-color:hsl(185deg 72% 25%);--ae-subpanel-bg-color:hsl(185deg 73% 3%);--ae-subpanel-border-color:hsl(185deg 72% 25%);--ae-subpanel-border-radius:0px;--ae-textarea-focus-color:hsl(182deg 95% 51%);--ae-input-focus-color:hsl(182deg 95% 51%);--ae-outside-gap-size:2px;--ae-inside-padding-size:8px;--ae-tool-button-size:34px;--ae-tool-button-radius:16px;--ae-generate-button-height:70px;--ae-cancel-color:hsl(182deg 95% 51%);--ae-max-padding:max(var(--ae-outside-gap-size),var(--ae-inside-padding-size));--ae-icon-color:hsl(182deg 95% 51%);--ae-icon-hover-color:hsl(185deg 73% 3%);--ae-icon-size:22px;--ae-nav-bg-color:hsl(185deg 73% 3%);--ae-nav-color:hsl(182deg 95% 75%);--ae-nav-hover-color:hsl(0deg 100% 50%);--ae-input-color:hsl(182deg 95% 75%);--ae-label-color:hsl(182deg 95% 75%);--ae-subgroup-input-color:hsl(182deg 95% 51%);--ae-placeholder-color:hsl(185deg 72% 25%);--ae-text-color:hsl(182deg 95% 75%);--ae-mobile-outside-gap-size:2px;--ae-mobile-inside-padding-size:8px;--ae-frame-bg-color:hsl(180deg 76% 5%);--ae-modal-bg-color:hsl(185deg 73% 3%);--ae-modal-icon-color:hsl(182deg 95% 51%); \ No newline at end of file diff --git a/extensions-builtin/sd_theme_editor/themes/tron2.css b/extensions-builtin/sd_theme_editor/themes/tron2.css deleted file mode 100644 index 98eeacbcd6b..00000000000 --- a/extensions-builtin/sd_theme_editor/themes/tron2.css +++ /dev/null @@ -1 +0,0 @@ ---ae-main-bg-color:hsl(185deg 75% 3%);--ae-primary-color:hsl(182deg 95% 51%);--ae-input-bg-color:hsl(184deg 89% 7%);--ae-input-border-color:hsl(185deg 72% 25%);--ae-panel-bg-color:hsl(185deg 73% 3%);--ae-panel-border-color:hsl(185deg 72% 25%);--ae-panel-border-radius:0px;--ae-subgroup-bg-color:hsl(185deg 73% 3%);--ae-subgroup-input-bg-color:hsl(185deg 73% 3%);--ae-subgroup-input-border-color:hsl(185deg 72% 25%);--ae-subpanel-bg-color:hsl(185deg 73% 3%);--ae-subpanel-border-color:hsl(185deg 72% 25%);--ae-subpanel-border-radius:0px;--ae-textarea-focus-color:hsl(182deg 95% 51%);--ae-input-focus-color:hsl(182deg 95% 51%);--ae-outside-gap-size:2px;--ae-inside-padding-size:8px;--ae-tool-button-size:34px;--ae-tool-button-radius:16px;--ae-generate-button-height:70px;--ae-cancel-color:hsl(182deg 95% 51%);--ae-max-padding:max(var(--ae-outside-gap-size),var(--ae-inside-padding-size));--ae-icon-color:hsl(182deg 95% 51%);--ae-icon-hover-color:hsl(185deg 73% 3%);--ae-icon-size:22px;--ae-nav-bg-color:hsl(185deg 73% 3%);--ae-nav-color:hsl(182deg 95% 75%);--ae-nav-hover-color:hsl(0deg 100% 50%);--ae-input-color:hsl(182deg 95% 75%);--ae-label-color:hsl(182deg 95% 75%);--ae-subgroup-input-color:hsl(182deg 95% 51%);--ae-placeholder-color:hsl(185deg 72% 25%);--ae-text-color:hsl(182deg 95% 75%);--ae-mobile-outside-gap-size:2px;--ae-mobile-inside-padding-size:8px;--ae-frame-bg-color:hsl(185deg 73% 3%); \ No newline at end of file diff --git a/html/200w.webp b/html/200w.webp deleted file mode 100644 index cd3782d08e2..00000000000 Binary files a/html/200w.webp and /dev/null differ diff --git a/html/card-no-preview.png b/html/card-no-preview.png index a1cac2e0768..e2beb269206 100644 Binary files a/html/card-no-preview.png and b/html/card-no-preview.png differ diff --git a/html/extra-networks-card.html b/html/extra-networks-card.html index 0cf61664354..39674666f1e 100644 --- a/html/extra-networks-card.html +++ b/html/extra-networks-card.html @@ -1,18 +1,14 @@ -
-
- +
+ {background_image} +
{metadata_button} {edit_button} -
-
- - -
- {name} +
+
+
+
+ {name} {description}
-
diff --git a/html/favicon.ico b/html/favicon.ico deleted file mode 100644 index 0bdafb82b16..00000000000 Binary files a/html/favicon.ico and /dev/null differ diff --git a/html/footer.html b/html/footer.html index 2418fd529b0..69b2372c755 100644 --- a/html/footer.html +++ b/html/footer.html @@ -1,55 +1,15 @@ - +
+ API +  •  + Github +  •  + Gradio +  •  + Startup profile +  •  + Reload UI +
+
+
+{versions} +
diff --git a/html/spotlight.css b/html/spotlight.css deleted file mode 100644 index c5f521591ac..00000000000 --- a/html/spotlight.css +++ /dev/null @@ -1,363 +0,0 @@ -:root{ - --primary-color:#ffffff; -} -#spotlight { - position: fixed; - top: -1px; - bottom: -1px; - width: 100%; - z-index: 99999; - color: #fff; - background-color: #000; - opacity: 0; - overflow: hidden; - user-select: none; - transition: opacity 0.2s ease-out; - font-family: Arial, sans-serif; - font-size: 16px; - font-weight: 400; - contain: strict; - touch-action: none; - pointer-events: none; -} -#spotlight.show { - opacity: 1; - transition: none; - pointer-events: auto; -} -#spotlight.white { - color: #212529; - background-color: #fff; -} -#spotlight.white .spl-spinner, -#spotlight.white .spl-prev, -#spotlight.white .spl-next, -#spotlight.white .spl-page ~ * { - filter: invert(1); -} -#spotlight.white .spl-progress { - background-color: rgba(0, 0, 0, 0.35); -} -#spotlight.white .spl-header, -#spotlight.white .spl-footer { - background-color: rgba(255, 255, 255, 0.65); -} -#spotlight.white .spl-button { - background: #212529; - color: #fff; -} -#spotlight .cover { - object-fit: cover; - height: 100%; - width: 100%; -} -#spotlight .contain { - object-fit: contain; - height: 100%; - width: 100%; -} -#spotlight .autofit { - object-fit: none; - width: auto; - height: auto; - max-height: none; - max-width: none; - transition: none; -} -.spl-track { - position: absolute; - width: 100%; - height: 100%; - contain: strict; -} -.spl-spinner { - position: absolute; - width: 100%; - height: 100%; - background-position: center; - background-repeat: no-repeat; - background-size: 42px; - opacity: 0; -} -.spl-spinner.spin { - background-image: url("svg/spotlight/preloader.svg"); - transition: opacity 0.2s linear 0.25s; - opacity: 1; -} -.spl-spinner.error { - background-image: url("svg/spotlight/error.svg"); - background-size: 128px; - transition: none; - opacity: 0.5; -} -.spl-scene { - position: absolute; - width: 100%; - height: 100%; - transition: transform 0.65s cubic-bezier(0.1, 1, 0.1, 1); - contain: layout size; - will-change: transform; -} -.spl-pane > * { - position: absolute; - width: auto; - height: auto; - max-width: 100%; - max-height: 100%; - left: 50%; - top: 50%; - margin: 0; - padding: 0; - border: 0; - transform: translate(-50%, -50%) scale(1); - transition: transform 0.65s cubic-bezier(0.3, 1, 0.3, 1), opacity 0.65s ease; - contain: layout style; - will-change: transform, opacity; - visibility: hidden; -} -.spl-pane { - position: absolute; - top: 0; - width: 100%; - height: 100%; - transition: transform 0.65s cubic-bezier(0.3, 1, 0.3, 1); - contain: layout size; - will-change: transform, contents; -} -.spl-pane.hide img { - display:none !important; -} -.spl-pane.hide { - background-size: 100%; - transition: background-size 0.65s cubic-bezier(0.3, 1, 0.3, 1) !important; - will-change: background-size !important; - transform: translate(0, 0) !important; -} -.spl-header { - position: absolute; - top: 0; - width: 100%; - height: 50px; - text-align: right; - background-color: rgba(0, 0, 0, 0.45); - transform: translateY(-100px); - transition: transform 0.35s ease; - overflow: hidden; - will-change: transform; -} -#spotlight.menu .spl-header, -.spl-header:hover { - transform: translateY(0); -} -.spl-header div { - display: inline-block; - vertical-align: middle; - white-space: nowrap; - width: 50px; - height: 50px; - opacity: 0.5; -} -.spl-progress { - position: absolute; - top: 0; - width: 100%; - height: 3px; - background-color: rgba(255, 255, 255, 0.45); - transform: translateX(-100%); - transition: transform linear; -} -.spl-footer { - position: absolute; - left: 0; - right: 0; - bottom: 0; - background-color: rgba(0, 0, 0, 0.45); - line-height: 20px; - padding: 20px 20px 0 20px; - padding-bottom: env(safe-area-inset-bottom, 0); - text-align: left; - font-size: 15px; - font-weight: 400; - transform: translateY(100%); - transition: transform 0.35s ease; - will-change: transform; -} -#spotlight.menu .spl-footer, -.spl-footer:hover { - transform: translateY(0); -} -.spl-title { - font-size: 22px; - margin-bottom: 20px; -} -.spl-description { - margin-bottom: 20px; -} -.spl-button { - display: inline-block; - background: #fff; - color: #000; - border-radius: 5px; - padding: 10px 20px; - margin-bottom: 20px; - cursor: pointer; -} -.spl-page { - float: left; - width: auto; - line-height: 50px; -} -.spl-page ~ * { - background-position: center; - background-repeat: no-repeat; - background-size: 21px; - float: right; -} -.spl-fullscreen { - background-color:var(--primary-color); - -webkit-mask: url("svg/fullscreen-line.svg") no-repeat 50% 50%; - mask: url("svg/fullscreen-line.svg") no-repeat 50% 50%; -} -.spl-fullscreen.on { - background-color:var(--primary-color); - -webkit-mask: url("svg/fullscreen-exit-line.svg") no-repeat 50% 50%; - mask: url("svg/fullscreen-exit-line.svg") no-repeat 50% 50%; -} -.spl-autofit { - background-color:var(--primary-color); - -webkit-mask: url("svg/aspect-ratio-line.svg") no-repeat 50% 50%; - mask: url("svg/aspect-ratio-line.svg") no-repeat 50% 50%; -} -.spl-zoom-out { - background-color:var(--primary-color); - -webkit-mask: url("svg/zoom-out-line.svg") no-repeat 50% 50%; - mask: url("svg/zoom-out-line.svg") no-repeat 50% 50%; - background-size: 22px; -} -.spl-zoom-in { - background-color:var(--primary-color); - -webkit-mask: url("svg/zoom-in-line.svg") no-repeat 50% 50%; - mask: url("svg/zoom-in-line.svg") no-repeat 50% 50%; - background-size: 22px; -} -.spl-download { - background-color:var(--primary-color); - -webkit-mask: url("svg/file-download-line.svg") no-repeat 50% 50%; - mask: url("svg/file-download-line.svg") no-repeat 50% 50%; - background-size: 20px; -} -.spl-theme { - background-image: url("svg/spotlight/theme.svg"); -} -.spl-play { - background-image: url("svg/spotlight/play.svg"); -} -.spl-play.on { - background-image: url("svg/spotlight/pause.svg"); - animation: pulsate 1s ease infinite; -} -.spl-close { - background-color:var(--primary-color); - -webkit-mask: url("svg/close-line.svg") no-repeat 50% 50%; - mask: url("svg/close-line.svg") no-repeat 50% 50%; -} -.spl-like{ - background-color:var(--primary-color); - -webkit-mask: url("svg/heart-line.svg") no-repeat 50% 50%; - mask: url("svg/heart-line.svg") no-repeat 50% 50%; - background-size: 22px; -} -.spl-like.on{ - background-color:var(--primary-color); - -webkit-mask: url("svg/heart-fill.svg") no-repeat 50% 50%; - mask: url("svg/heart-fill.svg") no-repeat 50% 50%; -} -.spl-tile{ - background-color:var(--primary-color); - -webkit-mask: url("svg/grid-line.svg") no-repeat 50% 50%; - mask: url("svg/grid-line.svg") no-repeat 50% 50%; - background-size: 22px; -} -.spl-tile.on{ - background-color:var(--primary-color); - -webkit-mask: url("svg/grid-fill.svg") no-repeat 50% 50%; - mask: url("svg/grid-fill.svg") no-repeat 50% 50%; -} - -.spl-prev, -.spl-next { - position: absolute; - top: 50%; - left: 20px; - width: 50px; - height: 50px; - opacity: 0.65; - background-color: rgba(0, 0, 0, 0.45); - border-radius: 100%; - cursor: pointer; - margin-top: -25px; - transform: translateX(-100px); - transition: transform 0.35s ease; - background-image: url("svg/spotlight/arrow.svg"); - background-position: center; - background-repeat: no-repeat; - background-size: 30px; - will-change: transform; -} -.spl-next { - left: auto; - right: 20px; - transform: translateX(100px) scaleX(-1); -} -#spotlight.menu .spl-prev { - transform: translateX(0); -} -#spotlight.menu .spl-next { - transform: translateX(0) scaleX(-1); -} -@media (hover: hover) { - .spl-page ~ div { - cursor: pointer; - transition: opacity 0.2s ease; - } - .spl-page ~ div:hover, - .spl-prev:hover, - .spl-next:hover { - opacity: 1; - } -} -@media (max-width: 500px) { - .spl-header div { - width: 44px; - } - .spl-footer .spl-title { - font-size: 20px; - } - .spl-footer { - font-size: 14px; - } - .spl-prev, - .spl-next { - width: 35px; - height: 35px; - margin-top: -17.5px; - background-size: 15px 15px; - } - .spl-spinner { - background-size: 30px 30px; - } -} -.hide-scrollbars { - overflow: hidden !important; -} -@keyframes pulsate { - 0% { - opacity: 1; - } - 50% { - opacity: 0.2; - } - 100% { - opacity: 1; - } -} \ No newline at end of file diff --git a/html/svg/play-line.svg b/html/svg/play-line.svg deleted file mode 100644 index a967d730875..00000000000 --- a/html/svg/play-line.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/html/svg/rocket-fill.svg b/html/svg/rocket-fill.svg deleted file mode 100644 index bb4e93ffa55..00000000000 --- a/html/svg/rocket-fill.svg +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - diff --git a/html/svg/skip-forward-line.svg b/html/svg/skip-forward-line.svg deleted file mode 100644 index 24eebda3ebe..00000000000 --- a/html/svg/skip-forward-line.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/html/svg/sort-asc.svg b/html/svg/sort-asc.svg deleted file mode 100644 index 96552675c8d..00000000000 --- a/html/svg/sort-asc.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/html/svg/sort-desc.svg b/html/svg/sort-desc.svg deleted file mode 100644 index a25ce6c2b87..00000000000 --- a/html/svg/sort-desc.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/html/svg/stop-line.svg b/html/svg/stop-line.svg deleted file mode 100644 index 3c5290b7834..00000000000 --- a/html/svg/stop-line.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/html/svg/terminal-box-line.svg b/html/svg/terminal-box-line.svg deleted file mode 100644 index 594c5296bd7..00000000000 --- a/html/svg/terminal-box-line.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/javascript/aspectRatioOverlay.js b/javascript/aspectRatioOverlay.js index fff1a992528..2cf2d571fc0 100644 --- a/javascript/aspectRatioOverlay.js +++ b/javascript/aspectRatioOverlay.js @@ -1,3 +1,4 @@ + let currentWidth = null; let currentHeight = null; let arFrameTimeout = setTimeout(function() {}, 0); diff --git a/javascript/badScaleChecker.js b/javascript/badScaleChecker.js deleted file mode 100644 index 625ad309da1..00000000000 --- a/javascript/badScaleChecker.js +++ /dev/null @@ -1,108 +0,0 @@ -(function() { - var ignore = localStorage.getItem("bad-scale-ignore-it") == "ignore-it"; - - function getScale() { - var ratio = 0, - screen = window.screen, - ua = navigator.userAgent.toLowerCase(); - - if (window.devicePixelRatio !== undefined) { - ratio = window.devicePixelRatio; - } else if (~ua.indexOf('msie')) { - if (screen.deviceXDPI && screen.logicalXDPI) { - ratio = screen.deviceXDPI / screen.logicalXDPI; - } - } else if (window.outerWidth !== undefined && window.innerWidth !== undefined) { - ratio = window.outerWidth / window.innerWidth; - } - - return ratio == 0 ? 0 : Math.round(ratio * 100); - } - - var showing = false; - - var div = document.createElement("div"); - div.style.position = "fixed"; - div.style.top = "0px"; - div.style.left = "0px"; - div.style.width = "100vw"; - div.style.backgroundColor = "firebrick"; - div.style.textAlign = "center"; - div.style.zIndex = 99; - - var b = document.createElement("b"); - b.innerHTML = 'Bad Scale: ??% '; - - div.appendChild(b); - - var note1 = document.createElement("p"); - note1.innerHTML = "Change your browser or your computer settings!"; - note1.title = 'Just make sure "computer-scale" * "browser-scale" = 100% ,\n' + - "you can keep your computer-scale and only change this page's scale,\n" + - "for example: your computer-scale is 125%, just use [\"CTRL\"+\"-\"] to make your browser-scale of this page to 80%."; - div.appendChild(note1); - - var note2 = document.createElement("p"); - note2.innerHTML = " Otherwise, it will cause this page to not function properly!"; - note2.title = "When you click \"Copy image to: [inpaint sketch]\" in some img2img's tab,\n" + - "if scale<100% the canvas will be invisible,\n" + - "else if scale>100% this page will take large amount of memory and CPU performance."; - div.appendChild(note2); - - var btn = document.createElement("button"); - btn.innerHTML = "Click here to ignore"; - - div.appendChild(btn); - - function tryShowTopBar(scale) { - if (showing) return; - - b.innerHTML = 'Bad Scale: ' + scale + '% '; - - var updateScaleTimer = setInterval(function() { - var newScale = getScale(); - b.innerHTML = 'Bad Scale: ' + newScale + '% '; - if (newScale == 100) { - var p = div.parentNode; - if (p != null) p.removeChild(div); - showing = false; - clearInterval(updateScaleTimer); - check(); - } - }, 999); - - btn.onclick = function() { - clearInterval(updateScaleTimer); - var p = div.parentNode; - if (p != null) p.removeChild(div); - ignore = true; - showing = false; - localStorage.setItem("bad-scale-ignore-it", "ignore-it"); - }; - - document.body.appendChild(div); - } - - function check() { - if (!ignore) { - var timer = setInterval(function() { - var scale = getScale(); - if (scale != 100 && !ignore) { - tryShowTopBar(scale); - clearInterval(timer); - } - if (ignore) { - clearInterval(timer); - } - }, 999); - } - } - - if (document.readyState != "complete") { - document.onreadystatechange = function() { - if (document.readyState != "complete") check(); - }; - } else { - check(); - } -})(); diff --git a/javascript/contextMenus.js b/javascript/contextMenus.js index 8d3088cfab2..ccae242f2b6 100644 --- a/javascript/contextMenus.js +++ b/javascript/contextMenus.js @@ -1,4 +1,4 @@ -/* + var contextMenuInit = function() { let eventListenerApplied = false; let menuSpecs = new Map(); @@ -174,4 +174,3 @@ var addContextMenuEventListener = initResponse[2]; //End example Context Menu Items onAfterUiUpdate(addContextMenuEventListener); -*/ diff --git a/javascript/dragdrop.js b/javascript/dragdrop.js index 488ef41df8a..5803daea5ef 100644 --- a/javascript/dragdrop.js +++ b/javascript/dragdrop.js @@ -1,109 +1,130 @@ // allows drag-dropping files into gradio image elements, and also pasting images from clipboard function isValidImageList(files) { - return ( - files && - files?.length === 1 && - ["image/png", "image/gif", "image/jpeg"].includes(files[0].type) - ); + return files && files?.length === 1 && ['image/png', 'image/gif', 'image/jpeg'].includes(files[0].type); } function dropReplaceImage(imgWrap, files) { - if (!isValidImageList(files)) { - return; - } - - const tmpFile = files[0]; - - imgWrap.querySelector('[aria-label="Clear"]')?.click(); - const callback = () => { - const fileInput = imgWrap.querySelector('input[type="file"]'); - if (fileInput) { - if (files.length === 0) { - files = new DataTransfer(); - files.items.add(tmpFile); - fileInput.files = files.files; - } else { - fileInput.files = files; - } - fileInput.dispatchEvent(new Event("change")); + if (!isValidImageList(files)) { + return; } - }; - - if (imgWrap.closest("#pnginfo_image")) { - // special treatment for PNG Info tab, wait for fetch request to finish - const oldFetch = window.fetch; - window.fetch = async (input, options) => { - const response = await oldFetch(input, options); - if ("api/predict/" === input) { - const content = await response.text(); - window.fetch = oldFetch; - window.requestAnimationFrame(() => callback()); - return new Response(content, { - status: response.status, - statusText: response.statusText, - headers: response.headers, - }); - } - return response; + + const tmpFile = files[0]; + + imgWrap.querySelector('.modify-upload button + button, .touch-none + div button + button')?.click(); + const callback = () => { + const fileInput = imgWrap.querySelector('input[type="file"]'); + if (fileInput) { + if (files.length === 0) { + files = new DataTransfer(); + files.items.add(tmpFile); + fileInput.files = files.files; + } else { + fileInput.files = files; + } + fileInput.dispatchEvent(new Event('change')); + } }; - } else { - window.requestAnimationFrame(() => callback()); - } + + if (imgWrap.closest('#pnginfo_image')) { + // special treatment for PNG Info tab, wait for fetch request to finish + const oldFetch = window.fetch; + window.fetch = async(input, options) => { + const response = await oldFetch(input, options); + if ('api/predict/' === input) { + const content = await response.text(); + window.fetch = oldFetch; + window.requestAnimationFrame(() => callback()); + return new Response(content, { + status: response.status, + statusText: response.statusText, + headers: response.headers + }); + } + return response; + }; + } else { + window.requestAnimationFrame(() => callback()); + } } -window.document.addEventListener("dragover", (e) => { - const target = e.composedPath()[0]; - const imgWrap = target.closest('[data-testid="image"]'); - if ( - !imgWrap && - target.placeholder && - target.placeholder.indexOf("Prompt") == -1 - ) { - return; - } - e.stopPropagation(); - e.preventDefault(); - e.dataTransfer.dropEffect = "copy"; +function eventHasFiles(e) { + if (!e.dataTransfer || !e.dataTransfer.files) return false; + if (e.dataTransfer.files.length > 0) return true; + if (e.dataTransfer.items.length > 0 && e.dataTransfer.items[0].kind == "file") return true; + + return false; +} + +function dragDropTargetIsPrompt(target) { + if (target?.placeholder && target?.placeholder.indexOf("Prompt") >= 0) return true; + if (target?.parentNode?.parentNode?.className?.indexOf("prompt") > 0) return true; + return false; +} + +window.document.addEventListener('dragover', e => { + const target = e.composedPath()[0]; + if (!eventHasFiles(e)) return; + + var targetImage = target.closest('[data-testid="image"]'); + if (!dragDropTargetIsPrompt(target) && !targetImage) return; + + e.stopPropagation(); + e.preventDefault(); + e.dataTransfer.dropEffect = 'copy'; }); -window.document.addEventListener("drop", (e) => { - const target = e.composedPath()[0]; - if (target.placeholder.indexOf("Prompt") == -1) { - return; - } - const imgWrap = target.closest('[data-testid="image"]'); - if (!imgWrap) { - return; - } - e.stopPropagation(); - e.preventDefault(); - const files = e.dataTransfer.files; - dropReplaceImage(imgWrap, files); +window.document.addEventListener('drop', e => { + const target = e.composedPath()[0]; + if (!eventHasFiles(e)) return; + if (dragDropTargetIsPrompt(target)) { + e.stopPropagation(); + e.preventDefault(); + + let prompt_target = get_tab_index('tabs') == 1 ? "img2img_prompt_image" : "txt2img_prompt_image"; + + const imgParent = gradioApp().getElementById(prompt_target); + const files = e.dataTransfer.files; + const fileInput = imgParent.querySelector('input[type="file"]'); + if (fileInput) { + fileInput.files = files; + fileInput.dispatchEvent(new Event('change')); + } + } + + var targetImage = target.closest('[data-testid="image"]'); + if (targetImage) { + e.stopPropagation(); + e.preventDefault(); + const files = e.dataTransfer.files; + dropReplaceImage(targetImage, files); + return; + } }); -window.addEventListener("paste", (e) => { - const files = e.clipboardData.files; - if (!isValidImageList(files)) { - return; - } - - const visibleImageFields = [ - ...gradioApp().querySelectorAll('[data-testid="image"]'), - ].filter((el) => uiElementIsVisible(el)); - if (!visibleImageFields.length) { - return; - } - - const firstFreeImageField = visibleImageFields.filter((el) => - el.querySelector("input[type=file]") - )?.[0]; - - dropReplaceImage( - firstFreeImageField - ? firstFreeImageField - : visibleImageFields[visibleImageFields.length - 1], - files - ); +window.addEventListener('paste', e => { + const files = e.clipboardData.files; + if (!isValidImageList(files)) { + return; + } + + const visibleImageFields = [...gradioApp().querySelectorAll('[data-testid="image"]')] + .filter(el => uiElementIsVisible(el)) + .sort((a, b) => uiElementInSight(b) - uiElementInSight(a)); + + + if (!visibleImageFields.length) { + return; + } + + const firstFreeImageField = visibleImageFields + .filter(el => el.querySelector('input[type=file]'))?.[0]; + + dropReplaceImage( + firstFreeImageField ? + firstFreeImageField : + visibleImageFields[visibleImageFields.length - 1] + , files + ); }); diff --git a/javascript/extensions.js b/javascript/extensions.js index 29185b4e5c8..312131b76eb 100644 --- a/javascript/extensions.js +++ b/javascript/extensions.js @@ -1,3 +1,4 @@ + function extensions_apply(_disabled_list, _update_list, disable_all) { var disable = []; var update = []; @@ -32,7 +33,7 @@ function extensions_check() { var id = randomId(); - requestProgress(id, gradioApp().getElementById('extensions_installed_top'), null, function() { + requestProgress(id, gradioApp().getElementById('extensions_installed_html'), null, function() { }); diff --git a/javascript/extraNetworks.js b/javascript/extraNetworks.js index 9a260fba40e..493f31af28a 100644 --- a/javascript/extraNetworks.js +++ b/javascript/extraNetworks.js @@ -1,579 +1,349 @@ -function setupExtraNetworksForTab(tabname) { - gradioApp() - .querySelector("#" + tabname + "_extra_tabs") - .classList.add("extra-networks"); - - let tabs = gradioApp().querySelector("#" + tabname + "_extra_tabs > div"); - let search = gradioApp().querySelector("#" + tabname + "_extra_search textarea" ); - let refresh = gradioApp().getElementById(tabname + "_extra_refresh"); - - //let sort = gradioApp().getElementById(tabname + '_extra_sort'); - //let sortOrder = gradioApp().getElementById(tabname + '_extra_sortorder'); - - let clear = document.createElement("div"); - clear.id = tabname + "_extra_clear"; - clear.classList.add("token-remove", "remove-all", "svelte-a6vu2r", "hide"); - clear.title = "Clear search"; - clear.innerHTML = - ''; - - search.classList.add("search"); - - tabs.appendChild(search); - tabs.appendChild(clear); - tabs.appendChild(refresh); - -/* - sort.classList.add('sort'); - sortOrder.classList.add('sortorder'); - sort.dataset.sortkey = 'sortDefault'; - tabs.appendChild(sort); - tabs.appendChild(sortOrder); */ - - clear.addEventListener("click", function (evt) { - search.value = ""; - updateInput(search); - }); - - setTimeout(function () { - refresh.click(); - }, 500); - - - setTimeout(extraNetworksApplyFilter[tabname], 1); - - search.addEventListener("input", function (evt) { - searchTerm = search.value.toLowerCase(); - - gradioApp() - .querySelectorAll("#" + tabname + "_extra_tabs div.card") - .forEach(function (elem) { - let text = - elem.querySelector(".name").textContent.toLowerCase() + - " " + - elem.querySelector(".search_term").textContent.toLowerCase(); - elem.parentElement.style.display = - text.indexOf(searchTerm) == -1 ? "none" : ""; - }); - }); -} - -function applyExtraNetworkFilter(tabname){ - setTimeout(extraNetworksApplyFilter[tabname], 1); -} - -var extraNetworksApplyFilter = {} -var activePromptTextarea = {}; - -function setupExtraNetworks() { - setupExtraNetworksForTab("txt2img"); - setupExtraNetworksForTab("img2img"); - - function registerPrompt(tabname, id) { - var textarea = gradioApp().querySelector("#" + id + " > label > textarea"); - - if (!activePromptTextarea[tabname]) { - activePromptTextarea[tabname] = textarea; - } - - textarea.addEventListener("focus", function () { - activePromptTextarea[tabname] = textarea; - }); - } - - registerPrompt("txt2img", "txt2img_prompt"); - registerPrompt("txt2img", "txt2img_neg_prompt"); - registerPrompt("img2img", "img2img_prompt"); - registerPrompt("img2img", "img2img_neg_prompt"); -} - -onUiLoaded(setupExtraNetworks); - -var re_extranet = /<([^:]+:[^:]+):[\d\.]+>/; -var re_extranet_g = /\s+<([^:]+:[^:]+):[\d\.]+>/g; - -function tryToRemoveExtraNetworkFromPrompt(textarea, text) { - var m = text.match(re_extranet); - if (!m) return false; - - var partToSearch = m[1]; - var replaced = false; - var newTextareaText = textarea.value.replaceAll( - re_extranet_g, - function (found) { - m = found.match(re_extranet); - if (m[1] == partToSearch) { - replaced = true; - return ""; - } - return found; - } - ); - - if (replaced) { - textarea.value = newTextareaText; - return true; - } - - return false; -} - -function cardClicked(tabname, textToAdd, allowNegativePrompt) { - var textarea = allowNegativePrompt - ? activePromptTextarea[tabname] - : gradioApp().querySelector("#" + tabname + "_prompt > label > textarea"); - - if (!tryToRemoveExtraNetworkFromPrompt(textarea, textToAdd)) { - textarea.value = - textarea.value + opts.extra_networks_add_text_separator + textToAdd; - } - - updateInput(textarea); -} - -function saveCardPreview(event, tabname, filename) { - var textarea = gradioApp().querySelector( - "#" + tabname + "_preview_filename > label > textarea" - ); - var button = gradioApp().getElementById(tabname + "_save_preview"); - - textarea.value = filename; - updateInput(textarea); - - button.click(); - - var search = gradioApp().querySelector( - "#" + tabname + "_extra_tabs textarea" - ); - - setTimeout(function () { - search.value = search.value.toLowerCase(); - updateInput(search); - }, 1000); - - event.stopPropagation(); - event.preventDefault(); -} - -function extraNetworksSearchButton(tabs_id, event) { - var searchTextarea = gradioApp().querySelector( - "#" + tabs_id + " > div > textarea" - ); - var button = event.target; - var text = button.classList.contains("search-all") - ? "" - : button.textContent.trim(); - //text = event.target.selectedIndex == 0 ? "" : event.target.options[event.target.selectedIndex].text; - - searchTextarea.value = text; - updateInput(searchTextarea); -} - -var globalPopup = null; -var globalPopupInner = null; -function popup(contents) { - if (!globalPopup) { - globalPopup = document.createElement("div"); - globalPopup.onclick = function () { - globalPopup.style.display = "none"; - }; - globalPopup.classList.add("global-popup"); - - var close = document.createElement("div"); - close.classList.add("global-popup-close"); - close.onclick = function () { - globalPopup.style.display = "none"; - }; - close.title = "Close"; - globalPopup.appendChild(close); - - globalPopupInner = document.createElement("div"); - globalPopupInner.onclick = function (event) { - event.stopPropagation(); - return false; - }; - globalPopupInner.classList.add("global-popup-inner"); - globalPopup.appendChild(globalPopupInner); - - gradioApp().appendChild(globalPopup); - } - - globalPopupInner.innerHTML = ""; - globalPopupInner.appendChild(contents); - - globalPopup.style.display = "flex"; -} - -function extraNetworksShowMetadata(text) { - var elem = document.createElement("pre"); - elem.classList.add("popup-metadata"); - elem.textContent = text; - - popup(elem); -} - -function requestGet(url, data, handler, errorHandler) { - var xhr = new XMLHttpRequest(); - var args = Object.keys(data) - .map(function (k) { - return encodeURIComponent(k) + "=" + encodeURIComponent(data[k]); - }) - .join("&"); - xhr.open("GET", url + "?" + args, true); - - xhr.onreadystatechange = function () { - if (xhr.readyState === 4) { - if (xhr.status === 200) { - try { - var js = JSON.parse(xhr.responseText); - handler(js); - } catch (error) { - console.error(error); - errorHandler(); - } - } else { - errorHandler(); - } - } - }; - var js = JSON.stringify(data); - xhr.send(js); -} - -function extraNetworksRequestMetadata(event, extraPage, cardName) { - var showError = function () { - extraNetworksShowMetadata("there was an error getting metadata"); - }; - - requestGet( - "./sd_extra_networks/metadata", - { page: extraPage, item: cardName }, - function (data) { - if (data && data.metadata) { - extraNetworksShowMetadata(data.metadata); - } else { - showError(); - } - }, - showError - ); - - event.stopPropagation(); -} - - -/* -function setupExtraNetworksForTab(tabname) { - gradioApp().querySelector('#' + tabname + '_extra_tabs').classList.add('extra-networks'); - - var tabs = gradioApp().querySelector('#' + tabname + '_extra_tabs > div'); - 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'); - - search.classList.add('search'); - sort.classList.add('sort'); - sortOrder.classList.add('sortorder'); - sort.dataset.sortkey = 'sortDefault'; - tabs.appendChild(search); - tabs.appendChild(sort); - tabs.appendChild(sortOrder); - tabs.appendChild(refresh); - - var applyFilter = function() { - var searchTerm = search.value.toLowerCase(); - - gradioApp().querySelectorAll('#' + tabname + '_extra_tabs div.card').forEach(function(elem) { - var searchOnly = elem.querySelector('.search_only'); - var text = elem.querySelector('.name').textContent.toLowerCase() + " " + elem.querySelector('.search_term').textContent.toLowerCase(); - - var visible = text.indexOf(searchTerm) != -1; - - if (searchOnly && searchTerm.length < 4) { - visible = false; - } - - elem.style.display = visible ? "" : "none"; - }); - }; - - 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); - 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; -} - -function applyExtraNetworkFilter(tabname) { - setTimeout(extraNetworksApplyFilter[tabname], 1); -} - -var extraNetworksApplyFilter = {}; -var activePromptTextarea = {}; - -function setupExtraNetworks() { - setupExtraNetworksForTab('txt2img'); - setupExtraNetworksForTab('img2img'); - - function registerPrompt(tabname, id) { - var textarea = gradioApp().querySelector("#" + id + " > label > textarea"); - - if (!activePromptTextarea[tabname]) { - activePromptTextarea[tabname] = textarea; - } - - textarea.addEventListener("focus", function() { - activePromptTextarea[tabname] = textarea; - }); - } - - registerPrompt('txt2img', 'txt2img_prompt'); - registerPrompt('txt2img', 'txt2img_neg_prompt'); - registerPrompt('img2img', 'img2img_prompt'); - registerPrompt('img2img', 'img2img_neg_prompt'); -} - -onUiLoaded(setupExtraNetworks); - -var re_extranet = /<([^:]+:[^:]+):[\d.]+>(.*)/; -var re_extranet_g = /\s+<([^:]+:[^:]+):[\d.]+>/g; - -function tryToRemoveExtraNetworkFromPrompt(textarea, text) { - var m = text.match(re_extranet); - var replaced = false; - var newTextareaText; - if (m) { - var extraTextAfterNet = m[2]; - var partToSearch = m[1]; - var foundAtPosition = -1; - newTextareaText = textarea.value.replaceAll(re_extranet_g, function(found, net, pos) { - m = found.match(re_extranet); - if (m[1] == partToSearch) { - replaced = true; - foundAtPosition = pos; - return ""; - } - return found; - }); - - if (foundAtPosition >= 0 && newTextareaText.substr(foundAtPosition, extraTextAfterNet.length) == extraTextAfterNet) { - newTextareaText = newTextareaText.substr(0, foundAtPosition) + newTextareaText.substr(foundAtPosition + extraTextAfterNet.length); - } - } else { - newTextareaText = textarea.value.replaceAll(new RegExp(text, "g"), function(found) { - if (found == text) { - replaced = true; - return ""; - } - return found; - }); - } - - if (replaced) { - textarea.value = newTextareaText; - return true; - } - - return false; -} - -function cardClicked(tabname, textToAdd, allowNegativePrompt) { - var textarea = allowNegativePrompt ? activePromptTextarea[tabname] : gradioApp().querySelector("#" + tabname + "_prompt > label > textarea"); - - if (!tryToRemoveExtraNetworkFromPrompt(textarea, textToAdd)) { - textarea.value = textarea.value + opts.extra_networks_add_text_separator + textToAdd; - } - - updateInput(textarea); -} - -function saveCardPreview(event, tabname, filename) { - var textarea = gradioApp().querySelector("#" + tabname + '_preview_filename > label > textarea'); - var button = gradioApp().getElementById(tabname + '_save_preview'); - - textarea.value = filename; - updateInput(textarea); - - button.click(); - - event.stopPropagation(); - event.preventDefault(); -} - -function extraNetworksSearchButton(tabs_id, event) { - var searchTextarea = gradioApp().querySelector("#" + tabs_id + ' > div > textarea'); - var button = event.target; - var text = button.classList.contains("search-all") ? "" : button.textContent.trim(); - - searchTextarea.value = text; - updateInput(searchTextarea); -} - -var globalPopup = null; -var globalPopupInner = null; -function closePopup() { - if (!globalPopup) return; - - globalPopup.style.display = "none"; -} -function popup(contents) { - if (!globalPopup) { - globalPopup = document.createElement('div'); - globalPopup.onclick = closePopup; - globalPopup.classList.add('global-popup'); - - var close = document.createElement('div'); - close.classList.add('global-popup-close'); - close.onclick = closePopup; - close.title = "Close"; - globalPopup.appendChild(close); - - globalPopupInner = document.createElement('div'); - globalPopupInner.onclick = function(event) { - event.stopPropagation(); return false; - }; - globalPopupInner.classList.add('global-popup-inner'); - globalPopup.appendChild(globalPopupInner); - - gradioApp().querySelector('.main').appendChild(globalPopup); - } - - globalPopupInner.innerHTML = ''; - globalPopupInner.appendChild(contents); - - globalPopup.style.display = "flex"; -} - -function extraNetworksShowMetadata(text) { - var elem = document.createElement('pre'); - elem.classList.add('popup-metadata'); - elem.textContent = text; - - popup(elem); -} - -function requestGet(url, data, handler, errorHandler) { - var xhr = new XMLHttpRequest(); - var args = Object.keys(data).map(function(k) { - return encodeURIComponent(k) + '=' + encodeURIComponent(data[k]); - }).join('&'); - xhr.open("GET", url + "?" + args, true); - - xhr.onreadystatechange = function() { - if (xhr.readyState === 4) { - if (xhr.status === 200) { - try { - var js = JSON.parse(xhr.responseText); - handler(js); - } catch (error) { - console.error(error); - errorHandler(); - } - } else { - errorHandler(); - } - } - }; - var js = JSON.stringify(data); - xhr.send(js); -} - -function extraNetworksRequestMetadata(event, extraPage, cardName) { - var showError = function() { - extraNetworksShowMetadata("there was an error getting metadata"); - }; - - requestGet("./sd_extra_networks/metadata", {page: extraPage, item: cardName}, function(data) { - if (data && data.metadata) { - extraNetworksShowMetadata(data.metadata); - } else { - showError(); - } - }, showError); - - event.stopPropagation(); -} - -var extraPageUserMetadataEditors = {}; - -function extraNetworksEditUserMetadata(event, tabname, extraPage, cardName) { - var id = tabname + '_' + extraPage + '_edit_user_metadata'; - - var editor = extraPageUserMetadataEditors[id]; - if (!editor) { - editor = {}; - editor.page = gradioApp().getElementById(id); - editor.nameTextarea = gradioApp().querySelector("#" + id + "_name" + ' textarea'); - editor.button = gradioApp().querySelector("#" + id + "_button"); - extraPageUserMetadataEditors[id] = editor; - } - - editor.nameTextarea.value = cardName; - updateInput(editor.nameTextarea); - - editor.button.click(); - - popup(editor.page); - - event.stopPropagation(); -} - -function extraNetworksRefreshSingleCard(page, tabname, name) { - requestGet("./sd_extra_networks/get-single-card", {page: page, tabname: tabname, name: name}, function(data) { - if (data && data.html) { - var card = gradioApp().querySelector('.card[data-name=' + JSON.stringify(name) + ']'); // likely using the wrong stringify function - - var newDiv = document.createElement('DIV'); - newDiv.innerHTML = data.html; - var newCard = newDiv.firstElementChild; - - newCard.style = ''; - card.parentElement.insertBefore(newCard, card); - card.parentElement.removeChild(card); - } - }); -} -*/ \ No newline at end of file +function toggleCss(key, css, enable) { + var style = document.getElementById(key); + if (enable && !style) { + style = document.createElement('style'); + style.id = key; + style.type = 'text/css'; + document.head.appendChild(style); + } + if (style && !enable) { + document.head.removeChild(style); + } + if (style) { + style.innerHTML == ''; + style.appendChild(document.createTextNode(css)); + } +} + +function setupExtraNetworksForTab(tabname) { + gradioApp().querySelector('#' + tabname + '_extra_tabs').classList.add('extra-networks'); + + var tabs = gradioApp().querySelector('#' + tabname + '_extra_tabs > div'); + var searchDiv = gradioApp().getElementById(tabname + '_extra_search'); + var search = searchDiv.querySelector('textarea'); + var sort = gradioApp().getElementById(tabname + '_extra_sort'); + var sortOrder = gradioApp().getElementById(tabname + '_extra_sortorder'); + var refresh = gradioApp().getElementById(tabname + '_extra_refresh'); + var showDirsDiv = gradioApp().getElementById(tabname + '_extra_show_dirs'); + var showDirs = gradioApp().querySelector('#' + tabname + '_extra_show_dirs input'); + + sort.dataset.sortkey = 'sortDefault'; + tabs.appendChild(searchDiv); + tabs.appendChild(sort); + tabs.appendChild(sortOrder); + tabs.appendChild(refresh); + tabs.appendChild(showDirsDiv); + + var applyFilter = function() { + var searchTerm = search.value.toLowerCase(); + + gradioApp().querySelectorAll('#' + tabname + '_extra_tabs div.card').forEach(function(elem) { + var searchOnly = elem.querySelector('.search_only'); + var text = elem.querySelector('.name').textContent.toLowerCase() + " " + elem.querySelector('.search_term').textContent.toLowerCase(); + + var visible = text.indexOf(searchTerm) != -1; + + if (searchOnly && searchTerm.length < 4) { + visible = false; + } + + elem.style.display = visible ? "" : "none"; + }); + }; + + 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); + 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; + + var showDirsUpdate = function() { + var css = '#' + tabname + '_extra_tabs .extra-network-subdirs { display: none; }'; + toggleCss(tabname + '_extra_show_dirs_style', css, !showDirs.checked); + localSet('extra-networks-show-dirs', showDirs.checked ? 1 : 0); + }; + showDirs.checked = localGet('extra-networks-show-dirs', 1) == 1; + showDirs.addEventListener("change", showDirsUpdate); + showDirsUpdate(); +} + +function applyExtraNetworkFilter(tabname) { + setTimeout(extraNetworksApplyFilter[tabname], 1); +} + +var extraNetworksApplyFilter = {}; +var activePromptTextarea = {}; + +function setupExtraNetworks() { + setupExtraNetworksForTab('txt2img'); + setupExtraNetworksForTab('img2img'); + + function registerPrompt(tabname, id) { + var textarea = gradioApp().querySelector("#" + id + " > label > textarea"); + + if (!activePromptTextarea[tabname]) { + activePromptTextarea[tabname] = textarea; + } + + textarea.addEventListener("focus", function() { + activePromptTextarea[tabname] = textarea; + }); + } + + registerPrompt('txt2img', 'txt2img_prompt'); + registerPrompt('txt2img', 'txt2img_neg_prompt'); + registerPrompt('img2img', 'img2img_prompt'); + registerPrompt('img2img', 'img2img_neg_prompt'); +} + +onUiLoaded(setupExtraNetworks); + +var re_extranet = /<([^:]+:[^:]+):[\d.]+>(.*)/; +var re_extranet_g = /\s+<([^:]+:[^:]+):[\d.]+>/g; + +function tryToRemoveExtraNetworkFromPrompt(textarea, text) { + var m = text.match(re_extranet); + var replaced = false; + var newTextareaText; + if (m) { + var extraTextAfterNet = m[2]; + var partToSearch = m[1]; + var foundAtPosition = -1; + newTextareaText = textarea.value.replaceAll(re_extranet_g, function(found, net, pos) { + m = found.match(re_extranet); + if (m[1] == partToSearch) { + replaced = true; + foundAtPosition = pos; + return ""; + } + return found; + }); + + if (foundAtPosition >= 0 && newTextareaText.substr(foundAtPosition, extraTextAfterNet.length) == extraTextAfterNet) { + newTextareaText = newTextareaText.substr(0, foundAtPosition) + newTextareaText.substr(foundAtPosition + extraTextAfterNet.length); + } + } else { + newTextareaText = textarea.value.replaceAll(new RegExp(text, "g"), function(found) { + if (found == text) { + replaced = true; + return ""; + } + return found; + }); + } + + if (replaced) { + textarea.value = newTextareaText; + return true; + } + + return false; +} + +function cardClicked(tabname, textToAdd, allowNegativePrompt) { + var textarea = allowNegativePrompt ? activePromptTextarea[tabname] : gradioApp().querySelector("#" + tabname + "_prompt > label > textarea"); + + if (!tryToRemoveExtraNetworkFromPrompt(textarea, textToAdd)) { + textarea.value = textarea.value + opts.extra_networks_add_text_separator + textToAdd; + } + + updateInput(textarea); +} + +function saveCardPreview(event, tabname, filename) { + var textarea = gradioApp().querySelector("#" + tabname + '_preview_filename > label > textarea'); + var button = gradioApp().getElementById(tabname + '_save_preview'); + + textarea.value = filename; + updateInput(textarea); + + button.click(); + + event.stopPropagation(); + event.preventDefault(); +} + +function extraNetworksSearchButton(tabs_id, event) { + var searchTextarea = gradioApp().querySelector("#" + tabs_id + ' > label > textarea'); + var button = event.target; + var text = button.classList.contains("search-all") ? "" : button.textContent.trim(); + + searchTextarea.value = text; + updateInput(searchTextarea); +} + +var globalPopup = null; +var globalPopupInner = null; +function closePopup() { + if (!globalPopup) return; + + globalPopup.style.display = "none"; +} +function popup(contents) { + if (!globalPopup) { + globalPopup = document.createElement('div'); + globalPopup.onclick = closePopup; + globalPopup.classList.add('global-popup'); + + var close = document.createElement('div'); + close.classList.add('global-popup-close'); + close.onclick = closePopup; + close.title = "Close"; + globalPopup.appendChild(close); + + globalPopupInner = document.createElement('div'); + globalPopupInner.onclick = function(event) { + event.stopPropagation(); return false; + }; + globalPopupInner.classList.add('global-popup-inner'); + globalPopup.appendChild(globalPopupInner); + + gradioApp().querySelector('.main').appendChild(globalPopup); + } + + globalPopupInner.innerHTML = ''; + globalPopupInner.appendChild(contents); + + globalPopup.style.display = "flex"; +} + +var storedPopupIds = {}; +function popupId(id) { + if (!storedPopupIds[id]) { + storedPopupIds[id] = gradioApp().getElementById(id); + } + + popup(storedPopupIds[id]); +} + +function extraNetworksShowMetadata(text) { + var elem = document.createElement('pre'); + elem.classList.add('popup-metadata'); + elem.textContent = text; + + popup(elem); +} + +function requestGet(url, data, handler, errorHandler) { + var xhr = new XMLHttpRequest(); + var args = Object.keys(data).map(function(k) { + return encodeURIComponent(k) + '=' + encodeURIComponent(data[k]); + }).join('&'); + xhr.open("GET", url + "?" + args, true); + + xhr.onreadystatechange = function() { + if (xhr.readyState === 4) { + if (xhr.status === 200) { + try { + var js = JSON.parse(xhr.responseText); + handler(js); + } catch (error) { + console.error(error); + errorHandler(); + } + } else { + errorHandler(); + } + } + }; + var js = JSON.stringify(data); + xhr.send(js); +} + +function extraNetworksRequestMetadata(event, extraPage, cardName) { + var showError = function() { + extraNetworksShowMetadata("there was an error getting metadata"); + }; + + requestGet("./sd_extra_networks/metadata", {page: extraPage, item: cardName}, function(data) { + if (data && data.metadata) { + extraNetworksShowMetadata(data.metadata); + } else { + showError(); + } + }, showError); + + event.stopPropagation(); +} + +var extraPageUserMetadataEditors = {}; + +function extraNetworksEditUserMetadata(event, tabname, extraPage, cardName) { + var id = tabname + '_' + extraPage + '_edit_user_metadata'; + + var editor = extraPageUserMetadataEditors[id]; + if (!editor) { + editor = {}; + editor.page = gradioApp().getElementById(id); + editor.nameTextarea = gradioApp().querySelector("#" + id + "_name" + ' textarea'); + editor.button = gradioApp().querySelector("#" + id + "_button"); + extraPageUserMetadataEditors[id] = editor; + } + + editor.nameTextarea.value = cardName; + updateInput(editor.nameTextarea); + + editor.button.click(); + + popup(editor.page); + + event.stopPropagation(); +} + +function extraNetworksRefreshSingleCard(page, tabname, name) { + requestGet("./sd_extra_networks/get-single-card", {page: page, tabname: tabname, name: name}, function(data) { + if (data && data.html) { + var card = gradioApp().querySelector('.card[data-name=' + JSON.stringify(name) + ']'); // likely using the wrong stringify function + + var newDiv = document.createElement('DIV'); + newDiv.innerHTML = data.html; + var newCard = newDiv.firstElementChild; + + newCard.style.display = ''; + card.parentElement.insertBefore(newCard, card); + card.parentElement.removeChild(card); + } + }); +} diff --git a/javascript/generationParams.js b/javascript/generationParams.js index 35ccd716df0..7c0fd221d63 100644 --- a/javascript/generationParams.js +++ b/javascript/generationParams.js @@ -1,4 +1,5 @@ // attaches listeners to the txt2img and img2img galleries to update displayed generation param text when the image changes + let txt2img_gallery, img2img_gallery, modal = undefined; onAfterUiUpdate(function() { if (!txt2img_gallery) { @@ -7,6 +8,10 @@ onAfterUiUpdate(function() { if (!img2img_gallery) { img2img_gallery = attachGalleryListeners("img2img"); } + if (!modal) { + modal = gradioApp().getElementById('lightboxModal'); + modalObserver.observe(modal, {attributes: true, attributeFilter: ['style']}); + } }); let modalObserver = new MutationObserver(function(mutations) { diff --git a/javascript/hints.js b/javascript/hints.js index f3dd9019c34..6de9372e8ea 100644 --- a/javascript/hints.js +++ b/javascript/hints.js @@ -23,12 +23,7 @@ var titles = { "\u{1f4cb}": "Apply selected styles to current prompt", "\u{1f4d2}": "Paste available values into the field", "\u{1f3b4}": "Show/hide extra networks", - - "\u{1f5e8}": "Interogate Clip", - "\u{1f5ea}": "Interogate Deepbooru", - "\u{1F300}": "Restore progress", - "\u{267E}": "Toggle generate forever", - + "\u{1f300}": "Restore progress", "Inpaint a part of image": "Draw a mask over an image, and the script will regenerate the masked area with content according to prompt", "SD upscale": "Upscale image normally, split result into tiles, improve each tile using img2img, merge whole image back", @@ -50,11 +45,6 @@ var titles = { "Skip": "Stop processing current image and continue processing.", "Interrupt": "Stop processing images and return any results accumulated so far.", "Save": "Write image to a directory (default - log/images) and generation parameters into csv file.", - "Zip": "Save as Zip", - "Send to txt2img": "Send to txt2img", - "Send to img2img": "Send to img2img", - "Send to inpaint": "Send to inpaint", - "Send to extras": "Send to extras", "X values": "Separate values for X axis using commas.", "Y values": "Separate values for Y axis using commas.", @@ -200,3 +190,14 @@ onUiUpdate(function(mutationRecords) { tooltipCheckTimer = setTimeout(processTooltipCheckNodes, 1000); } }); + +onUiLoaded(function() { + for (var comp of window.gradio_config.components) { + if (comp.props.webui_tooltip && comp.props.elem_id) { + var elem = gradioApp().getElementById(comp.props.elem_id); + if (elem) { + elem.title = comp.props.webui_tooltip; + } + } + } +}); diff --git a/javascript/hires_fix.js b/javascript/hires_fix.js index 2c111bd85bb..0d04ab3b424 100644 --- a/javascript/hires_fix.js +++ b/javascript/hires_fix.js @@ -1,19 +1,18 @@ -function onCalcResolutionHires(enable, width, height, hr_scale, hr_resize_x, hr_resize_y) { - function setInactive(elem, inactive) { - elem.classList.toggle('inactive', !!inactive); - } - - var hrUpscaleBy = gradioApp().getElementById('txt2img_hr_scale'); - var hrResizeX = gradioApp().getElementById('txt2img_hr_resize_x'); - var hrResizeY = gradioApp().getElementById('txt2img_hr_resize_y'); - - gradioApp().getElementById('txt2img_hires_fix_row2').style.display = opts.use_old_hires_fix_width_height ? "none" : "block"; - - setInactive(hrUpscaleBy, opts.use_old_hires_fix_width_height || hr_resize_x > 0 || hr_resize_y > 0); - setInactive(hrResizeX, opts.use_old_hires_fix_width_height || hr_resize_x == 0); - setInactive(hrResizeY, opts.use_old_hires_fix_width_height || hr_resize_y == 0); - - setTimeout(function () { - return [enable, width, height, hr_scale, hr_resize_x, hr_resize_y]; - }, 100); -} + +function onCalcResolutionHires(enable, width, height, hr_scale, hr_resize_x, hr_resize_y) { + function setInactive(elem, inactive) { + elem.classList.toggle('inactive', !!inactive); + } + + var hrUpscaleBy = gradioApp().getElementById('txt2img_hr_scale'); + var hrResizeX = gradioApp().getElementById('txt2img_hr_resize_x'); + var hrResizeY = gradioApp().getElementById('txt2img_hr_resize_y'); + + gradioApp().getElementById('txt2img_hires_fix_row2').style.display = opts.use_old_hires_fix_width_height ? "none" : ""; + + setInactive(hrUpscaleBy, opts.use_old_hires_fix_width_height || hr_resize_x > 0 || hr_resize_y > 0); + setInactive(hrResizeX, opts.use_old_hires_fix_width_height || hr_resize_x == 0); + setInactive(hrResizeY, opts.use_old_hires_fix_width_height || hr_resize_y == 0); + + return [enable, width, height, hr_scale, hr_resize_x, hr_resize_y]; +} diff --git a/javascript/imageMaskFix.js b/javascript/imageMaskFix.js index d1a0780703e..900c56f32fd 100644 --- a/javascript/imageMaskFix.js +++ b/javascript/imageMaskFix.js @@ -2,10 +2,6 @@ * temporary fix for https://github.com/AUTOMATIC1111/stable-diffusion-webui/issues/668 * @see https://github.com/gradio-app/gradio/issues/1721 */ - -/* -window.addEventListener( 'resize', () => imageMaskResize()); - function imageMaskResize() { const canvases = gradioApp().querySelectorAll('#img2maskimg .touch-none canvas'); if (!canvases.length) { @@ -41,299 +37,7 @@ function imageMaskResize() { c.style.maxHeight = '100%'; c.style.objectFit = 'contain'; }); - } - - onUiUpdate(() => imageMaskResize()); -*/ - -onUiLoaded(function () { - const color_box = ''; - const brush_size = ''; - let is_drawing = false; - let img_src = []; - let spl_instances = []; - let spl_pan_instances = []; - let img2img_tab_index = 0; - let intervalLastUIUpdate; - const container = gradioApp().querySelector(".gradio-container"); - const observer = new MutationObserver(() => - gradioApp() - .querySelectorAll('div[data-testid="image"]') - .forEach(function (elem, i) { - let img_parent = elem.parentElement.querySelector( - 'div[data-testid="image"] > div' - ); - let img = img_parent.querySelector("img"); - if (img) { - if (img_src[i] != img.src) { - let tool_buttons = img_parent.querySelectorAll("button"); - //console.log(tool_buttons); - if (tool_buttons.length > 2) { - img_parent.style.visibility = "hidden"; - - if (intervalLastUIUpdate != null) - clearInterval(intervalLastUIUpdate); - - intervalLastUIUpdate = setInterval(function () { - clearInterval(intervalLastUIUpdate); - img_parent.addEventListener("mouseup", function (e) {}); - - let spl_parent = elem.parentElement; - let spl; - let spl_pan; - let isPanning; - let splid; - - if (spl_parent.className != "spl-pane") { - spl = new Spotlight(); - spl.init(spl_parent, "-" + spl_parent.id); - - spl.addControl("undo", spl_undo_handler); - spl_pan = spl.addControl("pan", spl_pan_handler); - spl.addControl("brush", spl_brush_handler, brush_size); - if (tool_buttons.length == 5) { - spl.addControl("color", spl_color_handler, color_box); - } - spl.addControl("clear", spl_clear_handler); - - spl_instances[i] = spl; - spl_pan_instances[i] = spl_pan; - } else { - spl = spl_instances[i]; - spl_pan = spl_pan_instances[i]; - } - - img_src[i] = img.src; - //console.log("NEWIMAGE"); - - function spl_undo_handler(e) { - tool_buttons[0].click(); - } - - function spl_clear_handler(e) { - tool_buttons[2].click(); - spl.panzoom(false); - img_parent.classList.remove("no-point-events"); - img_parent.parentElement.classList.remove("move"); - document.removeEventListener("wheel", preventDefault, false); - setTimeout(function () { - spl.close(false, true); - img_parent.style.flexGrow = "1"; - img_src[i] = ""; - elem.style.transform = "none"; - }, 500); - } - - function spl_color_handler(e) {} - function spl_brush_handler(e) {} - - function preventDefault(e) { - e = e || window.event; - if (e.preventDefault) { - e.preventDefault(); - } - e.returnValue = false; - } - - function pan_toggle(val, target) { - isPanning = val; - target.classList.toggle("on", isPanning); - spl.panzoom(val); - - if (isPanning) { - img_parent.classList.add("no-point-events"); - img_parent.parentElement.classList.add("move"); - document.addEventListener("wheel", preventDefault, { - passive: false, - }); - } else { - img_parent.classList.remove("no-point-events"); - img_parent.parentElement.classList.remove("move"); - document.removeEventListener( - "wheel", - preventDefault, - false - ); - } - } - - function spl_pan_handler(e) { - isPanning = !isPanning; - pan_toggle(isPanning, this); - } - - function update_color(listener) { - let input_color = img_parent.querySelector( - "input[type='color']" - ); - let spl = - img_parent.parentElement.parentElement.parentElement - .parentElement.parentElement; - let spl_color = spl.querySelector( - ".spl-color input[type='color']" - ); - spl_color.value = input_color.value; - - if (listener) { - spl_color.addEventListener("input", function (ev) { - input_color.value = ev.target.value; - updateInput(input_color); - pan_toggle(false, spl_pan); - }); - } - } - - function update_brush(listener) { - let input_range = img_parent.querySelector( - "input[type='range']" - ); - let spl = - img_parent.parentElement.parentElement.parentElement - .parentElement.parentElement; - let spl_brush = spl.querySelector( - ".spl-brush input[type='range']" - ); - spl_brush.value = input_range.value; - - if (listener) { - spl_brush.addEventListener("input", function (ev) { - input_range.value = ev.target.value; - updateInput(input_range); - }); - } - } - - function init_drawing_tools() { - let input_color = img_parent.querySelector( - "input[type='color']" - ); - if (!input_color) { - let tbcolor = img_parent.querySelector( - "button[aria-label='Select brush color']" - ); - if (tbcolor) { - tbcolor.click(); - setTimeout(function () { - update_color(true); - }, 100); - } - } else { - setTimeout(function () { - update_color(false); - }, 100); - } - - let input_range = img_parent.querySelector( - "input[type='range']" - ); - if (!input_range) { - let tbrange = img_parent.querySelector( - "button[aria-label='Use brush']" - ); - - if (tbrange) { - tbrange.click(); - setTimeout(function () { - update_brush(true); - }, 100); - } - } else { - setTimeout(function () { - update_brush(false); - }, 100); - } - } - - let w = img.naturalWidth; - let h = img.naturalHeight; - img_parent.style.width = `${w}px`; - img_parent.style.height = `${h}px`; - - spl.show([ - { - media: "node", - src: elem, - //autohide: true, - //control: ["pan","clear","undo","fullscreen","autofit","zoom-in","zoom-out","close"], - class: "relative", - }, - ]); - - img_parent.style.flexGrow = "0"; - pan_toggle(false, spl_pan); - spl.panzoom(false); - setTimeout(function () { - init_drawing_tools(); - }, 500); - img_parent.style.visibility = "visible"; - }, 1000); - } - } - } - }) - ); - observer.observe(container, { childList: true, subtree: true }); - - /* gradioApp().querySelectorAll('#mode_img2img > .tabitem').forEach(function (tb, ti){ - tb.querySelectorAll('[id^="img2img_copy_to_"] > button').forEach(function (btn, bi){ - - btn.addEventListener("click", function(e) { - console.log(ti + " > " + bi); - let src_canvas = tb.querySelector('[key="drawing"]'); - if(src_canvas){ - let dest_canvas = gradioApp().querySelector('#mode_img2img .tabitem:nth-child('+parseInt(bi+1)+') [key="drawing"]'); - //let destCtx = dest_canvas.getContext('2d'); - //destCtx.drawImage(src_canvas, 0, 0); - console.log(src_canvas); - console.log(dest_canvas); - } - }) - }) - }) - - */ -}); - -/* -let intervalLastUIUpdate; -function onLastUIUpdate(){ - clearInterval(intervalLastUIUpdate); - const img2img_tab = gradioApp().querySelector('#img2img_img2img_tab'); - if(img2img_tab && selectedTabItemId=="tab_img2img"){ - const current_img2img_tab_index = get_img2img_tab_index()[0]; - //if(img2img_tab_index != current_img2img_tab_index){ - console.log(current_img2img_tab_index); - if(current_img2img_tab_index > 3 || current_img2img_tab_index == 0) return; - img2img_tab_index = current_img2img_tab_index; - let tabid; - - if(img2img_tab_index == 1){ - tabid = "#img2img_img2img_sketch_tab";// #img2img_sketch"; - }else if(img2img_tab_index == 2){ - tabid = "#img2img_inpaint_tab";// #img2maskimg"; - }else if(img2img_tab_index == 3){ - tabid = "#img2img_inpaint_sketch_tab";// #inpaint_sketch"; - } - //const parent_img2img_tab_img = gradioApp().querySelector('#mode_img2img > div:nth-child('+(img2img_tab_index+2)+') div[data-testid="image"] > div'); - const parent_img2img_tab_img = gradioApp().querySelector('#mode_img2img '+tabid+' div[data-testid="image"] > div'); - const img2img_tab_img = parent_img2img_tab_img.querySelector('img'); - if(img2img_tab_img){ - parent_img2img_tab_img.style.flexGrow = "0"; - img2img_tab_img.onload = function() { - let w = this.naturalWidth; - let h = this.naturalHeight; - parent_img2img_tab_img.style.width = `${w}px`; - parent_img2img_tab_img.style.height = `${h}px`; - } - }else{ - parent_img2img_tab_img.style.flexGrow = "1"; - } - //} - } } -onUiUpdate(function() { - if(intervalLastUIUpdate != null) clearInterval(intervalLastUIUpdate); - intervalLastUIUpdate = setInterval(onLastUIUpdate, 1000); -}) */ - +onAfterUiUpdate(imageMaskResize); +window.addEventListener('resize', imageMaskResize); diff --git a/javascript/imageviewer.js b/javascript/imageviewer.js index 6a910b57b18..c21d396eefd 100644 --- a/javascript/imageviewer.js +++ b/javascript/imageviewer.js @@ -1,242 +1,259 @@ -//called from progressbar -function showGalleryImage() { - //need to clean up the old code +// A full size 'lightbox' preview modal shown when left clicking on gallery previews +function closeModal() { + gradioApp().getElementById("lightboxModal").style.display = "none"; } -let like; -let tile; - -let slide = 0; -let gallery = []; -let fullImg_src; -//let control = ["pan","undo","like","tile","page","fullscreen","autofit","zoom-in","zoom-out","clear","close","download","prev","next"]; -let control = [ - "like", - "tile", - "page", - "fullscreen", - "autofit", - "zoom-in", - "zoom-out", - "clear", - "close", - "download", - "prev", - "next", -]; - -let img_browser; -let img_file_name; - -let spl_pane; -let spl_zoom_out; -let spl_zoom_in; -let spotlight_gallery; - -function tile_zoom_update(val) { - let current_tile_state_size = gallery[slide].tile_size; - current_tile_state_size += val * 5; - current_tile_state_size = Math.max(5, Math.min(100, current_tile_state_size)); - spl_pane.style.setProperty("background-size", current_tile_state_size + "%"); - gallery[slide].tile_size = current_tile_state_size; -} +function showModal(event) { + const source = event.target || event.srcElement; + const modalImage = gradioApp().getElementById("modalImage"); + const lb = gradioApp().getElementById("lightboxModal"); + modalImage.src = source.src; + if (modalImage.style.display === 'none') { + lb.style.setProperty('background-image', 'url(' + source.src + ')'); + } + lb.style.display = "flex"; + lb.focus(); -function tile_wheel(event) { - let delta = event["deltaY"]; - delta = (delta < 0 ? 1 : delta ? -1 : 0) * 0.5; - tile_zoom_update(delta); -} -function tile_zoom_in(event) { - tile_zoom_update(1); + const tabTxt2Img = gradioApp().getElementById("tab_txt2img"); + const tabImg2Img = gradioApp().getElementById("tab_img2img"); + // show the save button in modal only on txt2img or img2img tabs + if (tabTxt2Img.style.display != "none" || tabImg2Img.style.display != "none") { + gradioApp().getElementById("modal_save").style.display = "inline"; + } else { + gradioApp().getElementById("modal_save").style.display = "none"; + } + event.stopPropagation(); } -function tile_zoom_out(event) { - tile_zoom_update(-1); + +function negmod(n, m) { + return ((n % m) + m) % m; } -function removeTile() { - spl_pane.removeEventListener("wheel", tile_wheel); - spl_zoom_out.removeEventListener("click", tile_zoom_out); - spl_zoom_in.removeEventListener("click", tile_zoom_in); +function updateOnBackgroundChange() { + const modalImage = gradioApp().getElementById("modalImage"); + if (modalImage && modalImage.offsetParent) { + let currentButton = selected_gallery_button(); - spl_pane.classList.remove("hide"); - spl_pane.style.setProperty("background-image", "none"); - spotlight_gallery.zoom(0.0); + if (currentButton?.children?.length > 0 && modalImage.src != currentButton.children[0].src) { + modalImage.src = currentButton.children[0].src; + if (modalImage.style.display === 'none') { + const modal = gradioApp().getElementById("lightboxModal"); + modal.style.setProperty('background-image', `url(${modalImage.src})`); + } + } + } } -function addTile(spl_img) { - spl_pane.addEventListener("wheel", tile_wheel); - spl_zoom_out.addEventListener("click", tile_zoom_out); - spl_zoom_in.addEventListener("click", tile_zoom_in); - - const current_tile_state_size = gallery[slide].tile_size; - spl_pane.classList.add("hide"); - spl_pane.style.setProperty("background-position", "center"); - spl_pane.style.setProperty("background-size", current_tile_state_size + "%"); - if (spl_img) { - spl_pane.style.setProperty("background-image", `url(${spl_img.src})`); - } +function modalImageSwitch(offset) { + var galleryButtons = all_gallery_buttons(); + + if (galleryButtons.length > 1) { + var currentButton = selected_gallery_button(); + + var result = -1; + galleryButtons.forEach(function(v, i) { + if (v == currentButton) { + result = i; + } + }); + + if (result != -1) { + var nextButton = galleryButtons[negmod((result + offset), galleryButtons.length)]; + nextButton.click(); + const modalImage = gradioApp().getElementById("modalImage"); + const modal = gradioApp().getElementById("lightboxModal"); + modalImage.src = nextButton.children[0].src; + if (modalImage.style.display === 'none') { + modal.style.setProperty('background-image', `url(${modalImage.src})`); + } + setTimeout(function() { + modal.focus(); + }, 10); + } + } } -function tile_handler(event) { - const current_tile_state = !gallery[slide].tile; - gallery[slide].tile = current_tile_state; +function saveImage() { + const tabTxt2Img = gradioApp().getElementById("tab_txt2img"); + const tabImg2Img = gradioApp().getElementById("tab_img2img"); + const saveTxt2Img = "save_txt2img"; + const saveImg2Img = "save_img2img"; + if (tabTxt2Img.style.display != "none") { + gradioApp().getElementById(saveTxt2Img).click(); + } else if (tabImg2Img.style.display != "none") { + gradioApp().getElementById(saveImg2Img).click(); + } else { + console.error("missing implementation for saving modal of this type"); + } +} - this.classList.toggle("on"); +function modalSaveImage(event) { + saveImage(); + event.stopPropagation(); +} - if (current_tile_state) { - const spl_img = gradioApp().querySelector("#spotlight-gal .spl-pane img"); - addTile(spl_img); - } else { - removeTile(); - } +function modalNextImage(event) { + modalImageSwitch(1); + event.stopPropagation(); } -function like_handler(event) { - const current_like_state = !gallery[slide].like; - gallery[slide].like = current_like_state; - this.classList.toggle("on"); - - if (current_like_state) { - // add to favorites ... - //img_file_name.value = gallery[slide].src; - //console.log(gallery[slide].src); - } else { - // remove from favorites ... - } + +function modalPrevImage(event) { + modalImageSwitch(-1); + event.stopPropagation(); } -function createGallerySpotlight() { - //console.log("clicked"); - slide = 0; - gallery = []; - - gradioApp() - .querySelectorAll("#" + selectedTabItemId + " .thumbnails img") - .forEach(function (elem, i) { - elem.setAttribute("gal-id", i); - //if(fullImg_src == elem.src) slide = parseInt(i+1); - if (elem.parentElement.className.indexOf("selected") != -1) - slide = parseInt(i + 1); - //console.log(slide); - gallery[i] = { - src: elem.src, - title: "Seed:" + elem.src, - //description: "This is a description.", - like: false, - tile: false, - tile_size: 50, - }; - }); - - const options = { - class: "sd-gallery", - index: slide, - //control: ["like","page","theme","fullscreen","autofit","zoom-in","zoom-out","close","download","play","prev","next"], - control: control, - //animation: animation, - onshow: function (index) {}, - onchange: function (index, options) { - slide = index - 1; - tile.classList.toggle("on", gallery[slide].tile); - //if(img_browser){ - like.classList.toggle("on", gallery[slide].like); - - //} - - spl_pane = gradioApp().querySelector( - "#spotlight-gal .spl-pane:nth-child(" + index + ")" - ); - spl_zoom_out = gradioApp().querySelector("#spotlight-gal .spl-zoom-out"); - spl_zoom_in = gradioApp().querySelector("#spotlight-gal .spl-zoom-in"); - - const current_tile_state = gallery[slide].tile; - if (current_tile_state) { - addTile(); - } else { - removeTile(); - } - }, - onclose: function (index) { - gradioApp() - .querySelector( - "#" + - selectedTabItemId + - " .thumbnails .thumbnail-item:nth-child(" + - (slide + 1) + - ")" - ) - .click(); - }, - }; - - //assign(options, modifier); - - spotlight_gallery.show(gallery, options); - spotlight_gallery.panzoom(true); +function modalKeyHandler(event) { + switch (event.key) { + case "s": + saveImage(); + break; + case "ArrowLeft": + modalPrevImage(event); + break; + case "ArrowRight": + modalNextImage(event); + break; + case "Escape": + closeModal(); + break; + } } -function fullImg_click_handler(e) { - e.stopPropagation(); - e.preventDefault(); - createGallerySpotlight(); +function setupImageForLightbox(e) { + if (e.dataset.modded) { + return; + } + + e.dataset.modded = true; + e.style.cursor = 'pointer'; + e.style.userSelect = 'none'; + + var isFirefox = navigator.userAgent.toLowerCase().indexOf('firefox') > -1; + + // For Firefox, listening on click first switched to next image then shows the lightbox. + // If you know how to fix this without switching to mousedown event, please. + // For other browsers the event is click to make it possiblr to drag picture. + var event = isFirefox ? 'mousedown' : 'click'; + + e.addEventListener(event, function(evt) { + if (evt.button == 1) { + open(evt.target.src); + evt.preventDefault(); + return; + } + if (!opts.js_modal_lightbox || evt.button != 0) return; + + modalZoomSet(gradioApp().getElementById('modalImage'), opts.js_modal_lightbox_initially_zoomed); + evt.preventDefault(); + showModal(evt); + }, true); + } -let intervalUiUpdateIViewer; -function onUiHeaderTabUpdate() { - if (intervalUiUpdateIViewer != null) clearInterval(intervalUiUpdateIViewer); - intervalUiUpdateIViewer = setInterval(onUiUpdateIViewer, 500); +function modalZoomSet(modalImage, enable) { + if (modalImage) modalImage.classList.toggle('modalImageFullscreen', !!enable); } -let fullImg_preview; -function onUiUpdateIViewer() { - clearInterval(intervalUiUpdateIViewer); - //update_performant_inputs(selectedTabItemId); - - //fullImg_preview = gradioApp().querySelector('#'+selectedTabItemId+' [id$="2img_results"] .modify-upload + img.w-full.object-contain'); - fullImg_preview = gradioApp().querySelector( - "#" + selectedTabItemId + " .preview > img" - ); - if (opts.js_modal_lightbox && fullImg_preview) { - fullImg_src = fullImg_preview.src; - fullImg_preview.removeEventListener("click", fullImg_click_handler); - fullImg_preview.addEventListener("click", fullImg_click_handler, true); //bubbling phase - - /* - // this is an idea to integrate image browser extension seamlesly, - // without the need to change to the image browser tab extension users will be able to review images after generation - // and add them to favorites or delete the ones that don't like on the spot - const img_browser = gradioApp().querySelector('[id$="2img_images_history"]'); - const tbname = selectedTabItemId.split("_")[1]; - if(img_browser && tbname ==("txt2img" || "img2img")){ - const images_history = gradioApp().querySelector('[id$="'+tbname+'_images_history"]'); - const history_button_panel = images_history.querySelector('[id$="'+tbname+'_images_history_button_panel"]'); - const labels = images_history.querySelectorAll('label.block span'); - for(let i=0;i div > img'); + if (fullImg_preview != null) { + fullImg_preview.forEach(setupImageForLightbox); + } + updateOnBackgroundChange(); }); -document.addEventListener("DOMContentLoaded", function () {}); +document.addEventListener("DOMContentLoaded", function() { + //const modalFragment = document.createDocumentFragment(); + const modal = document.createElement('div'); + modal.onclick = closeModal; + modal.id = "lightboxModal"; + modal.tabIndex = 0; + modal.addEventListener('keydown', modalKeyHandler, true); + + const modalControls = document.createElement('div'); + modalControls.className = 'modalControls gradio-container'; + modal.append(modalControls); + + const modalZoom = document.createElement('span'); + modalZoom.className = 'modalZoom cursor'; + modalZoom.innerHTML = '⤡'; + modalZoom.addEventListener('click', modalZoomToggle, true); + modalZoom.title = "Toggle zoomed view"; + modalControls.appendChild(modalZoom); + + const modalTileImage = document.createElement('span'); + modalTileImage.className = 'modalTileImage cursor'; + modalTileImage.innerHTML = '⊞'; + modalTileImage.addEventListener('click', modalTileImageToggle, true); + modalTileImage.title = "Preview tiling"; + modalControls.appendChild(modalTileImage); + + const modalSave = document.createElement("span"); + modalSave.className = "modalSave cursor"; + modalSave.id = "modal_save"; + modalSave.innerHTML = "🖫"; + modalSave.addEventListener("click", modalSaveImage, true); + modalSave.title = "Save Image(s)"; + modalControls.appendChild(modalSave); + + const modalClose = document.createElement('span'); + modalClose.className = 'modalClose cursor'; + modalClose.innerHTML = '×'; + modalClose.onclick = closeModal; + modalClose.title = "Close image viewer"; + modalControls.appendChild(modalClose); + + const modalImage = document.createElement('img'); + modalImage.id = 'modalImage'; + modalImage.onclick = closeModal; + modalImage.tabIndex = 0; + modalImage.addEventListener('keydown', modalKeyHandler, true); + modal.appendChild(modalImage); + + const modalPrev = document.createElement('a'); + modalPrev.className = 'modalPrev'; + modalPrev.innerHTML = '❮'; + modalPrev.tabIndex = 0; + modalPrev.addEventListener('click', modalPrevImage, true); + modalPrev.addEventListener('keydown', modalKeyHandler, true); + modal.appendChild(modalPrev); + + const modalNext = document.createElement('a'); + modalNext.className = 'modalNext'; + modalNext.innerHTML = '❯'; + modalNext.tabIndex = 0; + modalNext.addEventListener('click', modalNextImage, true); + modalNext.addEventListener('keydown', modalKeyHandler, true); + + modal.appendChild(modalNext); + + try { + gradioApp().appendChild(modal); + } catch (e) { + gradioApp().body.appendChild(modal); + } + + document.body.appendChild(modal); + +}); diff --git a/javascript/imageviewerGamepad.js b/javascript/imageviewerGamepad.js index 8f824148d2f..a22c7e6e643 100644 --- a/javascript/imageviewerGamepad.js +++ b/javascript/imageviewerGamepad.js @@ -60,4 +60,4 @@ function sleepUntil(f, timeout) { } }, 20); }); -} \ No newline at end of file +} diff --git a/javascript/inputAccordion.js b/javascript/inputAccordion.js new file mode 100644 index 00000000000..f2839852ee7 --- /dev/null +++ b/javascript/inputAccordion.js @@ -0,0 +1,37 @@ +var observerAccordionOpen = new MutationObserver(function(mutations) { + mutations.forEach(function(mutationRecord) { + var elem = mutationRecord.target; + var open = elem.classList.contains('open'); + + var accordion = elem.parentNode; + accordion.classList.toggle('input-accordion-open', open); + + var checkbox = gradioApp().querySelector('#' + accordion.id + "-checkbox input"); + checkbox.checked = open; + updateInput(checkbox); + + var extra = gradioApp().querySelector('#' + accordion.id + "-extra"); + if (extra) { + extra.style.display = open ? "" : "none"; + } + }); +}); + +function inputAccordionChecked(id, checked) { + var label = gradioApp().querySelector('#' + id + " .label-wrap"); + if (label.classList.contains('open') != checked) { + label.click(); + } +} + +onUiLoaded(function() { + for (var accordion of gradioApp().querySelectorAll('.input-accordion')) { + var labelWrap = accordion.querySelector('.label-wrap'); + observerAccordionOpen.observe(labelWrap, {attributes: true, attributeFilter: ['class']}); + + var extra = gradioApp().querySelector('#' + accordion.id + "-extra"); + if (extra) { + labelWrap.insertBefore(extra, labelWrap.lastElementChild); + } + } +}); diff --git a/javascript/localStorage.js b/javascript/localStorage.js new file mode 100644 index 00000000000..dc1a36c3287 --- /dev/null +++ b/javascript/localStorage.js @@ -0,0 +1,26 @@ + +function localSet(k, v) { + try { + localStorage.setItem(k, v); + } catch (e) { + console.warn(`Failed to save ${k} to localStorage: ${e}`); + } +} + +function localGet(k, def) { + try { + return localStorage.getItem(k); + } catch (e) { + console.warn(`Failed to load ${k} from localStorage: ${e}`); + } + + return def; +} + +function localRemove(k) { + try { + return localStorage.removeItem(k); + } catch (e) { + console.warn(`Failed to remove ${k} from localStorage: ${e}`); + } +} diff --git a/javascript/localization.js b/javascript/localization.js index f90281648aa..8f00c186860 100644 --- a/javascript/localization.js +++ b/javascript/localization.js @@ -1,3 +1,4 @@ + // localization = {} -- the dict with translations is created by the backend var ignore_ids_for_localization = { @@ -10,11 +11,11 @@ var ignore_ids_for_localization = { train_hypernetwork: 'OPTION', txt2img_styles: 'OPTION', img2img_styles: 'OPTION', - setting_random_artist_categories: 'SPAN', - setting_face_restoration_model: 'SPAN', - setting_realesrgan_enabled_models: 'SPAN', - extras_upscaler_1: 'SPAN', - extras_upscaler_2: 'SPAN', + setting_random_artist_categories: 'OPTION', + setting_face_restoration_model: 'OPTION', + setting_realesrgan_enabled_models: 'OPTION', + extras_upscaler_1: 'OPTION', + extras_upscaler_2: 'OPTION', }; var re_num = /^[.\d]+$/; @@ -106,12 +107,41 @@ function processNode(node) { }); } +function localizeWholePage() { + processNode(gradioApp()); + + function elem(comp) { + var elem_id = comp.props.elem_id ? comp.props.elem_id : "component-" + comp.id; + return gradioApp().getElementById(elem_id); + } + + for (var comp of window.gradio_config.components) { + if (comp.props.webui_tooltip) { + let e = elem(comp); + + let tl = e ? getTranslation(e.title) : undefined; + if (tl !== undefined) { + e.title = tl; + } + } + if (comp.props.placeholder) { + let e = elem(comp); + let textbox = e ? e.querySelector('[placeholder]') : null; + + let tl = textbox ? getTranslation(textbox.placeholder) : undefined; + if (tl !== undefined) { + textbox.placeholder = tl; + } + } + } +} + function dumpTranslations() { if (!hasLocalization()) { // If we don't have any localization, // we will not have traversed the app to find // original_lines, so do that now. - processNode(gradioApp()); + localizeWholePage(); } var dumped = {}; if (localization.rtl) { @@ -153,7 +183,7 @@ document.addEventListener("DOMContentLoaded", function() { }); }); - processNode(gradioApp()); + localizeWholePage(); if (localization.rtl) { // if the language is from right to left, (new MutationObserver((mutations, observer) => { // wait for the style to load diff --git a/javascript/notification.js b/javascript/notification.js index 82577b2db4b..6d79956125c 100644 --- a/javascript/notification.js +++ b/javascript/notification.js @@ -1,3 +1,5 @@ +// Monitors the gallery and sends a browser notification when the leading image is new. + let lastHeadImg = null; let notificationButton = null; @@ -13,7 +15,7 @@ onAfterUiUpdate(function() { } } - const galleryPreviews = gradioApp().querySelectorAll('div[id^="tab_"][style*="display: block"] div[id$="_results"] .thumbnail-item > img'); + const galleryPreviews = gradioApp().querySelectorAll('div[id^="tab_"] div[id$="_results"] .thumbnail-item > img'); if (galleryPreviews == null) return; @@ -44,4 +46,4 @@ onAfterUiUpdate(function() { parent.focus(); this.close(); }; -}); \ No newline at end of file +}); diff --git a/javascript/progressbar.js b/javascript/progressbar.js index 8606030b26f..777614954b2 100644 --- a/javascript/progressbar.js +++ b/javascript/progressbar.js @@ -36,13 +36,13 @@ function pad2(x) { } function formatTime(secs) { - if (secs > 3600) { - return pad2(Math.floor(secs / 60 / 60)) + ":" + pad2(Math.floor(secs / 60) % 60) + ":" + pad2(Math.floor(secs) % 60); - } else if (secs > 60) { - return pad2(Math.floor(secs / 60)) + ":" + pad2(Math.floor(secs) % 60); - } else { - return Math.floor(secs) + "s"; - } + if (secs > 3600) { + return pad2(Math.floor(secs / 60 / 60)) + ":" + pad2(Math.floor(secs / 60) % 60) + ":" + pad2(Math.floor(secs) % 60); + } else if (secs > 60) { + return pad2(Math.floor(secs / 60)) + ":" + pad2(Math.floor(secs) % 60); + } else { + return Math.floor(secs) + "s"; + } } function setTitle(progress) { @@ -57,6 +57,7 @@ function setTitle(progress) { } } + function randomId() { return "task(" + Math.random().toString(36).slice(2, 7) + Math.random().toString(36).slice(2, 7) + Math.random().toString(36).slice(2, 7) + ")"; } @@ -64,145 +65,122 @@ function randomId() { // starts sending progress requests to "/internal/progress" uri, creating progressbar above progressbarContainer element and // preview inside gallery element. Cleans up all created stuff when the task is over and calls atEnd. // calls onProgress every time there is a progress update -function requestProgress( - id_task, - progressbarContainer, - gallery, - atEnd, - onProgress, - inactivityTimeout = 40 -) { - var dateStart = new Date(); - var wasEverActive = false; - var parentProgressbar = progressbarContainer.parentNode; - var parentGallery = gallery ? gallery.parentNode : null; - - var divProgress = document.createElement("div"); - divProgress.className = "progressDiv"; - - divProgress.style.display = opts.show_progressbar ? "block" : "none"; - var divInner = document.createElement("div"); - divInner.className = "progress"; - - divProgress.appendChild(divInner); - parentProgressbar.insertBefore(divProgress, progressbarContainer); - - if (parentGallery) { - var livePreview = gradioApp().querySelector(".livePreview"); - if (!livePreview) { - livePreview = document.createElement("div"); - livePreview.classList.add("livePreview", "init"); - parentGallery.insertBefore(livePreview, gallery); - } - livePreview.classList.remove("dropPreview"); - } +function requestProgress(id_task, progressbarContainer, gallery, atEnd, onProgress, inactivityTimeout = 40) { + var dateStart = new Date(); + var wasEverActive = false; + var parentProgressbar = progressbarContainer.parentNode; - var removeProgressBar = function () { - setTitle(""); - if (divProgress) { - parentProgressbar.removeChild(divProgress); - } + var divProgress = document.createElement('div'); + divProgress.className = 'progressDiv'; + divProgress.style.display = opts.show_progressbar ? "block" : "none"; + var divInner = document.createElement('div'); + divInner.className = 'progress'; - if (progressbarContainer.id == "txt2img_gallery_container") { - showSubmitButtons("txt2img", true); - } else if (progressbarContainer.id == "img2img_gallery_container") { - showSubmitButtons("img2img", true); - } - if (livePreview) { - if (parentGallery) parentGallery.removeChild(livePreview); - } - gradioApp() - .querySelectorAll("#tabs + div, #tabs + div > *:not(ul)") - .forEach(function (elem) { - elem.style.setProperty("display", "block", "important"); - }); - atEnd(); - }; - - var fun = function (id_task, id_live_preview) { - request( - "./internal/progress", - { id_task: id_task, id_live_preview: id_live_preview }, - function (res) { - if (res.completed) { - removeProgressBar(); - return; - } + divProgress.appendChild(divInner); + parentProgressbar.insertBefore(divProgress, progressbarContainer); - var rect = progressbarContainer.getBoundingClientRect(); + var livePreview = null; - if (rect.width) { - divProgress.style.width = rect.width + "px"; - } + var removeProgressBar = function() { + if (!divProgress) return; - let progressText = ""; + setTitle(""); + parentProgressbar.removeChild(divProgress); + if (gallery && livePreview) gallery.removeChild(livePreview); + atEnd(); - divInner.style.width = (res.progress || 0) * 100.0 + "%"; - divInner.style.background = res.progress ? "" : "transparent"; + divProgress = null; + }; - if (res.progress > 0) { - progressText = ((res.progress || 0) * 100.0).toFixed(0) + "%"; - } + var funProgress = function(id_task) { + request("./internal/progress", {id_task: id_task, live_preview: false}, function(res) { + if (res.completed) { + removeProgressBar(); + return; + } - if (res.eta) { - progressText += " ETA: " + formatTime(res.eta); - } + let progressText = ""; - setTitle(progressText); + divInner.style.width = ((res.progress || 0) * 100.0) + '%'; + divInner.style.background = res.progress ? "" : "transparent"; - if (res.textinfo && res.textinfo.indexOf("\n") == -1) { - progressText = res.textinfo + " " + progressText; - } + if (res.progress > 0) { + progressText = ((res.progress || 0) * 100.0).toFixed(0) + '%'; + } - divInner.textContent = progressText; + if (res.eta) { + progressText += " ETA: " + formatTime(res.eta); + } - var elapsedFromStart = (new Date() - dateStart) / 1000; + setTitle(progressText); - if (res.active) wasEverActive = true; + if (res.textinfo && res.textinfo.indexOf("\n") == -1) { + progressText = res.textinfo + " " + progressText; + } - if (!res.active && wasEverActive) { - removeProgressBar(); - return; - } + divInner.textContent = progressText; - if ( - elapsedFromStart > inactivityTimeout && - !res.queued && - !res.active - ) { - removeProgressBar(); - return; - } + var elapsedFromStart = (new Date() - dateStart) / 1000; - if (res.live_preview && gallery) { + if (res.active) wasEverActive = true; - livePreview.classList.remove("init"); + if (!res.active && wasEverActive) { + removeProgressBar(); + return; + } - var img = new Image(); - img.onload = function () { - img.width = img.naturalWidth; - img.height = img.naturalHeight; - livePreview.appendChild(img); - if (livePreview.childElementCount > 2) { - livePreview.removeChild(livePreview.firstElementChild); + if (elapsedFromStart > inactivityTimeout && !res.queued && !res.active) { + removeProgressBar(); + return; } - }; - img.src = res.live_preview; - } - if (onProgress) { - onProgress(res); - } + if (onProgress) { + onProgress(res); + } + + setTimeout(() => { + funProgress(id_task, res.id_live_preview); + }, opts.live_preview_refresh_period || 500); + }, function() { + removeProgressBar(); + }); + }; + + var funLivePreview = function(id_task, id_live_preview) { + request("./internal/progress", {id_task: id_task, id_live_preview: id_live_preview}, function(res) { + if (!divProgress) { + return; + } + + if (res.live_preview && gallery) { + var img = new Image(); + img.onload = function() { + if (!livePreview) { + livePreview = document.createElement('div'); + livePreview.className = 'livePreview'; + gallery.insertBefore(livePreview, gallery.firstElementChild); + } + + livePreview.appendChild(img); + if (livePreview.childElementCount > 2) { + livePreview.removeChild(livePreview.firstElementChild); + } + }; + img.src = res.live_preview; + } + + setTimeout(() => { + funLivePreview(id_task, res.id_live_preview); + }, opts.live_preview_refresh_period || 500); + }, function() { + removeProgressBar(); + }); + }; + + funProgress(id_task, 0); + + if (gallery) { + funLivePreview(id_task, 0); + } - setTimeout(() => { - fun(id_task, res.id_live_preview); - }, opts.live_preview_refresh_period || 500); - }, - function () { - removeProgressBar(); - } - ); - }; - - fun(id_task, 0); } diff --git a/javascript/resizeHandle.js b/javascript/resizeHandle.js new file mode 100644 index 00000000000..8c5c5169210 --- /dev/null +++ b/javascript/resizeHandle.js @@ -0,0 +1,141 @@ +(function() { + const GRADIO_MIN_WIDTH = 320; + const GRID_TEMPLATE_COLUMNS = '1fr 16px 1fr'; + const PAD = 16; + const DEBOUNCE_TIME = 100; + + const R = { + tracking: false, + parent: null, + parentWidth: null, + leftCol: null, + leftColStartWidth: null, + screenX: null, + }; + + let resizeTimer; + let parents = []; + + function setLeftColGridTemplate(el, width) { + el.style.gridTemplateColumns = `${width}px 16px 1fr`; + } + + function displayResizeHandle(parent) { + if (window.innerWidth < GRADIO_MIN_WIDTH * 2 + PAD * 4) { + parent.style.display = 'flex'; + if (R.handle != null) { + R.handle.style.opacity = '0'; + } + return false; + } else { + parent.style.display = 'grid'; + if (R.handle != null) { + R.handle.style.opacity = '100'; + } + return true; + } + } + + function afterResize(parent) { + if (displayResizeHandle(parent) && parent.style.gridTemplateColumns != GRID_TEMPLATE_COLUMNS) { + const oldParentWidth = R.parentWidth; + const newParentWidth = parent.offsetWidth; + const widthL = parseInt(parent.style.gridTemplateColumns.split(' ')[0]); + + const ratio = newParentWidth / oldParentWidth; + + const newWidthL = Math.max(Math.floor(ratio * widthL), GRADIO_MIN_WIDTH); + setLeftColGridTemplate(parent, newWidthL); + + R.parentWidth = newParentWidth; + } + } + + function setup(parent) { + const leftCol = parent.firstElementChild; + const rightCol = parent.lastElementChild; + + parents.push(parent); + + parent.style.display = 'grid'; + parent.style.gap = '0'; + parent.style.gridTemplateColumns = GRID_TEMPLATE_COLUMNS; + + const resizeHandle = document.createElement('div'); + resizeHandle.classList.add('resize-handle'); + parent.insertBefore(resizeHandle, rightCol); + + resizeHandle.addEventListener('mousedown', (evt) => { + if (evt.button !== 0) return; + + evt.preventDefault(); + evt.stopPropagation(); + + document.body.classList.add('resizing'); + + R.tracking = true; + R.parent = parent; + R.parentWidth = parent.offsetWidth; + R.handle = resizeHandle; + R.leftCol = leftCol; + R.leftColStartWidth = leftCol.offsetWidth; + R.screenX = evt.screenX; + }); + + resizeHandle.addEventListener('dblclick', (evt) => { + evt.preventDefault(); + evt.stopPropagation(); + + parent.style.gridTemplateColumns = GRID_TEMPLATE_COLUMNS; + }); + + afterResize(parent); + } + + window.addEventListener('mousemove', (evt) => { + if (evt.button !== 0) return; + + if (R.tracking) { + evt.preventDefault(); + evt.stopPropagation(); + + const delta = R.screenX - evt.screenX; + const leftColWidth = Math.max(Math.min(R.leftColStartWidth - delta, R.parent.offsetWidth - GRADIO_MIN_WIDTH - PAD), GRADIO_MIN_WIDTH); + setLeftColGridTemplate(R.parent, leftColWidth); + } + }); + + window.addEventListener('mouseup', (evt) => { + if (evt.button !== 0) return; + + if (R.tracking) { + evt.preventDefault(); + evt.stopPropagation(); + + R.tracking = false; + + document.body.classList.remove('resizing'); + } + }); + + + window.addEventListener('resize', () => { + clearTimeout(resizeTimer); + + resizeTimer = setTimeout(function() { + for (const parent of parents) { + afterResize(parent); + } + }, DEBOUNCE_TIME); + }); + + setupResizeHandle = setup; +})(); + +onUiLoaded(function() { + for (var elem of gradioApp().querySelectorAll('.resize-handle-row')) { + if (!elem.querySelector('.resize-handle')) { + setupResizeHandle(elem); + } + } +}); diff --git a/javascript/spotlight.js b/javascript/spotlight.js deleted file mode 100644 index 88ae8ed2faa..00000000000 --- a/javascript/spotlight.js +++ /dev/null @@ -1,13 +0,0 @@ -/** - * Spotlight.js v0.7.8 - * Copyright 2019-2021 Nextapps GmbH - * Author: Thomas Wilkerling - * Licence: Apache-2.0 - * https://github.com/nextapps-de/spotlight - */ - /* - this library was rewritten by anapnoe to work with https://github.com/anapnoe/stable-diffusion-webui-ux - it supports multi-instancing, enable-disable panzoom functionallity and input type tools - */ - -!function(e){"use strict";let t=function(t,i={}){this.controls=["info","theme","download","play","page","close","autofit","zoom-in","zoom-out","prev","next","fullscreen"],this.controls_default={page:1,close:1,autofit:1,"zoom-in":1,"zoom-out":1,prev:1,next:1,fullscreen:1},this.keycodes={BACKSPACE:8,ESCAPE:27,SPACEBAR:32,LEFT:37,RIGHT:39,UP:38,NUMBLOCK_PLUS:107,PLUS:187,DOWN:40,NUMBLOCK_MINUS:109,MINUS:189,INFO:73};let s=this;Object.assign||(Object.assign=function(e,t){let i=Object.keys(t);for(let s=0,o;s{s.toggleClass(e,t,!0)},this.removeClass=(e,t)=>{s.toggleClass(e,t)},this.toggleClass=(e,t,i)=>{e.classList[i?"add":"remove"](t)},this.hasClass=(e,t)=>e.classList.contains(t),this.setStyle=(e,t,i)=>{i=""+i,e["_s_"+t]!==i&&(e.style.setProperty(t,i),e["_s_"+t]=i)};let o=0;this.prepareStyle=(e,t)=>{t&&(s.setStyle(e,"transition","none"),t()),o||(o=e.clientTop&&0),t&&s.setStyle(e,"transition","")},this.setText=(e,t)=>{e.firstChild.nodeValue=t},this.getByClass=(e,t)=>(t||document).getElementsByClassName(e),this.getByTag=(e,t)=>(t||document).getElementsByTagName(e),this.addListener=(e,t,i,o)=>{s.toggleListener(!0,e,t,i,o)},this.removeListener=(e,t,i,o)=>{s.toggleListener(!1,e,t,i,o)},this.toggleListener=(e,t,i,s,o)=>{t[(e?"add":"remove")+"EventListener"](i,s,!o&&!1!==o||o)},this.cancelEvent=(e,t)=>{e.stopPropagation(),t&&e.preventDefault()},this.downloadImage=(e,t)=>{let i=s.createElement("a"),o=t.src;i.href=o,i.download=o.substring(o.lastIndexOf("/")+1),s.body.appendChild(i),i.click(),s.body.removeChild(i)},this.createElement=e=>document.createElement(e),this.toggleDisplay=(e,t)=>{s.setStyle(e,"display",t?"":"none")},this.toggleVisibility=(e,t)=>{s.setStyle(e,"visibility",t?"":"hidden")},this.toggleAnimation=(e,t)=>{s.setStyle(e,"transition",t?"":"none")},this.widget=this.createElement("div"),this.widget.innerHTML="
",this.video_support={},this.tpl_video=this.createElement("video"),this.parse_src=(e,t,i,o)=>{let n,l;if("node"!==o){let a=Object.keys(i);for(let r=0,d;r3&&0===d.indexOf("src")){if("video"===o){let p=s.video_support[d];if(p){if(p>0){n=i[d];break}}else if(s.tpl_video.canPlayType("video/"+d.substring(3).replace("-","").toLowerCase())){s.video_support[d]=1,n=i[d];break}else s.video_support[d]=-1}else{let c=parseInt(d.substring(4),10);if(c){let h=Math.abs(t-c);(!l||h{s.body||(s.id="spotlight"+t,s.widget.id="spotlight"+t,s.doc=document.body,s.body=e,s.slider=s.getOneByClass("scene"),s.header=s.getOneByClass("header"),s.footer=s.getOneByClass("footer"),s.title=s.getOneByClass("title"),s.description=s.getOneByClass("description"),s.button=s.getOneByClass("button"),s.page_prev=s.getOneByClass("prev"),s.page_next=s.getOneByClass("next"),s.page=s.getOneByClass("page"),s.progress=s.getOneByClass("progress"),s.spinner=s.getOneByClass("spinner"),s.panes=[s.getOneByClass("pane")],s.addControl("close",s.close),s.doc[s.prefix_request="requestFullscreen"]||s.doc[s.prefix_request="msRequestFullscreen"]||s.doc[s.prefix_request="webkitRequestFullscreen"]||s.doc[s.prefix_request="mozRequestFullscreen"]||(s.prefix_request=""),s.prefix_request?(s.prefix_exit=s.prefix_request.replace("request","exit").replace("mozRequest","mozCancel").replace("Request","Exit"),s.maximize=s.addControl("fullscreen",s.fullscreen)):s.controls.pop(),s.addControl("info",s.info),s.addControl("autofit",s.autofit),s.addControl("zoom-in",s.zoom_in),s.addControl("zoom-out",s.zoom_out),s.addControl("theme",s.theme),s.player=s.addControl("play",s.play),s.addControl("download",s.download),s.addListener(s.page_prev,"click",s.prev),s.addListener(s.page_next,"click",s.next),s.track=s.getOneByClass("track"),s.addListener(s.track,"mousedown",s.start),s.addListener(s.track,"mousemove",s.move),s.addListener(s.track,"mouseleave",s.end),s.addListener(s.track,"mouseup",s.end),s.addListener(s.track,"touchstart",s.start,{passive:!1}),s.addListener(s.track,"touchmove",s.move,{passive:!0}),s.addListener(s.track,"touchend",s.end),s.addListener(s.button,"click",function(){s.options_click?s.options_click(s.current_slide,s.options):s.options_href&&(location.href=s.options_href)}))},this.getOneByClass=e=>this.controls_dom[e]=this.getByClass("spl-"+e,this.widget)[0],this.addControl=(e,t,i="")=>{let o=s.createElement("div");return o.className="spl-"+e,o.innerHTML=i,s.addListener(o,"click",t),s.header.appendChild(o),s.controls_dom[e]=o},this.removeControl=e=>{let t=s.controls_dom[e];t&&(s.header.removeChild(t),s.controls_dom[e]=null)},this.dispatch=e=>{let t=e.target.closest(".spotlight");if(t){s.cancelEvent(e,!0);let i=t.closest(".spotlight-group");s.anchors=s.getByClass("spotlight",i);for(let o=0;o{s.anchors=e,t&&(s.options_group=t,s.options_onshow=t.onshow,s.options_onchange=t.onchange,s.options_onclose=t.onclose,i=i||t.index),s.init_gallery(i)},this.panzoom=e=>{s.toggleListener(e,s.track,"wheel",s.wheel_listener,{passive:!1}),s.toggleListener(e,s.track,"mousedown",s.start),s.toggleListener(e,s.track,"mousemove",s.move),s.toggleListener(e,s.track,"mouseleave",s.end),s.toggleListener(e,s.track,"mouseup",s.end),s.toggleListener(e,s.track,"touchstart",s.start,{passive:!1}),s.toggleListener(e,s.track,"touchmove",s.move,{passive:!0}),s.toggleListener(e,s.track,"touchend",s.end)},this.init_gallery=e=>{if(s.slide_count=s.anchors.length,s.slide_count){s.body||s.init(),s.options_onshow&&s.options_onshow(e);let t=s.panes[0],i=t.parentElement;for(let o=s.panes.length;o{let s=i[e];return void 0!==s?"false"!=(s=""+s)&&(s||t):t},this.apply_options=e=>{s.options={},s.options_group&&Object.assign(s.options,s.options_group),Object.assign(s.options,e.dataset||e),s.options_media=s.options.media,s.options_click=s.options.onclick,s.options_theme=s.options.theme,s.options_class=s.options.class,s.options_autohide=s.parse_option("autohide",!1),s.options_infinite=s.parse_option("infinite"),s.options_progress=s.parse_option("progress",!0),s.options_autoslide=s.parse_option("autoslide"),s.options_preload=s.parse_option("preload",!0),s.options_href=s.options.buttonHref,s.delay=s.options_autoslide&&parseFloat(s.options_autoslide)||7,s.toggle_theme||s.options_theme&&s.theme(s.options_theme),s.options_class&&s.addClass(s.widget,s.options_class),s.options_class&&s.prepareStyle(s.widget);let t=s.options.control;if(t){let i="string"==typeof t?t.split(","):t;for(let o=0;o{e?s.prepareStyle(s.media,s.prepare_animation):(s.toggleAnimation(s.slider,s.animation_slide),s.setStyle(s.media,"opacity",s.animation_fade?0:1),s.update_scroll(s.animation_scale&&.8),s.animation_custom&&s.addClass(s.media,s.animation_custom))},this.init_slide=e=>{if(s.panel=s.panes[e-1],s.media=s.panel.firstChild,s.current_slide=e,s.media)s.disable_autoresizer(),s.options_fit&&s.addClass(s.media,s.options_fit),s.prepare_animation(!0),s.animation_custom&&s.removeClass(s.media,s.animation_custom),s.animation_fade&&s.setStyle(s.media,"opacity",1),s.animation_scale&&s.setStyle(s.media,"transform",""),s.setStyle(s.media,"visibility","visible"),s.gallery_next&&(s.media_next.src=s.gallery_next),s.options_autoslide&&s.animate_bar(s.playing);else{let t=s.gallery.media;if(s.parse_option("spinner",!0),"node"===t){s.media=s.gallery.src,"string"==typeof s.media&&(s.media=gradioApp().querySelector(s.media)),s.media&&(s.media._root||(s.media._root=s.media.parentElement),s.update_media_viewport(),s.panel.appendChild(s.media),s.init_slide(e));return}s.toggle_spinner(s.options_spinner,!0),s.media=s.createElement("img"),s.media.onload=function(){s.media===s&&(s.media.onerror=null,s.toggle_spinner(s.options_spinner),s.init_slide(e),s.update_media_viewport())},s.media.src=s.gallery.src,s.panel.appendChild(s.media),s.media&&(s.options_spinner||s.setStyle(s.media,"visibility","visible"),s.media.onerror=function(){s.media===s&&(s.checkout(s.media),s.addClass(s.spinner,"error"),s.toggle_spinner(s.options_spinner))})}},this.toggle_spinner=(e,t)=>{e&&s.toggleClass(s.spinner,"spin",t)},this.has_fullscreen=()=>document.fullscreen||document.fullscreenElement||document.webkitFullscreenElement||document.mozFullScreenElement,this.resize_listener=()=>{if(s.update_widget_viewport(),s.media&&s.update_media_viewport(),s.prefix_request){let e=s.has_fullscreen();s.toggleClass(s.maximize,"on",e),e||s.detect_fullscreen()}},this.detect_fullscreen=()=>{s.toggleDisplay(s.maximize,screen.availHeight-e.innerHeight>0)},this.update_widget_viewport=()=>{s.viewport_w=s.widget.clientWidth,s.viewport_h=s.widget.clientHeight},this.update_media_viewport=()=>{s.media_w=s.media.clientWidth,s.media_h=s.media.clientHeight},this.update_scroll=e=>{s.setStyle(s.media,"transform","translate(-50%, -50%) scale("+(e||s.scale)+")")},this.update_panel=(e,t)=>{s.setStyle(s.panel,"transform",e||t?"translate("+e+"px, "+t+"px)":"")},this.update_slider=(e,t,i)=>{t?s.prepareStyle(s.slider,function(){s.update_slider(e,!1,i)}):s.setStyle(s.slider,"transform","translateX("+(-(100*e)+(i||0))+"%)")},this.toggle_listener=t=>{s.toggleListener(t,e,"keydown",s.key_listener),s.toggleListener(t,e,"resize",s.resize_listener)},this.history_listener=e=>{s.panel&&e.state.spl&&s.close(!0)},this.key_listener=e=>{if(s.panel){let t=!1!==s.options["zoom-in"];switch(e.keyCode){case s.keycodes.BACKSPACE:t&&s.autofit();break;case s.keycodes.SPACEBAR:s.options_autoslide&&s.play();break;case s.keycodes.LEFT:s.prev();break;case s.keycodes.RIGHT:s.next();break;case s.keycodes.NUMBLOCK_PLUS:case s.keycodes.PLUS:t&&s.zoom_in();break;case s.keycodes.NUMBLOCK_MINUS:case s.keycodes.MINUS:t&&s.zoom_out();break;case s.keycodes.INFO:s.info()}}},this.wheel_listener=e=>{if(s.panel&&!1!==s.options["zoom-in"]){let t=e.deltaY;(t=(t<0?1:t?-1:0)*.5)<0?s.zoom_out():s.zoom_in()}},this.play=(e,t)=>{let i="boolean"==typeof e?e:!this.playing;!s.playing===i&&(s.playing=s.playing?clearTimeout(s.playing):1,s.toggleClass(s.player,"on",s.playing),t||s.animate_bar(s.playing))},this.animate_bar=e=>{s.options_progress&&(s.prepareStyle(s.progress,function(){s.setStyle(s.progress,"transition-duration",""),s.setStyle(s.progress,"transform","")}),e&&(s.setStyle(s.progress,"transition-duration",s.delay+"s"),s.setStyle(s.progress,"transform","translateX(0)"))),e&&(s.playing=setTimeout(s.next,1e3*s.delay))},this.autohide=()=>{s.options_autohide&&(s.hide_cooldown=Date.now()+2950,s.hide||(s.addClass(s.widget,"menu"),s.schedule(3e3)))},this.schedule=e=>{s.hide=setTimeout(function(){let e=Date.now();e>=s.hide_cooldown?(s.removeClass(s.widget,"menu"),s.hide=0):s.schedule(s.hide_cooldown-e)},e)},this.menu=e=>{"boolean"==typeof e&&(s.hide=e?s.hide:0),s.hide?(s.hide=clearTimeout(s.hide),s.removeClass(s.widget,"menu")):s.autohide()},this.start=e=>{s.cancelEvent(e,!0),s.is_down=!0,s.dragged=!1;let t=e.touches;t&&(t=t[0])&&(e=t),s.slidable=s.media_w*s.scale<=s.viewport_w,s.startX=e.pageX,s.startY=e.pageY,s.toggleAnimation(s.panel)},this.end=e=>{if(s.cancelEvent(e),s.is_down){if(s.dragged){if(s.slidable&&s.dragged){let t=s.x<-(s.viewport_w/7)&&(s.current_slides.viewport_w/7&&(s.current_slide>1||s.options_infinite);(t||i)&&(s.update_slider(s.current_slide-1,!0,s.x/s.viewport_w*100),t&&s.next()||i&&s.prev()),s.x=0,s.update_panel()}s.toggleAnimation(s.panel,!0)}else s.menu();s.is_down=!1}},this.move=e=>{if(s.cancelEvent(e),s.is_down){let t=e.touches;t&&(t=t[0])&&(e=t);let i=(s.media_w*s.scale-s.viewport_w)/2;s.x-=s.startX-(s.startX=e.pageX),!s.slidable&&(s.x>i?s.x=i:s.x<-i&&(s.x=-i),s.media_h*s.scale>s.viewport_h&&(i=(s.media_h*s.scale-s.viewport_h)/2,s.y-=s.startY-(s.startY=e.pageY),s.y>i?s.y=i:s.y<-i&&(s.y=-i))),s.dragged=!0,s.update_panel(s.x,s.y)}else s.autohide()},this.fullscreen=e=>{let t=s.has_fullscreen();("boolean"!=typeof e||!!t!==e)&&(t?document[s.prefix_exit]():s.widget[s.prefix_request]())},this.theme=e=>{"string"!=typeof e&&(e=s.toggle_theme?"":s.options_theme||"white"),s.toggle_theme!==e&&(s.toggle_theme&&s.removeClass(s.widget,s.toggle_theme),e&&s.addClass(s.widget,e),s.toggle_theme=e)},this.autofit=e=>{"boolean"==typeof e&&(s.toggle_autofit=!e),s.toggle_autofit=1===s.scale&&!s.toggle_autofit,s.toggleClass(s.media,"autofit",s.toggle_autofit),s.setStyle(s.media,"transform",""),s.scale=1,s.x=0,s.y=0,s.update_media_viewport(),s.toggleAnimation(s.panel),s.update_panel()},this.zoom_in=e=>{let t=s.scale/.65;t<=50&&(s.disable_autoresizer(),s.x/=.65,s.y/=.65,s.update_panel(s.x,s.y),s.zoom(t))},this.zoom_out=e=>{let t=.65*s.scale;s.disable_autoresizer(),t>=1&&(1===t?s.x=s.y=0:(s.x*=.65,s.y*=.65),s.update_panel(s.x,s.y),s.zoom(t))},this.zoom=e=>{s.scale=e||1,s.update_scroll()},this.info=()=>{s.footer_visible=!s.footer_visible,s.toggleVisibility(s.footer,s.footer_visible)},this.disable_autoresizer=()=>{s.toggle_autofit&&s.autofit()},this.show_gallery=()=>{s.toggleAnimation(s.widget,!0),s.addClass(s.body,"hide-scrollbars"),s.addClass(s.widget,"show"),s.toggle_listener(!0),s.update_widget_viewport(),s.resize_listener(),s.autohide(),s.options_autoslide&&s.play(!0,!0)},this.download=()=>{s.downloadImage(s.body,s.media)},this.close=(e,t)=>{if(s.hasClass(s.body,"relative")&&!t){s.fullscreen(!1);return}t||setTimeout(function(){s.body.removeChild(s.widget),s.panel=s.media=s.gallery=s.options=s.options_group=s.anchors=s.options_onshow=s.options_onchange=s.options_onclose=s.options_click=null},200),s.removeClass(s.body,"hide-scrollbars"),s.removeClass(s.widget,"show"),s.fullscreen(!1),s.toggle_listener(),s.gallery_next&&(s.media_next.src=""),s.playing&&s.play(),s.media&&s.checkout(s.media),s.hide&&(s.hide=clearTimeout(s.hide)),s.toggle_theme&&s.theme(),s.options_class&&s.removeClass(s.widget,s.options_class),s.options_onclose&&s.options_onclose(),t&&(s.body.removeChild(s.widget),s.panel=s.media=s.gallery=s.options=s.options_group=s.anchors=s.options_onshow=s.options_onchange=s.options_onclose=s.options_click=null)},this.checkout=e=>{if(e._root)e._root.appendChild(e),e._root=null;else{let t=e.parentNode;t&&t.removeChild(e),e=e.src=e.onerror=""}},this.prev=e=>{if(e&&s.autohide(),s.slide_count>1){if(s.current_slide>1)return s.goto(s.current_slide-1);if(s.options_infinite)return s.update_slider(s.slide_count,!0),s.goto(s.slide_count)}},this.next=e=>{if(e&&s.autohide(),s.slide_count>1){if(s.current_slide{if(e!==s.current_slide){s.playing?(clearTimeout(s.playing),s.animate_bar()):s.autohide();let t=e>s.current_slide;return s.current_slide=e,s.setup_page(t),!0}},this.prepare=e=>{let t=s.anchors[s.current_slide-1];s.apply_options(t);let i=n&&n.downlink,o=Math.max(s.viewport_h,s.viewport_w)*l;i&&1200*i{if(s.x=0,s.y=0,s.scale=1,s.media){if(s.media.onerror)s.checkout(s.media);else{let t=s.media;setTimeout(function(){t&&s.media!==t&&(s.checkout(t),t=null)},650),s.prepare_animation(),s.update_panel()}}s.footer&&s.toggleVisibility(s.footer,0),s.prepare(e),s.update_slider(s.current_slide-1),s.removeClass(s.spinner,"error"),s.init_slide(s.current_slide),s.toggleAnimation(s.panel),s.update_panel();let i=s.gallery.title,o=s.parse_option("description"),n=s.parse_option("button"),l=i||o||n;l&&(i&&s.setText(s.title,i),o&&s.setText(s.description,o),n&&s.setText(s.button,n),s.toggleDisplay(s.title,i),s.toggleDisplay(s.description,o),s.toggleDisplay(s.button,n),s.setStyle(s.footer,"transform","all"===s.options_autohide?"":"none")),s.options_autohide||s.addClass(s.widget,"menu"),s.toggleVisibility(s.footer,s.footer_visible&&l),s.toggleVisibility(s.page_prev,s.options_infinite||s.current_slide>1),s.toggleVisibility(s.page_next,s.options_infinite||s.current_slide1?s.current_slide+" / "+s.slide_count:""),s.options_onchange&&s.options_onchange(s.current_slide,s.options)}};"undefined"!=typeof module&&void 0!==module.exports?module.exports=t:e.Spotlight=t}(window); \ No newline at end of file diff --git a/javascript/textualInversion.js b/javascript/textualInversion.js index 99360557649..20443fcca01 100644 --- a/javascript/textualInversion.js +++ b/javascript/textualInversion.js @@ -1,3 +1,6 @@ + + + function start_training_textual_inversion() { gradioApp().querySelector('#ti_error').innerHTML = ''; diff --git a/javascript/ui.js b/javascript/ui.js index da748446e20..dbab8334f92 100644 --- a/javascript/ui.js +++ b/javascript/ui.js @@ -1,1996 +1,323 @@ +// various functions for interaction with ui.py not large enough to warrant putting them in separate files + function set_theme(theme) { - /* - var gradioURL = window.location.href; - if (!gradioURL.includes('?__theme=')) { - window.location.replace(gradioURL + '?__theme=' + theme); - } - */ + var gradioURL = window.location.href; + if (!gradioURL.includes('?__theme=')) { + window.location.replace(gradioURL + '?__theme=' + theme); + } } -var selectedTabItemId = "tab_txt2img"; - function all_gallery_buttons() { - var allGalleryButtons = gradioApp().querySelectorAll('[style="display: block;"].tabitem div[id$=_gallery].gradio-gallery .thumbnails > .thumbnail-item.thumbnail-small'); - var visibleGalleryButtons = []; - allGalleryButtons.forEach(function(elem) { - if (elem.parentElement.offsetParent) { - visibleGalleryButtons.push(elem); - } - }); - return visibleGalleryButtons; + var allGalleryButtons = gradioApp().querySelectorAll('[style="display: block;"].tabitem div[id$=_gallery].gradio-gallery .thumbnails > .thumbnail-item.thumbnail-small'); + var visibleGalleryButtons = []; + allGalleryButtons.forEach(function(elem) { + if (elem.parentElement.offsetParent) { + visibleGalleryButtons.push(elem); + } + }); + return visibleGalleryButtons; } function selected_gallery_button() { - var allCurrentButtons = gradioApp().querySelectorAll('[style="display: block;"].tabitem div[id$=_gallery].gradio-gallery .thumbnail-item.thumbnail-small.selected'); - var visibleCurrentButton = null; - allCurrentButtons.forEach(function(elem) { - if (elem.parentElement.offsetParent) { - visibleCurrentButton = elem; - } - }); - return visibleCurrentButton; + return all_gallery_buttons().find(elem => elem.classList.contains('selected')) ?? null; } function selected_gallery_index() { - var buttons = all_gallery_buttons(); - var button = selected_gallery_button(); - - var result = -1; - buttons.forEach(function(v, i) { - if (v == button) { - result = i; - } - }); - - return result; + return all_gallery_buttons().findIndex(elem => elem.classList.contains('selected')); } function extract_image_from_gallery(gallery) { - if (gallery.length == 0) { - return [null]; - } - if (gallery.length == 1) { - return [gallery[0]]; - } + if (gallery.length == 0) { + return [null]; + } + if (gallery.length == 1) { + return [gallery[0]]; + } - var index = selected_gallery_index(); + var index = selected_gallery_index(); - if (index < 0 || index >= gallery.length) { - // Use the first image in the gallery as the default - index = 0; - } + if (index < 0 || index >= gallery.length) { + // Use the first image in the gallery as the default + index = 0; + } - return [gallery[index]]; + return [gallery[index]]; } window.args_to_array = Array.from; // Compatibility with e.g. extensions that may expect this to be around function switch_to_txt2img() { - gradioApp().querySelector('#tabs').querySelectorAll('button')[0].click(); + gradioApp().querySelector('#tabs').querySelectorAll('button')[0].click(); - return Array.from(arguments); + return Array.from(arguments); } function switch_to_img2img_tab(no) { - gradioApp().querySelector('#tabs').querySelectorAll('button')[1].click(); - gradioApp().getElementById('mode_img2img').querySelectorAll('button')[no].click(); + gradioApp().querySelector('#tabs').querySelectorAll('button')[1].click(); + gradioApp().getElementById('mode_img2img').querySelectorAll('button')[no].click(); } function switch_to_img2img() { - switch_to_img2img_tab(0); - return Array.from(arguments); + switch_to_img2img_tab(0); + return Array.from(arguments); } function switch_to_sketch() { - switch_to_img2img_tab(1); - return Array.from(arguments); + switch_to_img2img_tab(1); + return Array.from(arguments); } function switch_to_inpaint() { - switch_to_img2img_tab(2); - return Array.from(arguments); + switch_to_img2img_tab(2); + return Array.from(arguments); } function switch_to_inpaint_sketch() { - switch_to_img2img_tab(3); - return Array.from(arguments); + switch_to_img2img_tab(3); + return Array.from(arguments); } function switch_to_extras() { - gradioApp().querySelector('#tabs').querySelectorAll('button')[2].click(); + gradioApp().querySelector('#tabs').querySelectorAll('button')[2].click(); - return Array.from(arguments); + return Array.from(arguments); } function get_tab_index(tabId) { - let buttons = gradioApp().getElementById(tabId).querySelector('div').querySelectorAll('button'); - for (let i = 0; i < buttons.length; i++) { - if (buttons[i].classList.contains('selected')) { - return i; - } - } - return 0; + let buttons = gradioApp().getElementById(tabId).querySelector('div').querySelectorAll('button'); + for (let i = 0; i < buttons.length; i++) { + if (buttons[i].classList.contains('selected')) { + return i; + } + } + return 0; } function create_tab_index_args(tabId, args) { - var res = Array.from(args); - res[0] = get_tab_index(tabId); - return res; + var res = Array.from(args); + res[0] = get_tab_index(tabId); + return res; } function get_img2img_tab_index() { - let res = Array.from(arguments); - res.splice(-2); - res[0] = get_tab_index('mode_img2img'); - return res; + let res = Array.from(arguments); + res.splice(-2); + res[0] = get_tab_index('mode_img2img'); + return res; } function create_submit_args(args) { - var res = Array.from(args); - - // As it is currently, txt2img and img2img send back the previous output args (txt2img_gallery, generation_info, html_info) whenever you generate a new image. - // This can lead to uploading a huge gallery of previously generated images, which leads to an unnecessary delay between submitting and beginning to generate. - // I don't know why gradio is sending outputs along with inputs, but we can prevent sending the image gallery here, which seems to be an issue for some. - // If gradio at some point stops sending outputs, this may break something - if (Array.isArray(res[res.length - 3])) { - res[res.length - 3] = null; - } + var res = Array.from(args); + + // As it is currently, txt2img and img2img send back the previous output args (txt2img_gallery, generation_info, html_info) whenever you generate a new image. + // This can lead to uploading a huge gallery of previously generated images, which leads to an unnecessary delay between submitting and beginning to generate. + // I don't know why gradio is sending outputs along with inputs, but we can prevent sending the image gallery here, which seems to be an issue for some. + // If gradio at some point stops sending outputs, this may break something + if (Array.isArray(res[res.length - 3])) { + res[res.length - 3] = null; + } - return res; + return res; } function showSubmitButtons(tabname, show) { - gradioApp().getElementById(tabname + "_interrupt").style.display = show ? "none" : "flex"; - gradioApp().getElementById(tabname + "_skip").style.display = show ? "none" : "flex"; - gradioApp().getElementById(tabname + "_generate").style.display = !show ? "none" : "flex"; + gradioApp().getElementById(tabname + '_interrupt').style.display = show ? "none" : "block"; + gradioApp().getElementById(tabname + '_skip').style.display = show ? "none" : "block"; } function showRestoreProgressButton(tabname, show) { - var button = gradioApp().getElementById(tabname + "_restore_progress"); - if (!button) return; + var button = gradioApp().getElementById(tabname + "_restore_progress"); + if (!button) return; - button.style.display = show ? "flex" : "none"; + button.style.display = show ? "flex" : "none"; } - function submit() { - showSubmitButtons('txt2img', false); + showSubmitButtons('txt2img', false); - var id = randomId(); - localStorage.setItem("txt2img_task_id", id); + var id = randomId(); + localSet("txt2img_task_id", id); - requestProgress(id, gradioApp().getElementById('txt2img_gallery_container'), gradioApp().getElementById('txt2img_gallery'), function() { - showSubmitButtons('txt2img', true); - localStorage.removeItem("txt2img_task_id"); - showRestoreProgressButton('txt2img', false); - }); + requestProgress(id, gradioApp().getElementById('txt2img_gallery_container'), gradioApp().getElementById('txt2img_gallery'), function() { + showSubmitButtons('txt2img', true); + localRemove("txt2img_task_id"); + showRestoreProgressButton('txt2img', false); + }); - var res = create_submit_args(arguments); + var res = create_submit_args(arguments); - res[0] = id; + res[0] = id; - return res; + return res; } function submit_img2img() { - showSubmitButtons('img2img', false); + showSubmitButtons('img2img', false); - var id = randomId(); - localStorage.setItem("img2img_task_id", id); + var id = randomId(); + localSet("img2img_task_id", id); - requestProgress(id, gradioApp().getElementById('img2img_gallery_container'), gradioApp().getElementById('img2img_gallery'), function() { - showSubmitButtons('img2img', true); - localStorage.removeItem("img2img_task_id"); - showRestoreProgressButton('img2img', false); - }); + requestProgress(id, gradioApp().getElementById('img2img_gallery_container'), gradioApp().getElementById('img2img_gallery'), function() { + showSubmitButtons('img2img', true); + localRemove("img2img_task_id"); + showRestoreProgressButton('img2img', false); + }); - var res = create_submit_args(arguments); + var res = create_submit_args(arguments); - res[0] = id; - res[1] = get_tab_index('mode_img2img'); + res[0] = id; + res[1] = get_tab_index('mode_img2img'); - return res; + return res; } function restoreProgressTxt2img() { - showRestoreProgressButton("txt2img", false); - var id = localStorage.getItem("txt2img_task_id"); - - id = localStorage.getItem("txt2img_task_id"); + showRestoreProgressButton("txt2img", false); + var id = localGet("txt2img_task_id"); - if (id) { - requestProgress(id, gradioApp().getElementById('txt2img_gallery_container'), gradioApp().getElementById('txt2img_gallery'), function() { - showSubmitButtons('txt2img', true); - }, null, 0); - } + if (id) { + requestProgress(id, gradioApp().getElementById('txt2img_gallery_container'), gradioApp().getElementById('txt2img_gallery'), function() { + showSubmitButtons('txt2img', true); + }, null, 0); + } - return id; + return id; } function restoreProgressImg2img() { - showRestoreProgressButton("img2img", false); + showRestoreProgressButton("img2img", false); - var id = localStorage.getItem("img2img_task_id"); + var id = localGet("img2img_task_id"); - if (id) { - requestProgress(id, gradioApp().getElementById('img2img_gallery_container'), gradioApp().getElementById('img2img_gallery'), function() { - showSubmitButtons('img2img', true); - }, null, 0); - } + if (id) { + requestProgress(id, gradioApp().getElementById('img2img_gallery_container'), gradioApp().getElementById('img2img_gallery'), function() { + showSubmitButtons('img2img', true); + }, null, 0); + } - return id; + return id; } + onUiLoaded(function() { - showRestoreProgressButton('txt2img', localStorage.getItem("txt2img_task_id")); - showRestoreProgressButton('img2img', localStorage.getItem("img2img_task_id")); + showRestoreProgressButton('txt2img', localGet("txt2img_task_id")); + showRestoreProgressButton('img2img', localGet("img2img_task_id")); }); function modelmerger() { - var id = randomId(); - requestProgress(id, gradioApp().getElementById('modelmerger_results_panel'), null, function() {}); + var id = randomId(); + requestProgress(id, gradioApp().getElementById('modelmerger_results_panel'), null, function() {}); - var res = create_submit_args(arguments); - res[0] = id; - return res; + var res = create_submit_args(arguments); + res[0] = id; + return res; } function ask_for_style_name(_, prompt_text, negative_prompt_text) { - var name_ = prompt('Style name:'); - return [name_, prompt_text, negative_prompt_text]; + var name_ = prompt('Style name:'); + return [name_, prompt_text, negative_prompt_text]; } function confirm_clear_prompt(prompt, negative_prompt) { - if (confirm("Delete prompt?")) { - prompt = ""; - negative_prompt = ""; - } - - return [prompt, negative_prompt]; -} - - -var promptTokecountUpdateFuncs = {}; - -function recalculatePromptTokens(name) { - if (promptTokecountUpdateFuncs[name]) { - promptTokecountUpdateFuncs[name](); - } -} - -function recalculate_prompts_txt2img() { - recalculatePromptTokens('txt2img_prompt'); - recalculatePromptTokens('txt2img_neg_prompt'); - return Array.from(arguments); -} + if (confirm("Delete prompt?")) { + prompt = ""; + negative_prompt = ""; + } -function recalculate_prompts_img2img() { - recalculatePromptTokens('img2img_prompt'); - recalculatePromptTokens('img2img_neg_prompt'); - return Array.from(arguments); + return [prompt, negative_prompt]; } var opts = {}; -onUiUpdate(function() { - - if (Object.keys(opts).length != 0) return; - - var json_elem = gradioApp().getElementById("settings_json"); - if (json_elem == null) return; - - var textarea = json_elem.querySelector("textarea"); - var jsdata = textarea.value; - opts = JSON.parse(jsdata); - executeCallbacks(optionsChangedCallbacks); - - Object.defineProperty(textarea, "value", { - set: function (newValue) { - var valueProp = Object.getOwnPropertyDescriptor( - HTMLTextAreaElement.prototype, - "value" - ); - var oldValue = valueProp.get.call(textarea); - valueProp.set.call(textarea, newValue); - - if (oldValue != newValue) { - opts = JSON.parse(textarea.value); - } - - executeCallbacks(optionsChangedCallbacks); - }, - get: function () { - var valueProp = Object.getOwnPropertyDescriptor( - HTMLTextAreaElement.prototype, - "value" - ); - return valueProp.get.call(textarea); - }, - }); - - //console.log(opts); - - json_elem.parentElement.style.display = "none"; - - function registerTextarea(id, id_counter, id_button) { - var prompt = gradioApp().getElementById(id); - var counter = gradioApp().getElementById(id_counter); - var textarea = gradioApp().querySelector("#" + id + " > label > textarea"); - - if (counter.parentElement == prompt.parentElement) { - return; - } - - prompt.parentElement.insertBefore(counter, prompt); - counter.classList.add("token-counter"); - prompt.parentElement.style.position = "relative"; - - promptTokecountUpdateFuncs[id] = function () { - update_token_counter(id_button); - }; - textarea.addEventListener("input", promptTokecountUpdateFuncs[id]); - } - - registerTextarea( - "txt2img_prompt", - "txt2img_token_counter", - "txt2img_token_button" - ); - registerTextarea( - "txt2img_neg_prompt", - "txt2img_negative_token_counter", - "txt2img_negative_token_button" - ); - registerTextarea( - "img2img_prompt", - "img2img_token_counter", - "img2img_token_button" - ); - registerTextarea( - "img2img_neg_prompt", - "img2img_negative_token_counter", - "img2img_negative_token_button" - ); - - var show_all_pages = gradioApp().getElementById("settings_show_all_pages"); - var settings_tabs = gradioApp().querySelector("#settings div"); - if (show_all_pages && settings_tabs) { - settings_tabs.appendChild(show_all_pages); - show_all_pages.onclick = function () { - gradioApp() - .querySelectorAll("#settings > div") - .forEach(function (elem) { - elem.style.display = "block"; - }); - gradioApp() - .querySelectorAll("#settings > div > div > div") - .forEach(function (elem) { - elem.style.maxHeight = "none"; - }); - }; - } - /* - ^ matches the start - * matches any position - $ matches the end - */ - /* anapnoe ui start */ - - /* auto grow textarea */ - function autoGrowPromptTextarea() { - gradioApp() - .querySelectorAll('[id$="_prompt"] textarea') - .forEach(function (elem) { - elem.parentElement.click(); - }); - } - - gradioApp() - .querySelectorAll( - '[id$="_prompt"] textarea, [id^="setting_"] textarea, textarea' - ) - .forEach(function (elem) { - elem.style.boxSizing = "border-box"; - var offset = elem.offsetHeight - elem.clientHeight; - elem.addEventListener("input", function (e) { - e.target.style.minHeight = "auto"; - e.target.style.minHeight = e.target.scrollHeight + offset + 2 + "px"; - }); - - elem.parentElement.addEventListener("click", function (e) { - let textarea = e.currentTarget.querySelector("textarea"); - textarea.style.minHeight = "auto"; - textarea.style.minHeight = textarea.scrollHeight + offset + 2 + "px"; - }); - }); - - /* resizable split view */ - const resizeEvent = window.document.createEvent("UIEvents"); - resizeEvent.initUIEvent("resize", true, false, window, 0); - - gradioApp() - .querySelectorAll('[id $="2img_splitter"]') - .forEach((elem) => { - elem.addEventListener("mousedown", function (e) { - e.preventDefault(); - - let resizer = e.currentTarget; - let container = resizer.parentElement; +onAfterUiUpdate(function() { + if (Object.keys(opts).length != 0) return; - let flexDir = window - .getComputedStyle(container) - .getPropertyValue("flex-direction"); + var json_elem = gradioApp().getElementById('settings_json'); + if (json_elem == null) return; - let leftSide = resizer.previousElementSibling; - let rightSide = resizer.nextElementSibling; + var textarea = json_elem.querySelector('textarea'); + var jsdata = textarea.value; + opts = JSON.parse(jsdata); - let dir = flexDir == "row-reverse" ? -1.0 : 1.0; + executeCallbacks(optionsChangedCallbacks); /*global optionsChangedCallbacks*/ - let x = e.clientX; - let y = e.clientY; - let leftWidth = leftSide.getBoundingClientRect().width; + Object.defineProperty(textarea, 'value', { + set: function(newValue) { + var valueProp = Object.getOwnPropertyDescriptor(HTMLTextAreaElement.prototype, 'value'); + var oldValue = valueProp.get.call(textarea); + valueProp.set.call(textarea, newValue); - function mouseMoveHandler(e) { - resizer.style.cursor = "col-resize"; - container.style.cursor = "col-resize"; - - const dx = (e.clientX - x) * dir; - const dy = (e.clientY - y) * dir; - - const newLeftWidth = - ((leftWidth + dx) * 100) / container.getBoundingClientRect().width; - leftSide.style.flexBasis = `${newLeftWidth}%`; - leftSide.style.userSelect = "none"; - leftSide.style.pointerEvents = "none"; - rightSide.style.userSelect = "none"; - rightSide.style.pointerEvents = "none"; - //window.dispatchEvent(resizeEvent); - } - - function mouseUpHandler() { - resizer.style.removeProperty("cursor"); - container.style.removeProperty("cursor"); - leftSide.style.removeProperty("user-select"); - leftSide.style.removeProperty("pointer-events"); - rightSide.style.removeProperty("user-select"); - rightSide.style.removeProperty("pointer-events"); - container.removeEventListener("mousemove", mouseMoveHandler); - container.removeEventListener("mouseup", mouseUpHandler); - //window.dispatchEvent(resizeEvent); - } - - container.addEventListener("mousemove", mouseMoveHandler); - container.addEventListener("mouseup", mouseUpHandler); - }); - - let flex_reverse = false; - elem.addEventListener("dblclick", function (e) { - flex_reverse = !flex_reverse; - e.preventDefault(); - - let resizer = e.currentTarget; - let container = resizer.parentElement; - //let flexDir = window.getComputedStyle(container).getPropertyValue('flex-direction'); - - if (flex_reverse) { - container.style.flexDirection = "row-reverse"; - } else { - container.style.flexDirection = "row"; - } - }); - }); - - // set this globally - //let selectedTabItemId = "tab_txt2img"; - /* switch tab item from instance button, this is the only method that works i havent found a workaround yet */ - const Observe = (sel, opt, cb) => { - const Obs = new MutationObserver((m) => [...m].forEach(cb)); - gradioApp() - .querySelectorAll(sel) - .forEach((el) => Obs.observe(el, opt)); - }; - Observe( - "#tabs > div.tabitem", - { - attributesList: ["style"], - attributeOldValue: true, - }, - (m) => { - if (m.target.style.display === "block") { - let idx = parseInt(m.target.getAttribute("tab-item")); - selectedTabItemId = m.target.id; - tabItemChanged(idx); - } - } - ); - - function tabItemChanged(idx) { - gradioApp() - .querySelectorAll( - "#tabs > div > button.selected, #nav_menu_header_tabs > button.selected" - ) - .forEach(function (tab) { - tab.classList.remove("selected"); - }); - - gradioApp() - .querySelectorAll( - "#tabs > div > button:nth-child(" + - (idx + 1) + - "), #nav_menu_header_tabs > button:nth-child(" + - (idx + 1) + - ")" - ) - .forEach(function (tab) { - tab.classList.add("selected"); - }); - //gardio removes listeners and attributes from tab buttons we add them again here - gradioApp() - .querySelectorAll("#tabs > div > button") - .forEach(function (tab, index) { - tab.setAttribute("tab-id", index); - tab.removeEventListener("mouseup", navTabClicked); - tab.addEventListener("mouseup", navTabClicked); - if (tab.innerHTML.indexOf("Theme") != -1) tab.style.display = "none"; - }); - - /* gradioApp().querySelectorAll('[id^="image_buttons_"] button').forEach(function (elem){ - - if(elem.id == "txt2img_tab"){ - elem.setAttribute("tab-id", 0); - elem.removeEventListener('click', navTabClicked); - elem.addEventListener('click', navTabClicked); - }else if(elem.id == "img2img_tab" || elem.id == "inpaint_tab"){ - elem.setAttribute("tab-id", 1); - elem.removeEventListener('click', navTabClicked); - elem.addEventListener('click', navTabClicked); - }if(elem.id == "extras_tab"){ - elem.setAttribute("tab-id", 2); - elem.removeEventListener('click', navTabClicked); - elem.addEventListener('click', navTabClicked); - } - }) */ - - /* const pdiv = gradioApp().querySelector("#"+selectedTabItemId+" .progressDiv"); - if(!pdiv && selectedTabItemId == "tab_txt2img"){ - showSubmitButtons('txt2img', true); - }else if(!pdiv && selectedTabItemId == "tab_img2img"){ - showSubmitButtons('img2img', true); - } */ - - //window.onUiHeaderTabUpdate(); - // also here the same issue - /* - gradioApp().querySelectorAll('[id^="image_buttons"] [id$="_tab"]').forEach(function (button, index){ - if(button.id == ("img2img_tab" || "inpaint_tab") ){ - button.setAttribute("tab-id", 1 ); - }else if(button.id == "extras_tab"){ - button.setAttribute("tab-id", 2 ); - } - - button.removeEventListener('mouseup', navTabClicked); - button.addEventListener('mouseup', navTabClicked); - - - }) - */ - - netMenuVisibility(); - } - - // menu - function disableScroll() { - scrollTop = window.pageYOffset || document.documentElement.scrollTop; - scrollLeft = window.pageXOffset || document.documentElement.scrollLeft; - window.scrollTo(scrollLeft, scrollTop); - - window.onscroll = function () { - window.scrollTo(scrollLeft, scrollTop); - }; - } - - function enableScroll() { - window.onscroll = function () {}; - } - - function getPos(el) { - let rect = el.getBoundingClientRect(); - return { x: rect.left, y: rect.top }; - } - - function toggleMenu(isopen, icon, panel, func) { - if (isopen) { - panel.classList.add("open"); - icon.classList.add("fixed"); - gradioApp().addEventListener("click", func); - disableScroll(); - } else { - panel.classList.remove("open"); - icon.classList.remove("fixed"); - gradioApp().removeEventListener("click", func); - enableScroll(); - } - } - - // close aside views - function closeAsideViews(menu) { - if (quick_menu != menu && quick_menu_open) quick_menu.click(); - if (net_menu != menu && net_menu_open) net_menu.click(); - if (theme_menu != menu && theme_menu_open) theme_menu.click(); - } - - // if we change to other view other than 2img and if aside mode is selected close extra networks aside and hide the net menu icon - let net_container = gradioApp().querySelector("#txt2img_extra_networks_row"); - let net_menu_open = false; - const net_menu = gradioApp().querySelector("#extra_networks_menu"); - function netMenuVisibility() { - if (selectedTabItemId.indexOf("2img") != -1) { - net_menu.style.display = "block"; - let nid = selectedTabItemId.split("_")[1]; - net_container = gradioApp().querySelector( - "#" + nid + "_extra_networks_row" - ); - if (net_container.classList.contains("aside")) { - net_menu.style.display = "block"; - toggleMenu(net_menu_open, net_menu, net_container, null); - } else { - net_menu.style.display = "none"; - } - } else { - net_menu.style.display = "none"; - } - } - - // mobile nav menu - const tabs_menu = gradioApp().querySelector("#tabs > div:first-child"); - const nav_menu = gradioApp().querySelector("#nav_menu"); - const header = gradioApp().querySelector("#header-top"); - let menu_open = false; - const z_menu = nav_menu.cloneNode(true); - z_menu.id = "clone_nav_menu"; - header.parentElement.append(z_menu); - function toggleNavMenu(e) { - e.stopPropagation(); - menu_open = !menu_open; - toggleMenu(menu_open, nav_menu, tabs_menu, toggleNavMenu); - } - z_menu.addEventListener("click", toggleNavMenu); - - // quicksettings nav menu - let quick_menu_open = false; - const quicksettings_overflow = gradioApp().querySelector( - "#quicksettings_overflow" - ); - const quick_menu = gradioApp().querySelector("#quick_menu"); - function toggleQuickMenu(e) { - closeAsideViews(quick_menu); - quick_menu_open = !quick_menu_open; - const withinBoundaries = e.composedPath().includes(quicksettings_overflow); - if (!quick_menu_open && withinBoundaries) { - quick_menu_open = true; - } else { - e.preventDefault(); - e.stopPropagation(); - toggleMenu( - quick_menu_open, - quick_menu, - quicksettings_overflow, - toggleQuickMenu - ); - } - } - quick_menu.addEventListener("click", toggleQuickMenu); - - // extra networks nav menu - function clickedOutside(e) { - //console.log(e.target.getAttribute('data-testid')); - if ( - e.target.getAttribute("data-testid") != "textbox" && - e.target.getAttribute("data-testid") - ) { - if (net_menu_open && e.target.closest('[id$="2img_settings_scroll"]')) - net_menu.click(); - } - } - function toggleNetMenu(e) { - closeAsideViews(net_menu); - net_menu_open = !net_menu_open; - e.preventDefault(); - e.stopPropagation(); - toggleMenu(net_menu_open, net_menu, net_container, clickedOutside); - } - net_menu.addEventListener("click", toggleNetMenu); - gradioApp() - .querySelectorAll('button[id*="2img_extra_networks"]') - .forEach((elem) => { - elem.addEventListener("click", toggleNetMenu); - }); - - // theme nav menu - let theme_container = gradioApp().querySelector("#tab_ui_theme"); - let theme_menu_open = false; - const theme_menu = gradioApp().querySelector("#theme_menu"); - function toggleThemeMenu(e) { - closeAsideViews(theme_menu); - theme_menu_open = !theme_menu_open; - e.preventDefault(); - e.stopPropagation(); - toggleMenu(theme_menu_open, theme_menu, theme_container, null); - } - theme_menu.addEventListener("click", toggleThemeMenu); - - const theme_tab = gradioApp().querySelector("#tab_ui_theme"); - function theme_aside(value) { - if (value) { - theme_tab.classList.add("aside"); - } else { - theme_tab.classList.remove("aside"); - } - } - if (theme_tab) theme_aside(true); - - function generateOnRepeat(elem, isforever) { - if (elem.generateOnRepeatInterval != null) - clearInterval(elem.generateOnRepeatInterval); - if (isforever) { - const generate_button = elem.previousElementSibling; - elem.generateOnRepeatInterval = setInterval(function () { - if (window.getComputedStyle(generate_button).display !== "none") { - generate_button.click(); - } - }, 500); - } - } - - function toggleGenerateForever(e) { - e.target.classList.toggle("active"); - if (e.target.className.indexOf("active") != -1) { - generateOnRepeat(e.target, true); - } else { - generateOnRepeat(e.target, false); - } - e.preventDefault(); - e.stopPropagation(); - } - - gradioApp() - .querySelectorAll('button[id*="2img_generate_forever"]') - .forEach((elem) => { - elem.addEventListener("click", toggleGenerateForever); - }); - - /* let generateOnRepeat = function (genbuttonid, interruptbuttonid) { - let genbutton = gradioApp().querySelector(genbuttonid); - let interruptbutton = gradioApp().querySelector(interruptbuttonid); - if (!interruptbutton.offsetParent) { - genbutton.click(); - } - clearInterval(window.generateOnRepeatInterval); - window.generateOnRepeatInterval = setInterval(function () { - if (!interruptbutton.offsetParent) { - genbutton.click(); - } - }, 500); - }; - - appendContextMenuOption("#txt2img_generate", "Generate forever", function () { - generateOnRepeat("#txt2img_generate", "#txt2img_interrupt"); - }); - appendContextMenuOption("#img2img_generate", "Generate forever", function () { - generateOnRepeat("#img2img_generate", "#img2img_interrupt"); - }); - - let cancelGenerateForever = function () { - clearInterval(window.generateOnRepeatInterval); - }; */ - - // - /* - function attachAccordionListeners(elem) { - elem.querySelectorAll(".gradio-accordion > div.wrap").forEach((elem) => { - elem.addEventListener("click", toggleAccordion); - }); - } - function toggleAccordion(e) { - //e.preventDefault(); - //e.stopPropagation(); - //e.stopImmediatePropagation(); - let accordion_content = - e.currentTarget.parentElement.querySelector(".gap.svelte-vt1mxs"); - - if (accordion_content) { - e.preventDefault(); - e.stopPropagation(); - let accordion_icon = e.currentTarget.parentElement.querySelector( - ".label-wrap > .icon" - ); - if (accordion_content.className.indexOf("hidden") != -1) { - accordion_content.classList.remove("hidden"); - accordion_icon.style.setProperty("transform", "rotate(0deg)"); - e.currentTarget.classList.add("hide"); - } else { - accordion_content.classList.add("hidden"); - accordion_icon.style.setProperty("transform", "rotate(90deg)"); - e.currentTarget.classList.remove("hide"); - } - } else { - let accordion_btn = - e.currentTarget.parentElement.querySelector(".label-wrap"); - e.currentTarget.classList.add("hide"); - accordion_btn.click(); - //maybe here we need to setInterval until the content is available - setTimeout(function () { - accordion_content = accordion_btn.parentElement; - //console.log(accordion_content); - attachAccordionListeners(accordion_content); - }, 1000); - } - } - - attachAccordionListeners(gradioApp()); - */ - // additional ui styles - let styleobj = {}; - const r = gradioApp(); - const style = document.createElement("style"); - style.id = "ui-styles"; - r.appendChild(style); - - function updateOpStyles() { - let ops_styles = ""; - for (const key in styleobj) { - ops_styles += styleobj[key]; - } - const ui_styles = gradioApp().getElementById("ui-styles"); - ui_styles.innerHTML = ops_styles; - //console.log(ui_styles); - } - - // generated image fit contain - scale - function imageGeneratedFitMethod(value) { - styleobj.ui_view_fit = - "[id$='2img_gallery'] div>img {object-fit:" + value + "!important;}"; - } - gradioApp() - .querySelector("#setting_ui_output_image_fit") - .addEventListener("click", function (e) { - if (e.target && e.target.matches("input[type='radio']")) { - imageGeneratedFitMethod(e.target.value.toLowerCase()); - updateOpStyles(); - } - }); - imageGeneratedFitMethod(opts.ui_output_image_fit.toLowerCase()); - - // livePreview fit contain - scale - function imagePreviewFitMethod(value) { - styleobj.ui_fit = ".livePreview img {object-fit:" + value + "!important;}"; - } - gradioApp() - .querySelector("#setting_live_preview_image_fit") - .addEventListener("click", function (e) { - if (e.target && e.target.matches("input[type='radio']")) { - imagePreviewFitMethod(e.target.value.toLowerCase()); - updateOpStyles(); - } - }); - imagePreviewFitMethod(opts.live_preview_image_fit.toLowerCase()); - - // viewports order left - right - function viewportOrder(value) { - styleobj.ui_views_order = - "[id$=_prompt_image] + div {flex-direction:" + value + ";}"; - } - gradioApp() - .querySelector("#setting_ui_views_order") - .addEventListener("click", function (e) { - if (e.target && e.target.matches("input[type='radio']")) { - viewportOrder(e.target.value.toLowerCase()); - updateOpStyles(); - } - }); - viewportOrder(opts.ui_views_order.toLowerCase()); - - // sd max resolution output - function sdMaxOutputResolution(value) { - gradioApp() - .querySelectorAll('[id$="2img_width"] input,[id$="2img_height"] input') - .forEach((elem) => { - elem.max = value; - }); - } - gradioApp() - .querySelector("#setting_sd_max_resolution") - .addEventListener("input", function (e) { - let intvalue = parseInt(e.target.value); - intvalue = Math.min(Math.max(intvalue, 512), 16384); - sdMaxOutputResolution(intvalue); - }); - sdMaxOutputResolution(opts.sd_max_resolution); - - function extra_networks_visibility(value) { - gradioApp() - .querySelectorAll('[id$="2img_extra_networks_row"]') - .forEach((elem) => { - if (value) { - elem.classList.remove("!hidden"); - } else { - elem.classList.add("!hidden"); - } - }); - } - gradioApp() - .querySelector("#setting_extra_networks_default_visibility input") - .addEventListener("click", function (e) { - extra_networks_visibility(e.target.checked); - }); - extra_networks_visibility(opts.extra_networks_default_visibility); - - function extra_networks_card_size(value) { - styleobj.extra_networks_card_size = - ":root{--ae-extra-networks-card-size:" + value + ";}"; - } - gradioApp() - .querySelectorAll("#setting_extra_networks_cards_size input") - .forEach(function (elem) { - elem.addEventListener("input", function (e) { - extra_networks_card_size(e.target.value); - updateOpStyles(); - }); - }); - extra_networks_card_size(opts.extra_networks_cards_size); - - function extra_networks_cards_visible_rows(value) { - styleobj.extra_networks_cards_visible_rows = - ":root{--ae-extra-networks-visible-rows:" + value + ";}"; - } - gradioApp() - .querySelectorAll("#setting_extra_networks_cards_visible_rows input") - .forEach(function (elem) { - elem.addEventListener("input", function (e) { - extra_networks_cards_visible_rows(e.target.value); - updateOpStyles(); - }); - }); - extra_networks_cards_visible_rows(opts.extra_networks_cards_visible_rows); - - function extra_networks_aside(value) { - gradioApp() - .querySelectorAll('[id$="2img_extra_networks_row"]') - .forEach((elem) => { - if (value) { - elem.classList.add("aside"); - } else { - elem.classList.remove("aside"); - } - netMenuVisibility(); - }); - } - gradioApp() - .querySelector("#setting_extra_networks_aside input") - .addEventListener("click", function (e) { - extra_networks_aside(e.target.checked); - }); - extra_networks_aside(opts.extra_networks_aside); - - // hidden - header ui tabs - let radio_hidden_html = ""; - let radio_header_html = ""; - let hiddentabs = {}; - let headertabs = {}; - const setting_ui_hidden_tabs = gradioApp().querySelector( - "#setting_ui_hidden_tabs textarea" - ); - const setting_ui_header_tabs = gradioApp().querySelector( - "#setting_ui_header_tabs textarea" - ); - const parent_header_tabs = gradioApp().querySelector("#nav_menu_header_tabs"); - setting_ui_hidden_tabs.style.display = "none"; - setting_ui_header_tabs.style.display = "none"; - - const maintabs = gradioApp().querySelectorAll( - "#tabs > div:first-child > button" - ); - const tabitems = gradioApp().querySelectorAll("#tabs > div.tabitem"); - - function tabOpsSave(setting) { - updateInput(setting); - - } - - function tabsHiddenChange() { - const keys = Object.keys(hiddentabs); - setting_ui_hidden_tabs.value = ""; - keys.forEach((key, index) => { - //console.log(`${key}: ${hiddentabs[key]} ${index}`); - if (hiddentabs[key] == true) { - styleobj[key] = - "#tabs > div:first-child > button:nth-child(" + - (index + 1) + - "){display:none;}"; - setting_ui_hidden_tabs.value += key + ","; - } else { - styleobj[key] = - "#tabs > div:first-child > button:nth-child(" + - (index + 1) + - "){display:block;}"; - } - }); - - tabOpsSave(setting_ui_hidden_tabs); - tabsHeaderChange(); - } - function tabsHeaderChange() { - const keys = Object.keys(headertabs); - setting_ui_header_tabs.value = ""; - keys.forEach((key, index) => { - //console.log(`${key}: ${hiddentabs[key]} ${index}`); - let nkey = key + "_hr"; - if (headertabs[key] == true && hiddentabs[key] == false) { - styleobj[nkey] = - "#nav_menu_header_tabs > button:nth-child(" + - (index + 1) + - "){display:block;}"; - setting_ui_header_tabs.value += key + ","; - } else { - styleobj[nkey] = - "#nav_menu_header_tabs > button:nth-child(" + - (index + 1) + - "){display:none;}"; - } - }); - - tabOpsSave(setting_ui_header_tabs); - } - - function navigate2TabItem(idx) { - gradioApp() - .querySelectorAll("#tabs > div.tabitem") - .forEach(function (tabitem, index) { - if (idx == index) { - tabitem.style.display = "block"; - } else { - tabitem.style.display = "none"; - } - }); - } - - function navTabClicked(e) { - const idx = parseInt(e.currentTarget.getAttribute("tab-id")); - navigate2TabItem(idx); - } - - maintabs.forEach(function (elem, index) { - let tabvalue = elem.innerText.replaceAll(" ", ""); - hiddentabs[tabvalue] = false; - headertabs[tabvalue] = false; - let checked_hidden = ""; - let checked_header = ""; - if (setting_ui_hidden_tabs.value.indexOf(tabvalue) != -1) { - hiddentabs[tabvalue] = true; - checked_hidden = "checked"; - } - if (setting_ui_header_tabs.value.indexOf(tabvalue) != -1) { - headertabs[tabvalue] = true; - checked_header = "checked"; - } - radio_hidden_html += - '"; - - radio_header_html += - '"; - - tabitems[index].setAttribute("tab-item", index); - elem.setAttribute("tab-id", index); - - let clonetab = elem.cloneNode(true); - clonetab.id = tabvalue + "_clone"; - parent_header_tabs.append(clonetab); - clonetab.addEventListener("click", navTabClicked); - }); - - let div = document.createElement("div"); - div.id = "hidden_radio_tabs_container"; - div.classList.add("flex", "flex-wrap", "gap-2", "wrap", "svelte-1qxcj04"); - div.innerHTML = radio_hidden_html; - setting_ui_hidden_tabs.parentElement.appendChild(div); - - div = document.createElement("div"); - div.id = "header_radio_tabs_container"; - div.classList.add("flex", "flex-wrap", "gap-2", "wrap", "svelte-1qxcj04"); - div.innerHTML = radio_header_html; - setting_ui_header_tabs.parentElement.appendChild(div); - - // hidden tabs - gradioApp() - .querySelector("#hidden_radio_tabs_container") - .addEventListener("click", function (e) { - if (e.target && e.target.matches("input[type='checkbox']")) { - let tabvalue = e.target.value.replaceAll(" ", ""); - hiddentabs[tabvalue] = e.target.checked; - tabsHiddenChange(); - updateOpStyles(); - } - }); - // header tabs - gradioApp() - .querySelector("#header_radio_tabs_container") - .addEventListener("click", function (e) { - if (e.target && e.target.matches("input[type='checkbox']")) { - let tabvalue = e.target.value.replaceAll(" ", ""); - headertabs[tabvalue] = e.target.checked; - tabsHeaderChange(); - updateOpStyles(); - } - }); - - tabsHiddenChange(); - - gradioApp() - .querySelectorAll('[id^="image_buttons_"] button, #png_2img_results button') - .forEach(function (elem) { - //console.log(opts.send_seed); - if (elem.id == "txt2img_tab") { - elem.setAttribute("tab-id", 0); - elem.addEventListener("click", navTabClicked); - } else if (elem.id == "img2img_tab" || elem.id == "inpaint_tab") { - elem.setAttribute("tab-id", 1); - elem.addEventListener("click", navTabClicked); - } - if (elem.id == "extras_tab") { - elem.setAttribute("tab-id", 2); - elem.addEventListener("click", navTabClicked); - } - }); - - gradioApp() - .querySelectorAll('[id$="2img_extra_tabs"] .search') - .forEach(function (elem) { - elem.addEventListener("keyup", function (e) { - if (e.defaultPrevented) { - return; // Do nothing if event already handled - } - switch (e.code) { - case "Escape": - if (e.target.value == "") { - net_menu.click(); - } else { - e.target.value = ""; - updateInput(e.target); + if (oldValue != newValue) { + opts = JSON.parse(textarea.value); } - break; - } - }); - }); - - // add - remove quicksettings - const settings_submit = gradioApp().querySelector("#settings_submit"); - const quick_parent = gradioApp().querySelector( - "#quicksettings_overflow_container" - ); - const setting_quicksettings = gradioApp().querySelector( - "#setting_quicksettings textarea" - ); - function saveQuickSettings() { - updateInput(setting_quicksettings); - const cEvent = new Event("click"); //submit - Object.defineProperty(cEvent, "target", { value: settings_submit }); - settings_submit.dispatchEvent(cEvent); - console.log(setting_quicksettings.value); - } - - /* - function addModelCheckpoint(){ - if(setting_quicksettings.value.indexOf("sd_model_checkpoint") === -1){ - setting_quicksettings.value += ",sd_model_checkpoint"; - } - saveQuickSettings(); - } - */ - - function add2quickSettings(id, section, checked) { - let field_settings = setting_quicksettings.value.replace(" ", ""); - if (checked) { - field_settings += "," + id; - let setting_row = gradioApp().querySelector("#row_setting_" + id); - quick_parent.append(setting_row); - setting_row.classList.add("warning"); - } else { - field_settings = field_settings.replaceAll(id, ","); - const setting_parent = gradioApp().querySelector( - "#" + section + "_settings_2img_settings" - ); - let quick_row = gradioApp().querySelector("#row_setting_" + id); - setting_parent.append(quick_row); - quick_row.classList.remove("warning"); - } - field_settings = field_settings.replace(/,{2,}/g, ","); - setting_quicksettings.value = field_settings; - //addModelCheckpoint(); - saveQuickSettings(); - //console.log(section + " - " + id + " - " + checked); - } - gradioApp() - .querySelectorAll('[id*="add2quick_"]') - .forEach(function (elem) { - let trg = elem.id.split("_add2quick_setting_"); - let sid = trg[0]; - let tid = trg[1]; - let elem_input = gradioApp().querySelector("#" + elem.id + " input"); - if (elem_input) { - elem_input.addEventListener("click", function (e) { - add2quickSettings(tid, sid, e.target.checked); - }); - } - }); - //addModelCheckpoint(); - - // input release component dispatcher - let cached_clone_range; - let cached_clone_num; - let active_clone_input = []; - let focus_input; - - function ui_input_release_component(elem) { - //console.log("ok"); - if (active_clone_input.length > 0) return; - - //img2img_width - let parent = elem.parentElement; - let comp_parent = parent.parentElement.parentElement; - - if ( - comp_parent.id == "img2img_width" || - comp_parent.id == "img2img_height" || - comp_parent.id == "img2img_scale" || - comp_parent.id.indexOf("--ae-") != -1 || - comp_parent.id.indexOf("theme") != -1 || - comp_parent.className.indexOf("posex") != -1 - ) - return; - - let clone_num = elem.cloneNode(); - active_clone_input.push(clone_num); - - let label = parent.querySelector("label"); - - clone_num.id = "num_clone"; - clone_num.value = elem.value; - parent.append(clone_num); - elem.classList.add("hidden"); - - clone_num.addEventListener("change", function (e) { - elem.value = clone_num.value; - updateInput(elem); - }); - clone_num.addEventListener("focus", function (e) { - focus_input = clone_num; - }); - - cached_clone_num = clone_num; - cached_clone_range = false; - - if (label) { - let comp_range = comp_parent.querySelector("input[type='range']"); - let clone_range = comp_range.cloneNode(); - active_clone_input.push(clone_range); - - clone_range.id = comp_range.id + "_clone"; - clone_range.value = comp_range.value; - comp_range.parentElement.append(clone_range); - comp_range.classList.add("hidden"); - - clone_range.addEventListener("input", function (e) { - clone_num.value = e.target.value; - }); - clone_range.addEventListener("change", function (e) { - elem.value = clone_range.value; - updateInput(elem); - }); - clone_num.addEventListener("input", function (e) { - clone_range.value = e.target.value; - }); - - cached_clone_range = clone_range; - } - } - /* function ui_input_focus_handler(e) { - if (e.target != focus_input) { - focus_input = false; - ui_input_release_handler(e); - } - } */ - - function ui_input_release_handler(e) { - const len = active_clone_input.length; - if (focus_input) { - return; - } - if (len > 0) { - if (e.target.id.indexOf("_clone") == -1) { - for (var i = len - 1; i >= 0; i--) { - let relem = active_clone_input[i]; - relem.previousElementSibling.classList.remove("hidden"); - relem.remove(); - active_clone_input.pop(); + executeCallbacks(optionsChangedCallbacks); + }, + get: function() { + var valueProp = Object.getOwnPropertyDescriptor(HTMLTextAreaElement.prototype, 'value'); + return valueProp.get.call(textarea); } - } - } - - let elem_type = e.target.tagName; - if (elem_type == "INPUT") { - let elem = e.target; - if (elem.type == "number") { - ui_input_release_component(elem); - } else if (elem.type == "range") { - elem = e.target.parentElement.querySelector("input[type='number']"); - if (elem) { - ui_input_release_component(elem); - } - } - } - } - let timeoutId; - - function ui_input_touchmove_handler(e) { - if (cached_clone_range && cached_clone_num) { - if (e.touches) { - const rect = cached_clone_range.getBoundingClientRect(); - const xoffset_min = rect.left + window.scrollX; - //const xoffset_max = (rect.right + window.scrollX); - //const yoffset_min = (rect.top + window.scrollY); - //const yoffset_max = (rect.bottom + window.scrollY); - //if( e.touches[0].pageY > yoffset_min && e.touches[0].pageY < yoffset_max && e.touches[0].pageX > xoffset_min && e.touches[0].pageX < xoffset_max){ - e.preventDefault(); - const percent = - parseInt(((e.touches[0].pageX - xoffset_min) / rect.width) * 10000) / - 10000; - cached_clone_range.value = - percent * (cached_clone_range.max - cached_clone_range.min) + - parseFloat(cached_clone_range.min); - cached_clone_num.value = cached_clone_range.value; - //} - } - } - } - function ui_input_touchend_handler(e) { - if (cached_clone_range && cached_clone_num) { - const elem = cached_clone_range.previousElementSibling; - elem.value = cached_clone_range.value; - updateInput(elem); - } - } - - function slider_contextmenu(e) { - e.preventDefault(); - } - function slider_touchend(e) { - if (timeoutId) clearTimeout(timeoutId); - } - function slider_touchmove(e) { - if (timeoutId) clearTimeout(timeoutId); - } - function slider_touchstart(e) { - const gcontainer = e.target; - //gcontainer.removeEventListener('contextmenu', slider_contextmenu); - gcontainer.removeEventListener("touchend", slider_touchend); - gcontainer.removeEventListener("touchmove", slider_touchmove); - gcontainer.removeEventListener("touchend", ui_input_touchend_handler); - gcontainer.removeEventListener("touchmove", ui_input_touchmove_handler); - - timeoutId = setTimeout(function () { - timeoutId = null; - focus_input = false; - e.stopPropagation(); - ui_input_release_handler(e); - ui_input_touchmove_handler(e); - gcontainer.addEventListener("touchmove", ui_input_touchmove_handler, { - passive: false, - }); - gcontainer.addEventListener("touchend", ui_input_touchend_handler); - }, 500); - - //gcontainer.addEventListener('contextmenu', slider_contextmenu); - gcontainer.addEventListener("touchend", slider_touchend); - gcontainer.addEventListener("touchmove", slider_touchmove, { - passive: false, - }); - } - - function ui_dispatch_input_release(value) { - const gcontainer = gradioApp().querySelector(".gradio-container"); - if (value) { - gcontainer.addEventListener("mouseover", ui_input_release_handler); - gcontainer.addEventListener("touchstart", slider_touchstart, { - passive: false, - }); - } else { - gcontainer.removeEventListener("mouseover", ui_input_release_handler); - gcontainer.removeEventListener("touchstart", slider_touchstart); - //gcontainer.removeEventListener('contextmenu', slider_contextmenu); - gcontainer.removeEventListener("touchend", slider_touchend); - gcontainer.removeEventListener("touchmove", slider_touchmove); - gcontainer.removeEventListener("touchend", ui_input_touchend_handler); - gcontainer.removeEventListener("touchmove", ui_input_touchmove_handler); - } - } - gradioApp() - .querySelector("#setting_ui_dispatch_input_release input") - .addEventListener("click", function (e) { - ui_dispatch_input_release(e.target.checked); }); - ui_dispatch_input_release(opts.ui_dispatch_input_release); - - // step ticks for performant input range - function ui_show_range_ticks(value, interactive) { - if (value) { - const range_selectors = "input[type='range']"; - //const range_selectors = "[id$='_clone']:is(input[type='range'])"; - gradioApp() - .querySelectorAll(range_selectors) - .forEach(function (elem) { - let spacing = (elem.step / (elem.max - elem.min)) * 100.0; - let tsp = "max(3px, calc(" + spacing + "% - 1px))"; - let fsp = "max(4px, calc(" + spacing + "% + 0px))"; - var style = elem.style; - style.setProperty( - "--ae-slider-bg-overlay", - "repeating-linear-gradient( 90deg, transparent, transparent " + - tsp + - ", var(--ae-input-border-color) " + - tsp + - ", var(--ae-input-border-color) " + - fsp + - " )" - ); - }); - } else if (interactive) { - gradioApp() - .querySelectorAll("input[type='range']") - .forEach(function (elem) { - var style = elem.style; - style.setProperty("--ae-slider-bg-overlay", "transparent"); - }); - } - } - gradioApp() - .querySelector("#setting_ui_show_range_ticks input") - .addEventListener("click", function (e) { - ui_show_range_ticks(e.target.checked, true); - }); - ui_show_range_ticks(opts.ui_show_range_ticks); - - const gradio_main = gradioApp().querySelector(".gradio-container > div.main"); - function ui_no_slider_layout(value) { - if (value) { - gradio_main.classList.add("no-slider-layout"); - } else { - gradio_main.classList.remove("no-slider-layout"); - } - } - gradioApp() - .querySelector("#setting_ui_no_slider_layout input") - .addEventListener("click", function (e) { - ui_no_slider_layout(e.target.checked, true); - }); - ui_no_slider_layout(opts.ui_no_slider_layout); - - // draggable reordable quicksettings - const container = gradioApp().querySelector( - "#quicksettings_overflow_container" - ); - let draggables; - let lastElemAfter; - let islastChild; - let timeout; - - function preventBehavior(e) { - e.stopPropagation(); - e.preventDefault(); - return false; - } - let sdCheckpointModels = []; - function getSdCheckpointModels() { - gradioApp() - .querySelectorAll("#txt2img_checkpoints_cards .card") - .forEach(function (elem, i) { - sdCheckpointModels[i] = elem.getAttribute("onclick").split('"')[1]; - }); - } - getSdCheckpointModels(); - - function remove_overrides() { - let checked_overrides = []; - gradioApp() - .querySelectorAll("#setting_ignore_overrides input") - .forEach(function (elem, i) { - if (elem.checked) { - checked_overrides[i] = elem.nextElementSibling.innerHTML; - } - }); - //console.log(checked_overrides); - gradioApp() - .querySelectorAll("[id$='2img_override_settings'] .token") - .forEach(function (token) { - let token_arr = token.querySelector("span").innerHTML.split(":"); - let token_name = token_arr[0]; - let token_value = token_arr[1]; - token_value = token_value.replaceAll(" ", ""); - - if (token_name.indexOf("Model hash") != -1) { - const info_label = gradioApp().querySelector( - "[id$='2img_override_settings'] label span" - ); - info_label.innerHTML = "Override settings MDL: unknown"; - for (let m = 0; m < sdCheckpointModels.length; m++) { - let m_str = sdCheckpointModels[m]; - if (m_str.indexOf(token_value) != -1) { - info_label.innerHTML = - "Override settings MDL: " + m_str.split("[")[0] + ""; - break; - } - } - } - if (checked_overrides.indexOf(token_name) != -1) { - token.querySelector(".token-remove").click(); - gradioApp() - .querySelector( - "#" + selectedTabItemId + " [id$='2img_override_settings']" - ) - .parentElement.classList.add("show"); - } else { - // maybe we add them again, for now we can select and add the removed tokens manually from the drop down - } - }); - } - gradioApp() - .querySelector("#setting_ignore_overrides") - .addEventListener("click", function (e) { - setTimeout(function () { - remove_overrides(); - }, 100); - }); - - function update_input_fields(tab) { - /* - let input_selectors = "#tab_"+ tab + " [id^='num_clone']:is(input[type='number'])"; - gradioApp().querySelectorAll(input_selectors).forEach(function (elem){ - let elem_source = elem.previousElementSibling; - elem.value = elem_source.value; - updateInput(elem); - }) - */ - remove_overrides(); - autoGrowPromptTextarea(); - } - - gradioApp() - .querySelectorAll( - "#tab_pnginfo #png_2img_results button, [id$='2img_actions_column'] #paste" - ) - .forEach(function (elem) { - elem.addEventListener("click", function (e) { - let button_id; - if (e.target.id == "paste") { - button_id = e.target.nextElementSibling.id.split("_")[0]; - } else { - button_id = e.target.id.split("_")[0]; - } - setTimeout(function () { - update_input_fields(button_id); - }, 500); - }); - }); - - const pnginfo = gradioApp().querySelector("#tab_pnginfo"); - function forwardFromPngInfo() { - if (selectedTabItemId == "tab_txt2img") { - pnginfo.querySelector("#txt2img_tab").click(); - //close generation info - gradioApp() - .querySelector( - "#txt2img_results > div:last-child > div.gradio-accordion > div.hide" - ) - ?.click(); - - const img_src = pnginfo.querySelector("img"); - const gallery_parent = gradioApp().querySelector( - "#txt2img_gallery_container" - ); - const live_preview = gallery_parent.querySelector(".livePreview"); - if (live_preview) { - live_preview.innerHTML = - ''; - } else { - const div = document.createElement("div"); - div.classList.add("livePreview", "dropPreview"); - div.innerHTML = - ''; - gallery_parent.prepend(div); - } - } else if (selectedTabItemId == "tab_img2img") { - pnginfo.querySelector("#img2img_tab").click(); - //close generation info - gradioApp() - .querySelector( - "#img2img_results > div:last-child > div.gradio-accordion > div.hide" - ) - ?.click(); - } - } - - function fetchPngInfoData(files) { - /* const oldFetch = window.fetch; - - window.fetch = async (input, options) => { - const response = await oldFetch(input, options); - if( 'run/predict/' === input ) { - if(response.ok){ - window.fetch = oldFetch; - } - } - return response; - }; */ - - const fileInput = gradioApp().querySelector( - '#pnginfo_image input[type="file"]' - ); - if (fileInput.files != files) { - fileInput.files = files; - fileInput.dispatchEvent(new Event("change")); - } - - setTimeout(function () { - forwardFromPngInfo(); - }, 500); - } - - function drop2View(e) { - e.stopPropagation(); - e.preventDefault(); - const files = e.dataTransfer.files; - if (!isValidImageList(files)) { - return; - } - const data_image = gradioApp().querySelector( - '#pnginfo_image [data-testid="image"]' - ); - data_image.querySelector('[aria-label="Clear"]')?.click(); - setTimeout(function () { - fetchPngInfoData(files); - }, 1000); - } - - gradioApp() - .querySelectorAll('[id$="2img_results"]') - .forEach((elem) => { - elem.addEventListener("drop", drop2View); - }); - - // function that gets the element next of cursor/touch - function getElementAfter(container, y) { - return draggables.reduce( - (closest, child) => { - const box = child.getBoundingClientRect(); - const offset = y - box.top - box.height / 2; - if (offset < 0 && offset > closest.offset) { - return { offset: offset, element: child }; - } else { - return closest; - } - }, - { offset: Number.NEGATIVE_INFINITY } - ).element; - } - - function dragOrderChange(elementAfter, isComplete, delem) { - if (lastElemAfter !== elementAfter || islastChild) { - if (lastElemAfter != null) { - lastElemAfter.classList.remove("marker-top", "marker-bottom"); - } - - if (elementAfter == null) { - islastChild = true; - lastElemAfter.classList.add("marker-bottom"); - } else { - islastChild = false; - elementAfter.classList.add("marker-top"); - lastElemAfter = elementAfter; - } - } + json_elem.parentElement.style.display = "none"; - if (isComplete) { - if (elementAfter == null) { - container.append(delem); - } else { - container.insertBefore(delem, elementAfter); - } + setupTokenCounters(); - let order_settings = ""; + var show_all_pages = gradioApp().getElementById('settings_show_all_pages'); + var settings_tabs = gradioApp().querySelector('#settings div'); + if (show_all_pages && settings_tabs) { + settings_tabs.appendChild(show_all_pages); + show_all_pages.onclick = function() { + gradioApp().querySelectorAll('#settings > div').forEach(function(elem) { + if (elem.id == "settings_tab_licenses") { + return; + } - gradioApp() - .querySelectorAll("#quicksettings_overflow_container > div") - .forEach(function (el) { - el.classList.remove("marker-top", "marker-bottom", "dragging"); - order_settings += el.id.split("row_setting_")[1] + ","; - }); - //console.log(order_settings); - const setting_quicksettings = gradioApp().querySelector( - "#setting_quicksettings textarea" - ); - setting_quicksettings.value = order_settings; - updateInput(setting_quicksettings); - - const cEvent = new Event("click"); //submit - Object.defineProperty(cEvent, "target", { value: settings_submit }); - settings_submit.dispatchEvent(cEvent); - - container.classList.remove("no-scroll"); - } - } - - function touchmove(e) { - let y = e.touches[0].clientY; - let elementAfter = getElementAfter(container, y); - dragOrderChange(elementAfter); - } - function touchstart(e) { - e.currentTarget.draggable = "false"; - let target = e.currentTarget; - // touch should be hold for 1 second - timeout = setTimeout(function () { - target.classList.add("dragging"); - container.classList.add("no-scroll"); - target.addEventListener("touchmove", touchmove); - container.addEventListener("touchmove", preventBehavior, { - passive: false, - }); - }, 1000); - - target.addEventListener("touchend", touchend); - target.addEventListener("touchcancel", touchcancel); - } - function touchend(e) { - e.currentTarget.draggable = "true"; - clearTimeout(timeout); - e.currentTarget.removeEventListener("touchmove", touchmove); - container.removeEventListener("touchmove", preventBehavior); - let y = e.changedTouches[0].clientY; - let elementAfter = getElementAfter(container, y); - dragOrderChange(elementAfter, true, e.currentTarget); - } - function touchcancel(e) { - e.currentTarget.draggable = "true"; - clearTimeout(timeout); - e.currentTarget.classList.remove("dragging"); - e.currentTarget.removeEventListener("touchmove", touchmove); - container.removeEventListener("touchmove", preventBehavior); - } - - function dragstart(e) { - e.currentTarget.draggable = "false"; - e.currentTarget.classList.add("dragging"); - } - function dragend(e) { - e.stopPropagation(); - e.preventDefault(); - e.currentTarget.draggable = "true"; - let y = e.clientY; - let elementAfter = getElementAfter(container, y); - dragOrderChange(elementAfter, true, e.currentTarget); - } - function dragOver(e) { - e.preventDefault(); - let y = e.clientY; - let elementAfter = getElementAfter(container, y); - dragOrderChange(elementAfter); - } - - function actionQuickSettingsDraggable(checked) { - if (checked) { - draggables = Array.from( - gradioApp().querySelectorAll( - "#quicksettings_overflow_container > div:not(.dragging)" - ) - ); - gradioApp().addEventListener("drop", preventBehavior); - } else { - gradioApp().removeEventListener("drop", preventBehavior); + elem.style.display = "block"; + }); + }; } - - gradioApp() - .querySelectorAll("#quicksettings_overflow_container > div") - .forEach(function (elem) { - elem.draggable = checked; - if (checked) { - elem.addEventListener("touchstart", touchstart); - elem.addEventListener("dragstart", dragstart); - elem.addEventListener("dragend", dragend); - elem.addEventListener("dragover", dragOver); - } else { - elem.removeEventListener("touchstart", touchstart, false); - elem.removeEventListener("touchend", touchend, false); - elem.removeEventListener("touchcancel", touchcancel, false); - elem.removeEventListener("touchmove", touchmove, false); - elem.removeEventListener("dragstart", dragstart, false); - elem.removeEventListener("dragend", dragend, false); - elem.removeEventListener("dragover", dragOver, false); - } - }); - } - - gradioApp() - .querySelector("#quicksettings_draggable") - .addEventListener("click", function (e) { - if (e.target && e.target.matches("input[type='checkbox']")) { - actionQuickSettingsDraggable(e.target.checked); - } - }); - - updateOpStyles(); - - /* anapnoe ui end */ }); onOptionsChanged(function() { - var elem = gradioApp().getElementById('sd_checkpoint_hash'); - var sd_checkpoint_hash = opts.sd_checkpoint_hash || ""; - var shorthash = sd_checkpoint_hash.substring(0, 10); - - if (elem && elem.textContent != shorthash) { - elem.textContent = shorthash; - elem.title = sd_checkpoint_hash; - elem.href = "https://google.com/search?q=" + sd_checkpoint_hash; - } + var elem = gradioApp().getElementById('sd_checkpoint_hash'); + var sd_checkpoint_hash = opts.sd_checkpoint_hash || ""; + var shorthash = sd_checkpoint_hash.substring(0, 10); + + if (elem && elem.textContent != shorthash) { + elem.textContent = shorthash; + elem.title = sd_checkpoint_hash; + elem.href = "https://google.com/search?q=" + sd_checkpoint_hash; + } }); let txt2img_textarea, img2img_textarea = undefined; -let wait_time = 800; -let token_timeouts = {}; - -function update_txt2img_tokens(...args) { - update_token_counter("txt2img_token_button"); - if (args.length == 2) { - return args[0]; - } - return args; -} - -function update_img2img_tokens(...args) { - update_token_counter( - "img2img_token_button" - ); - if (args.length == 2) { - return args[0]; - } - return args; -} -function update_token_counter(button_id) { - if (token_timeouts[button_id]) { - clearTimeout(token_timeouts[button_id]); - } - token_timeouts[button_id] = setTimeout(() => gradioApp().getElementById(button_id)?.click(), wait_time); -} +function restart_reload() { + document.body.innerHTML = '

Reloading...

'; + var requestPing = function() { + requestGet("./internal/ping", {}, function(data) { + location.reload(); + }, function() { + setTimeout(requestPing, 500); + }); + }; + setTimeout(requestPing, 2000); -function restart_reload() { - let bg_color = window - .getComputedStyle(gradioApp().querySelector("#header-top")) - .getPropertyValue("--ae-main-bg-color"); - let primary_color = window - .getComputedStyle(gradioApp().querySelector(".icon-info")) - .getPropertyValue("--ae-primary-color"); - let panel_color = window - .getComputedStyle(gradioApp().querySelector(".gradio-box")) - .getPropertyValue("--ae-panel-bg-color"); - - localStorage.setItem("bg_color", bg_color); - localStorage.setItem("primary_color", primary_color); - localStorage.setItem("panel_color", panel_color); - - if (localStorage.hasOwnProperty("bg_color")) { - bg_color = localStorage.getItem("bg_color"); - primary_color = localStorage.getItem("primary_color"); - panel_color = localStorage.getItem("panel_color"); - } - - document.body.style.backgroundColor = bg_color; - - let style = document.createElement("style"); - style.type = "text/css"; - style.innerHTML = - ".loader{position:absolute;top:50vh;left:50vw;height:60px;width:160px;margin:0;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%)} .circles{position:absolute;left:-5px;top:0;height:60px;width:180px} .circles span{position:absolute;top:25px;height:12px;width:12px;border-radius:12px;background-color:" + - panel_color + - "} .circles span.one{right:80px} .circles span.two{right:40px} .circles span.three{right:0px} .circles{-webkit-animation:animcircles 0.5s infinite linear;animation:animcircles 0.5s infinite linear} @-webkit-keyframes animcircles{0%{-webkit-transform:translate(0px,0px);transform:translate(0px,0px)}100%{-webkit-transform:translate(-40px,0px);transform:translate(-40px,0px)}} @keyframes animcircles{0%{-webkit-transform:translate(0px,0px);transform:translate(0px,0px)}100%{-webkit-transform:translate(-40px,0px);transform:translate(-40px,0px)}} .pacman{position:absolute;left:0;top:0;height:60px;width:60px} .pacman .eye{position:absolute;top:10px;left:30px;height:7px;width:7px;border-radius:7px;background-color:" + - bg_color + - '} .pacman span{position:absolute;top:0;left:0;height:60px;width:60px} .pacman span::before{content:"";position:absolute;left:0;height:30px;width:60px;background-color:' + - primary_color + - "} .pacman .top::before{top:0;border-radius:60px 60px 0px 0px} .pacman .bottom::before{bottom:0;border-radius:0px 0px 60px 60px} .pacman .left::before{bottom:0;height:60px;width:30px;border-radius:60px 0px 0px 60px} .pacman .top{-webkit-animation:animtop 0.5s infinite;animation:animtop 0.5s infinite} @-webkit-keyframes animtop{0%,100%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}50%{-webkit-transform:rotate(-45deg);transform:rotate(-45deg)}} @keyframes animtop{0%,100%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}50%{-webkit-transform:rotate(-45deg);transform:rotate(-45deg)}} .pacman .bottom{-webkit-animation:animbottom 0.5s infinite;animation:animbottom 0.5s infinite} @-webkit-keyframes animbottom{0%,100%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}50%{-webkit-transform:rotate(45deg);transform:rotate(45deg)}} @keyframes animbottom{0%,100%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}50%{-webkit-transform:rotate(45deg);transform:rotate(45deg)}}"; - - document.getElementsByTagName("head")[0].appendChild(style); - document.body.innerHTML = - '
'; - - var requestPing = function () { - requestGet( - "./internal/ping", - {}, - function (data) { - location.reload(); - }, - function () { - setTimeout(requestPing, 500); - } - ); - }; - - setTimeout(requestPing, 2000); - - return []; + return []; } // Simulate an `input` DOM event for Gradio Textbox component. Needed after you edit its contents in javascript, otherwise your edits // will only visible on web page and not sent to python. function updateInput(target) { - const e = new Event("input", { bubbles: true }); - Object.defineProperty(e, "target", { value: target }); - target.dispatchEvent(e); - const eb = new Event("blur"); - Object.defineProperty(eb, "target", { value: target }); - target.dispatchEvent(eb); + let e = new Event("input", {bubbles: true}); + Object.defineProperty(e, "target", {value: target}); + target.dispatchEvent(e); } -document.addEventListener("readystatechange", function (e) { - document.body.style.display = "none"; - if (localStorage.hasOwnProperty("bg_color")) { - document.getElementsByTagName("html")[0].style.backgroundColor = - localStorage.getItem("bg_color"); - document.body.style.backgroundColor = localStorage.getItem("bg_color"); - } -}); - -window.onload = function () { - document.getElementsByTagName("html")[0].style.backgroundColor = - localStorage.getItem("bg_color"); - document.body.style.backgroundColor = localStorage.getItem("bg_color"); - document.body.style.display = "none"; - document.body.classList.add("dark"); - setTimeout(function () { - document.body.style.display = "block"; - }, 1000); -}; var desiredCheckpointName = null; function selectCheckpoint(name) { @@ -2038,4 +365,4 @@ function switchWidthHeight(tabname) { updateInput(width); updateInput(height); return []; -} \ No newline at end of file +} diff --git a/javascript/ui_settings_hints.js b/javascript/ui_settings_hints.js index 0f3c6acd850..d088f9494f8 100644 --- a/javascript/ui_settings_hints.js +++ b/javascript/ui_settings_hints.js @@ -1,3 +1,5 @@ +// various hints and extra info for the settings tab + var settingsHintsSetup = false; onOptionsChanged(function() { diff --git a/launch.py b/launch.py index e4c2ce99e72..f83820d2534 100644 --- a/launch.py +++ b/launch.py @@ -25,6 +25,13 @@ def main(): + if args.dump_sysinfo: + filename = launch_utils.dump_sysinfo() + + print(f"Sysinfo saved as {filename}. Exiting...") + + exit(0) + launch_utils.startup_timer.record("initial startup") with launch_utils.startup_timer.subcategory("prepare environment"): diff --git a/modules/api/api.py b/modules/api/api.py index 606db179d4c..e6edffe7144 100644 --- a/modules/api/api.py +++ b/modules/api/api.py @@ -4,6 +4,8 @@ import time import datetime import uvicorn +import ipaddress +import requests import gradio as gr from threading import Lock from io import BytesIO @@ -15,7 +17,7 @@ from secrets import compare_digest import modules.shared as shared -from modules import sd_samplers, deepbooru, sd_hijack, images, scripts, ui, postprocessing, errors, restart +from modules import sd_samplers, deepbooru, sd_hijack, images, scripts, ui, postprocessing, errors, restart, shared_items from modules.api import models from modules.shared import opts from modules.processing import StableDiffusionProcessingTxt2Img, StableDiffusionProcessingImg2Img, process_images @@ -23,8 +25,7 @@ from modules.textual_inversion.preprocess import preprocess from modules.hypernetworks.hypernetwork import create_hypernetwork, train_hypernetwork from PIL import PngImagePlugin,Image -from modules.sd_models import checkpoints_list, unload_model_weights, reload_model_weights, checkpoint_aliases -from modules.sd_vae import vae_dict +from modules.sd_models import unload_model_weights, reload_model_weights, checkpoint_aliases from modules.sd_models_config import find_checkpoint_config_near_filename from modules.realesrgan_model import get_realesrgan_models from modules import devices @@ -56,7 +57,41 @@ def setUpscalers(req: dict): return reqDict +def verify_url(url): + """Returns True if the url refers to a global resource.""" + + import socket + from urllib.parse import urlparse + try: + parsed_url = urlparse(url) + domain_name = parsed_url.netloc + host = socket.gethostbyname_ex(domain_name) + for ip in host[2]: + ip_addr = ipaddress.ip_address(ip) + if not ip_addr.is_global: + return False + except Exception: + return False + + return True + + def decode_base64_to_image(encoding): + if encoding.startswith("http://") or encoding.startswith("https://"): + if not opts.api_enable_requests: + raise HTTPException(status_code=500, detail="Requests not allowed") + + if opts.api_forbid_local_requests and not verify_url(encoding): + raise HTTPException(status_code=500, detail="Request to local resource not allowed") + + headers = {'user-agent': opts.api_useragent} if opts.api_useragent else {} + response = requests.get(encoding, timeout=30, headers=headers) + try: + image = Image.open(BytesIO(response.content)) + return image + except Exception as e: + raise HTTPException(status_code=500, detail="Invalid image url") from e + if encoding.startswith("data:image/"): encoding = encoding.split(";")[1].split(",")[1] try: @@ -197,6 +232,7 @@ def __init__(self, app: FastAPI, queue_lock: Lock): self.add_api_route("/sdapi/v1/prompt-styles", self.get_prompt_styles, methods=["GET"], response_model=List[models.PromptStyleItem]) self.add_api_route("/sdapi/v1/embeddings", self.get_embeddings, methods=["GET"], response_model=models.EmbeddingsResponse) self.add_api_route("/sdapi/v1/refresh-checkpoints", self.refresh_checkpoints, methods=["POST"]) + self.add_api_route("/sdapi/v1/refresh-vae", self.refresh_vae, methods=["POST"]) self.add_api_route("/sdapi/v1/create/embedding", self.create_embedding, methods=["POST"], response_model=models.CreateResponse) self.add_api_route("/sdapi/v1/create/hypernetwork", self.create_hypernetwork, methods=["POST"], response_model=models.CreateResponse) self.add_api_route("/sdapi/v1/preprocess", self.preprocess, methods=["POST"], response_model=models.PreprocessResponse) @@ -329,6 +365,7 @@ def text2imgapi(self, txt2imgreq: models.StableDiffusionTxt2ImgProcessingAPI): with self.queue_lock: with closing(StableDiffusionProcessingTxt2Img(sd_model=shared.sd_model, **args)) as p: + p.is_api = True p.scripts = script_runner p.outpath_grids = opts.outdir_txt2img_grids p.outpath_samples = opts.outdir_txt2img_samples @@ -343,6 +380,7 @@ def text2imgapi(self, txt2imgreq: models.StableDiffusionTxt2ImgProcessingAPI): processed = process_images(p) finally: shared.state.end() + shared.total_tqdm.clear() b64images = list(map(encode_pil_to_base64, processed.images)) if send_images else [] @@ -388,6 +426,7 @@ def img2imgapi(self, img2imgreq: models.StableDiffusionImg2ImgProcessingAPI): with self.queue_lock: with closing(StableDiffusionProcessingImg2Img(sd_model=shared.sd_model, **args)) as p: p.init_images = [decode_base64_to_image(x) for x in init_images] + p.is_api = True p.scripts = script_runner p.outpath_grids = opts.outdir_img2img_grids p.outpath_samples = opts.outdir_img2img_samples @@ -402,6 +441,7 @@ def img2imgapi(self, img2imgreq: models.StableDiffusionImg2ImgProcessingAPI): processed = process_images(p) finally: shared.state.end() + shared.total_tqdm.clear() b64images = list(map(encode_pil_to_base64, processed.images)) if send_images else [] @@ -530,7 +570,7 @@ def set_config(self, req: Dict[str, Any]): raise RuntimeError(f"model {checkpoint_name!r} not found") for k, v in req.items(): - shared.opts.set(k, v) + shared.opts.set(k, v, is_api=True) shared.opts.save(shared.config_filename) return @@ -562,10 +602,12 @@ def get_latent_upscale_modes(self): ] def get_sd_models(self): - return [{"title": x.title, "model_name": x.model_name, "hash": x.shorthash, "sha256": x.sha256, "filename": x.filename, "config": find_checkpoint_config_near_filename(x)} for x in checkpoints_list.values()] + import modules.sd_models as sd_models + return [{"title": x.title, "model_name": x.model_name, "hash": x.shorthash, "sha256": x.sha256, "filename": x.filename, "config": find_checkpoint_config_near_filename(x)} for x in sd_models.checkpoints_list.values()] def get_sd_vaes(self): - return [{"model_name": x, "filename": vae_dict[x]} for x in vae_dict.keys()] + import modules.sd_vae as sd_vae + return [{"model_name": x, "filename": sd_vae.vae_dict[x]} for x in sd_vae.vae_dict.keys()] def get_hypernetworks(self): return [{"name": name, "path": shared.hypernetworks[name]} for name in shared.hypernetworks] @@ -608,6 +650,10 @@ def refresh_checkpoints(self): with self.queue_lock: shared.refresh_checkpoints() + def refresh_vae(self): + with self.queue_lock: + shared_items.refresh_vae_list() + def create_embedding(self, args: dict): try: shared.state.begin(job="create_embedding") diff --git a/modules/api/models.py b/modules/api/models.py index bf97b1a3771..6a574771c33 100644 --- a/modules/api/models.py +++ b/modules/api/models.py @@ -50,10 +50,12 @@ def __init__( additional_fields = None, ): def field_type_generator(k, v): - # field_type = str if not overrides.get(k) else overrides[k]["type"] - # print(k, v.annotation, v.default) field_type = v.annotation + if field_type == 'Image': + # images are sent as base64 strings via API + field_type = 'str' + return Optional[field_type] def merge_class_params(class_): @@ -63,7 +65,6 @@ def merge_class_params(class_): parameters = {**parameters, **inspect.signature(classes.__init__).parameters} return parameters - self._model_name = model_name self._class_data = merge_class_params(class_instance) @@ -72,7 +73,7 @@ def merge_class_params(class_): field=underscore(k), field_alias=k, field_type=field_type_generator(k, v), - field_value=v.default + field_value=None if isinstance(v.default, property) else v.default ) for (k,v) in self._class_data.items() if k not in API_NOT_ALLOWED ] @@ -208,11 +209,9 @@ class PreprocessResponse(BaseModel): fields = {} for key, metadata in opts.data_labels.items(): value = opts.data.get(key) - optType = opts.typemap.get(type(metadata.default), type(metadata.default)) + optType = opts.typemap.get(type(metadata.default), type(metadata.default)) if metadata.default else Any - if metadata.default is None: - pass - elif metadata is not None: + if metadata is not None: fields.update({key: (Optional[optType], Field(default=metadata.default, description=metadata.label))}) else: fields.update({key: (Optional[optType], Field())}) diff --git a/modules/cache.py b/modules/cache.py index 71fe6302134..ff26a2132d9 100644 --- a/modules/cache.py +++ b/modules/cache.py @@ -1,11 +1,12 @@ import json +import os import os.path import threading import time from modules.paths import data_path, script_path -cache_filename = os.path.join(data_path, "cache.json") +cache_filename = os.environ.get('SD_WEBUI_CACHE_FILE', os.path.join(data_path, "cache.json")) cache_data = None cache_lock = threading.Lock() @@ -29,9 +30,12 @@ def thread_func(): time.sleep(1) with cache_lock: - with open(cache_filename, "w", encoding="utf8") as file: + cache_filename_tmp = cache_filename + "-" + with open(cache_filename_tmp, "w", encoding="utf8") as file: json.dump(cache_data, file, indent=4) + os.replace(cache_filename_tmp, cache_filename) + dump_cache_after = None dump_cache_thread = None diff --git a/modules/call_queue.py b/modules/call_queue.py index 61aa240fb32..ddf0d57383c 100644 --- a/modules/call_queue.py +++ b/modules/call_queue.py @@ -1,11 +1,10 @@ from functools import wraps import html -import threading import time -from modules import shared, progress, errors +from modules import shared, progress, errors, devices, fifo_lock -queue_lock = threading.Lock() +queue_lock = fifo_lock.FIFOLock() def wrap_queued_call(func): @@ -75,6 +74,8 @@ def f(*args, extra_outputs_array=extra_outputs, **kwargs): error_message = f'{type(e).__name__}: {e}' res = extra_outputs_array + [f"
{html.escape(error_message)}
"] + devices.torch_gc() + shared.state.skipped = False shared.state.interrupted = False shared.state.job_count = 0 diff --git a/modules/cmd_args.py b/modules/cmd_args.py index dd5fadc4ec4..aab62286e24 100644 --- a/modules/cmd_args.py +++ b/modules/cmd_args.py @@ -16,6 +16,8 @@ parser.add_argument("--log-startup", action='store_true', help="launch.py argument: print a detailed log of what's happening at startup") parser.add_argument("--skip-prepare-environment", action='store_true', help="launch.py argument: skip all environment preparation") parser.add_argument("--skip-install", action='store_true', help="launch.py argument: skip installation of packages") +parser.add_argument("--dump-sysinfo", action='store_true', help="launch.py argument: dump limited sysinfo file (without information about extensions, options) to disk and quit") +parser.add_argument("--loglevel", type=str, help="log level; one of: CRITICAL, ERROR, WARNING, INFO, DEBUG", default=None) parser.add_argument("--do-not-download-clip", action='store_true', help="do not download CLIP model even if it's not included in the checkpoint") parser.add_argument("--data-dir", type=str, default=os.path.dirname(os.path.dirname(os.path.realpath(__file__))), help="base path where all user data is stored") parser.add_argument("--config", type=str, default=sd_default_config, help="path to config which constructs model",) @@ -34,9 +36,10 @@ parser.add_argument("--localizations-dir", type=str, default=os.path.join(script_path, 'localizations'), help="localizations directory") parser.add_argument("--allow-code", action='store_true', help="allow custom script execution from webui") parser.add_argument("--medvram", action='store_true', help="enable stable diffusion model optimizations for sacrificing a little speed for low VRM usage") +parser.add_argument("--medvram-sdxl", action='store_true', help="enable --medvram optimization just for SDXL models") parser.add_argument("--lowvram", action='store_true', help="enable stable diffusion model optimizations for sacrificing a lot of speed for very low VRM usage") parser.add_argument("--lowram", action='store_true', help="load stable diffusion checkpoint weights to VRAM instead of RAM") -parser.add_argument("--always-batch-cond-uncond", action='store_true', help="disables cond/uncond batching that is enabled to save memory with --medvram or --lowvram") +parser.add_argument("--always-batch-cond-uncond", action='store_true', help="does not do anything") parser.add_argument("--unload-gfpgan", action='store_true', help="does not do anything.") parser.add_argument("--precision", type=str, help="evaluate at this precision", choices=["full", "autocast"], default="autocast") parser.add_argument("--upcast-sampling", action='store_true', help="upcast sampling. No effect with --no-half. Usually produces similar results to --no-half with better performance while using less memory.") @@ -67,6 +70,7 @@ parser.add_argument("--disable-opt-split-attention", action='store_true', help="prefer no cross-attention layer optimization for automatic choice of optimization") parser.add_argument("--disable-nan-check", action='store_true', help="do not check if produced images/latent spaces have nans; useful for running without a checkpoint in CI") parser.add_argument("--use-cpu", nargs='+', help="use CPU as torch device for specified modules", default=[], type=str.lower) +parser.add_argument("--disable-model-loading-ram-optimization", action='store_true', help="disable an optimization that reduces RAM use when loading a model") parser.add_argument("--listen", action='store_true', help="launch gradio with 0.0.0.0 as server name, allowing to respond to network requests") parser.add_argument("--port", type=int, help="launch gradio with given server port, you need root/admin rights for ports < 1024, defaults to 7860 if available", default=None) parser.add_argument("--show-negative-prompt", action='store_true', help="does not do anything", default=False) @@ -79,7 +83,7 @@ parser.add_argument("--gradio-auth-path", type=str, help='set gradio authentication file path ex. "/path/to/auth/file" same auth format as --gradio-auth', default=None) parser.add_argument("--gradio-img2img-tool", type=str, help='does not do anything') parser.add_argument("--gradio-inpaint-tool", type=str, help="does not do anything") -parser.add_argument("--gradio-allowed-path", action='append', help="add path to gradio's allowed_paths, make it possible to serve files from it") +parser.add_argument("--gradio-allowed-path", action='append', help="add path to gradio's allowed_paths, make it possible to serve files from it", default=[data_path]) parser.add_argument("--opt-channelslast", action='store_true', help="change memory type for stable diffusion to channels last") parser.add_argument("--styles-file", type=str, help="filename to use for styles", default=os.path.join(data_path, 'styles.csv')) parser.add_argument("--autolaunch", action='store_true', help="open the webui URL in the system's default browser upon launch", default=False) @@ -111,3 +115,5 @@ parser.add_argument('--add-stop-route', action='store_true', help='add /_stop route to stop server') parser.add_argument('--api-server-stop', action='store_true', help='enable server stop/restart/kill via api') parser.add_argument('--timeout-keep-alive', type=int, default=30, help='set timeout_keep_alive for uvicorn') +parser.add_argument("--disable-all-extensions", action='store_true', help="prevent all extensions from running regardless of any other settings", default=False) +parser.add_argument("--disable-extra-extensions", action='store_true', help=" prevent all extensions except built-in from running regardless of any other settings", default=False) diff --git a/modules/config_states.py b/modules/config_states.py index 6f1ab53fc59..b766aef11d8 100644 --- a/modules/config_states.py +++ b/modules/config_states.py @@ -8,14 +8,12 @@ import tqdm from datetime import datetime -from collections import OrderedDict import git from modules import shared, extensions, errors from modules.paths_internal import script_path, config_states_dir - -all_config_states = OrderedDict() +all_config_states = {} def list_config_states(): @@ -28,10 +26,14 @@ def list_config_states(): for filename in os.listdir(config_states_dir): if filename.endswith(".json"): path = os.path.join(config_states_dir, filename) - with open(path, "r", encoding="utf-8") as f: - j = json.load(f) - j["filepath"] = path - config_states.append(j) + try: + with open(path, "r", encoding="utf-8") as f: + j = json.load(f) + assert "created_at" in j, '"created_at" does not exist' + j["filepath"] = path + config_states.append(j) + except Exception as e: + print(f'[ERROR]: Config states {path}, {e}') config_states = sorted(config_states, key=lambda cs: cs["created_at"], reverse=True) diff --git a/modules/devices.py b/modules/devices.py index 57e51da30e2..c01f06024b4 100644 --- a/modules/devices.py +++ b/modules/devices.py @@ -3,7 +3,7 @@ from functools import lru_cache import torch -from modules import errors +from modules import errors, shared if sys.platform == "darwin": from modules import mac_specific @@ -17,8 +17,6 @@ def has_mps() -> bool: def get_cuda_device_string(): - from modules import shared - if shared.cmd_opts.device_id is not None: return f"cuda:{shared.cmd_opts.device_id}" @@ -40,8 +38,6 @@ def get_optimal_device(): def get_device_for(task): - from modules import shared - if task in shared.cmd_opts.use_cpu: return cpu @@ -71,14 +67,17 @@ def enable_tf32(): torch.backends.cudnn.allow_tf32 = True - errors.run(enable_tf32, "Enabling TF32") -cpu = torch.device("cpu") -device = device_interrogate = device_gfpgan = device_esrgan = device_codeformer = None -dtype = torch.float16 -dtype_vae = torch.float16 -dtype_unet = torch.float16 +cpu: torch.device = torch.device("cpu") +device: torch.device = None +device_interrogate: torch.device = None +device_gfpgan: torch.device = None +device_esrgan: torch.device = None +device_codeformer: torch.device = None +dtype: torch.dtype = torch.float16 +dtype_vae: torch.dtype = torch.float16 +dtype_unet: torch.dtype = torch.float16 unet_needs_upcast = False @@ -90,26 +89,10 @@ def cond_cast_float(input): return input.float() if unet_needs_upcast else input -def randn(seed, shape): - from modules.shared import opts - - torch.manual_seed(seed) - if opts.randn_source == "CPU" or device.type == 'mps': - return torch.randn(shape, device=cpu).to(device) - return torch.randn(shape, device=device) - - -def randn_without_seed(shape): - from modules.shared import opts - - if opts.randn_source == "CPU" or device.type == 'mps': - return torch.randn(shape, device=cpu).to(device) - return torch.randn(shape, device=device) +nv_rng = None def autocast(disable=False): - from modules import shared - if disable: return contextlib.nullcontext() @@ -128,8 +111,6 @@ class NansException(Exception): def test_for_nans(x, where): - from modules import shared - if shared.cmd_opts.disable_nan_check: return @@ -169,3 +150,4 @@ def first_time_calculation(): x = torch.zeros((1, 1, 3, 3)).to(device, dtype) conv2d = torch.nn.Conv2d(1, 1, (3, 3)).to(device, dtype) conv2d(x) + diff --git a/modules/errors.py b/modules/errors.py index 5271a9fe1de..8c339464d46 100644 --- a/modules/errors.py +++ b/modules/errors.py @@ -14,7 +14,8 @@ def record_exception(): if exception_records and exception_records[-1] == e: return - exception_records.append((e, tb)) + from modules import sysinfo + exception_records.append(sysinfo.format_exception(e, tb)) if len(exception_records) > 5: exception_records.pop(0) @@ -83,3 +84,53 @@ def run(code, task): code() except Exception as e: display(task, e) + + +def check_versions(): + from packaging import version + from modules import shared + + import torch + import gradio + + expected_torch_version = "2.0.0" + expected_xformers_version = "0.0.20" + expected_gradio_version = "3.41.2" + + if version.parse(torch.__version__) < version.parse(expected_torch_version): + print_error_explanation(f""" +You are running torch {torch.__version__}. +The program is tested to work with torch {expected_torch_version}. +To reinstall the desired version, run with commandline flag --reinstall-torch. +Beware that this will cause a lot of large files to be downloaded, as well as +there are reports of issues with training tab on the latest version. + +Use --skip-version-check commandline argument to disable this check. + """.strip()) + + if shared.xformers_available: + import xformers + + if version.parse(xformers.__version__) < version.parse(expected_xformers_version): + print_error_explanation(f""" +You are running xformers {xformers.__version__}. +The program is tested to work with xformers {expected_xformers_version}. +To reinstall the desired version, run with commandline flag --reinstall-xformers. + +Use --skip-version-check commandline argument to disable this check. + """.strip()) + + if gradio.__version__ != expected_gradio_version: + print_error_explanation(f""" +You are running gradio {gradio.__version__}. +The program is designed to work with gradio {expected_gradio_version}. +Using a different version of gradio is extremely likely to break the program. + +Reasons why you have the mismatched gradio version can be: + - you use --skip-install flag. + - you use webui.py to start the program instead of launch.py. + - an extension installs the incompatible gradio version. + +Use --skip-version-check commandline argument to disable this check. + """.strip()) + diff --git a/modules/extensions.py b/modules/extensions.py index 09d1e550d07..bf9a1878f5d 100644 --- a/modules/extensions.py +++ b/modules/extensions.py @@ -1,7 +1,7 @@ import os import threading -from modules import shared, errors, cache +from modules import shared, errors, cache, scripts from modules.gitpython_hack import Repo from modules.paths_internal import extensions_dir, extensions_builtin_dir, script_path # noqa: F401 @@ -11,9 +11,9 @@ def active(): - if shared.opts.disable_all_extensions == "all": + if shared.cmd_opts.disable_all_extensions or shared.opts.disable_all_extensions == "all": return [] - elif shared.opts.disable_all_extensions == "extra": + elif shared.cmd_opts.disable_extra_extensions or shared.opts.disable_all_extensions == "extra": return [x for x in extensions if x.enabled and x.is_builtin] else: return [x for x in extensions if x.enabled] @@ -61,7 +61,7 @@ def read_from_repo(): self.from_dict(d) except FileNotFoundError: pass - self.status = 'unknown' + self.status = 'unknown' if self.status == '' else self.status def do_read_info_from_repo(self): repo = None @@ -90,8 +90,6 @@ def do_read_info_from_repo(self): self.have_info_from_repo = True def list_files(self, subdir, extension): - from modules import scripts - dirpath = os.path.join(self.path, subdir) if not os.path.isdir(dirpath): return [] @@ -141,8 +139,12 @@ def list_extensions(): if not os.path.isdir(extensions_dir): return - if shared.opts.disable_all_extensions == "all": + if shared.cmd_opts.disable_all_extensions: + print("*** \"--disable-all-extensions\" arg was used, will not load any extensions ***") + elif shared.opts.disable_all_extensions == "all": print("*** \"Disable all extensions\" option was set, will not load any extensions ***") + elif shared.cmd_opts.disable_extra_extensions: + print("*** \"--disable-extra-extensions\" arg was used, will only load built-in extensions ***") elif shared.opts.disable_all_extensions == "extra": print("*** \"Disable all extensions\" option was set, will only load built-in extensions ***") diff --git a/modules/extra_networks.py b/modules/extra_networks.py index 6ae07e91b1c..b9533677887 100644 --- a/modules/extra_networks.py +++ b/modules/extra_networks.py @@ -1,4 +1,7 @@ +import json +import os import re +import logging from collections import defaultdict from modules import errors @@ -84,27 +87,55 @@ def deactivate(self, p): raise NotImplementedError -def activate(p, extra_network_data): - """call activate for extra networks in extra_network_data in specified order, then call - activate for all remaining registered networks with an empty argument list""" +def lookup_extra_networks(extra_network_data): + """returns a dict mapping ExtraNetwork objects to lists of arguments for those extra networks. - activated = [] + Example input: + { + 'lora': [], + 'lyco': [], + 'hypernet': [] + } + + Example output: + + { + : [, ], + : [] + } + """ + + res = {} - for extra_network_name, extra_network_args in extra_network_data.items(): + for extra_network_name, extra_network_args in list(extra_network_data.items()): extra_network = extra_network_registry.get(extra_network_name, None) + alias = extra_network_aliases.get(extra_network_name, None) - if extra_network is None: - extra_network = extra_network_aliases.get(extra_network_name, None) + if alias is not None and extra_network is None: + extra_network = alias if extra_network is None: - print(f"Skipping unknown extra network: {extra_network_name}") + logging.info(f"Skipping unknown extra network: {extra_network_name}") continue + res.setdefault(extra_network, []).extend(extra_network_args) + + return res + + +def activate(p, extra_network_data): + """call activate for extra networks in extra_network_data in specified order, then call + activate for all remaining registered networks with an empty argument list""" + + activated = [] + + for extra_network, extra_network_args in lookup_extra_networks(extra_network_data).items(): + try: extra_network.activate(p, extra_network_args) activated.append(extra_network) except Exception as e: - errors.display(e, f"activating extra network {extra_network_name} with arguments {extra_network_args}") + errors.display(e, f"activating extra network {extra_network.name} with arguments {extra_network_args}") for extra_network_name, extra_network in extra_network_registry.items(): if extra_network in activated: @@ -123,19 +154,16 @@ def deactivate(p, extra_network_data): """call deactivate for extra networks in extra_network_data in specified order, then call deactivate for all remaining registered networks""" - for extra_network_name in extra_network_data: - extra_network = extra_network_registry.get(extra_network_name, None) - if extra_network is None: - continue + data = lookup_extra_networks(extra_network_data) + for extra_network in data: try: extra_network.deactivate(p) except Exception as e: - errors.display(e, f"deactivating extra network {extra_network_name}") + errors.display(e, f"deactivating extra network {extra_network.name}") for extra_network_name, extra_network in extra_network_registry.items(): - args = extra_network_data.get(extra_network_name, None) - if args is not None: + if extra_network in data: continue try: @@ -177,3 +205,20 @@ def parse_prompts(prompts): return res, extra_data + +def get_user_metadata(filename): + if filename is None: + return {} + + basename, ext = os.path.splitext(filename) + metadata_filename = basename + '.json' + + metadata = {} + try: + if os.path.isfile(metadata_filename): + with open(metadata_filename, "r", encoding="utf8") as file: + metadata = json.load(file) + except Exception as e: + errors.display(e, f"reading extra network user metadata from {metadata_filename}") + + return metadata diff --git a/modules/extras.py b/modules/extras.py index e9c0263ec7d..2a310ae3f25 100644 --- a/modules/extras.py +++ b/modules/extras.py @@ -7,7 +7,7 @@ import torch import tqdm -from modules import shared, images, sd_models, sd_vae, sd_models_config +from modules import shared, images, sd_models, sd_vae, sd_models_config, errors from modules.ui_common import plaintext_to_html import gradio as gr import safetensors.torch @@ -72,7 +72,20 @@ def to_half(tensor, enable): return tensor -def run_modelmerger(id_task, primary_model_name, secondary_model_name, tertiary_model_name, interp_method, multiplier, save_as_half, custom_name, checkpoint_format, config_source, bake_in_vae, discard_weights, save_metadata): +def read_metadata(primary_model_name, secondary_model_name, tertiary_model_name): + metadata = {} + + for checkpoint_name in [primary_model_name, secondary_model_name, tertiary_model_name]: + checkpoint_info = sd_models.checkpoints_list.get(checkpoint_name, None) + if checkpoint_info is None: + continue + + metadata.update(checkpoint_info.metadata) + + return json.dumps(metadata, indent=4, ensure_ascii=False) + + +def run_modelmerger(id_task, primary_model_name, secondary_model_name, tertiary_model_name, interp_method, multiplier, save_as_half, custom_name, checkpoint_format, config_source, bake_in_vae, discard_weights, save_metadata, add_merge_recipe, copy_metadata_fields, metadata_json): shared.state.begin(job="model-merge") def fail(message): @@ -241,11 +254,25 @@ def filename_nothing(): shared.state.textinfo = "Saving" print(f"Saving to {output_modelname}...") - metadata = None + metadata = {} + + if save_metadata and copy_metadata_fields: + if primary_model_info: + metadata.update(primary_model_info.metadata) + if secondary_model_info: + metadata.update(secondary_model_info.metadata) + if tertiary_model_info: + metadata.update(tertiary_model_info.metadata) if save_metadata: - metadata = {"format": "pt"} + try: + metadata.update(json.loads(metadata_json)) + except Exception as e: + errors.display(e, "readin metadata from json") + + metadata["format"] = "pt" + if save_metadata and add_merge_recipe: merge_recipe = { "type": "webui", # indicate this model was merged with webui's built-in merger "primary_model_hash": primary_model_info.sha256, @@ -261,7 +288,6 @@ def filename_nothing(): "is_inpainting": result_is_inpainting_model, "is_instruct_pix2pix": result_is_instruct_pix2pix_model } - metadata["sd_merge_recipe"] = json.dumps(merge_recipe) sd_merge_models = {} @@ -281,11 +307,12 @@ def add_model_metadata(checkpoint_info): if tertiary_model_info: add_model_metadata(tertiary_model_info) + metadata["sd_merge_recipe"] = json.dumps(merge_recipe) metadata["sd_merge_models"] = json.dumps(sd_merge_models) _, extension = os.path.splitext(output_modelname) if extension.lower() == ".safetensors": - safetensors.torch.save_file(theta_0, output_modelname, metadata=metadata) + safetensors.torch.save_file(theta_0, output_modelname, metadata=metadata if len(metadata)>0 else None) else: torch.save(theta_0, output_modelname) diff --git a/modules/fifo_lock.py b/modules/fifo_lock.py new file mode 100644 index 00000000000..c35b3ae25a3 --- /dev/null +++ b/modules/fifo_lock.py @@ -0,0 +1,37 @@ +import threading +import collections + + +# reference: https://gist.github.com/vitaliyp/6d54dd76ca2c3cdfc1149d33007dc34a +class FIFOLock(object): + def __init__(self): + self._lock = threading.Lock() + self._inner_lock = threading.Lock() + self._pending_threads = collections.deque() + + def acquire(self, blocking=True): + with self._inner_lock: + lock_acquired = self._lock.acquire(False) + if lock_acquired: + return True + elif not blocking: + return False + + release_event = threading.Event() + self._pending_threads.append(release_event) + + release_event.wait() + return self._lock.acquire() + + def release(self): + with self._inner_lock: + if self._pending_threads: + release_event = self._pending_threads.popleft() + release_event.set() + + self._lock.release() + + __enter__ = acquire + + def __exit__(self, t, v, tb): + self.release() diff --git a/modules/generation_parameters_copypaste.py b/modules/generation_parameters_copypaste.py index 88f4381bab2..d39f2ebac36 100644 --- a/modules/generation_parameters_copypaste.py +++ b/modules/generation_parameters_copypaste.py @@ -6,10 +6,10 @@ import gradio as gr from modules.paths import data_path -from modules import shared, ui_tempdir, script_callbacks +from modules import shared, ui_tempdir, script_callbacks, processing from PIL import Image -re_param_code = r'\s*([\w ]+):\s*("(?:\\"[^,]|\\"|\\|[^\"])+"|[^,]*)(?:,|$)' +re_param_code = r'\s*([\w ]+):\s*("(?:\\.|[^\\"])+"|[^,]*)(?:,|$)' re_param = re.compile(re_param_code) re_imagesize = re.compile(r"^(\d+)x(\d+)$") re_hypernet_hash = re.compile("\(([0-9a-f]+)\)$") @@ -32,6 +32,7 @@ def __init__(self, paste_button, tabname, source_text_component=None, source_ima def reset(): paste_fields.clear() + registered_param_bindings.clear() def quote(text): @@ -198,7 +199,6 @@ def restore_old_hires_fix_params(res): height = int(res.get("Size-2", 512)) if firstpass_width == 0 or firstpass_height == 0: - from modules import processing firstpass_width, firstpass_height = processing.old_hires_fix_first_pass_dimensions(width, height) res['Size-1'] = firstpass_width @@ -280,6 +280,9 @@ def parse_generation_parameters(x: str): if "Hires sampler" not in res: res["Hires sampler"] = "Use same sampler" + if "Hires checkpoint" not in res: + res["Hires checkpoint"] = "Use same checkpoint" + if "Hires prompt" not in res: res["Hires prompt"] = "" @@ -304,32 +307,28 @@ def parse_generation_parameters(x: str): if "Schedule rho" not in res: res["Schedule rho"] = 0 + if "VAE Encoder" not in res: + res["VAE Encoder"] = "Full" + + if "VAE Decoder" not in res: + res["VAE Decoder"] = "Full" + return res infotext_to_setting_name_mapping = [ - ('Clip skip', 'CLIP_stop_at_last_layers', ), + +] +"""Mapping of infotext labels to setting names. Only left for backwards compatibility - use OptionInfo(..., infotext='...') instead. +Example content: + +infotext_to_setting_name_mapping = [ ('Conditional mask weight', 'inpainting_mask_weight'), ('Model hash', 'sd_model_checkpoint'), ('ENSD', 'eta_noise_seed_delta'), ('Schedule type', 'k_sched_type'), - ('Schedule max sigma', 'sigma_max'), - ('Schedule min sigma', 'sigma_min'), - ('Schedule rho', 'rho'), - ('Noise multiplier', 'initial_noise_multiplier'), - ('Eta', 'eta_ancestral'), - ('Eta DDIM', 'eta_ddim'), - ('Discard penultimate sigma', 'always_discard_next_to_last_sigma'), - ('UniPC variant', 'uni_pc_variant'), - ('UniPC skip type', 'uni_pc_skip_type'), - ('UniPC order', 'uni_pc_order'), - ('UniPC lower order final', 'uni_pc_lower_order_final'), - ('Token merging ratio', 'token_merging_ratio'), - ('Token merging ratio hr', 'token_merging_ratio_hr'), - ('RNG', 'randn_source'), - ('NGMS', 's_min_uncond'), - ('Pad conds', 'pad_cond_uncond'), ] +""" def create_override_settings_dict(text_pairs): @@ -350,7 +349,8 @@ def create_override_settings_dict(text_pairs): params[k] = v.strip() - for param_name, setting_name in infotext_to_setting_name_mapping: + mapping = [(info.infotext, k) for k, info in shared.opts.data_labels.items() if info.infotext] + for param_name, setting_name in mapping + infotext_to_setting_name_mapping: value = params.get(param_name, None) if value is None: @@ -399,14 +399,20 @@ def paste_func(prompt): return res if override_settings_component is not None: + already_handled_fields = {key: 1 for _, key in paste_fields} + def paste_settings(params): vals = {} - for param_name, setting_name in infotext_to_setting_name_mapping: + mapping = [(info.infotext, k) for k, info in shared.opts.data_labels.items() if info.infotext] + for param_name, setting_name in mapping + infotext_to_setting_name_mapping: + if param_name in already_handled_fields: + continue + v = params.get(param_name, None) if v is None: continue - + if setting_name == "sd_model_checkpoint" and shared.opts.disable_weights_auto_swap: continue @@ -416,7 +422,7 @@ def paste_settings(params): if v == current_value: continue - vals[param_name] = v + vals[param_name] = v vals_pairs = [f"{k}: {v}" for k, v in vals.items()] diff --git a/modules/gradio_extensons.py b/modules/gradio_extensons.py new file mode 100644 index 00000000000..aac742ef0c1 --- /dev/null +++ b/modules/gradio_extensons.py @@ -0,0 +1,73 @@ +import gradio as gr + +from modules import scripts, ui_tempdir, patches + + +def add_classes_to_gradio_component(comp): + """ + this adds gradio-* to the component for css styling (ie gradio-button to gr.Button), as well as some others + """ + + comp.elem_classes = [f"gradio-{comp.get_block_name()}", *(comp.elem_classes or [])] + + if getattr(comp, 'multiselect', False): + comp.elem_classes.append('multiselect') + + +def IOComponent_init(self, *args, **kwargs): + self.webui_tooltip = kwargs.pop('tooltip', None) + + if scripts.scripts_current is not None: + scripts.scripts_current.before_component(self, **kwargs) + + scripts.script_callbacks.before_component_callback(self, **kwargs) + + res = original_IOComponent_init(self, *args, **kwargs) + + add_classes_to_gradio_component(self) + + scripts.script_callbacks.after_component_callback(self, **kwargs) + + if scripts.scripts_current is not None: + scripts.scripts_current.after_component(self, **kwargs) + + return res + + +def Block_get_config(self): + config = original_Block_get_config(self) + + webui_tooltip = getattr(self, 'webui_tooltip', None) + if webui_tooltip: + config["webui_tooltip"] = webui_tooltip + + config.pop('example_inputs', None) + + return config + + +def BlockContext_init(self, *args, **kwargs): + res = original_BlockContext_init(self, *args, **kwargs) + + add_classes_to_gradio_component(self) + + return res + + +def Blocks_get_config_file(self, *args, **kwargs): + config = original_Blocks_get_config_file(self, *args, **kwargs) + + for comp_config in config["components"]: + if "example_inputs" in comp_config: + comp_config["example_inputs"] = {"serialized": []} + + return config + + +original_IOComponent_init = patches.patch(__name__, obj=gr.components.IOComponent, field="__init__", replacement=IOComponent_init) +original_Block_get_config = patches.patch(__name__, obj=gr.blocks.Block, field="get_config", replacement=Block_get_config) +original_BlockContext_init = patches.patch(__name__, obj=gr.blocks.BlockContext, field="__init__", replacement=BlockContext_init) +original_Blocks_get_config_file = patches.patch(__name__, obj=gr.blocks.Blocks, field="get_config_file", replacement=Blocks_get_config_file) + + +ui_tempdir.install_ui_tempdir_override() diff --git a/modules/hypernetworks/hypernetwork.py b/modules/hypernetworks/hypernetwork.py index c4821d21a7e..70f1cbd26b6 100644 --- a/modules/hypernetworks/hypernetwork.py +++ b/modules/hypernetworks/hypernetwork.py @@ -10,7 +10,7 @@ import tqdm from einops import rearrange, repeat from ldm.util import default -from modules import devices, processing, sd_models, shared, sd_samplers, hashes, sd_hijack_checkpoint, errors +from modules import devices, sd_models, shared, sd_samplers, hashes, sd_hijack_checkpoint, errors from modules.textual_inversion import textual_inversion, logging from modules.textual_inversion.learn_schedule import LearnRateScheduler from torch import einsum @@ -469,8 +469,7 @@ def create_hypernetwork(name, enable_sizes, overwrite_old, layer_structure=None, def train_hypernetwork(id_task, hypernetwork_name, learn_rate, batch_size, gradient_step, data_root, log_directory, training_width, training_height, varsize, steps, clip_grad_mode, clip_grad_value, shuffle_tags, tag_drop_out, latent_sampling_method, use_weight, create_image_every, save_hypernetwork_every, template_filename, preview_from_txt2img, preview_prompt, preview_negative_prompt, preview_steps, preview_sampler_index, preview_cfg_scale, preview_seed, preview_width, preview_height): - # images allows training previews to have infotext. Importing it at the top causes a circular import problem. - from modules import images + from modules import images, processing save_hypernetwork_every = save_hypernetwork_every or 0 create_image_every = create_image_every or 0 diff --git a/modules/images.py b/modules/images.py index 38aa933d6e5..eb644733898 100644 --- a/modules/images.py +++ b/modules/images.py @@ -21,8 +21,6 @@ from modules.paths_internal import roboto_ttf_file from modules.shared import opts -import modules.sd_vae as sd_vae - LANCZOS = (Image.Resampling.LANCZOS if hasattr(Image, 'Resampling') else Image.LANCZOS) @@ -318,7 +316,7 @@ def resize(im, w, h): return res -invalid_filename_chars = '<>:"/\\|?*\n' +invalid_filename_chars = '<>:"/\\|?*\n\r\t' invalid_filename_prefix = ' ' invalid_filename_postfix = ' .' re_nonletters = re.compile(r'[\s' + string.punctuation + ']+') @@ -342,16 +340,6 @@ def sanitize_filename_part(text, replace_spaces=True): class FilenameGenerator: - def get_vae_filename(self): #get the name of the VAE file. - if sd_vae.loaded_vae_file is None: - return "NoneType" - file_name = os.path.basename(sd_vae.loaded_vae_file) - split_file_name = file_name.split('.') - if len(split_file_name) > 1 and split_file_name[0] == '': - return split_file_name[1] # if the first character of the filename is "." then [1] is obtained. - else: - return split_file_name[0] - replacements = { 'seed': lambda self: self.seed if self.seed is not None else '', 'seed_first': lambda self: self.seed if self.p.batch_size == 1 else self.p.all_seeds[0], @@ -367,7 +355,9 @@ def get_vae_filename(self): #get the name of the VAE file. 'date': lambda self: datetime.datetime.now().strftime('%Y-%m-%d'), 'datetime': lambda self, *args: self.datetime(*args), # accepts formats: [datetime], [datetime], [datetime